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
str
String
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
buf
Buffer
Returns String
bufferToInt
Converts a Buffer
to a Number
将Buffer
转成Number
Parameters
buf
BufferThrows 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
self
Object theObject
to define properties on 定义属性的对象fields
Array 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
data
any 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
msgHash
BufferprivateKey
BufferchainId
Number根据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
sig
String
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
num
Buffer
Returns BN
generateAddress
Generates an address of a newly created contract
为新创建的合约生成一个address(合约即交易,它的address都可以通过合约部署者的账户address及其nonce生成)
Parameters
from
Buffer the address which is creating this new address合约部署者账户addressnonce
Buffer the nonce of the from account 账户的nonce(即下一笔交易数)
Returns Buffer
generateAddress2
Generates an address for a contract created using CREATE2
使用CREATE2为合约的创建生成一个address
Parameters
from
Buffer the address which is creating this new addresssalt
Buffer a saltinitCode
Buffer 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
publicKey
Buffer
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
address
String
Returns Boolean
isValidChecksumAddress
Checks if the address is a valid checksummed address
查看地址是否是有效的校验和地址
Parameters
address
Buffer
Returns Boolean
isValidPrivate
Checks if the private key satisfies the rules of the curve secp256k1.
查看私钥是否满足曲线secp256k1的规则
Parameters
privateKey
Buffer
Returns Boolean
isValidPublic
Checks if the public key satisfies the rules of the curve secp256k1 and the requirements of Ethereum.
查看公钥是否满足曲线secp256k1的规则和以太坊的需求
Parameters
publicKey
Buffer The two points of an uncompressed key, unless sanitize is enabledsanitize
Boolean 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 databits
Number 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
privateKey
Buffer 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
pubKey
Buffer The two points of an uncompressed key, unless sanitize is enabledsanitize
Boolean 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 datapadded
Boolean 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 padlength
Number the number of bytes the output should beright
Boolean 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
v
any the value
toChecksumAddress
Returns a checksummed address
将address转成校验和地址
Parameters
address
String
Returns String
toUnsigned
Converts a BN
to an unsigned integer and returns it as a Buffer
. Assumes 256-bit numbers.
将BN转成无符号整数并将其返回成Buffer,是256比特的数字
Parameters
num
BN
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
address
String
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
privateKey
Buffer 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
bytes
Number 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 ...
随机推荐
- oracle数据库无法导出空表的问题解决(开始于oracle11g)
--设置系统参数 alter system set deferred_segment_creation=false; Select 'alter table '||table_name||' allo ...
- java设计模式-----20、模板方法模式
概念: Template Method模式也叫模板方法模式,是行为模式之一,它把具有特定步骤算法中的某些必要的处理委让给抽象方法,通过子类继承对抽象方法的不同实现改变整个算法的行为. 模板方法模式的应 ...
- jQuery复选框全选和全选取消
jQuery(".salaryIds").each(function(){ if(jQuery("#salaryIds").attr("checked ...
- CSS 美化复选框 - 无图片方式
今天和大家分享一个不使用图片美化复选框的方式.来看下效果图吧,如下是3种不同状态下的效果: 一. Html结构 <div class="check-wrap"> < ...
- Sql server 索引详解
参考资料:老K写的,http://www.cnblogs.com/AK2012/archive/2013/01/04/2844283.html SQL索引在数据库优化中占有一个非常大的比例, 一个好的 ...
- qt多线程信号槽传输方式
//简单介绍一下QT信号与槽的连接方式: //Qt::AutoConnection表示系统自动选择相应的连接方式,如果信号与槽在同一线程,就采用Qt::DirectConnection, //如 ...
- python 遇到的一些坑
lst = [1, 2, 4] print lst.__iter__().next() # 打印出来的是 1 print lst.__iter__().next() # 打印出来的是 1 # 调用__ ...
- Problem2-Project Euler
Even Fibonacci numbers Each new term in the Fibonacci sequence is generated by adding the previous ...
- LeetCode题解之Leaf-Similar Trees
1.题目描述 2.问题分析 将叶子节点的值放入vector,然后比较. 3.代码 bool leafSimilar(TreeNode* root1, TreeNode* root2) { vector ...
- VMWare12虚拟机实现主客机间的文件拖拽(复制粘贴)和文件夹共享
版本: 主机:Windows 7 64位旗舰版 虚拟机: VMWare 12 + Windows 7 64位旗舰版 VMWare pro 12 + Ubuntu16.04LTS 64位 注:由于VMW ...