ethereumjs/ethereumjs-util

Most of the string manipulation methods are provided by ethjs-util

更多的字符串处理方法可以看ethjs-util

addHexPrefix

index.js:563-569

Adds "0x" to a given String if it does not already start with "0x"

在没有"0x"前缀的十六进制字符串前面添加前缀

Parameters

Returns String

baToJSON

index.js:613-623

Converts a Buffer or Array to JSON

BufferArray转成JSON

Parameters

Returns (Array | String | null)

BN

index.js:62-62

BN

Type: Function

大数

bufferToHex

index.js:194-197

Converts a Buffer into a hex String

将 Buffer转成16进制的String

Parameters

Returns String

bufferToInt

index.js:185-187

Converts a Buffer to a Number

Buffer转成Number

Parameters

  • buf Buffer

  • Throws any If the input number exceeds 53 bits.

Returns Number

defineProperties

index.js:635-728

Defines properties on a Object. It make the assumption that underlying data is binary.

定义对象的属性。假设下面的数据都为二进制数

Parameters

  • self Object the Object 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 have
    • allowLess - if the field can be less than the length
    • allowEmpty
  • data any data to be validated against the definitions

ecrecover

index.js:383-391

ECDSA public key recovery from signature

从签名r,s,v和消息hash得到公钥

Parameters

Returns Buffer publicKey

ecsign

index.js:351-359

ECDSA sign签名,返回r,s,v

Parameters

  • msgHash Buffer
  • privateKey Buffer
  • chainId Number根据chainId是否设置来决定v=v+2 * chainId+35(chainId不为0)还是v= v+27(为0或undefined)

Returns Object

fromRpcSig

index.js:421-440

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

Returns Object

toRpcSig

index.js:401-413

Convert signature parameters into the format of eth_sign RPC method

将签名参数转成符合eth_sign RPC方法的格式,即将r,s,v转成65字节的格式

Parameters

Returns String sig

fromSigned

index.js:204-206

Interprets a Buffer as a signed integer and returns a BN. Assumes 256-bit numbers.

将Buffer转成一个签名整数并返回BN大数对象,假设为一个256位的数字

Parameters

Returns BN

generateAddress

index.js:507-521

Generates an address of a newly created contract

为新创建的合约生成一个address(合约即交易,它的address都可以通过合约部署者的账户address及其nonce生成)

Parameters

  • from Buffer the address which is creating this new address合约部署者账户address
  • nonce Buffer the nonce of the from account 账户的nonce(即下一笔交易数)

Returns Buffer

generateAddress2

index.js:530-546

Generates an address for a contract created using CREATE2

使用CREATE2为合约的创建生成一个address

Parameters

  • from Buffer the address which is creating this new address
  • salt Buffer a salt
  • initCode Buffer the init code of the contract being created 合约的encode

Returns Buffer

hashPersonalMessage

index.js:369-372

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

index.js:336-342

Converts a public key to the Ethereum format.

将公钥转成以太坊的格式

Parameters

Returns Buffer

isPrecompiled

index.js:553-556

Returns true if the supplied address belongs to a precompiled account (Byzantium)

如果提供的地址属于预编译帐户,则返回true

Parameters

Returns Boolean

isValidAddress

index.js:456-458

Checks if the address is a valid. Accepts checksummed addresses too

检查地址是否有效,接受校验和地址

Parameters

Returns Boolean

isValidChecksumAddress

index.js:497-499

Checks if the address is a valid checksummed address

查看地址是否是有效的校验和地址

Parameters

Returns Boolean

isValidPrivate

index.js:279-281

Checks if the private key satisfies the rules of the curve secp256k1.

查看私钥是否满足曲线secp256k1的规则

Parameters

Returns Boolean

isValidPublic

index.js:290-301

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 enabled
  • sanitize Boolean Accept public keys in other formats (optional, default false)

Returns Boolean

keccak

index.js:223-228

Creates Keccak hash of the input

生成输入的Keccak hash散列值

Parameters

  • a (Buffer | Array | String | Number) the input data
  • bits Number the Keccak width (optional, default 256)设置返回的hash值的长度

Returns Buffer

keccak256

index.js:235-237

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

index.js:447-449

Returns the ethereum address of a given private key

根据私钥得到以太坊地址

Parameters

  • privateKey Buffer A private key must be 256 bits wide

Returns Buffer

pubToAddress

index.js:310-318

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 enabled
  • sanitize Boolean Accept public keys in other formats (optional, default false)

Returns Buffer

ripemd160

index.js:255-263

Creates RIPEMD160 hash of the input

生成输入的RIPEMD160 hash散列值

Parameters

  • a (Buffer | Array | String | Number) the input data
  • padded Boolean whether it should be padded to 256 bits or not设置为true,则当返回的hash值长度不为256时左填充0

Returns Buffer

rlp

index.js:68-68

rlp编码

Type: Function

rlphash

index.js:270-272

Creates SHA-3 hash of the RLP encoded version of the input

生成输入的RLP编码的SHA-3 hash散列值

Parameters

Returns Buffer

secp256k1

index.js:74-74

secp256k1

Type: Object

setLengthRight

index.js:131-133

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

  • msg (Buffer | Array) the value to pad
  • length Number the number of bytes the output should be

Returns (Buffer | Array)

setLengthLeft

index.js:106-122

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
  • length Number the number of bytes the output should be
  • right Boolean whether to start padding form the left or right (optional, default false)right = true就相当于右填充

Returns (Buffer | Array)

sha256

index.js:244-247

Creates SHA256 hash of the input

创建输入的SHA256 hash散列值

Parameters

Returns Buffer

toBuffer

index.js:153-177

Attempts to turn a value into a Buffer. As input it supports BufferStringNumber, null/undefined, BN and other objects with a toArray() method.

将值转成Buffer,值输入支持BufferStringNumber, null/undefined, BN和具有toArray()方法的对象

Parameters

  • v any the value

toChecksumAddress

index.js:476-490

Returns a checksummed address

将address转成校验和地址

Parameters

Returns String

toUnsigned

index.js:213-215

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

index.js:140-148

Trims leading zeros from a Buffer or an Array

BufferArray前面的0删掉

Parameters

Returns (Buffer | Array | String)

isValidSignature

index.js:582-606

Validate ECDSA signature

是否是有效的签名

Parameters

Returns Boolean

isZeroAddress

index.js:466-469

Checks if a given address is a zero address

查看给定的address是否是0x0000...000地址

Parameters

Returns Boolean

KECCAK256_NULL

index.js:32-32

Keccak-256 hash of null (a Buffer)

Buffer类型的null的Keccak-256 hash散列值

Type: Buffer

KECCAK256_NULL_S

index.js:26-26

Keccak-256 hash of null (a String)

String类型的null的Keccak-256 hash散列值

Type: String

KECCAK256_RLP

index.js:56-56

Keccak-256 hash of the RLP of null (a Buffer)

Buffer类型的RLP编码格式的null的Keccak-256 hash散列值

Type: Buffer

KECCAK256_RLP_S

index.js:50-50

Keccak-256 hash of the RLP of null (a String)

Type: String

String类型的RLP编码格式的null的Keccak-256 hash散列值

KECCAK256_RLP_ARRAY

index.js:44-44

Keccak-256 of an RLP of an empty array (a Buffer)

Buffer类型的RLP编码格式的空数组的Keccak-256 hash散列值

Type: Buffer

KECCAK256_RLP_ARRAY_S

index.js:38-38

Keccak-256 of an RLP of an empty array (a String)

String类型的RLP编码格式的空数组的Keccak-256 hash散列值

Type: String

MAX_INTEGER

index.js:14-14

the max integer that this VM can handle (a BN)

设置虚拟机能够处理的最大整数

Type: BN

privateToPublic

index.js:325-329

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

index.js:20-20

2^256 (a BN)

得到2的256次幂的值

Type: BN

zeroAddress

index.js:91-95

Returns a zero address

返回0x000...000地址

Returns String

zeros

index.js:82-84

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的更多相关文章

  1. ethereumjs/ethereumjs-wallet

    Utilities for handling Ethereum keys ethereumjs-wallet A lightweight wallet implementation. At the m ...

  2. ethereumjs/ethereumjs-vm-4-tests

    根据代码发现还要了解的模块有: ethereumjs/merkle-patricia-tree -对应数据存储的数据结构 ethereumjs-blockchain —— 区块链 ethereumjs ...

  3. ethereumjs/ethereumjs-tx

    https://github.com/ethereumjs/ethereumjs-tx A simple module for creating, manipulating and signing e ...

  4. ethereumjs/ethereumjs-icap

    https://github.com/ethereumjs/ethereumjs-icap ethereumjs-icap 安装: npm install ethereumjs-icap --save ...

  5. ethereumjs/ethereumjs-common-1-简介

    为了了解ethereumjs/ethereumjs-block-3-代码的使用需要了解的一个模块 https://github.com/ethereumjs/ethereumjs-common Com ...

  6. ethereumjs/ethereumjs-common-2-API文档

    https://github.com/ethereumjs/ethereumjs-common/blob/master/docs/index.md 该API的调用的详细例子可见ethereumjs/e ...

  7. ethereumjs/browser-builds

    https://github.com/ethereumjs/browser-builds ethereumjs - Browser Builds This repository contains br ...

  8. ethereumjs/ethereumjs-vm-3-StateManager

    https://github.com/ethereumjs/ethereumjs-vm/blob/master/docs/stateManager.md StateManager 要与本博客的ethe ...

  9. ethereumjs/ethereumjs-vm-2-API文档

    https://github.com/ethereumjs/ethereumjs-vm/blob/master/docs/index.md vm.runBlockchain Processes blo ...

随机推荐

  1. Java集合类源码解析:LinkedHashMap

    前言 今天继续学习关于Map家族的另一个类 LinkedHashMap .先说明一下,LinkedHashMap 是继承于 HashMap 的,所以本文只针对 LinkedHashMap 的特性学习, ...

  2. nginx+tomcat抵御慢速连接攻击

    一.安装nginx apt-get install nginx 安装中途可能会要求填写许可,输入‘y’就好了 如果安装提示“E: Unable to locate package nginx”,那么输 ...

  3. 【 js 基础 】【读书笔记】作用域和闭包

    一.编译过程 常见编译性语言,在程序代码执行之前会经历三个步骤,称为编译. 步骤一:分词或者词法分析 将由字符组成的字符串分解成有意义的代码块,这些代码块被称为词法单元. 例子:  var a = 2 ...

  4. linux 新建用户和权限分配

    1.创建新用户:testuser 命令:#useradd 选项 用户名 选项: -c comment 指定一段注释性描述. -d 目录 指定用户主目录,如果此目录不存在,则同时使用-m选项,可以创建主 ...

  5. instanceof与constructor的区别

    名词介绍 instanceof 的作用是判断实例对象是否为构造函数的实例,实际上判断的是实例对象的__proto__属性与构造函数的prototype属性是否指向同一引用: constructor 的 ...

  6. BZOJ5473: 仙人掌

    传送门 首先,所有连通块的个数的期望再减去每个点孤立的概率就是答案. 设 \(d_i\) 表示 \(i\) 的度数,那么每个点孤立的概率为 \(\frac{1}{2^{d_i}}\) 考虑计算所有连通 ...

  7. BZOJ2208: [Jsoi2010]连通数(tarjan bitset floyd)

    题意 题目链接 Sol 数据水的一批,\(O(n^3)\)暴力可过 实际上只要bitset优化一下floyd复杂度就是对的了(\(O(\frac{n^3}{32})\)) 还可以缩点之后bitset维 ...

  8. 【代码笔记】iOS-json文件的使用

    一,工程图. 二,代码. - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the ...

  9. 将caj文件转化为pdf文件进行全文下载脚本(ubuntu下亲测有用)

    最近ubuntu下caj阅读器,突然崩掉了,而偏偏要准备开题,在网上搜索原因未果,准备放弃时候,突然在网上看到一个脚本,说是很好用,可以在指定页面将caj文件转化为pdf文件,亲测有用,这里直接给出脚 ...

  10. JavaScript Math对象方法

    console.log(Math.abs(123));//绝对值 console.log(Math.ceil(123.3));//向上舍入 console.log(Math.floor(123));/ ...