ethereumjs-util
Version:
A collection of utility functions for Ethereum
296 lines • 12 kB
JavaScript
var __read = (this && this.__read) || function (o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m) return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
}
catch (error) { e = { error: error }; }
finally {
try {
if (r && !r.done && (m = i["return"])) m.call(i);
}
finally { if (e) throw e.error; }
}
return ar;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.isZeroAddress = exports.zeroAddress = exports.importPublic = exports.privateToAddress = exports.privateToPublic = exports.publicToAddress = exports.pubToAddress = exports.isValidPublic = exports.isValidPrivate = exports.generateAddress2 = exports.generateAddress = exports.isValidChecksumAddress = exports.toChecksumAddress = exports.isValidAddress = exports.Account = void 0;
var assert_1 = __importDefault(require("assert"));
var externals_1 = require("./externals");
var secp256k1_1 = require("ethereum-cryptography/secp256k1");
var internal_1 = require("./internal");
var constants_1 = require("./constants");
var bytes_1 = require("./bytes");
var hash_1 = require("./hash");
var helpers_1 = require("./helpers");
var types_1 = require("./types");
var Account = /** @class */ (function () {
/**
* This constructor assigns and validates the values.
* Use the static factory methods to assist in creating an Account from varying data types.
*/
function Account(nonce, balance, stateRoot, codeHash) {
if (nonce === void 0) { nonce = new externals_1.BN(0); }
if (balance === void 0) { balance = new externals_1.BN(0); }
if (stateRoot === void 0) { stateRoot = constants_1.KECCAK256_RLP; }
if (codeHash === void 0) { codeHash = constants_1.KECCAK256_NULL; }
this.nonce = nonce;
this.balance = balance;
this.stateRoot = stateRoot;
this.codeHash = codeHash;
this._validate();
}
Account.fromAccountData = function (accountData) {
var nonce = accountData.nonce, balance = accountData.balance, stateRoot = accountData.stateRoot, codeHash = accountData.codeHash;
return new Account(nonce ? new externals_1.BN((0, bytes_1.toBuffer)(nonce)) : undefined, balance ? new externals_1.BN((0, bytes_1.toBuffer)(balance)) : undefined, stateRoot ? (0, bytes_1.toBuffer)(stateRoot) : undefined, codeHash ? (0, bytes_1.toBuffer)(codeHash) : undefined);
};
Account.fromRlpSerializedAccount = function (serialized) {
var values = externals_1.rlp.decode(serialized);
if (!Array.isArray(values)) {
throw new Error('Invalid serialized account input. Must be array');
}
return this.fromValuesArray(values);
};
Account.fromValuesArray = function (values) {
var _a = __read(values, 4), nonce = _a[0], balance = _a[1], stateRoot = _a[2], codeHash = _a[3];
return new Account(new externals_1.BN(nonce), new externals_1.BN(balance), stateRoot, codeHash);
};
Account.prototype._validate = function () {
if (this.nonce.lt(new externals_1.BN(0))) {
throw new Error('nonce must be greater than zero');
}
if (this.balance.lt(new externals_1.BN(0))) {
throw new Error('balance must be greater than zero');
}
if (this.stateRoot.length !== 32) {
throw new Error('stateRoot must have a length of 32');
}
if (this.codeHash.length !== 32) {
throw new Error('codeHash must have a length of 32');
}
};
/**
* Returns a Buffer Array of the raw Buffers for the account, in order.
*/
Account.prototype.raw = function () {
return [
(0, types_1.bnToUnpaddedBuffer)(this.nonce),
(0, types_1.bnToUnpaddedBuffer)(this.balance),
this.stateRoot,
this.codeHash,
];
};
/**
* Returns the RLP serialization of the account as a `Buffer`.
*/
Account.prototype.serialize = function () {
return externals_1.rlp.encode(this.raw());
};
/**
* Returns a `Boolean` determining if the account is a contract.
*/
Account.prototype.isContract = function () {
return !this.codeHash.equals(constants_1.KECCAK256_NULL);
};
/**
* Returns a `Boolean` determining if the account is empty complying to the definition of
* account emptiness in [EIP-161](https://eips.ethereum.org/EIPS/eip-161):
* "An account is considered empty when it has no code and zero nonce and zero balance."
*/
Account.prototype.isEmpty = function () {
return this.balance.isZero() && this.nonce.isZero() && this.codeHash.equals(constants_1.KECCAK256_NULL);
};
return Account;
}());
exports.Account = Account;
/**
* Checks if the address is a valid. Accepts checksummed addresses too.
*/
var isValidAddress = function (hexAddress) {
try {
(0, helpers_1.assertIsString)(hexAddress);
}
catch (e) {
return false;
}
return /^0x[0-9a-fA-F]{40}$/.test(hexAddress);
};
exports.isValidAddress = isValidAddress;
/**
* Returns a checksummed address.
*
* If an eip1191ChainId is provided, the chainId will be included in the checksum calculation. This
* has the effect of checksummed addresses for one chain having invalid checksums for others.
* For more details see [EIP-1191](https://eips.ethereum.org/EIPS/eip-1191).
*
* WARNING: Checksums with and without the chainId will differ and the EIP-1191 checksum is not
* backwards compatible to the original widely adopted checksum format standard introduced in
* [EIP-55](https://eips.ethereum.org/EIPS/eip-55), so this will break in existing applications.
* Usage of this EIP is therefore discouraged unless you have a very targeted use case.
*/
var toChecksumAddress = function (hexAddress, eip1191ChainId) {
(0, helpers_1.assertIsHexString)(hexAddress);
var address = (0, internal_1.stripHexPrefix)(hexAddress).toLowerCase();
var prefix = '';
if (eip1191ChainId) {
var chainId = (0, types_1.toType)(eip1191ChainId, types_1.TypeOutput.BN);
prefix = chainId.toString() + '0x';
}
var hash = (0, hash_1.keccakFromString)(prefix + address).toString('hex');
var ret = '0x';
for (var i = 0; i < address.length; i++) {
if (parseInt(hash[i], 16) >= 8) {
ret += address[i].toUpperCase();
}
else {
ret += address[i];
}
}
return ret;
};
exports.toChecksumAddress = toChecksumAddress;
/**
* Checks if the address is a valid checksummed address.
*
* See toChecksumAddress' documentation for details about the eip1191ChainId parameter.
*/
var isValidChecksumAddress = function (hexAddress, eip1191ChainId) {
return (0, exports.isValidAddress)(hexAddress) && (0, exports.toChecksumAddress)(hexAddress, eip1191ChainId) === hexAddress;
};
exports.isValidChecksumAddress = isValidChecksumAddress;
/**
* Generates an address of a newly created contract.
* @param from The address which is creating this new address
* @param nonce The nonce of the from account
*/
var generateAddress = function (from, nonce) {
(0, helpers_1.assertIsBuffer)(from);
(0, helpers_1.assertIsBuffer)(nonce);
var nonceBN = new externals_1.BN(nonce);
if (nonceBN.isZero()) {
// in RLP we want to encode null in the case of zero nonce
// read the RLP documentation for an answer if you dare
return (0, hash_1.rlphash)([from, null]).slice(-20);
}
// Only take the lower 160bits of the hash
return (0, hash_1.rlphash)([from, Buffer.from(nonceBN.toArray())]).slice(-20);
};
exports.generateAddress = generateAddress;
/**
* Generates an address for a contract created using CREATE2.
* @param from The address which is creating this new address
* @param salt A salt
* @param initCode The init code of the contract being created
*/
var generateAddress2 = function (from, salt, initCode) {
(0, helpers_1.assertIsBuffer)(from);
(0, helpers_1.assertIsBuffer)(salt);
(0, helpers_1.assertIsBuffer)(initCode);
(0, assert_1.default)(from.length === 20);
(0, assert_1.default)(salt.length === 32);
var address = (0, hash_1.keccak256)(Buffer.concat([Buffer.from('ff', 'hex'), from, salt, (0, hash_1.keccak256)(initCode)]));
return address.slice(-20);
};
exports.generateAddress2 = generateAddress2;
/**
* Checks if the private key satisfies the rules of the curve secp256k1.
*/
var isValidPrivate = function (privateKey) {
return (0, secp256k1_1.privateKeyVerify)(privateKey);
};
exports.isValidPrivate = isValidPrivate;
/**
* Checks if the public key satisfies the rules of the curve secp256k1
* and the requirements of Ethereum.
* @param publicKey The two points of an uncompressed key, unless sanitize is enabled
* @param sanitize Accept public keys in other formats
*/
var isValidPublic = function (publicKey, sanitize) {
if (sanitize === void 0) { sanitize = false; }
(0, helpers_1.assertIsBuffer)(publicKey);
if (publicKey.length === 64) {
// Convert to SEC1 for secp256k1
return (0, secp256k1_1.publicKeyVerify)(Buffer.concat([Buffer.from([4]), publicKey]));
}
if (!sanitize) {
return false;
}
return (0, secp256k1_1.publicKeyVerify)(publicKey);
};
exports.isValidPublic = isValidPublic;
/**
* Returns the ethereum address of a given public key.
* Accepts "Ethereum public keys" and SEC1 encoded keys.
* @param pubKey The two points of an uncompressed key, unless sanitize is enabled
* @param sanitize Accept public keys in other formats
*/
var pubToAddress = function (pubKey, sanitize) {
if (sanitize === void 0) { sanitize = false; }
(0, helpers_1.assertIsBuffer)(pubKey);
if (sanitize && pubKey.length !== 64) {
pubKey = Buffer.from((0, secp256k1_1.publicKeyConvert)(pubKey, false).slice(1));
}
(0, assert_1.default)(pubKey.length === 64);
// Only take the lower 160bits of the hash
return (0, hash_1.keccak)(pubKey).slice(-20);
};
exports.pubToAddress = pubToAddress;
exports.publicToAddress = exports.pubToAddress;
/**
* Returns the ethereum public key of a given private key.
* @param privateKey A private key must be 256 bits wide
*/
var privateToPublic = function (privateKey) {
(0, helpers_1.assertIsBuffer)(privateKey);
// skip the type flag and use the X, Y points
return Buffer.from((0, secp256k1_1.publicKeyCreate)(privateKey, false)).slice(1);
};
exports.privateToPublic = privateToPublic;
/**
* Returns the ethereum address of a given private key.
* @param privateKey A private key must be 256 bits wide
*/
var privateToAddress = function (privateKey) {
return (0, exports.publicToAddress)((0, exports.privateToPublic)(privateKey));
};
exports.privateToAddress = privateToAddress;
/**
* Converts a public key to the Ethereum format.
*/
var importPublic = function (publicKey) {
(0, helpers_1.assertIsBuffer)(publicKey);
if (publicKey.length !== 64) {
publicKey = Buffer.from((0, secp256k1_1.publicKeyConvert)(publicKey, false).slice(1));
}
return publicKey;
};
exports.importPublic = importPublic;
/**
* Returns the zero address.
*/
var zeroAddress = function () {
var addressLength = 20;
var addr = (0, bytes_1.zeros)(addressLength);
return (0, bytes_1.bufferToHex)(addr);
};
exports.zeroAddress = zeroAddress;
/**
* Checks if a given address is the zero address.
*/
var isZeroAddress = function (hexAddress) {
try {
(0, helpers_1.assertIsString)(hexAddress);
}
catch (e) {
return false;
}
var zeroAddr = (0, exports.zeroAddress)();
return zeroAddr === hexAddress;
};
exports.isZeroAddress = isZeroAddress;
//# sourceMappingURL=account.js.map
;