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 ...
随机推荐
- c# XML 有多个重复子节点操作
1,继续添加ebm子节点 public static void CreateXml() { //创XML建对象 XmlDocument doc = new XmlDocument(); //声明根节点 ...
- [PHP] 排序和查找算法
知乎:冒泡排序(bubble sort)的原理是什么? 潘屹峰: 冒泡排序的原理可以顾名思义:把每个数据看成一个气泡,按初始顺序自底向上依次对两两气泡进行比较,对上重下轻的气泡交换顺序(这里用气泡轻. ...
- iOS: Designated Initializer(指定初始化函数)
偶然间看到“ Designated Initializer”一词,心里一惊,这是什么东西,怎么没听说过?难道是我道行太浅?真的是这样?(好伤心啊)一阵子我怀疑之后,果断上网查了一下这个 Designa ...
- elasticsearch6.7 04.API规范
API Conventions elasticsearch的REST的API是使用HTTP的JSON格式暴露的. 除非另有说明,本章中列出的约定可以在整个REST API中应用. 多索引 索引名称支持 ...
- Parcel + Vue 2.x 极速零配置打包体验
继 Browserify.Webpack 之后,又一款打包工具 Parcel 横空出世 Parcel.js 的官网有这样的自我介绍 “极速零配置Web应用打包工具” 简单接触了一下,单从效率上来说,确 ...
- Python并发编程(守护进程,进程锁,进程队列)
进程的其他方法 P = Process(target=f,) P.Pid 查看进程号 查看进程的名字p.name P.is_alive() 返回一个true或者False P.terminate( ...
- js-权威指南学习笔记21
第二十一章 多媒体和图形编程 1.为了强制让图片缓存起来,首先利用Image()构造函数来创建一个屏幕外的图片对象,之后将该对象的src属性设置成期望的URL. 2.由于各家浏览器制造商未能在对标准音 ...
- CentOS7添加入windows2008的AD域
采用域控对用户权限进行限制的时候,经常会出现需要将linux加入windows域,毕竟windows的AD域超级强大.用户名可以由windows进行统一管理,方便办公使用.下面简单介绍如何进行配置. ...
- phar 反序列化学习
前言 phar 是 php 支持的一种伪协议, 在一些文件处理函数的路径参数中使用的话就会触发反序列操作. 利用条件 phar 文件要能够上传到服务器端. 要有可用的魔术方法作为"跳板&qu ...
- 微信小程序开发1-入门知识准备
注:一个物联网专业的学生狗,平时学习较多的是嵌入式编程方面的知识,最近可能是闲的蛋疼,想要研究研究客户端开发,对于网页,手机Android客户端从来没有接触过,因此所有东西都要从头来过,慢慢学习.不过 ...