ethereumjs/ethereumjs-util
ethereumjs/ethereumjs-util
Most of the string manipulation methods are provided by ethjs-util
更多的字符串处理方法可以看ethjs-util
addHexPrefix
Adds "0x" to a given String if it does not already start with "0x"
在没有"0x"前缀的十六进制字符串前面添加前缀
Parameters
strString
Returns String
baToJSON
Converts a Buffer or Array to JSON
将Buffer或Array转成JSON
Parameters
Returns (Array | String | null)
BN
Type: Function
大数
bufferToHex
Converts a Buffer into a hex String
将 Buffer转成16进制的String
Parameters
bufBuffer
Returns String
bufferToInt
Converts a Buffer to a Number
将Buffer转成Number
Parameters
bufBufferThrows any If the input number exceeds 53 bits.
Returns Number
defineProperties
Defines properties on a Object. It make the assumption that underlying data is binary.
定义对象的属性。假设下面的数据都为二进制数
Parameters
selfObject theObjectto define properties on 定义属性的对象fieldsArray an array fields to define. Fields can contain:name- the name of the properties
length- the number of bytes the field can haveallowLess- if the field can be less than the lengthallowEmpty
dataany data to be validated against the definitions
ecrecover
ECDSA public key recovery from signature
从签名r,s,v和消息hash得到公钥
Parameters
Returns Buffer publicKey
ecsign
ECDSA sign签名,返回r,s,v
Parameters
msgHashBufferprivateKeyBufferchainIdNumber根据chainId是否设置来决定v=v+2 * chainId+35(chainId不为0)还是v= v+27(为0或undefined)
Returns Object
fromRpcSig
Convert signature format of the eth_sign RPC method to signature parameters
将eth_sign RPC方法的签名格式转换为签名参数,即将65字节的格式转成分开的r,s,v
NOTE: all because of a bug in geth: https://github.com/ethereum/go-ethereum/issues/2053
即r,v,s签名中的v = v +27
Parameters
sigString
Returns Object
toRpcSig
Convert signature parameters into the format of eth_sign RPC method
将签名参数转成符合eth_sign RPC方法的格式,即将r,s,v转成65字节的格式
Parameters
Returns String sig
fromSigned
Interprets a Buffer as a signed integer and returns a BN. Assumes 256-bit numbers.
将Buffer转成一个签名整数并返回BN大数对象,假设为一个256位的数字
Parameters
numBuffer
Returns BN
generateAddress
Generates an address of a newly created contract
为新创建的合约生成一个address(合约即交易,它的address都可以通过合约部署者的账户address及其nonce生成)
Parameters
fromBuffer the address which is creating this new address合约部署者账户addressnonceBuffer the nonce of the from account 账户的nonce(即下一笔交易数)
Returns Buffer
generateAddress2
Generates an address for a contract created using CREATE2
使用CREATE2为合约的创建生成一个address
Parameters
fromBuffer the address which is creating this new addresssaltBuffer a saltinitCodeBuffer the init code of the contract being created 合约的encode
Returns Buffer
hashPersonalMessage
Returns the keccak-256 hash of message, prefixed with the header used by the eth_sign RPC call. The output of this function can be fed into ecsign to produce the same signature as the eth_sign call for a given message, or fed to ecrecover along with a signature to recover the public key used to produce the signature.
返回消息的keccak-256散列,以eth_sign RPC调用使用的头作为前缀。可以将此函数的输出输入ecsign,以生成与给定消息的eth_sign调用相同的签名,也可以将该函数的输出与签名一起输入ecrecovery,以恢复用于生成签名的公钥。
Parameters
message
Returns Buffer hash
importPublic
Converts a public key to the Ethereum format.
将公钥转成以太坊的格式
Parameters
publicKeyBuffer
Returns Buffer
isPrecompiled
Returns true if the supplied address belongs to a precompiled account (Byzantium)
如果提供的地址属于预编译帐户,则返回true
Parameters
Returns Boolean
isValidAddress
Checks if the address is a valid. Accepts checksummed addresses too
检查地址是否有效,接受校验和地址
Parameters
addressString
Returns Boolean
isValidChecksumAddress
Checks if the address is a valid checksummed address
查看地址是否是有效的校验和地址
Parameters
addressBuffer
Returns Boolean
isValidPrivate
Checks if the private key satisfies the rules of the curve secp256k1.
查看私钥是否满足曲线secp256k1的规则
Parameters
privateKeyBuffer
Returns Boolean
isValidPublic
Checks if the public key satisfies the rules of the curve secp256k1 and the requirements of Ethereum.
查看公钥是否满足曲线secp256k1的规则和以太坊的需求
Parameters
publicKeyBuffer The two points of an uncompressed key, unless sanitize is enabledsanitizeBoolean Accept public keys in other formats (optional, defaultfalse)
Returns Boolean
keccak
Creates Keccak hash of the input
生成输入的Keccak hash散列值
Parameters
a(Buffer | Array | String | Number) the input databitsNumber the Keccak width (optional, default256)设置返回的hash值的长度
Returns Buffer
keccak256
Creates Keccak-256 hash of the input, alias for keccak(a, 256)
生成输入的256比特Keccak hash散列值,返回hash值的长度为256bits.
与keccak(a, 256)等价,因为keccak默认为256,所以keccak256(s)==keccak(s)
Parameters
Returns Buffer
privateToAddress
Returns the ethereum address of a given private key
根据私钥得到以太坊地址
Parameters
privateKeyBuffer A private key must be 256 bits wide
Returns Buffer
pubToAddress
Returns the ethereum address of a given public key. Accepts "Ethereum public keys" and SEC1 encoded keys.
根据公钥得到以太坊地址,接受以太坊公钥和SEC1加密密钥
Parameters
pubKeyBuffer The two points of an uncompressed key, unless sanitize is enabledsanitizeBoolean Accept public keys in other formats (optional, defaultfalse)
Returns Buffer
ripemd160
Creates RIPEMD160 hash of the input
生成输入的RIPEMD160 hash散列值
Parameters
a(Buffer | Array | String | Number) the input datapaddedBoolean whether it should be padded to 256 bits or not设置为true,则当返回的hash值长度不为256时左填充0
Returns Buffer
rlp
Type: Function
rlphash
Creates SHA-3 hash of the RLP encoded version of the input
生成输入的RLP编码的SHA-3 hash散列值
Parameters
Returns Buffer
secp256k1
Type: Object
setLengthRight
Right Pads an Array or Buffer with leading zeros till it has length bytes. Or it truncates the beginning if it exceeds.
使用0右填充Array or Buffer直至长度满足length,或是当长度超过的时候进行截断。
⚠️setLengthRight其实就是调用了setLengthLeft(msg, length, true)
Parameters
setLengthLeft
Left Pads an Array or Buffer with leading zeros till it has length bytes. Or it truncates the beginning if it exceeds.
使用0左填充Array or Buffer直至长度满足length,或是当长度超过的时候进行截断
Parameters
msg(Buffer | Array) the value to padlengthNumber the number of bytes the output should berightBoolean whether to start padding form the left or right (optional, defaultfalse)right = true就相当于右填充
sha256
Creates SHA256 hash of the input
创建输入的SHA256 hash散列值
Parameters
Returns Buffer
toBuffer
Attempts to turn a value into a Buffer. As input it supports Buffer, String, Number, null/undefined, BN and other objects with a toArray() method.
将值转成Buffer,值输入支持Buffer, String, Number, null/undefined, BN和具有toArray()方法的对象
Parameters
vany the value
toChecksumAddress
Returns a checksummed address
将address转成校验和地址
Parameters
addressString
Returns String
toUnsigned
Converts a BN to an unsigned integer and returns it as a Buffer. Assumes 256-bit numbers.
将BN转成无符号整数并将其返回成Buffer,是256比特的数字
Parameters
numBN
Returns Buffer
unpad
Trims leading zeros from a Buffer or an Array
将Buffer或Array前面的0删掉
Parameters
Returns (Buffer | Array | String)
isValidSignature
Validate ECDSA signature
是否是有效的签名
Parameters
Returns Boolean
isZeroAddress
Checks if a given address is a zero address
查看给定的address是否是0x0000...000地址
Parameters
addressString
Returns Boolean
KECCAK256_NULL
Keccak-256 hash of null (a Buffer)
Buffer类型的null的Keccak-256 hash散列值
Type: Buffer
KECCAK256_NULL_S
Keccak-256 hash of null (a String)
String类型的null的Keccak-256 hash散列值
Type: String
KECCAK256_RLP
Keccak-256 hash of the RLP of null (a Buffer)
Buffer类型的RLP编码格式的null的Keccak-256 hash散列值
Type: Buffer
KECCAK256_RLP_S
Keccak-256 hash of the RLP of null (a String)
Type: String
String类型的RLP编码格式的null的Keccak-256 hash散列值
KECCAK256_RLP_ARRAY
Keccak-256 of an RLP of an empty array (a Buffer)
Buffer类型的RLP编码格式的空数组的Keccak-256 hash散列值
Type: Buffer
KECCAK256_RLP_ARRAY_S
Keccak-256 of an RLP of an empty array (a String)
String类型的RLP编码格式的空数组的Keccak-256 hash散列值
Type: String
MAX_INTEGER
the max integer that this VM can handle (a BN)
设置虚拟机能够处理的最大整数
Type: BN
privateToPublic
Returns the ethereum public key of a given private key
根据私钥得到以太坊的公钥
Parameters
privateKeyBuffer A private key must be 256 bits wide
Returns Buffer
TWO_POW256
2^256 (a BN)
得到2的256次幂的值
Type: BN
zeroAddress
Returns a zero address
返回0x000...000地址
Returns String
zeros
Returns a buffer filled with 0s
返回布满0的buffer
Parameters
bytesNumber the number of bytes the buffer should be
Returns Buffer
实现代码:
const createKeccakHash = require('keccak')
const secp256k1 = require('secp256k1')
const assert = require('assert')
const rlp = require('rlp')
const BN = require('bn.js')
const createHash = require('create-hash')
const Buffer = require('safe-buffer').Buffer
Object.assign(exports, require('ethjs-util'))
/**
* the max integer that this VM can handle (a ```BN```)
* @var {BN} MAX_INTEGER
*/
exports.MAX_INTEGER = new BN('ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', )
/**
* 2^256 (a ```BN```)
* @var {BN} TWO_POW256
*/
exports.TWO_POW256 = new BN('', )
/**
* Keccak-256 hash of null (a ```String```)
* @var {String} KECCAK256_NULL_S
*/
exports.KECCAK256_NULL_S = 'c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470'
/**
* Keccak-256 hash of null (a ```Buffer```)
* @var {Buffer} KECCAK256_NULL
*/
exports.KECCAK256_NULL = Buffer.from(exports.KECCAK256_NULL_S, 'hex')
/**
* Keccak-256 of an RLP of an empty array (a ```String```)
* @var {String} KECCAK256_RLP_ARRAY_S
*/
exports.KECCAK256_RLP_ARRAY_S = '1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347'
/**
* Keccak-256 of an RLP of an empty array (a ```Buffer```)
* @var {Buffer} KECCAK256_RLP_ARRAY
*/
exports.KECCAK256_RLP_ARRAY = Buffer.from(exports.KECCAK256_RLP_ARRAY_S, 'hex')
/**
* Keccak-256 hash of the RLP of null (a ```String```)
* @var {String} KECCAK256_RLP_S
*/
exports.KECCAK256_RLP_S = '56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421'
/**
* Keccak-256 hash of the RLP of null (a ```Buffer```)
* @var {Buffer} KECCAK256_RLP
*/
exports.KECCAK256_RLP = Buffer.from(exports.KECCAK256_RLP_S, 'hex')
/**
* [`BN`](https://github.com/indutny/bn.js)
* @var {Function}
*/
exports.BN = BN
/**
* [`rlp`](https://github.com/ethereumjs/rlp)
* @var {Function}
*/
exports.rlp = rlp
/**
* [`secp256k1`](https://github.com/cryptocoinjs/secp256k1-node/)
* @var {Object}
*/
exports.secp256k1 = secp256k1
/**
* Returns a buffer filled with 0s
* @method zeros
* @param {Number} bytes the number of bytes the buffer should be
* @return {Buffer}
*/
exports.zeros = function (bytes) {
return Buffer.allocUnsafe(bytes).fill()
}
/**
* Returns a zero address
* @method zeroAddress
* @return {String}
*/
exports.zeroAddress = function () {
const addressLength =
const zeroAddress = exports.zeros(addressLength)
return exports.bufferToHex(zeroAddress)
}
/**
* Left Pads an `Array` or `Buffer` with leading zeros till it has `length` bytes.
* Or it truncates the beginning if it exceeds.
* @method setLengthLeft
* @param {Buffer|Array} msg the value to pad
* @param {Number} length the number of bytes the output should be
* @param {Boolean} [right=false] whether to start padding form the left or right
* @return {Buffer|Array}
*/
exports.setLengthLeft = exports.setLength = function (msg, length, right) {
const buf = exports.zeros(length)
msg = exports.toBuffer(msg)
if (right) {
if (msg.length < length) {
msg.copy(buf)//将msg的所有数据复制到buf,其实就相当于右填充
return buf
}
return msg.slice(, length)
} else {
if (msg.length < length) {
msg.copy(buf, length - msg.length)//将msg的所有数据复制到buf,从buf的length - msg.length位置开始
return buf
}
return msg.slice(-length)
}
}
/**
* Right Pads an `Array` or `Buffer` with leading zeros till it has `length` bytes.
* Or it truncates the beginning if it exceeds.
* @param {Buffer|Array} msg the value to pad
* @param {Number} length the number of bytes the output should be
* @return {Buffer|Array}
*/
exports.setLengthRight = function (msg, length) {
return exports.setLength(msg, length, true)
}
/**
* Trims leading zeros from a `Buffer` or an `Array`
* @param {Buffer|Array|String} a
* @return {Buffer|Array|String}
*/
exports.unpad = exports.stripZeros = function (a) {
a = exports.stripHexPrefix(a)
let first = a[]
while (a.length > && first.toString() === '') {
a = a.slice()
first = a[]
}
return a
}
/**
* Attempts to turn a value into a `Buffer`. As input it supports `Buffer`, `String`, `Number`, null/undefined, `BN` and other objects with a `toArray()` method.
* @param {*} v the value
*/
exports.toBuffer = function (v) {
if (!Buffer.isBuffer(v)) {
if (Array.isArray(v)) {
v = Buffer.from(v)
} else if (typeof v === 'string') {
if (exports.isHexString(v)) {
v = Buffer.from(exports.padToEven(exports.stripHexPrefix(v)), 'hex')
} else {
v = Buffer.from(v)
}
} else if (typeof v === 'number') {
v = exports.intToBuffer(v)
} else if (v === null || v === undefined) {
v = Buffer.allocUnsafe()
} else if (BN.isBN(v)) {
v = v.toArrayLike(Buffer)
} else if (v.toArray) {
// converts a BN to a Buffer
v = Buffer.from(v.toArray())
} else {
throw new Error('invalid type')
}
}
return v
}
/**
* Converts a `Buffer` to a `Number`
* @param {Buffer} buf
* @return {Number}
* @throws If the input number exceeds 53 bits.
*/
exports.bufferToInt = function (buf) {
return new BN(exports.toBuffer(buf)).toNumber()
}
/**
* Converts a `Buffer` into a hex `String`
* @param {Buffer} buf
* @return {String}
*/
exports.bufferToHex = function (buf) {
buf = exports.toBuffer(buf)
return '0x' + buf.toString('hex')
}
/**
* Interprets a `Buffer` as a signed integer and returns a `BN`. Assumes 256-bit numbers.
* @param {Buffer} num
* @return {BN}
*/
exports.fromSigned = function (num) {
return new BN(num).fromTwos()
}
/**
* Converts a `BN` to an unsigned integer and returns it as a `Buffer`. Assumes 256-bit numbers.
* @param {BN} num
* @return {Buffer}
*/
exports.toUnsigned = function (num) {
return Buffer.from(num.toTwos().toArray())
}
/**
* Creates Keccak hash of the input
* @param {Buffer|Array|String|Number} a the input data
* @param {Number} [bits=256] the Keccak width
* @return {Buffer}
*/
exports.keccak = function (a, bits) {
a = exports.toBuffer(a)
if (!bits) bits =
return createKeccakHash('keccak' + bits).update(a).digest()
}
/**
* Creates Keccak-256 hash of the input, alias for keccak(a, 256)
* @param {Buffer|Array|String|Number} a the input data
* @return {Buffer}
*/
exports.keccak256 = function (a) {
return exports.keccak(a)
}
/**
* Creates SHA256 hash of the input
* @param {Buffer|Array|String|Number} a the input data
* @return {Buffer}
*/
exports.sha256 = function (a) {
a = exports.toBuffer(a)
return createHash('sha256').update(a).digest()
}
/**
* Creates RIPEMD160 hash of the input
* @param {Buffer|Array|String|Number} a the input data
* @param {Boolean} padded whether it should be padded to 256 bits or not
* @return {Buffer}
*/
exports.ripemd160 = function (a, padded) {
a = exports.toBuffer(a)
const hash = createHash('rmd160').update(a).digest()
if (padded === true) {
return exports.setLength(hash, )
} else {
return hash
}
}
/**
* Creates SHA-3 hash of the RLP encoded version of the input
* @param {Buffer|Array|String|Number} a the input data
* @return {Buffer}
*/
exports.rlphash = function (a) {
return exports.keccak(rlp.encode(a))
}
/**
* Checks if the private key satisfies the rules of the curve secp256k1.
* @param {Buffer} privateKey
* @return {Boolean}
*/
exports.isValidPrivate = function (privateKey) {
return secp256k1.privateKeyVerify(privateKey)
}
/**
* Checks if the public key satisfies the rules of the curve secp256k1
* and the requirements of Ethereum.
* @param {Buffer} publicKey The two points of an uncompressed key, unless sanitize is enabled
* @param {Boolean} [sanitize=false] Accept public keys in other formats
* @return {Boolean}
*/
exports.isValidPublic = function (publicKey, sanitize) {
if (publicKey.length === ) {
// Convert to SEC1 for secp256k1
return secp256k1.publicKeyVerify(Buffer.concat([ Buffer.from([]), publicKey ]))
}
if (!sanitize) {
return false
}
return secp256k1.publicKeyVerify(publicKey)
}
/**
* Returns the ethereum address of a given public key.
* Accepts "Ethereum public keys" and SEC1 encoded keys.
* @param {Buffer} pubKey The two points of an uncompressed key, unless sanitize is enabled
* @param {Boolean} [sanitize=false] Accept public keys in other formats
* @return {Buffer}
*/
exports.pubToAddress = exports.publicToAddress = function (pubKey, sanitize) {
pubKey = exports.toBuffer(pubKey)
if (sanitize && (pubKey.length !== )) {
pubKey = secp256k1.publicKeyConvert(pubKey, false).slice()
}
assert(pubKey.length === )
// Only take the lower 160bits of the hash
return exports.keccak(pubKey).slice(-)
}
/**
* Returns the ethereum public key of a given private key
* @param {Buffer} privateKey A private key must be 256 bits wide
* @return {Buffer}
*/
const privateToPublic = exports.privateToPublic = function (privateKey) {
privateKey = exports.toBuffer(privateKey)
// skip the type flag and use the X, Y points
return secp256k1.publicKeyCreate(privateKey, false).slice()
}
/**
* Converts a public key to the Ethereum format.
* @param {Buffer} publicKey
* @return {Buffer}
*/
exports.importPublic = function (publicKey) {
publicKey = exports.toBuffer(publicKey)
if (publicKey.length !== ) {
publicKey = secp256k1.publicKeyConvert(publicKey, false).slice()
}
return publicKey
}
/**
* ECDSA sign
* @param {Buffer} msgHash
* @param {Buffer} privateKey
* @param {Number} [chainId]
* @return {Object}
*/
exports.ecsign = function (msgHash, privateKey, chainId) {
const sig = secp256k1.sign(msgHash, privateKey)
const ret = {}
ret.r = sig.signature.slice(, )
ret.s = sig.signature.slice(, )
ret.v = chainId ? sig.recovery + (chainId * + ) : sig.recovery +
return ret
}
/**
* Returns the keccak-256 hash of `message`, prefixed with the header used by the `eth_sign` RPC call.
* The output of this function can be fed into `ecsign` to produce the same signature as the `eth_sign`
* call for a given `message`, or fed to `ecrecover` along with a signature to recover the public key
* used to produce the signature.
* @param message
* @returns {Buffer} hash
*/
exports.hashPersonalMessage = function (message) {
const prefix = exports.toBuffer('\u0019Ethereum Signed Message:\n' + message.length.toString())
return exports.keccak(Buffer.concat([prefix, message]))
}
/**
* ECDSA public key recovery from signature
* @param {Buffer} msgHash
* @param {Number} v
* @param {Buffer} r
* @param {Buffer} s
* @param {Number} [chainId]
* @return {Buffer} publicKey
*/
exports.ecrecover = function (msgHash, v, r, s, chainId) {
const signature = Buffer.concat([exports.setLength(r, ), exports.setLength(s, )], )
const recovery = calculateSigRecovery(v, chainId)
if (!isValidSigRecovery(recovery)) {
throw new Error('Invalid signature v value')
}
const senderPubKey = secp256k1.recover(msgHash, signature, recovery)
return secp256k1.publicKeyConvert(senderPubKey, false).slice()
}
/**
* Convert signature parameters into the format of `eth_sign` RPC method
* @param {Number} v
* @param {Buffer} r
* @param {Buffer} s
* @param {Number} [chainId]
* @return {String} sig
*/
exports.toRpcSig = function (v, r, s, chainId) {
let recovery = calculateSigRecovery(v, chainId)
if (!isValidSigRecovery(recovery)) {
throw new Error('Invalid signature v value')
}
// geth (and the RPC eth_sign method) uses the 65 byte format used by Bitcoin
return exports.bufferToHex(Buffer.concat([
exports.setLengthLeft(r, ),
exports.setLengthLeft(s, ),
exports.toBuffer(v)
]))
}
/**
* Convert signature format of the `eth_sign` RPC method to signature parameters
* NOTE: all because of a bug in geth: https://github.com/ethereum/go-ethereum/issues/2053
* @param {String} sig
* @return {Object}
*/
exports.fromRpcSig = function (sig) {
sig = exports.toBuffer(sig)
// NOTE: with potential introduction of chainId this might need to be updated
if (sig.length !== ) {
throw new Error('Invalid signature length')
}
let v = sig[]
// support both versions of `eth_sign` responses
if (v < ) {
v +=
}
return {
v: v,
r: sig.slice(, ),
s: sig.slice(, )
}
}
/**
* Returns the ethereum address of a given private key
* @param {Buffer} privateKey A private key must be 256 bits wide
* @return {Buffer}
*/
exports.privateToAddress = function (privateKey) {
return exports.publicToAddress(privateToPublic(privateKey))
}
/**
* Checks if the address is a valid. Accepts checksummed addresses too
* @param {String} address
* @return {Boolean}
*/
exports.isValidAddress = function (address) {
return /^0x[-9a-fA-F]{}$/.test(address)
}
/**
* Checks if a given address is a zero address
* @method isZeroAddress
* @param {String} address
* @return {Boolean}
*/
exports.isZeroAddress = function (address) {
const zeroAddress = exports.zeroAddress()
return zeroAddress === exports.addHexPrefix(address)
}
/**
* Returns a checksummed address
* @param {String} address
* @return {String}
*/
exports.toChecksumAddress = function (address) {
address = exports.stripHexPrefix(address).toLowerCase()
const hash = exports.keccak(address).toString('hex')
let ret = '0x'
for (let i = ; i < address.length; i++) {
if (parseInt(hash[i], ) >= ) {
ret += address[i].toUpperCase()
} else {
ret += address[i]
}
}
return ret
}
/**
* Checks if the address is a valid checksummed address
* @param {Buffer} address
* @return {Boolean}
*/
exports.isValidChecksumAddress = function (address) {
return exports.isValidAddress(address) && (exports.toChecksumAddress(address) === address)
}
/**
* Generates an address of a newly created contract
* @param {Buffer} from the address which is creating this new address
* @param {Buffer} nonce the nonce of the from account
* @return {Buffer}
*/
exports.generateAddress = function (from, nonce) {
from = exports.toBuffer(from)
nonce = new BN(nonce)
if (nonce.isZero()) {
// in RLP we want to encode null in the case of zero nonce
// read the RLP documentation for an answer if you dare
nonce = null
} else {
nonce = Buffer.from(nonce.toArray())
}
// Only take the lower 160bits of the hash
return exports.rlphash([from, nonce]).slice(-)
}
/**
* Generates an address for a contract created using CREATE2
* @param {Buffer} from the address which is creating this new address
* @param {Buffer} salt a salt
* @param {Buffer} initCode the init code of the contract being created
* @return {Buffer}
*/
exports.generateAddress2 = function (from, salt, initCode) {
from = exports.toBuffer(from)
salt = exports.toBuffer(salt)
initCode = exports.toBuffer(initCode)
assert(from.length === )
assert(salt.length === )
let address = exports.keccak256(Buffer.concat([
Buffer.from('ff', 'hex'),
from,
salt,
exports.keccak256(initCode)
]))
return address.slice(-)
}
/**
* Returns true if the supplied address belongs to a precompiled account (Byzantium)
* @param {Buffer|String} address
* @return {Boolean}
*/
exports.isPrecompiled = function (address) {
const a = exports.unpad(address)
return a.length === && a[] >= && a[] <=
}
/**
* Adds "0x" to a given `String` if it does not already start with "0x"
* @param {String} str
* @return {String}
*/
exports.addHexPrefix = function (str) {
if (typeof str !== 'string') {
return str
}
return exports.isHexPrefixed(str) ? str : '0x' + str
}
/**
* Validate ECDSA signature
* @method isValidSignature
* @param {Buffer} v
* @param {Buffer} r
* @param {Buffer} s
* @param {Boolean} [homestead=true]
* @param {Number} [chainId]
* @return {Boolean}
*/
exports.isValidSignature = function (v, r, s, homestead, chainId) {
const SECP256K1_N_DIV_2 = new BN('7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0', )
const SECP256K1_N = new BN('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141', )
if (r.length !== || s.length !== ) {
return false
}
if (!isValidSigRecovery(calculateSigRecovery(v, chainId))) {
return false
}
r = new BN(r)
s = new BN(s)
if (r.isZero() || r.gt(SECP256K1_N) || s.isZero() || s.gt(SECP256K1_N)) {
return false
}
if ((homestead === false) && (new BN(s).cmp(SECP256K1_N_DIV_2) === )) {
return false
}
return true
}
/**
* Converts a `Buffer` or `Array` to JSON
* @param {Buffer|Array} ba
* @return {Array|String|null}
*/
exports.baToJSON = function (ba) {
if (Buffer.isBuffer(ba)) {
return '0x' + ba.toString('hex')
} else if (ba instanceof Array) {
const array = []
for (let i = ; i < ba.length; i++) {
array.push(exports.baToJSON(ba[i]))
}
return array
}
}
/**
* Defines properties on a `Object`. It make the assumption that underlying data is binary.
* @param {Object} self the `Object` to define properties on
* @param {Array} fields an array fields to define. Fields can contain:
* * `name` - the name of the properties
* * `length` - the number of bytes the field can have
* * `allowLess` - if the field can be less than the length
* * `allowEmpty`
* @param {*} data data to be validated against the definitions
*/
exports.defineProperties = function (self, fields, data) {
self.raw = []
self._fields = []
// attach the `toJSON`
self.toJSON = function (label) {
if (label) {
const obj = {}
self._fields.forEach((field) => {
obj[field] = '0x' + self[field].toString('hex')
})
return obj
}
return exports.baToJSON(this.raw)
}
self.serialize = function serialize () {
return rlp.encode(self.raw)
}
fields.forEach((field, i) => {
self._fields.push(field.name)
function getter () {
return self.raw[i]
}
function setter (v) {
v = exports.toBuffer(v)
if (v.toString('hex') === '' && !field.allowZero) {
v = Buffer.allocUnsafe()
}
if (field.allowLess && field.length) {
v = exports.stripZeros(v)
assert(field.length >= v.length, 'The field ' + field.name + ' must not have more ' + field.length + ' bytes')
} else if (!(field.allowZero && v.length === ) && field.length) {
assert(field.length === v.length, 'The field ' + field.name + ' must have byte length of ' + field.length)
}
self.raw[i] = v
}
Object.defineProperty(self, field.name, {
enumerable: true,
configurable: true,
get: getter,
set: setter
})
if (field.default) {
self[field.name] = field.default
}
// attach alias
if (field.alias) {
Object.defineProperty(self, field.alias, {
enumerable: false,
configurable: true,
set: setter,
get: getter
})
}
})
// if the constuctor is passed data
if (data) {
if (typeof data === 'string') {
data = Buffer.from(exports.stripHexPrefix(data), 'hex')
}
if (Buffer.isBuffer(data)) {
data = rlp.decode(data)
}
if (Array.isArray(data)) {
if (data.length > self._fields.length) {
throw (new Error('wrong number of fields in data'))
}
// make sure all the items are buffers
data.forEach((d, i) => {
self[self._fields[i]] = exports.toBuffer(d)
})
} else if (typeof data === 'object') {
const keys = Object.keys(data)
fields.forEach((field) => {
if (keys.indexOf(field.name) !== -) self[field.name] = data[field.name]
if (keys.indexOf(field.alias) !== -) self[field.alias] = data[field.alias]
})
} else {
throw new Error('invalid data')
}
}
}
function calculateSigRecovery (v, chainId) {
return chainId ? v - ( * chainId + ) : v -
}
function isValidSigRecovery (recovery) {
return recovery === || recovery ===
}
ethereumjs/ethereumjs-util的更多相关文章
- ethereumjs/ethereumjs-wallet
Utilities for handling Ethereum keys ethereumjs-wallet A lightweight wallet implementation. At the m ...
- ethereumjs/ethereumjs-vm-4-tests
根据代码发现还要了解的模块有: ethereumjs/merkle-patricia-tree -对应数据存储的数据结构 ethereumjs-blockchain —— 区块链 ethereumjs ...
- ethereumjs/ethereumjs-tx
https://github.com/ethereumjs/ethereumjs-tx A simple module for creating, manipulating and signing e ...
- ethereumjs/ethereumjs-icap
https://github.com/ethereumjs/ethereumjs-icap ethereumjs-icap 安装: npm install ethereumjs-icap --save ...
- ethereumjs/ethereumjs-common-1-简介
为了了解ethereumjs/ethereumjs-block-3-代码的使用需要了解的一个模块 https://github.com/ethereumjs/ethereumjs-common Com ...
- ethereumjs/ethereumjs-common-2-API文档
https://github.com/ethereumjs/ethereumjs-common/blob/master/docs/index.md 该API的调用的详细例子可见ethereumjs/e ...
- ethereumjs/browser-builds
https://github.com/ethereumjs/browser-builds ethereumjs - Browser Builds This repository contains br ...
- ethereumjs/ethereumjs-vm-3-StateManager
https://github.com/ethereumjs/ethereumjs-vm/blob/master/docs/stateManager.md StateManager 要与本博客的ethe ...
- ethereumjs/ethereumjs-vm-2-API文档
https://github.com/ethereumjs/ethereumjs-vm/blob/master/docs/index.md vm.runBlockchain Processes blo ...
随机推荐
- 【Linux】rpm常用命令及rpm参数介绍
RPM是RedhatPackageManager的缩写,是由RedHat公司开发的软件包安装和管理程序,同Windows平台上的Uninstaller比较类似.使用RPM,用户可以自行安装和管理Lin ...
- 最新版本Bootstrap样式很奇怪(4.1版本)
下载最新版4.1版的Bootstrap编译好的CSS,引入的样式及其怪异. 这种情况重新下载3.3.7低版本就可以了.
- git命令(持续更新)
将远程仓库中的代码下载到本地仓库:git clone git仓库地址 将本地仓库中修改的文件提交到远程仓库:git push -u origin master 将当前目录添加到本地仓库,.表示当前目录 ...
- Code Signal_练习题_arrayMaxConsecutiveSum
Given array of integers, find the maximal possible sum of some of its k consecutive elements. Exampl ...
- 转 Fira Code | 为写程序而生的字体
原文:Fira Code | 为写程序而生的字体 Fira Code | 为写程序而生的字体 己短不可藏 6月前 · 1199 人阅读 关注TA 程序员福利!!!今天为大家带来一个专为程序员写程序设计 ...
- singleInstance和singleTask导致startActivityForResult回调失败
先来了解下这两种启动模式: 1.singleInstance,全局唯一,它的实例在全局(即在众多任务栈中)是唯一的,它单独地存在于属于自己的任务栈中,而且这个任务栈没有其他实例. 2.singleTa ...
- 学习MVC之租房网站(十二)-缓存和静态页面
在上一篇<学习MVC之租房网站(十一)-定时任务和云存储>学习了Quartz的使用.发邮件,并将通过UEditor上传的图片保存到云存储.在项目的最后,再学习优化网站性能的一些技术:缓存和 ...
- 今日面试WPS总结
1.使用正则来实现替换文件名前三位+...+后两位+后缀名 '1234.56789.jpg'.replace(/^(.{3})(.+?)(.{2})(?=\.[^\.]+)$/,"$1$3& ...
- Oracle EBS OPM reshedule batch
--reschedule_batch --created by jenrry DECLARE x_message_count NUMBER; x_message_list VARCHAR2 (2000 ...
- 关于MSCOMM.OCX无法正常注册的问题解决
[问题] 关于“Component'MSCOMM32.OCX'or one of its dependencies not correctly registered: afole is missing ...