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
- bufBuffer
- Throws 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 the- Objectto 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 have
- allowLess- if the field can be less than the length
- allowEmpty
 
- 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
- msgHashBuffer
- privateKeyBuffer
- chainIdNumber根据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合约部署者账户address
- nonceBuffer 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 address
- saltBuffer a salt
- initCodeBuffer 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 enabled
- sanitizeBoolean Accept public keys in other formats (optional, default- false)
Returns Boolean
keccak
Creates Keccak hash of the input
生成输入的Keccak hash散列值
Parameters
- a(Buffer | Array | String | Number) the input data
- bitsNumber the Keccak width (optional, default- 256)设置返回的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 enabled
- sanitizeBoolean Accept public keys in other formats (optional, default- false)
Returns Buffer
ripemd160
Creates RIPEMD160 hash of the input
生成输入的RIPEMD160 hash散列值
Parameters
- a(Buffer | Array | String | Number) the input data
- paddedBoolean 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 pad
- lengthNumber the number of bytes the output should be
- rightBoolean whether to start padding form the left or right (optional, default- false)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 ... 
随机推荐
- MySQL的安装与维护
			一.数据库的基本概念 数据库: 以一定方式储存在一起.能为多个用户共享.具有尽可能小的冗余度的特点.是与应用程序彼此独立的数据集合. DBMS(DataBase Management System,数 ... 
- Fibonacci (hdu1568)数学公式
			Fibonacci Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Subm ... 
- bind(port)与.localAddress(new InetSocketAddress(port))区别
			两者并没有什么区别,最后都会调用AbstractBootstrap这个抽象类的bind()方法. 
- 在Windows上搭建kafka环境
			英文文档:https://dzone.com/articles/running-apache-kafka-on-windows-os 第一步:安装JDK 百度很多,不赘述 第二步:安装ZooKeepe ... 
- Linux 安装Python虚拟环境,virtualenvwrapper
			virtualenvwrapper工具学习 1.因为virtualenv 工具使用的并不方便 2.安装virtualenvwrapper pip3 install -i https://pypi.do ... 
- python邮件发送
			'''qq邮件与其他邮件有所不同,下以我的qq邮件为例(切勿转载):''' import osimport smtplibfrom email.mime.text import MIMEText # ... 
- 【代码笔记】iOS-二维码
			一,工程图. 二,代码. ViewController.m #import "ViewController.h" #import "ScanViewController. ... 
- import、export使用介绍
			import.export使用介绍 ES6提供的import.export方法, 使组件化开发模式迈向新高度.本文来介绍import.export的语法及使用方法. 根据 export 的导出方式,可 ... 
- Vue -- webpack 项目自动打包压缩成zip文件
			这段时间用 Vue2.0 开发项目,每次打包都会用到 npm run build 命令,但是每次部署时给后端发包都要手动zip压缩,这样一两次还行,但遇到项目板块测试和临时加急功能测试的时候,一天可能 ... 
- [我的阿里云服务器] —— WordPress Permalink Settings
			前言: 固定链接(Permalink)是博客日志.分类及其他博客内容列表的永久URL. 别人可以通过固定链接链接到你的文章上,你也可以在email中发送某篇日志的链接. 所有日志的URL应为永久性.固 ... 
