Socket
Socket
Sign inDemoInstall

ipld-ethereum

Package Overview
Dependencies
Maintainers
3
Versions
15
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

ipld-ethereum - npm Package Compare versions

Comparing version 2.0.3 to 3.0.0

.travis.yml

33

CHANGELOG.md

@@ -0,1 +1,34 @@

<a name="3.0.0"></a>
# [3.0.0](https://github.com/ipld/js-ipld-ethereum/compare/v2.0.3...v3.0.0) (2019-05-08)
### Bug Fixes
* **package:** update cids to version 0.6.0 ([c38363a](https://github.com/ipld/js-ipld-ethereum/commit/c38363a))
* **package:** update multihashing-async to version 0.6.0 ([4eaa791](https://github.com/ipld/js-ipld-ethereum/commit/4eaa791))
### Features
* new IPLD Format API ([dc19aa7](https://github.com/ipld/js-ipld-ethereum/commit/dc19aa7))
### BREAKING CHANGES
* The API is now async/await based
There are numerous changes, the most significant one is that the API
is no longer callback based, but it using async/await.
If you want to access the original JavaScript Ethereum object, it is
now stored in a property called `_ethObj`. So if you e.g. called
`deserialized.hash()`, you now have to call
`deserialized._ethObj.hash()`.
For the full new API please see the [IPLD Formats spec].
[IPLD Formats spec]: https://github.com/ipld/interface-ipld-format
<a name="2.0.3"></a>

@@ -2,0 +35,0 @@ ## [2.0.3](https://github.com/ipld/js-ipld-ethereum/compare/v2.0.2...v2.0.3) (2019-01-18)

79

eth-account-snapshot/index.js
'use strict'
const EthAccount = require('ethereumjs-account')
const multicodec = require('multicodec')
const cidFromHash = require('../util/cidFromHash')

@@ -7,65 +9,24 @@ const createResolver = require('../util/createResolver')

module.exports = createResolver('eth-account-snapshot', EthAccount, mapFromEthObj)
const deserialize = (serialized) => {
const ethObj = new EthAccount(serialized)
function mapFromEthObj (account, options, callback) {
const paths = []
// external links
paths.push({
path: 'storage',
value: { '/': cidFromHash('eth-storage-trie', account.stateRoot).toBaseEncodedString() }
})
// resolve immediately if empty, otherwise link to code
if (emptyCodeHash.equals(account.codeHash)) {
paths.push({
path: 'code',
value: Buffer.from(''),
})
} else {
paths.push({
path: 'code',
value: { '/': cidFromHash('raw', account.codeHash).toBaseEncodedString() }
})
const deserialized = {
balance: ethObj.balance,
code: emptyCodeHash.equals(ethObj.codeHash)
? Buffer.alloc(0)
: cidFromHash(multicodec.RAW, ethObj.codeHash),
codeHash: ethObj.codeHash,
isEmpty: ethObj.isEmpty(),
isContract: ethObj.isContract(),
nonce: ethObj.nonce,
stateRoot: ethObj.stateRoot,
storage: cidFromHash(multicodec.ETH_STORAGE_TRIE, ethObj.stateRoot),
_ethObj: ethObj
}
// external links as data
Object.defineProperty(deserialized, '_ethObj', { enumerable: false })
paths.push({
path: 'stateRoot',
value: account.stateRoot
})
return deserialized
}
paths.push({
path: 'codeHash',
value: account.codeHash
})
// internal data
paths.push({
path: 'nonce',
value: account.nonce
})
paths.push({
path: 'balance',
value: account.balance
})
// helpers
paths.push({
path: 'isEmpty',
value: account.isEmpty()
})
paths.push({
path: 'isContract',
value: account.isContract()
})
callback(null, paths)
}
module.exports = createResolver(multicodec.ETH_ACCOUNT_SNAPSHOT, deserialize)
/* eslint-env mocha */
'use strict'
const expect = require('chai').expect
const chai = require('chai')
chai.use(require('dirty-chai'))
const expect = chai.expect
const dagEthAccount = require('../index')

@@ -9,27 +11,23 @@ const resolver = dagEthAccount.resolver

const emptyCodeHash = require('../../util/emptyCodeHash')
const CID = require('cids')
const multicodec = require('multicodec')
describe('IPLD format resolver (local)', () => {
let testBlob
let testData = {
nonce: new Buffer('02', 'hex'),
balance: new Buffer('04a817c800', 'hex'),
const testData = {
nonce: Buffer.from('02', 'hex'),
balance: Buffer.from('04a817c800', 'hex'),
codeHash: emptyCodeHash,
stateRoot: new Buffer('012304a817c80004a817c80004a817c80004a817c80004a817c80004a817c800', 'hex')
stateRoot: Buffer.from('012304a817c80004a817c80004a817c80004a817c80004a817c80004a817c800', 'hex')
}
before((done) => {
const testAccount = new Account(testData)
dagEthAccount.util.serialize(testAccount, (err, result) => {
if (err) return done(err)
testBlob = result
done()
})
const testAccount = new Account(testData)
const testBlob = dagEthAccount.util.serialize({
_ethObj: testAccount
})
it('multicodec is eth-account-snapshot', () => {
expect(resolver.multicodec).to.equal('eth-account-snapshot')
expect(dagEthAccount.codec).to.equal(multicodec.ETH_ACCOUNT_SNAPSHOT)
})
it('defaultHashAlg is keccak-256', () => {
expect(resolver.defaultHashAlg).to.equal('keccak-256')
expect(dagEthAccount.defaultHashAlg).to.equal(multicodec.KECCAK_256)
})

@@ -39,26 +37,70 @@

it('path within scope', () => {
resolver.resolve(testBlob, 'nonce', (err, result) => {
expect(err).to.not.exist
expect(result.value.toString('hex')).to.equal(testData.nonce.toString('hex'))
})
const result = resolver.resolve(testBlob, 'nonce')
expect(result.value).to.eql(testData.nonce)
})
it('resolves empty code', () => {
resolver.resolve(testBlob, 'code', (err, result) => {
expect(err).to.not.exist
expect(result.remainderPath).to.equal('')
expect(Buffer.isBuffer(result.value)).to.equal(true)
expect(result.value.length).to.equal(0)
})
it('resolves "storage" to correct type', () => {
const result = resolver.resolve(testBlob, 'storage')
expect(CID.isCID(result.value)).to.be.true()
})
it('resolves "code" to correct type', () => {
const result = resolver.resolve(testBlob, 'storage')
expect(CID.isCID(result.value)).to.be.true()
})
it('resolves "stateRoot" to correct type', () => {
const result = resolver.resolve(testBlob, 'stateRoot')
expect(Buffer.isBuffer(result.value)).to.be.true()
})
it('resolves "codeHash" to correct type', () => {
const result = resolver.resolve(testBlob, 'codeHash')
expect(Buffer.isBuffer(result.value)).to.be.true()
})
it('resolves "nonce" to correct type', () => {
const result = resolver.resolve(testBlob, 'nonce')
expect(Buffer.isBuffer(result.value)).to.be.true()
})
it('resolves "balance" to correct type', () => {
const result = resolver.resolve(testBlob, 'balance')
expect(Buffer.isBuffer(result.value)).to.be.true()
})
it('resolves "isEmpty" to correct type', () => {
const result = resolver.resolve(testBlob, 'isEmpty')
expect(result.value).to.be.false()
})
it('resolves "isContract" to correct type', () => {
const result = resolver.resolve(testBlob, 'isContract')
expect(result.value).to.be.false()
})
})
it('resolves empty code', () => {
const result = resolver.resolve(testBlob, 'code')
expect(result.remainderPath).to.equal('')
expect(Buffer.isBuffer(result.value)).to.be.true()
expect(result.value.length).to.equal(0)
})
describe('resolver.tree', () => {
it('basic sanity test', () => {
resolver.tree(testBlob, (err, paths) => {
expect(err).to.not.exist
expect(Array.isArray(paths)).to.eql(true)
})
it('basic sanity test', async () => {
const tree = resolver.tree(testBlob)
const paths = [...tree]
expect(paths).to.have.members([
'storage',
'code',
'stateRoot',
'codeHash',
'nonce',
'balance',
'isEmpty',
'isContract'
])
})
})
})
'use strict'
const waterfall = require('async/waterfall')
const each = require('async/each')
const asyncify = require('async/asyncify')
const RLP = require('rlp')
const EthBlockHead = require('ethereumjs-block/header')
const multihash = require('multihashing-async')
const cidFromHash = require('../util/cidFromHash')
const ethBlockResolver = require('../eth-block').resolver
const multicodec = require('multicodec')
const ipldEthBlock = require('../eth-block')
const createResolver = require('../util/createResolver')
const ethBlockListResolver = createResolver('eth-block-list', undefined, mapFromEthObj)
const util = ethBlockListResolver.util
util.serialize = asyncify((ethBlockList) => {
const rawOmmers = ethBlockList.map((ethBlock) => ethBlock.raw)
return RLP.encode(rawOmmers)
})
util.deserialize = asyncify((serialized) => {
const deserialize = (serialized) => {
const rawOmmers = RLP.decode(serialized)
return rawOmmers.map((rawBlock) => new EthBlockHead(rawBlock))
})
util.cid = (blockList, options, callback) => {
if (typeof options === 'function') {
callback = options
options = {}
}
options = options || {}
const hashAlg = options.hashAlg || 'keccak-256'
const version = typeof options.version === 'undefined' ? 1 : options.version
const deserialized = rawOmmers.map((rawBlock) => {
return ipldEthBlock.util.deserialize(rawBlock)
})
waterfall([
(cb) => util.serialize(blockList, cb),
(data, cb) => multihash.digest(data, hashAlg, cb),
asyncify((mhash) => cidFromHash('eth-block-list', mhash, options))
], callback)
deserialized.count = deserialized.length
return deserialized
}
module.exports = ethBlockListResolver
const ethBlockListResolver = createResolver(
multicodec.ETH_BLOCK_LIST, deserialize)
ethBlockListResolver.util.serialize = (ethBlockList) => {
const rawOmmers = ethBlockList.map((ethBlock) => ethBlock._ethObj.raw)
return RLP.encode(rawOmmers)
}
function mapFromEthObj (ethBlockList, options, callback) {
let paths = []
// external links (none)
// external links as data (none)
// helpers
paths.push({
path: 'count',
value: ethBlockList.length
})
// internal data
// add paths for each block
each(ethBlockList, (ethBlock, next) => {
const index = ethBlockList.indexOf(ethBlock)
const blockPath = index.toString()
// block root
paths.push({
path: blockPath,
value: ethBlock
})
// block children
ethBlockResolver._mapFromEthObject(ethBlock, {}, (err, subpaths) => {
if (err) return next(err)
// append blockPath to each subpath
subpaths.forEach((path) => path.path = blockPath + '/' + path.path)
paths = paths.concat(subpaths)
next()
})
}, (err) => {
if (err) return callback(err)
callback(null, paths)
})
}
module.exports = ethBlockListResolver
/* eslint-env mocha */
'use strict'
const expect = require('chai').expect
const chai = require('chai')
chai.use(require('dirty-chai'))
const expect = chai.expect
const CID = require('cids')
const multihash = require('multihashes')
const RLP = require('rlp')
const EthBlock = require('ethereumjs-block')
const multicodec = require('multicodec')
const EthBlockFromRpc = require('ethereumjs-block/from-rpc')
const dagEthBlockList = require('../index')

@@ -16,70 +19,117 @@ const resolver = dagEthBlockList.resolver

describe('IPLD format resolver (local)', () => {
let testBlob
let ethBlock = EthBlockFromRpc(block97Data, [ommerData0, ommerData1])
before((done) => {
dagEthBlockList.util.serialize(ethBlock.uncleHeaders, (err, result) => {
if (err) return done(err)
testBlob = result
done()
})
const ethBlock = EthBlockFromRpc(block97Data, [ommerData0, ommerData1])
const uncleHeaders = ethBlock.uncleHeaders.map((block) => {
return { _ethObj: block }
})
const testBlob = dagEthBlockList.util.serialize(uncleHeaders)
it('multicodec is eth-block-list', () => {
expect(resolver.multicodec).to.equal('eth-block-list')
expect(dagEthBlockList.codec).to.equal(multicodec.ETH_BLOCK_LIST)
})
it('defaultHashAlg is keccak-256', () => {
expect(resolver.defaultHashAlg).to.equal('keccak-256')
expect(dagEthBlockList.defaultHashAlg).to.equal(multicodec.KECCAK_256)
})
describe('resolver.resolve', () => {
it('uncle #0', (done) => {
resolver.resolve(testBlob, '0', (err, result) => {
expect(err).to.not.exist()
expect(result.value.hash().toString('hex')).to.equal('acfa207ce9d5139b85ecfdc197f8d283fc241f95f176f008f44aab35ef1f901f')
expect(result.remainderPath).to.equal('')
done()
})
it('uncle #0', () => {
const result = resolver.resolve(testBlob, '0')
expect(
result.value._ethObj.hash().toString('hex')
).to.equal(
'acfa207ce9d5139b85ecfdc197f8d283fc241f95f176f008f44aab35ef1f901f'
)
expect(result.remainderPath).to.equal('')
})
it('uncle #1', (done) => {
resolver.resolve(testBlob, '1', (err, result) => {
expect(err).to.not.exist()
expect(result.value.hash().toString('hex')).to.equal('fe426f2eb0adc88f05ea737da1ebb79e03bca546563ad74bda7bffeb37ad4d6a')
expect(result.remainderPath).to.equal('')
done()
})
it('uncle #1', () => {
const result = resolver.resolve(testBlob, '1')
expect(
result.value._ethObj.hash().toString('hex')
).to.equal(
'fe426f2eb0adc88f05ea737da1ebb79e03bca546563ad74bda7bffeb37ad4d6a'
)
expect(result.remainderPath).to.equal('')
})
it('uncle count', (done) => {
resolver.resolve(testBlob, 'count', (err, result) => {
expect(err).to.not.exist()
expect(result.value).to.equal(2)
expect(result.remainderPath).to.equal('')
done()
})
it('uncle count', () => {
const result = resolver.resolve(testBlob, 'count')
expect(result.value).to.equal(2)
expect(result.remainderPath).to.equal('')
})
it('resolve block data off uncle #0', (done) => {
resolver.resolve(testBlob, '0/timestamp', (err, result) => {
expect(err).to.not.exist()
expect(result.remainderPath.length).to.equal(0)
expect(result.value.toString('hex')).to.equal('55ba43df')
expect(result.remainderPath).to.equal('')
done()
})
it('resolve block data off uncle #0', () => {
const result = resolver.resolve(testBlob, '0/timestamp')
expect(result.remainderPath.length).to.equal(0)
expect(result.value.toString('hex')).to.equal('55ba43df')
expect(result.remainderPath).to.equal('')
})
it('resolves root to correct type', () => {
const result = resolver.resolve(testBlob, '')
expect(Array.isArray(result.value)).to.be.true()
})
it('resolves "0" to correct type', () => {
const result = resolver.resolve(testBlob, '0')
expect(typeof result.value === 'object').to.be.true()
})
// Only testing `parent` here as the rest of the properties is already
// tested by the eth-block tests
it('resolves "parent" to correct type', () => {
const result = resolver.resolve(testBlob, '0/parent')
expect(CID.isCID(result.value)).to.be.true()
})
})
describe('resolver.tree', () => {
it('returns all uncles', (done) => {
resolver.tree(testBlob, (err, paths) => {
expect(err).to.not.exist()
expect(typeof paths).to.eql('object')
expect(Array.isArray(paths)).to.eql(true)
const expectedPaths = ethBlock.uncleHeaders.length * 21 + 1
expect(paths.length).to.eql(expectedPaths)
done()
})
it('returns all uncles', () => {
const tree = resolver.tree(testBlob)
const paths = [...tree]
expect(paths).to.have.members([
'count',
'0',
'0/parent',
'0/ommers',
'0/transactions',
'0/transactionReceipts',
'0/state',
'0/parentHash',
'0/ommerHash',
'0/transactionTrieRoot',
'0/transactionReceiptTrieRoot',
'0/stateRoot',
'0/authorAddress',
'0/bloom',
'0/difficulty',
'0/number',
'0/gasLimit',
'0/gasUsed',
'0/timestamp',
'0/extraData',
'0/mixHash',
'0/nonce',
'1',
'1/parent',
'1/ommers',
'1/transactions',
'1/transactionReceipts',
'1/state',
'1/parentHash',
'1/ommerHash',
'1/transactionTrieRoot',
'1/transactionReceiptTrieRoot',
'1/stateRoot',
'1/authorAddress',
'1/bloom',
'1/difficulty',
'1/number',
'1/gasLimit',
'1/gasUsed',
'1/timestamp',
'1/extraData',
'1/mixHash',
'1/nonce'
])
})

@@ -89,51 +139,40 @@ })

describe('util', () => {
it('generates correct cid', (done) => {
dagEthBlockList.util.cid(ethBlock.uncleHeaders, (err, cid) => {
expect(err).to.not.exist()
expect(cid.version).to.equal(1)
expect(cid.codec).to.equal('eth-block-list')
const mhash = multihash.decode(cid.multihash)
expect(mhash.name).to.equal('keccak-256')
expect(mhash.digest.toString('hex')).to.equal(ethBlock.header.uncleHash.toString('hex'))
done()
})
it('generates correct cid', async () => {
const cid = await dagEthBlockList.util.cid(testBlob)
expect(cid.version).to.equal(1)
expect(cid.codec).to.equal('eth-block-list')
const mhash = multihash.decode(cid.multihash)
expect(mhash.name).to.equal('keccak-256')
expect(mhash.digest.toString('hex')).to.equal(ethBlock.header.uncleHash.toString('hex'))
})
it('should create CID, no options', (done) => {
dagEthBlockList.util.cid(ethBlock.uncleHeaders, (err, cid) => {
expect(err).to.not.exist()
expect(cid.version).to.equal(1)
expect(cid.codec).to.equal('eth-block-list')
expect(cid.multihash).to.exist()
const mh = multihash.decode(cid.multihash)
expect(mh.name).to.equal('keccak-256')
done()
})
it('should create CID, no options', async () => {
const cid = await dagEthBlockList.util.cid(testBlob)
expect(cid.version).to.equal(1)
expect(cid.codec).to.equal('eth-block-list')
expect(cid.multihash).to.exist()
const mh = multihash.decode(cid.multihash)
expect(mh.name).to.equal('keccak-256')
})
it('should create CID, empty options', (done) => {
dagEthBlockList.util.cid(ethBlock.uncleHeaders, {}, (err, cid) => {
expect(err).to.not.exist()
expect(cid.version).to.equal(1)
expect(cid.codec).to.equal('eth-block-list')
expect(cid.multihash).to.exist()
const mh = multihash.decode(cid.multihash)
expect(mh.name).to.equal('keccak-256')
done()
})
it('should create CID, empty options', async () => {
const cid = await dagEthBlockList.util.cid(ethBlock.uncleHeaders, {})
expect(cid.version).to.equal(1)
expect(cid.codec).to.equal('eth-block-list')
expect(cid.multihash).to.exist()
const mh = multihash.decode(cid.multihash)
expect(mh.name).to.equal('keccak-256')
})
it('should create CID, hashAlg', (done) => {
dagEthBlockList.util.cid(ethBlock.uncleHeaders, { hashAlg: 'keccak-512' }, (err, cid) => {
expect(err).to.not.exist()
expect(cid.version).to.equal(1)
expect(cid.codec).to.equal('eth-block-list')
expect(cid.multihash).to.exist()
const mh = multihash.decode(cid.multihash)
expect(mh.name).to.equal('keccak-512')
done()
it('should create CID, hashAlg', async () => {
const cid = await dagEthBlockList.util.cid(testBlob, {
hashAlg: multicodec.KECCAK_512
})
expect(cid.version).to.equal(1)
expect(cid.codec).to.equal('eth-block-list')
expect(cid.multihash).to.exist()
const mh = multihash.decode(cid.multihash)
expect(mh.name).to.equal('keccak-512')
})
})
})
'use strict'
const EthBlockHeader = require('ethereumjs-block/header')
const multicodec = require('multicodec')
const cidFromHash = require('../util/cidFromHash')
const createResolver = require('../util/createResolver')
module.exports = createResolver('eth-block', EthBlockHeader, mapFromEthObj)
const deserialize = (serialized) => {
const ethObj = new EthBlockHeader(serialized)
const deserialized = {
authorAddress: ethObj.coinbase,
bloom: ethObj.bloom,
difficulty: ethObj.difficulty,
extraData: ethObj.extraData,
gasLimit: ethObj.gasLimit,
gasUsed: ethObj.gasUsed,
mixHash: ethObj.mixHash,
nonce: ethObj.nonce,
number: ethObj.number,
ommerHash: ethObj.uncleHash,
ommers: cidFromHash(multicodec.ETH_BLOCK_LIST, ethObj.uncleHash),
parent: cidFromHash(multicodec.ETH_BLOCK, ethObj.parentHash),
parentHash: ethObj.parentHash,
state: cidFromHash(multicodec.ETH_STATE_TRIE, ethObj.stateRoot),
stateRoot: ethObj.stateRoot,
timestamp: ethObj.timestamp,
transactions: cidFromHash(multicodec.ETH_TX_TRIE, ethObj.transactionsTrie),
transactionReceipts: cidFromHash(
multicodec.ETH_TX_RECEIPT_TRIE, ethObj.receiptTrie),
transactionReceiptTrieRoot: ethObj.receiptTrie,
transactionTrieRoot: ethObj.transactionsTrie,
_ethObj: ethObj
}
function mapFromEthObj (ethObj, options, callback) {
const paths = []
Object.defineProperty(deserialized, '_ethObj', { enumerable: false })
// external links
paths.push({
path: 'parent',
value: { '/': cidFromHash('eth-block', ethObj.parentHash).toBaseEncodedString() }
})
paths.push({
path: 'ommers',
value: { '/': cidFromHash('eth-block-list', ethObj.uncleHash).toBaseEncodedString() }
})
paths.push({
path: 'transactions',
value: { '/': cidFromHash('eth-tx-trie', ethObj.transactionsTrie).toBaseEncodedString() }
})
paths.push({
path: 'transactionReceipts',
value: { '/': cidFromHash('eth-tx-receipt-trie', ethObj.receiptTrie).toBaseEncodedString() }
})
paths.push({
path: 'state',
value: { '/': cidFromHash('eth-state-trie', ethObj.stateRoot).toBaseEncodedString() }
})
return deserialized
}
// external links as data
paths.push({
path: 'parentHash',
value: ethObj.parentHash
})
paths.push({
path: 'ommerHash',
value: ethObj.uncleHash
})
paths.push({
path: 'transactionTrieRoot',
value: ethObj.transactionsTrie
})
paths.push({
path: 'transactionReceiptTrieRoot',
value: ethObj.receiptTrie
})
paths.push({
path: 'stateRoot',
value: ethObj.stateRoot
})
// internal data
paths.push({
path: 'authorAddress',
value: ethObj.coinbase
})
paths.push({
path: 'bloom',
value: ethObj.bloom
})
paths.push({
path: 'difficulty',
value: ethObj.difficulty
})
paths.push({
path: 'number',
value: ethObj.number
})
paths.push({
path: 'gasLimit',
value: ethObj.gasLimit
})
paths.push({
path: 'gasUsed',
value: ethObj.gasUsed
})
paths.push({
path: 'timestamp',
value: ethObj.timestamp
})
paths.push({
path: 'extraData',
value: ethObj.extraData
})
paths.push({
path: 'mixHash',
value: ethObj.mixHash
})
paths.push({
path: 'nonce',
value: ethObj.nonce
})
callback(null, paths)
}
module.exports = createResolver(multicodec.ETH_BLOCK, deserialize)

@@ -9,66 +9,47 @@ /* eslint-env mocha */

const EthBlockHeader = require('ethereumjs-block/header')
const multihashing = require('multihashing-async')
const multihash = require('multihashes')
const waterfall = require('async/waterfall')
const asyncify = require('async/asyncify')
const multicodec = require('multicodec')
const ipldEthBlock = require('../index')
const isExternalLink = require('../../util/isExternalLink')
const resolver = ipldEthBlock.resolver
describe('IPLD format resolver (local)', () => {
let testBlob
let testEthBlock
let testData = {
const testData = {
// 12345678901234567890123456789012
parentHash: new Buffer('0100000000000000000000000000000000000000000000000000000000000000', 'hex'),
uncleHash: new Buffer('0200000000000000000000000000000000000000000000000000000000000000', 'hex'),
coinbase: new Buffer('0300000000000000000000000000000000000000', 'hex'),
stateRoot: new Buffer('0400000000000000000000000000000000000000000000000000000000000000', 'hex'),
transactionsTrie: new Buffer('0500000000000000000000000000000000000000000000000000000000000000', 'hex'),
receiptTrie: new Buffer('0600000000000000000000000000000000000000000000000000000000000000', 'hex'),
// bloom: new Buffer('07000000000000000000000000000000', 'hex'),
difficulty: new Buffer('0800000000000000000000000000000000000000000000000000000000000000', 'hex'),
number: new Buffer('0900000000000000000000000000000000000000000000000000000000000000', 'hex'),
gasLimit: new Buffer('1000000000000000000000000000000000000000000000000000000000000000', 'hex'),
gasUsed: new Buffer('1100000000000000000000000000000000000000000000000000000000000000', 'hex'),
timestamp: new Buffer('1200000000000000000000000000000000000000000000000000000000000000', 'hex'),
extraData: new Buffer('1300000000000000000000000000000000000000000000000000000000000000', 'hex'),
mixHash: new Buffer('1400000000000000000000000000000000000000000000000000000000000000', 'hex'),
nonce: new Buffer('1500000000000000000000000000000000000000000000000000000000000000', 'hex')
parentHash: Buffer.from('0100000000000000000000000000000000000000000000000000000000000000', 'hex'),
uncleHash: Buffer.from('0200000000000000000000000000000000000000000000000000000000000000', 'hex'),
coinbase: Buffer.from('0300000000000000000000000000000000000000', 'hex'),
stateRoot: Buffer.from('0400000000000000000000000000000000000000000000000000000000000000', 'hex'),
transactionsTrie: Buffer.from('0500000000000000000000000000000000000000000000000000000000000000', 'hex'),
receiptTrie: Buffer.from('0600000000000000000000000000000000000000000000000000000000000000', 'hex'),
// bloom: Buffer.from('07000000000000000000000000000000', 'hex'),
difficulty: Buffer.from('0800000000000000000000000000000000000000000000000000000000000000', 'hex'),
number: Buffer.from('0900000000000000000000000000000000000000000000000000000000000000', 'hex'),
gasLimit: Buffer.from('1000000000000000000000000000000000000000000000000000000000000000', 'hex'),
gasUsed: Buffer.from('1100000000000000000000000000000000000000000000000000000000000000', 'hex'),
timestamp: Buffer.from('1200000000000000000000000000000000000000000000000000000000000000', 'hex'),
extraData: Buffer.from('1300000000000000000000000000000000000000000000000000000000000000', 'hex'),
mixHash: Buffer.from('1400000000000000000000000000000000000000000000000000000000000000', 'hex'),
nonce: Buffer.from('1500000000000000000000000000000000000000000000000000000000000000', 'hex')
}
before((done) => {
testEthBlock = new EthBlockHeader(testData)
waterfall([
(cb) => ipldEthBlock.util.serialize(testEthBlock, cb),
(serialized, cb) => multihashing(serialized, 'keccak-256', (err, hash) => {
if (err) {
return cb(err)
}
testBlob = serialized
cb()
})
], done)
const testEthBlock = new EthBlockHeader(testData)
const testBlob = ipldEthBlock.util.serialize({
_ethObj: testEthBlock
})
it('multicodec is eth-block', () => {
expect(resolver.multicodec).to.equal('eth-block')
expect(ipldEthBlock.codec).to.equal(multicodec.ETH_BLOCK)
})
it('defaultHashAlg is keccak-256', () => {
expect(resolver.defaultHashAlg).to.equal('keccak-256')
expect(ipldEthBlock.defaultHashAlg).to.equal(multicodec.KECCAK_256)
})
it('can parse the cid', (done) => {
ipldEthBlock.util.cid(testEthBlock, (err, cid) => {
expect(err).not.to.exist()
let encodedCid = cid.toBaseEncodedString()
let reconstructedCid = new CID(encodedCid)
expect(cid.version).to.equal(reconstructedCid.version)
expect(cid.codec).to.equal(reconstructedCid.codec)
expect(cid.multihash.toString('hex')).to.equal(reconstructedCid.multihash.toString('hex'))
done()
})
it('can parse the cid', async () => {
const cid = await ipldEthBlock.util.cid(testBlob)
const encodedCid = cid.toBaseEncodedString()
const reconstructedCid = new CID(encodedCid)
expect(cid.version).to.equal(reconstructedCid.version)
expect(cid.codec).to.equal(reconstructedCid.codec)
expect(cid.multihash.toString('hex')).to.equal(reconstructedCid.multihash.toString('hex'))
})

@@ -78,55 +59,162 @@

it('path within scope', () => {
resolver.resolve(testBlob, 'number', (err, result) => {
expect(err).not.to.exist()
expect(result.value.toString('hex')).to.equal(testData.number.toString('hex'))
})
const result = resolver.resolve(testBlob, 'number')
expect(result.value.toString('hex')).to.equal(testData.number.toString('hex'))
})
})
it('resolver.tree', () => {
resolver.tree(testBlob, (err, paths) => {
expect(err).not.to.exist()
expect(Array.isArray(paths)).to.eql(true)
expect(paths.length).to.eql(20)
paths.forEach((path) => {
expect(typeof path).to.eql('string')
})
it('resolves "parent" to correct type', () => {
const result = resolver.resolve(testBlob, 'parent')
expect(CID.isCID(result.value)).to.be.true()
})
it('resolves "ommers" to correct type', () => {
const result = resolver.resolve(testBlob, 'ommers')
expect(CID.isCID(result.value)).to.be.true()
})
it('resolves "transactions" to correct type', () => {
const result = resolver.resolve(testBlob, 'transactions')
expect(CID.isCID(result.value)).to.be.true()
})
it('resolves "transactionReceipts" to correct type', () => {
const result = resolver.resolve(testBlob, 'transactionReceipts')
expect(CID.isCID(result.value)).to.be.true()
})
it('resolves "state" to correct type', () => {
const result = resolver.resolve(testBlob, 'state')
expect(CID.isCID(result.value)).to.be.true()
})
it('resolves "parentHash" to correct type', () => {
const result = resolver.resolve(testBlob, 'parentHash')
expect(Buffer.isBuffer(result.value)).to.be.true()
})
it('resolves "ommerHash" to correct type', () => {
const result = resolver.resolve(testBlob, 'ommerHash')
expect(Buffer.isBuffer(result.value)).to.be.true()
})
it('resolves "transactionTrieRoot" to correct type', () => {
const result = resolver.resolve(testBlob, 'transactionTrieRoot')
expect(Buffer.isBuffer(result.value)).to.be.true()
})
it('resolves "transactionReceiptTrieRoot" to correct type', () => {
const result = resolver.resolve(testBlob, 'transactionReceiptTrieRoot')
expect(Buffer.isBuffer(result.value)).to.be.true()
})
it('resolves "stateRoot" to correct type', () => {
const result = resolver.resolve(testBlob, 'stateRoot')
expect(Buffer.isBuffer(result.value)).to.be.true()
})
it('resolves "authorAddress" to correct type', () => {
const result = resolver.resolve(testBlob, 'authorAddress')
expect(Buffer.isBuffer(result.value)).to.be.true()
})
it('resolves "bloom" to correct type', () => {
const result = resolver.resolve(testBlob, 'bloom')
expect(Buffer.isBuffer(result.value)).to.be.true()
})
it('resolves "difficulty" to correct type', () => {
const result = resolver.resolve(testBlob, 'difficulty')
expect(Buffer.isBuffer(result.value)).to.be.true()
})
it('resolves "number" to correct type', () => {
const result = resolver.resolve(testBlob, 'number')
expect(Buffer.isBuffer(result.value)).to.be.true()
})
it('resolves "gasLimit" to correct type', () => {
const result = resolver.resolve(testBlob, 'gasLimit')
expect(Buffer.isBuffer(result.value)).to.be.true()
})
it('resolves "gasUsed" to correct type', () => {
const result = resolver.resolve(testBlob, 'gasUsed')
expect(Buffer.isBuffer(result.value)).to.be.true()
})
it('resolves "timestamp" to correct type', () => {
const result = resolver.resolve(testBlob, 'timestamp')
expect(Buffer.isBuffer(result.value)).to.be.true()
})
it('resolves "extraData" to correct type', () => {
const result = resolver.resolve(testBlob, 'extraData')
expect(Buffer.isBuffer(result.value)).to.be.true()
})
it('resolves "mixHash" to correct type', () => {
const result = resolver.resolve(testBlob, 'mixHash')
expect(Buffer.isBuffer(result.value)).to.be.true()
})
it('resolves "nonce" to correct type', () => {
const result = resolver.resolve(testBlob, 'nonce')
expect(Buffer.isBuffer(result.value)).to.be.true()
})
})
it('resolver.tree', async () => {
const tree = resolver.tree(testBlob)
const paths = [...tree]
expect(paths).to.have.members([
'parent',
'ommers',
'transactions',
'transactionReceipts',
'state',
'parentHash',
'ommerHash',
'transactionTrieRoot',
'transactionReceiptTrieRoot',
'stateRoot',
'authorAddress',
'bloom',
'difficulty',
'number',
'gasLimit',
'gasUsed',
'timestamp',
'extraData',
'mixHash',
'nonce'
])
})
describe('util', () => {
it('should create CID, no options', (done) => {
ipldEthBlock.util.cid(testEthBlock, (err, cid) => {
expect(err).to.not.exist()
expect(cid.version).to.equal(1)
expect(cid.codec).to.equal('eth-block')
expect(cid.multihash).to.exist()
const mh = multihash.decode(cid.multihash)
expect(mh.name).to.equal('keccak-256')
done()
})
it('should create CID, no options', async () => {
const cid = await ipldEthBlock.util.cid(testBlob)
expect(cid.version).to.equal(1)
expect(cid.codec).to.equal('eth-block')
expect(cid.multihash).to.exist()
const mh = multihash.decode(cid.multihash)
expect(mh.name).to.equal('keccak-256')
})
it('should create CID, empty options', (done) => {
ipldEthBlock.util.cid(testEthBlock, {}, (err, cid) => {
expect(err).to.not.exist()
expect(cid.version).to.equal(1)
expect(cid.codec).to.equal('eth-block')
expect(cid.multihash).to.exist()
const mh = multihash.decode(cid.multihash)
expect(mh.name).to.equal('keccak-256')
done()
})
it('should create CID, empty options', async () => {
const cid = await ipldEthBlock.util.cid(testBlob, {})
expect(cid.version).to.equal(1)
expect(cid.codec).to.equal('eth-block')
expect(cid.multihash).to.exist()
const mh = multihash.decode(cid.multihash)
expect(mh.name).to.equal('keccak-256')
})
it('should create CID, hashAlg', (done) => {
ipldEthBlock.util.cid(testEthBlock, { hashAlg: 'keccak-512' }, (err, cid) => {
expect(err).to.not.exist()
expect(cid.version).to.equal(1)
expect(cid.codec).to.equal('eth-block')
expect(cid.multihash).to.exist()
const mh = multihash.decode(cid.multihash)
expect(mh.name).to.equal('keccak-512')
done()
it('should create CID, hashAlg', async () => {
const cid = await ipldEthBlock.util.cid(testBlob, {
hashAlg: multicodec.KECCAK_512
})
expect(cid.version).to.equal(1)
expect(cid.codec).to.equal('eth-block')
expect(cid.multihash).to.exist()
const mh = multihash.decode(cid.multihash)
expect(mh.name).to.equal('keccak-512')
})

@@ -137,101 +225,80 @@ })

describe('manual ancestor walking', () => {
let cid1
let cid2
let ethBlock1
let ethBlock2
let ethBlock3
let cid1
let cid2
let cid3
let serialized1
let serialized2
let serialized3
before((done) => {
before(async () => {
ethBlock1 = {
_ethObj: new EthBlockHeader({
number: 1
})
}
serialized1 = ipldEthBlock.util.serialize(ethBlock1)
cid1 = await ipldEthBlock.util.cid(serialized1)
waterfall([
asyncify(() => {
return ethBlock1 = new EthBlockHeader({
number: 1
})
}),
ipldEthBlock.util.cid,
asyncify((cid) => { cid1 = cid }),
ethBlock2 = {
_ethObj: new EthBlockHeader({
number: 2,
parentHash: ethBlock1._ethObj.hash()
})
}
serialized2 = ipldEthBlock.util.serialize(ethBlock2)
cid2 = await ipldEthBlock.util.cid(serialized2)
asyncify(() => {
return ethBlock2 = new EthBlockHeader({
number: 2,
parentHash: ethBlock1.hash()
})
}),
ipldEthBlock.util.cid,
asyncify((cid) => { cid2 = cid }),
asyncify(() => {
return ethBlock3 = new EthBlockHeader({
number: 3,
parentHash: ethBlock2.hash()
})
}),
ipldEthBlock.util.cid,
asyncify((cid) => { cid3 = cid }),
], done)
ethBlock3 = {
_ethObj: new EthBlockHeader({
number: 3,
parentHash: ethBlock2._ethObj.hash()
})
}
serialized3 = ipldEthBlock.util.serialize(ethBlock3)
await ipldEthBlock.util.cid(serialized3)
})
it('root path (same as get)', (done) => {
ipldEthBlock.resolver._resolveFromEthObject(ethBlock1, '/', (err, result) => {
expect(err).to.not.exist()
ipldEthBlock.util.cid(result.value, (err, cid) => {
expect(err).to.not.exist()
expect(cid).to.eql(cid1)
done()
})
})
it('root path (same as get)', () => {
const result = ipldEthBlock.resolver.resolve(serialized1, '/')
const deserialized = ipldEthBlock.util.deserialize(serialized1)
expect(result.value).to.eql(deserialized)
})
it('value within 1st node scope', (done) => {
ipldEthBlock.resolver._resolveFromEthObject(ethBlock3, 'number', (err, result) => {
expect(err).to.not.exist()
expect(result.remainderPath).to.eql('')
expect(isExternalLink(result.value)).to.eql(false)
expect(result.value.toString('hex')).to.eql('03')
done()
})
it('value within 1st node scope', () => {
const result = ipldEthBlock.resolver.resolve(serialized3, 'number')
expect(result.remainderPath).to.eql('')
expect(CID.isCID(result.value)).to.be.false()
expect(result.value.toString('hex')).to.eql('03')
})
it('value within nested scope (1 level)', (done) => {
ipldEthBlock.resolver._resolveFromEthObject(ethBlock3, 'parent/number', (err, result) => {
expect(err).to.not.exist()
expect(result.remainderPath).to.eql('number')
expect(isExternalLink(result.value)).to.eql(true)
expect(result.value['/']).to.eql(cid2.toBaseEncodedString())
ipldEthBlock.resolver._resolveFromEthObject(ethBlock2, result.remainderPath, (err, result) => {
expect(err).to.not.exist()
expect(result.remainderPath).to.eql('')
expect(isExternalLink(result.value)).to.eql(false)
expect(result.value.toString('hex')).to.eql('02')
done()
})
})
it('value within nested scope (1 level)', () => {
const result = ipldEthBlock.resolver.resolve(serialized3, 'parent/number')
expect(result.remainderPath).to.eql('number')
expect(CID.isCID(result.value)).to.be.true()
expect(result.value.equals(cid2)).to.be.true()
const result2 = ipldEthBlock.resolver.resolve(serialized2, result.remainderPath)
expect(result2.remainderPath).to.eql('')
expect(CID.isCID(result2.value)).to.be.false()
expect(result2.value.toString('hex')).to.eql('02')
})
it('value within nested scope (1 level)', (done) => {
ipldEthBlock.resolver._resolveFromEthObject(ethBlock3, 'parent/parent/number', (err, result) => {
expect(err).to.not.exist()
expect(result.remainderPath).to.eql('parent/number')
expect(isExternalLink(result.value)).to.eql(true)
expect(result.value['/']).to.eql(cid2.toBaseEncodedString())
ipldEthBlock.resolver._resolveFromEthObject(ethBlock2, result.remainderPath, (err, result) => {
expect(err).to.not.exist()
expect(result.remainderPath).to.eql('number')
expect(isExternalLink(result.value)).to.eql(true)
expect(result.value['/']).to.eql(cid1.toBaseEncodedString())
ipldEthBlock.resolver._resolveFromEthObject(ethBlock1, result.remainderPath, (err, result) => {
expect(err).to.not.exist()
expect(result.remainderPath).to.eql('')
expect(isExternalLink(result.value)).to.eql(false)
expect(result.value.toString('hex')).to.eql('01')
done()
})
})
})
it('value within nested scope (2 levels)', () => {
const result = ipldEthBlock.resolver.resolve(serialized3, 'parent/parent/number')
expect(result.remainderPath).to.eql('parent/number')
expect(CID.isCID(result.value)).to.be.true()
expect(result.value.equals(cid2)).to.be.true()
const result2 = ipldEthBlock.resolver.resolve(serialized2, result.remainderPath)
expect(result2.remainderPath).to.eql('number')
expect(CID.isCID(result2.value)).to.be.true()
expect(result2.value.equals(cid1)).to.be.true()
const result3 = ipldEthBlock.resolver.resolve(serialized1, result2.remainderPath)
expect(result3.remainderPath).to.eql('')
expect(CID.isCID(result3.value)).to.be.false()
expect(result3.value.toString('hex')).to.eql('01')
})
})
'use strict'
/* eslint max-nested-callbacks: ["error", 5] */
const multicodec = require('multicodec')

@@ -7,4 +7,5 @@ const ethAccountSnapshotResolver = require('../eth-account-snapshot')

const ethStateTrieResolver = createTrieResolver('eth-state-trie', ethAccountSnapshotResolver)
const ethStateTrieResolver = createTrieResolver(
multicodec.ETH_STATE_TRIE, ethAccountSnapshotResolver)
module.exports = ethStateTrieResolver

@@ -7,11 +7,8 @@ /* eslint-env mocha */

const expect = chai.expect
const async = require('async')
const Account = require('ethereumjs-account')
const Trie = require('merkle-patricia-tree')
const TrieNode = require('merkle-patricia-tree/trieNode')
const multihashing = require('multihashing-async')
const multicodec = require('multicodec')
const CID = require('cids')
const cidFromHash = require('../../util/cidFromHash')
const promisify = require('promisify-es6')
const ipldEthStateTrie = require('../index')
const isExternalLink = require('../../util/isExternalLink')
const resolver = ipldEthStateTrie.resolver

@@ -23,10 +20,6 @@

let testContractData = {
balance: new Buffer('012345', 'hex'),
codeHash: new Buffer('abcd04a817c80004a817c80004a817c80004a817c80004a817c80004a817c800', 'hex'),
stateRoot: new Buffer('012304a817c80004a817c80004a817c80004a817c80004a817c80004a817c800', 'hex')
balance: Buffer.from('012345', 'hex'),
codeHash: Buffer.from('abcd04a817c80004a817c80004a817c80004a817c80004a817c80004a817c800', 'hex'),
stateRoot: Buffer.from('012304a817c80004a817c80004a817c80004a817c80004a817c80004a817c800', 'hex')
}
function prepareTestContract (done) {
testContract = new Account(testContractData)
done()
}

@@ -36,125 +29,121 @@ // setup external account test data

let testExternalAccountData = {
balance: new Buffer('abcdef', 'hex'),
nonce: new Buffer('02', 'hex')
balance: Buffer.from('abcdef', 'hex'),
nonce: Buffer.from('02', 'hex')
}
function prepareTestExternalAccount (done) {
testExternalAccount = new Account(testExternalAccountData)
done()
}
// setup test trie
let trie
let trieNodes = {}
let dagNodes = {}
before((done) => {
trie = new Trie()
async.waterfall([
(cb) => prepareTestContract(cb),
(cb) => prepareTestExternalAccount(cb),
(cb) => populateTrie(trie, cb),
(cb) => dumpTrieNonInlineNodes(trie, trieNodes, cb),
// (cb) => logTrie(trie, cb),
(cb) => async.mapValues(trieNodes, (node, key, cb) => {
ipldEthStateTrie.util.serialize(node, cb)
}, cb)
], (err, result) => {
if (err) {
return done(err)
}
dagNodes = result
done()
before(async () => {
testContract = new Account(testContractData)
testExternalAccount = new Account(testExternalAccountData)
const trie = await populateTrie()
const trieNodes = await dumpTrieNonInlineNodes(trie)
Object.entries(trieNodes).map(([key, node]) => {
dagNodes[key] = ipldEthStateTrie.util.serialize({ _ethObj: node })
})
})
function populateTrie (trie, cb) {
async.series([
(cb) => trie.put(new Buffer('000a0a00', 'hex'), testExternalAccount.serialize(), cb),
(cb) => trie.put(new Buffer('000a0a01', 'hex'), testExternalAccount.serialize(), cb),
(cb) => trie.put(new Buffer('000a0a02', 'hex'), testExternalAccount.serialize(), cb),
(cb) => trie.put(new Buffer('000a0b00', 'hex'), testExternalAccount.serialize(), cb),
(cb) => trie.put(new Buffer('000b0a00', 'hex'), testContract.serialize(), cb),
(cb) => trie.put(new Buffer('000b0b00', 'hex'), testContract.serialize(), cb),
(cb) => trie.put(new Buffer('000c0a00', 'hex'), testContract.serialize(), cb)
], (err) => {
if (err) return cb(err)
cb()
})
async function populateTrie () {
const trie = new Trie()
const put = promisify(trie.put.bind(trie))
await put(Buffer.from('000a0a00', 'hex'), testExternalAccount.serialize())
await put(Buffer.from('000a0a01', 'hex'), testExternalAccount.serialize())
await put(Buffer.from('000a0a02', 'hex'), testExternalAccount.serialize())
await put(Buffer.from('000a0b00', 'hex'), testExternalAccount.serialize())
await put(Buffer.from('000b0a00', 'hex'), testContract.serialize())
await put(Buffer.from('000b0b00', 'hex'), testContract.serialize())
await put(Buffer.from('000c0a00', 'hex'), testContract.serialize())
return trie
}
function cid (data, cb) {
multihashing(data, 'keccak-256', (err, hash) => {
if (err) {
return cb(err)
}
const cid = new CID(1, resolver.multicodec, hash)
cb(null, cid)
})
}
it('multicodec is eth-state-trie', () => {
expect(resolver.multicodec).to.equal('eth-state-trie')
expect(ipldEthStateTrie.codec).to.equal(multicodec.ETH_STATE_TRIE)
})
it('defaultHashAlg is keccak-256', () => {
expect(resolver.defaultHashAlg).to.equal('keccak-256')
expect(ipldEthStateTrie.defaultHashAlg).to.equal(multicodec.KECCAK_256)
})
describe('resolver.resolve', () => {
it('root node resolves to branch', (done) => {
let rootNode = dagNodes['']
resolver.resolve(rootNode, '0/0/0/c/0/a/0/0/codeHash', (err, result) => {
expect(err).to.not.exist()
let trieNode = result.value
expect(result.remainderPath).to.eql('c/0/a/0/0/codeHash')
expect(isExternalLink(trieNode)).to.eql(true)
cid(dagNodes['0/0/0'], (err, cid) => {
expect(err).to.not.exist()
expect(trieNode['/']).to.eql(cid.toBaseEncodedString())
done()
})
})
it('root node resolves to branch', async () => {
const rootNode = dagNodes['']
const result = resolver.resolve(rootNode, '0/0/0/c/0/a/0/0/codeHash')
const trieNode = result.value
expect(result.remainderPath).to.eql('c/0/a/0/0/codeHash')
expect(CID.isCID(trieNode)).to.be.true()
const cid = await ipldEthStateTrie.util.cid(dagNodes['0/0/0'])
expect(trieNode.equals(cid)).to.be.true()
})
it('neck node resolves down to c branch', (done) => {
let neckNode = dagNodes['0/0/0']
resolver.resolve(neckNode, 'c/0/a/0/0/codeHash', (err, result) => {
expect(err).to.not.exist()
let trieNode = result.value
expect(result.remainderPath).to.eql('0/a/0/0/codeHash')
expect(isExternalLink(trieNode)).to.eql(true)
cid(dagNodes['0/0/0/c'], (err, cid) => {
expect(err).to.not.exist()
expect(trieNode['/']).to.eql(cid.toBaseEncodedString())
done()
})
})
it('neck node resolves down to c branch', async () => {
const neckNode = dagNodes['0/0/0']
const result = resolver.resolve(neckNode, 'c/0/a/0/0/codeHash')
const trieNode = result.value
expect(result.remainderPath).to.eql('0/a/0/0/codeHash')
expect(CID.isCID(trieNode)).to.be.true()
const cid = await ipldEthStateTrie.util.cid(dagNodes['0/0/0/c'])
expect(trieNode.equals(cid)).to.be.true()
})
it('"c" branch node resolves down to account data', (done) => {
let cBranchNode = dagNodes['0/0/0/c']
resolver.resolve(cBranchNode, '0/a/0/0/codeHash', (err, result) => {
expect(err).to.not.exist()
let trieNode = result.value
expect(result.remainderPath).to.eql('')
expect(isExternalLink(trieNode)).to.eql(false)
expect(Buffer.isBuffer(result.value)).to.eql(true)
expect(result.value.toString('hex')).to.eql(testContract.codeHash.toString('hex'))
done()
})
it('"c" branch node resolves down to account data', () => {
const cBranchNode = dagNodes['0/0/0/c']
const result = resolver.resolve(cBranchNode, '0/a/0/0/codeHash')
const trieNode = result.value
expect(result.remainderPath).to.eql('')
expect(CID.isCID(trieNode)).to.be.false()
expect(Buffer.isBuffer(result.value)).to.eql(true)
expect(result.value.toString('hex')).to.eql(testContract.codeHash.toString('hex'))
})
it('resolves "0" to correct type', () => {
const result = resolver.resolve(dagNodes['0/0/0/c'], '0')
expect(CID.isCID(result.value)).to.be.false()
expect(typeof result.value === 'object').to.be.true()
})
it('resolves "0/a" to correct type', () => {
const result = resolver.resolve(dagNodes['0/0/0/c'], '0/a')
expect(CID.isCID(result.value)).to.be.false()
expect(typeof result.value === 'object').to.be.true()
})
it('resolves "0/a/0" to correct type', () => {
const result = resolver.resolve(dagNodes['0/0/0/c'], '0/a/0')
expect(CID.isCID(result.value)).to.be.false()
expect(typeof result.value === 'object').to.be.true()
})
it('resolves "0/a/0/0" to correct type', () => {
const result = resolver.resolve(dagNodes['0/0/0/c'], '0/a/0/0')
expect(CID.isCID(result.value)).to.be.false()
expect(typeof result.value === 'object').to.be.true()
})
// Only testing `storage` here as the rest of the properties is already
// tested by the eth-account-snapshot tests
it('resolves "0/a/0/0/storage" to correct type', () => {
const result = resolver.resolve(dagNodes['0/0/0/c'], '0/a/0/0/storage')
expect(CID.isCID(result.value)).to.be.true()
})
})
describe('resolver.tree', () => {
it('"c" branch node lists account paths', (done) => {
let cBranchNode = dagNodes['0/0/0/c']
resolver.tree(cBranchNode, (err, childPaths) => {
expect(err).to.not.exist()
expect(Array.isArray(childPaths)).to.eql(true)
childPaths.forEach((path) =>{
expect(typeof path).to.eql('string')
})
expect(childPaths.length).to.eql(9)
expect(childPaths).to.contain('0/a/0/0/balance')
done()
})
it('"c" branch node lists account paths', () => {
const cBranchNode = dagNodes['0/0/0/c']
const tree = resolver.tree(cBranchNode)
const paths = [...tree]
expect(paths).to.have.members([
'0',
'0/a',
'0/a/0',
'0/a/0/0',
'0/a/0/0/storage',
'0/a/0/0/code',
'0/a/0/0/stateRoot',
'0/a/0/0/codeHash',
'0/a/0/0/nonce',
'0/a/0/0/balance',
'0/a/0/0/isEmpty',
'0/a/0/0/isContract'
])
})

@@ -164,24 +153,15 @@ })

function dumpTrieNonInlineNodes (trie, fullNodes, cb) {
trie._findDbNodes((nodeRef, node, key, next) => {
fullNodes[nibbleToPath(key)] = node
next()
}, cb)
}
function logTrie (trie, cb) {
trie._walkTrie(trie.root, (nodeRef, node, key, walkController) => {
console.log('node:', nibbleToPath(key), node.type, TrieNode.isRawNode(nodeRef) ? 'raw':'hashed', 'ref:'+cidFromHash('eth-state-trie', nodeRef).toBaseEncodedString())
var children = node.getChildren()
if (node.type === 'leaf') {
console.log(' + value')
}
children.forEach((childData, index) => {
var keyExtension = childData[0]
var childRef = childData[1]
console.log(' -', nibbleToPath(keyExtension), TrieNode.isRawNode(childRef) ? 'raw':'hashed', 'ref:'+cidFromHash('eth-state-trie', childRef).toBaseEncodedString())
function dumpTrieNonInlineNodes (trie) {
const fullNodes = {}
return new Promise((resolve, reject) => {
trie._findDbNodes((nodeRef, node, key, next) => {
fullNodes[nibbleToPath(key)] = node
next()
}, (err) => {
if (err) {
return reject(err)
}
return resolve(fullNodes)
})
walkController.next()
}, cb)
})
}

@@ -192,5 +172,1 @@

}
function contains (array, item) {
return array.indexOf(item) !== -1
}
'use strict'
/* eslint max-nested-callbacks: ["error", 5] */
const multicodec = require('multicodec')
const createTrieResolver = require('../util/createTrieResolver')
const ethStorageTrieResolver = createTrieResolver('eth-storage-trie')
const ethStorageTrieResolver = createTrieResolver(multicodec.ETH_STORAGE_TRIE)
module.exports = ethStorageTrieResolver
/* eslint-env mocha */
'use strict'
const expect = require('chai').expect
const async = require('async')
const chai = require('chai')
chai.use(require('dirty-chai'))
const expect = chai.expect
const CID = require('cids')
const Trie = require('merkle-patricia-tree')
const TrieNode = require('merkle-patricia-tree/trieNode')
const multicodec = require('multicodec')
const promisify = require('promisify-es6')
const ipldEthStateTrie = require('../index')
const isExternalLink = require('../../util/isExternalLink')
const resolver = ipldEthStateTrie.resolver

@@ -14,112 +16,137 @@

// setup test trie
let trie
let trieNodes = []
let dagNodes
before((done) => {
trie = new Trie()
async.waterfall([
(cb) => populateTrie(trie, cb),
(cb) => dumpTrieNonInlineNodes(trie, trieNodes, cb),
(cb) => async.map(trieNodes, ipldEthStateTrie.util.serialize, cb)
], (err, result) => {
if (err) return done(err)
dagNodes = result
done()
before(async () => {
const trie = await populateTrie()
const trieNodes = await dumpTrieNonInlineNodes(trie)
dagNodes = trieNodes.map((node) => {
return ipldEthStateTrie.util.serialize({ _ethObj: node })
})
})
function populateTrie (trie, cb) {
async.series([
(cb) => trie.put(new Buffer('000a0a00', 'hex'), new Buffer('cafe01', 'hex'), cb),
(cb) => trie.put(new Buffer('000a0a01', 'hex'), new Buffer('cafe02', 'hex'), cb),
(cb) => trie.put(new Buffer('000a0a02', 'hex'), new Buffer('cafe03', 'hex'), cb),
(cb) => trie.put(new Buffer('000a0b00', 'hex'), new Buffer('cafe04', 'hex'), cb),
(cb) => trie.put(new Buffer('000b0a00', 'hex'), new Buffer('cafe05', 'hex'), cb),
(cb) => trie.put(new Buffer('000b0b00', 'hex'), new Buffer('cafe06', 'hex'), cb),
(cb) => trie.put(new Buffer('000c0a00', 'hex'), new Buffer('cafe07', 'hex'), cb)
], (err) => {
if (err) return cb(err)
cb()
})
async function populateTrie () {
const trie = new Trie()
const put = promisify(trie.put.bind(trie))
await put(Buffer.from('000a0a00', 'hex'), Buffer.from('cafe01', 'hex'))
await put(Buffer.from('000a0a01', 'hex'), Buffer.from('cafe02', 'hex'))
await put(Buffer.from('000a0a02', 'hex'), Buffer.from('cafe03', 'hex'))
await put(Buffer.from('000a0b00', 'hex'), Buffer.from('cafe04', 'hex'))
await put(Buffer.from('000b0a00', 'hex'), Buffer.from('cafe05', 'hex'))
await put(Buffer.from('000b0b00', 'hex'), Buffer.from('cafe06', 'hex'))
await put(Buffer.from('000c0a00', 'hex'), Buffer.from('cafe07', 'hex'))
return trie
}
// function logTrie(cb){
// async.each(dagNodes, (node, next) => {
// let index = dagNodes.indexOf(node)
// let trieNode = trieNodes[index]
// resolver.tree(node, (err, paths) => {
// if (err) return next(err)
// let cidForHash = require('ipld-eth-trie/src/common').cidForHash
// let cid = cidForHash('eth-storage-trie', trieNode.hash())
// console.log(index, paths.map(path => path.path), cid.toBaseEncodedString())
// next()
// })
// }, cb)
// }
it('multicodec is eth-storage-trie', () => {
expect(resolver.multicodec).to.equal('eth-storage-trie')
expect(ipldEthStateTrie.codec).to.equal(multicodec.ETH_STORAGE_TRIE)
})
it('defaultHashAlg is keccak-256', () => {
expect(resolver.defaultHashAlg).to.equal('keccak-256')
expect(ipldEthStateTrie.defaultHashAlg).to.equal(multicodec.KECCAK_256)
})
describe('resolver.resolve', () => {
it('root node resolves to neck', (done) => {
let rootNode = dagNodes[0]
resolver.resolve(rootNode, '0/0/0/c/0/a/0/0/', (err, result) => {
expect(err).to.not.exist()
let trieNode = result.value
expect(result.remainderPath).to.eql('c/0/a/0/0/')
expect(isExternalLink(trieNode)).to.eql(true)
done()
})
it('root node resolves to neck', () => {
const rootNode = dagNodes[0]
const result = resolver.resolve(rootNode, '0/0/0/c/0/a/0/0/')
const trieNode = result.value
expect(result.remainderPath).to.eql('c/0/a/0/0')
expect(CID.isCID(trieNode)).to.be.true()
})
it('neck node resolves "c" down to buffer', (done) => {
let node = dagNodes[1]
resolver.resolve(node, 'c/0/a/0/0/', (err, result) => {
expect(err).to.not.exist()
let trieNode = result.value
expect(result.remainderPath).to.eql('')
expect(isExternalLink(trieNode)).to.eql(false)
expect(Buffer.isBuffer(result.value)).to.eql(true)
done()
})
it('neck node resolves "c" down to buffer', () => {
const node = dagNodes[1]
const result = resolver.resolve(node, 'c/0/a/0/0/')
const trieNode = result.value
expect(result.remainderPath).to.eql('')
expect(CID.isCID(trieNode)).to.be.false()
expect(Buffer.isBuffer(result.value)).to.be.true()
})
it('neck node resolves "b" down to branch', (done) => {
let node = dagNodes[1]
resolver.resolve(node, 'b/0/a/0/0/', (err, result) => {
expect(err).to.not.exist()
let trieNode = result.value
expect(result.remainderPath).to.eql('0/a/0/0/')
expect(isExternalLink(trieNode)).to.eql(true)
done()
})
it('neck node resolves "b" down to branch', () => {
const node = dagNodes[1]
const result = resolver.resolve(node, 'b/0/a/0/0/')
const trieNode = result.value
expect(result.remainderPath).to.eql('0/a/0/0')
expect(CID.isCID(trieNode)).to.be.true()
})
it('neck node resolves "a" down to branch', (done) => {
let node = dagNodes[1]
resolver.resolve(node, 'a/0/a/0/0/', (err, result) => {
expect(err).to.not.exist()
let trieNode = result.value
expect(result.remainderPath).to.eql('0/a/0/0/')
expect(isExternalLink(trieNode)).to.eql(true)
done()
})
it('neck node resolves "a" down to branch', () => {
const node = dagNodes[1]
const result = resolver.resolve(node, 'a/0/a/0/0/')
const trieNode = result.value
expect(result.remainderPath).to.eql('0/a/0/0')
expect(CID.isCID(trieNode)).to.be.true()
})
it('resolves "a" to correct type', () => {
const result = resolver.resolve(dagNodes[1], 'a')
expect(CID.isCID(result.value)).to.be.true()
})
it('resolves "b" to correct type', () => {
const result = resolver.resolve(dagNodes[1], 'b')
expect(CID.isCID(result.value)).to.be.true()
})
it('resolves "c" to correct type', () => {
const result = resolver.resolve(dagNodes[1], 'c')
expect(CID.isCID(result.value)).to.be.false()
expect(typeof result.value === 'object').to.be.true()
})
it('resolves "c/0" to correct type', () => {
const result = resolver.resolve(dagNodes[1], 'c/0')
expect(CID.isCID(result.value)).to.be.false()
expect(typeof result.value === 'object').to.be.true()
})
it('resolves "c/0/a" to correct type', () => {
const result = resolver.resolve(dagNodes[1], 'c/0/a')
expect(CID.isCID(result.value)).to.be.false()
expect(typeof result.value === 'object').to.be.true()
})
it('resolves "c/0/a/0" to correct type', () => {
const result = resolver.resolve(dagNodes[1], 'c/0/a/0')
expect(CID.isCID(result.value)).to.be.false()
expect(typeof result.value === 'object').to.be.true()
})
it('resolves "c/0/a/0/0" to correct type', () => {
const result = resolver.resolve(dagNodes[1], 'c/0/a/0/0')
expect(CID.isCID(result.value)).to.be.false()
expect(typeof result.value === 'object').to.be.true()
})
})
describe('resolver.tree', () => {
it('returns all uncles', () => {
const tree = resolver.tree(dagNodes[1])
const paths = [...tree]
expect(paths).to.have.members([
'a',
'b',
'c',
'c/0',
'c/0/a',
'c/0/a/0',
'c/0/a/0/0'
])
})
})
})
function dumpTrieNonInlineNodes (trie, fullNodes, cb) {
trie._findDbNodes((nodeRef, node, key, next) => {
fullNodes.push(node)
next()
}, cb)
function dumpTrieNonInlineNodes (trie) {
const fullNodes = []
return new Promise((resolve, reject) => {
trie._findDbNodes((nodeRef, node, key, next) => {
fullNodes.push(node)
next()
}, (err) => {
if (err) {
return reject(err)
}
return resolve(fullNodes)
})
})
}
function contains (array, item) {
return array.indexOf(item) !== -1
}
'use strict'
/* eslint max-nested-callbacks: ["error", 5] */
const multicodec = require('multicodec')

@@ -7,4 +7,5 @@ const ethTxResolver = require('../eth-tx')

const ethTxTrieResolver = createTrieResolver('eth-tx-trie', ethTxResolver)
const ethTxTrieResolver = createTrieResolver(
multicodec.ETH_TX_TRIE, ethTxResolver)
module.exports = ethTxTrieResolver
/* eslint-env mocha */
'use strict'
const expect = require('chai').expect
const async = require('async')
const chai = require('chai')
chai.use(require('dirty-chai'))
const expect = chai.expect
const CID = require('cids')
const EthBlock = require('ethereumjs-block')
const EthTx = require('ethereumjs-tx')
const Trie = require('merkle-patricia-tree')
const ipldEthStateTrie = require('../index')
const isExternalLink = require('../../util/isExternalLink')
const resolver = ipldEthStateTrie.resolver
const multicodec = require('multicodec')
const promisify = require('promisify-es6')
const ipldEthTxTrie = require('../index')
const resolver = ipldEthTxTrie.resolver

@@ -16,19 +18,12 @@ describe('IPLD format resolver (local)', () => {

let ethBlock
let trie
let trieNodes = []
let dagNodes
before((done) => {
trie = new Trie()
async.waterfall([
(cb) => populateTrie(cb),
(cb) => dumpTrieDbNodes(trie, trieNodes, cb),
(cb) => async.map(trieNodes, ipldEthStateTrie.util.serialize, cb)
], (err, result) => {
if (err) return done(err)
dagNodes = result
done()
before(async () => {
const trie = await populateTrie()
const trieNodes = await dumpTrieDbNodes(trie)
dagNodes = trieNodes.map((node) => {
return ipldEthTxTrie.util.serialize({ _ethObj: node })
})
})
function populateTrie (cb) {
async function populateTrie () {
ethBlock = new EthBlock()

@@ -38,100 +33,102 @@ // taken from block 0xc596cb892b649b4917da8c6b78611346d55daf7bcf4375da86a2d98810888e84

new EthTx({
to: new Buffer('0c7c0b72004a7a66ffa780637427fed0c4faac47', 'hex'),
from: new Buffer('41959417325160f8952bc933ae8317b4e5140dda', 'hex'),
gas: new Buffer('5e1b', 'hex'),
gasPrice: new Buffer('098bca5a00', 'hex'),
to: Buffer.from('0c7c0b72004a7a66ffa780637427fed0c4faac47', 'hex'),
from: Buffer.from('41959417325160f8952bc933ae8317b4e5140dda', 'hex'),
gas: Buffer.from('5e1b', 'hex'),
gasPrice: Buffer.from('098bca5a00', 'hex'),
input: null,
nonce: new Buffer('00', 'hex'),
value: new Buffer('44004c09e76a0000', 'hex'),
r: new Buffer('7150d00a9dcd8a8287ad220010c52ff2608906b746de23c993999768091ff210', 'hex'),
s: new Buffer('5585fabcd1dc415e1668d4cbc2d419cf0381bf9707480ad2f86d0800732f6d7e', 'hex'),
v: new Buffer('1b', 'hex')
nonce: Buffer.from('00', 'hex'),
value: Buffer.from('44004c09e76a0000', 'hex'),
r: Buffer.from('7150d00a9dcd8a8287ad220010c52ff2608906b746de23c993999768091ff210', 'hex'),
s: Buffer.from('5585fabcd1dc415e1668d4cbc2d419cf0381bf9707480ad2f86d0800732f6d7e', 'hex'),
v: Buffer.from('1b', 'hex')
}),
new EthTx({
to: new Buffer('f4702bb51b8270729db362b0d4f82a56bdd66c65', 'hex'),
from: new Buffer('56ce1399be2831f8a3f918a0408c05bbad658ef3', 'hex'),
gas: new Buffer('5208', 'hex'),
gasPrice: new Buffer('04e3b29200', 'hex'),
to: Buffer.from('f4702bb51b8270729db362b0d4f82a56bdd66c65', 'hex'),
from: Buffer.from('56ce1399be2831f8a3f918a0408c05bbad658ef3', 'hex'),
gas: Buffer.from('5208', 'hex'),
gasPrice: Buffer.from('04e3b29200', 'hex'),
input: null,
nonce: new Buffer('9d', 'hex'),
value: new Buffer('120a871cc0020000', 'hex'),
r: new Buffer('5d92c10b5789801d4ce0fc558eedc6e6cccbaf0105a7c1f909feabcedfe56cd9', 'hex'),
s: new Buffer('72cc370fa5fd3b43c2ba4e9e70fea1b5e950b4261ab4274982d8ae15a3403a33', 'hex'),
v: new Buffer('1b', 'hex')
nonce: Buffer.from('9d', 'hex'),
value: Buffer.from('120a871cc0020000', 'hex'),
r: Buffer.from('5d92c10b5789801d4ce0fc558eedc6e6cccbaf0105a7c1f909feabcedfe56cd9', 'hex'),
s: Buffer.from('72cc370fa5fd3b43c2ba4e9e70fea1b5e950b4261ab4274982d8ae15a3403a33', 'hex'),
v: Buffer.from('1b', 'hex')
}),
new EthTx({
to: new Buffer('b8201140a49b0d5b65a23b4b2fa8a6efff87c576', 'hex'),
from: new Buffer('1e9939daaad6924ad004c2560e90804164900341', 'hex'),
gas: new Buffer('9858', 'hex'),
gasPrice: new Buffer('04a817c800', 'hex'),
to: Buffer.from('b8201140a49b0d5b65a23b4b2fa8a6efff87c576', 'hex'),
from: Buffer.from('1e9939daaad6924ad004c2560e90804164900341', 'hex'),
gas: Buffer.from('9858', 'hex'),
gasPrice: Buffer.from('04a817c800', 'hex'),
input: null,
nonce: new Buffer('022f5d', 'hex'),
value: new Buffer('0de4ea09ac8f1e88', 'hex'),
r: new Buffer('7ee15b226f6c767ccace78a4b5b4cbf0be6ec20a899e058d3c95977bacd0cbd5', 'hex'),
s: new Buffer('27e75bcd3bfd199e8c3e3f0c90b0d39f01b773b3da64060e06c0d568ae5c7523', 'hex'),
v: new Buffer('1b', 'hex')
nonce: Buffer.from('022f5d', 'hex'),
value: Buffer.from('0de4ea09ac8f1e88', 'hex'),
r: Buffer.from('7ee15b226f6c767ccace78a4b5b4cbf0be6ec20a899e058d3c95977bacd0cbd5', 'hex'),
s: Buffer.from('27e75bcd3bfd199e8c3e3f0c90b0d39f01b773b3da64060e06c0d568ae5c7523', 'hex'),
v: Buffer.from('1b', 'hex')
}),
new EthTx({
to: new Buffer('c4f381af25c41786110242623373cc9c7647f3f1', 'hex'),
from: new Buffer('ea674fdde714fd979de3edf0f56aa9716b898ec8', 'hex'),
gas: new Buffer('015f90', 'hex'),
gasPrice: new Buffer('04a817c800', 'hex'),
to: Buffer.from('c4f381af25c41786110242623373cc9c7647f3f1', 'hex'),
from: Buffer.from('ea674fdde714fd979de3edf0f56aa9716b898ec8', 'hex'),
gas: Buffer.from('015f90', 'hex'),
gasPrice: Buffer.from('04a817c800', 'hex'),
input: null,
nonce: new Buffer('0fc02d', 'hex'),
value: new Buffer('0e139507cd50c018', 'hex'),
r: new Buffer('059934eeace580cc2bdc292415976692c751f0bcb025930bd40fcc31e91208f3', 'hex'),
s: new Buffer('77ff34a10a3de0d906a0363b4bdbc0e9a06cb4378476d96dfd446225d8d9949c', 'hex'),
v: new Buffer('1c', 'hex')
nonce: Buffer.from('0fc02d', 'hex'),
value: Buffer.from('0e139507cd50c018', 'hex'),
r: Buffer.from('059934eeace580cc2bdc292415976692c751f0bcb025930bd40fcc31e91208f3', 'hex'),
s: Buffer.from('77ff34a10a3de0d906a0363b4bdbc0e9a06cb4378476d96dfd446225d8d9949c', 'hex'),
v: Buffer.from('1c', 'hex')
})
]
ethBlock.genTxTrie((err) => {
if (err) return cb(err)
trie = ethBlock.txTrie
cb()
})
await promisify(ethBlock.genTxTrie.bind(ethBlock))()
return ethBlock.txTrie
}
it('multicodec is eth-tx-trie', () => {
expect(resolver.multicodec).to.equal('eth-tx-trie')
expect(ipldEthTxTrie.codec).to.equal(multicodec.ETH_TX_TRIE)
})
it('defaultHashAlg is keccak-256', () => {
expect(resolver.defaultHashAlg).to.equal('keccak-256')
expect(ipldEthTxTrie.defaultHashAlg).to.equal(multicodec.KECCAK_256)
})
describe('resolver.resolve', () => {
it('root node resolving first tx value', (done) => {
let rootNode = dagNodes[0]
resolver.resolve(rootNode, '8/0/value', (err, result) => {
expect(err).to.not.exist()
let trieNode = result.value
expect(result.remainderPath).to.eql('0/value')
expect(isExternalLink(trieNode)).to.eql(true)
done()
})
it('root node resolving first tx value', () => {
const rootNode = dagNodes[0]
const result = resolver.resolve(rootNode, '8/0/value')
const trieNode = result.value
expect(result.remainderPath).to.eql('0/value')
expect(CID.isCID(trieNode)).to.be.true()
})
it('"8" branch node resolves down to tx value', (done) => {
let branchNode = dagNodes[2]
resolver.resolve(branchNode, '0/value', (err, result) => {
expect(err).to.not.exist()
let trieNode = result.value
expect(result.remainderPath).to.eql('')
expect(isExternalLink(trieNode)).to.eql(false)
expect(Buffer.isBuffer(result.value)).to.eql(true)
let firstTx = ethBlock.transactions[0]
expect(result.value.toString('hex')).to.eql(firstTx.value.toString('hex'))
done()
})
it('"8" branch node resolves down to tx value', () => {
const branchNode = dagNodes[2]
const result = resolver.resolve(branchNode, '0/value')
const trieNode = result.value
expect(result.remainderPath).to.eql('')
expect(CID.isCID(trieNode)).to.be.false()
expect(Buffer.isBuffer(result.value)).to.be.true()
const firstTx = ethBlock.transactions[0]
expect(result.value.toString('hex')).to.eql(firstTx.value.toString('hex'))
})
it('resolves "0" to correct type', () => {
const result = resolver.resolve(dagNodes[0], '0')
expect(CID.isCID(result.value)).to.be.true()
})
it('resolves "8" to correct type', () => {
const result = resolver.resolve(dagNodes[0], '0')
expect(CID.isCID(result.value)).to.be.true()
})
})
describe('resolver.tree', () => {
it('root has two children', (done) => {
let rootNode = dagNodes[0]
resolver.tree(rootNode, {}, (err, result) => {
expect(err).to.not.exist()
expect(result.length).to.eql(2)
done()
})
it('root has two children', () => {
const rootNode = dagNodes[0]
const tree = resolver.tree(rootNode)
const paths = [...tree]
expect(paths).to.have.members([
'0',
'8'
])
})

@@ -141,7 +138,15 @@ })

function dumpTrieDbNodes (trie, fullNodes, cb) {
trie._findDbNodes((root, node, key, next) => {
fullNodes.push(node)
next()
}, cb)
function dumpTrieDbNodes (trie) {
const fullNodes = []
return new Promise((resolve, reject) => {
trie._findDbNodes((root, node, key, next) => {
fullNodes.push(node)
next()
}, (err) => {
if (err) {
return reject(err)
}
return resolve(fullNodes)
})
})
}
'use strict'
const EthTx = require('ethereumjs-tx')
const createResolver = require('../util/createResolver')
const multicodec = require('multicodec')
module.exports = createResolver('eth-tx', EthTx, mapFromEthObj)
const deserialize = (serialized) => {
const ethObj = new EthTx(serialized)
const deserialized = {
data: ethObj.data,
fromAddress: ethObj.from,
gasLimit: ethObj.gasLimit,
gasPrice: ethObj.gasPrice,
isContractPublish: ethObj.toCreationAddress(),
nonce: ethObj.nonce,
r: ethObj.r,
s: ethObj.s,
signature: [ethObj.v, ethObj.r, ethObj.s],
toAddress: ethObj.to,
v: ethObj.v,
value: ethObj.value,
_ethObj: ethObj
}
function mapFromEthObj (tx, options, callback) {
const paths = []
Object.defineProperty(deserialized, '_ethObj', { enumerable: false })
// external links (none)
return deserialized
}
// external links as data (none)
// internal data
paths.push({
path: 'nonce',
value: tx.nonce
})
paths.push({
path: 'gasPrice',
value: tx.gasPrice
})
paths.push({
path: 'gasLimit',
value: tx.gasLimit
})
paths.push({
path: 'toAddress',
value: tx.to
})
paths.push({
path: 'value',
value: tx.value
})
paths.push({
path: 'data',
value: tx.data
})
paths.push({
path: 'v',
value: tx.v
})
paths.push({
path: 'r',
value: tx.r
})
paths.push({
path: 's',
value: tx.s
})
// helpers
paths.push({
path: 'fromAddress',
value: tx.from
})
paths.push({
path: 'signature',
value: [tx.v, tx.r, tx.s]
})
paths.push({
path: 'isContractPublish',
value: tx.toCreationAddress()
})
callback(null, paths)
}
module.exports = createResolver(multicodec.ETH_TX, deserialize)
/* eslint-env mocha */
'use strict'
const expect = require('chai').expect
const chai = require('chai')
chai.use(require('dirty-chai'))
const expect = chai.expect
const Transaction = require('ethereumjs-tx')
const dagEthBlock = require('../index')
const resolver = dagEthBlock.resolver
const util = dagEthBlock.util
const dagEthTx = require('../index')
const resolver = dagEthTx.resolver
const util = dagEthTx.util
const multihash = require('multihashes')
const multicodec = require('multicodec')
describe('IPLD format resolver (local)', () => {
let testIpfsBlob
let testData = {
nonce: new Buffer('01', 'hex'),
gasPrice: new Buffer('04a817c800', 'hex'),
gasLimit: new Buffer('061a80', 'hex'),
to: new Buffer('0731729bb6624343958d05be7b1d9257a8e802e7', 'hex'),
value: new Buffer('1234', 'hex'),
const testData = {
nonce: Buffer.from('01', 'hex'),
gasPrice: Buffer.from('04a817c800', 'hex'),
gasLimit: Buffer.from('061a80', 'hex'),
to: Buffer.from('0731729bb6624343958d05be7b1d9257a8e802e7', 'hex'),
value: Buffer.from('1234', 'hex'),
// signature
v: new Buffer('1c', 'hex'),
r: new Buffer('33752a492fb77aca190ba9ba356bb8c9ad22d9aaa82c10bc8fc8ccca70da1985', 'hex'),
s: new Buffer('6ee2a50ec62e958fa2c9e214dae7de8ab4ab9a951b621a9deb04bb1bb37dd20f', 'hex')
v: Buffer.from('1c', 'hex'),
r: Buffer.from('33752a492fb77aca190ba9ba356bb8c9ad22d9aaa82c10bc8fc8ccca70da1985', 'hex'),
s: Buffer.from('6ee2a50ec62e958fa2c9e214dae7de8ab4ab9a951b621a9deb04bb1bb37dd20f', 'hex')
}
before((done) => {
const testTx = new Transaction(testData)
dagEthBlock.util.serialize(testTx, (err, result) => {
if (err) return done(err)
testIpfsBlob = result
done()
})
const testTx = new Transaction(testData)
const testTxBlob = dagEthTx.util.serialize({
_ethObj: testTx
})
it('multicodec is eth-tx', () => {
expect(resolver.multicodec).to.equal('eth-tx')
expect(dagEthTx.codec).to.equal(multicodec.ETH_TX)
})
it('defaultHashAlg is keccak-256', () => {
expect(resolver.defaultHashAlg).to.equal('keccak-256')
expect(dagEthTx.defaultHashAlg).to.equal(multicodec.KECCAK_256)
})

@@ -44,60 +41,134 @@

it('path within scope', () => {
resolver.resolve(testIpfsBlob, 'nonce', (err, result) => {
expect(err).to.not.exist()
expect(result.value.toString('hex')).to.equal(testData.nonce.toString('hex'))
// expect(result.value).to.equal(testData.nonce.toString('hex'))
})
const result = resolver.resolve(testTxBlob, 'nonce')
expect(result.value).to.eql(testData.nonce)
})
})
describe('resolver.resolve', () => {
it('resolver.tree', () => {
resolver.tree(testIpfsBlob, (err, paths) => {
expect(err).to.not.exist()
expect(typeof paths).to.eql('object')
// expect(Array.isArray(paths)).to.eql(true)
})
it('resolves "nonce" to correct type', () => {
const result = resolver.resolve(testTxBlob, 'nonce')
expect(Buffer.isBuffer(result.value)).to.be.true()
})
it('resolves "gasPrice" to correct type', () => {
const result = resolver.resolve(testTxBlob, 'gasPrice')
expect(Buffer.isBuffer(result.value)).to.be.true()
})
it('resolves "gasLimit" to correct type', () => {
const result = resolver.resolve(testTxBlob, 'gasLimit')
expect(Buffer.isBuffer(result.value)).to.be.true()
})
it('resolves "toAddress" to correct type', () => {
const result = resolver.resolve(testTxBlob, 'toAddress')
expect(Buffer.isBuffer(result.value)).to.be.true()
})
it('resolves "value" to correct type', () => {
const result = resolver.resolve(testTxBlob, 'value')
expect(Buffer.isBuffer(result.value)).to.be.true()
})
it('resolves "data" to correct type', () => {
const result = resolver.resolve(testTxBlob, 'data')
expect(Buffer.isBuffer(result.value)).to.be.true()
})
it('resolves "v" to correct type', () => {
const result = resolver.resolve(testTxBlob, 'v')
expect(Buffer.isBuffer(result.value)).to.be.true()
})
it('resolves "r" to correct type', () => {
const result = resolver.resolve(testTxBlob, 'r')
expect(Buffer.isBuffer(result.value)).to.be.true()
})
it('resolves "s" to correct type', () => {
const result = resolver.resolve(testTxBlob, 's')
expect(Buffer.isBuffer(result.value)).to.be.true()
})
it('resolves "fromAddress" to correct type', () => {
const result = resolver.resolve(testTxBlob, 'fromAddress')
expect(Buffer.isBuffer(result.value)).to.be.true()
})
it('resolves "signature" to correct type', () => {
const result = resolver.resolve(testTxBlob, 'signature')
expect(Array.isArray(result.value)).to.be.true()
})
it('resolves "signature/0" to correct type', () => {
const result = resolver.resolve(testTxBlob, 'signature/0')
expect(Buffer.isBuffer(result.value)).to.be.true()
})
it('resolves "signature/1" to correct type', () => {
const result = resolver.resolve(testTxBlob, 'signature/1')
expect(Buffer.isBuffer(result.value)).to.be.true()
})
it('resolves "signature/2" to correct type', () => {
const result = resolver.resolve(testTxBlob, 'signature/2')
expect(Buffer.isBuffer(result.value)).to.be.true()
})
it('resolves "isContractPublish" to correct type', () => {
const result = resolver.resolve(testTxBlob, 'isContractPublish')
expect(typeof result.value).to.equal('boolean')
})
})
it('resolver.tree', () => {
const tree = resolver.tree(testTxBlob)
const paths = [...tree]
expect(paths).to.have.members([
'nonce',
'gasPrice',
'gasLimit',
'toAddress',
'value',
'data',
'v',
'r',
's',
'fromAddress',
'signature',
'signature/0',
'signature/1',
'signature/2',
'isContractPublish'
])
})
describe('util', () => {
it('create CID, no options', (done) => {
const testTx = new Transaction(testData)
util.cid(testTx, (err, cid) => {
expect(err).to.not.exist()
expect(cid.version).to.equal(1)
expect(cid.codec).to.equal('eth-tx')
expect(cid.multihash).to.exist()
const mh = multihash.decode(cid.multihash)
expect(mh.name).to.equal('keccak-256')
done()
})
it('create CID, no options', async () => {
const cid = await util.cid(testTxBlob)
expect(cid.version).to.equal(1)
expect(cid.codec).to.equal('eth-tx')
expect(cid.multihash).to.exist()
const mh = multihash.decode(cid.multihash)
expect(mh.name).to.equal('keccak-256')
})
it('create CID, empty options', (done) => {
const testTx = new Transaction(testData)
util.cid(testTx, {}, (err, cid) => {
expect(err).to.not.exist()
expect(cid.version).to.equal(1)
expect(cid.codec).to.equal('eth-tx')
expect(cid.multihash).to.exist()
const mh = multihash.decode(cid.multihash)
expect(mh.name).to.equal('keccak-256')
done()
})
})
it('create CID, empty options', async () => {
const cid = await util.cid(testTxBlob, {})
expect(cid.version).to.equal(1)
expect(cid.codec).to.equal('eth-tx')
expect(cid.multihash).to.exist()
const mh = multihash.decode(cid.multihash)
expect(mh.name).to.equal('keccak-256')
})
it('create CID, hashAlg', (done) => {
const testTx = new Transaction(testData)
util.cid(testTx, { hashAlg: 'keccak-512' }, (err, cid) => {
expect(err).to.not.exist()
expect(cid.version).to.equal(1)
expect(cid.codec).to.equal('eth-tx')
expect(cid.multihash).to.exist()
const mh = multihash.decode(cid.multihash)
expect(mh.name).to.equal('keccak-512')
done()
it('create CID, hashAlg', async () => {
const cid = await util.cid(testTxBlob, {
hashAlg: multicodec.KECCAK_512
})
})
expect(cid.version).to.equal(1)
expect(cid.codec).to.equal('eth-tx')
expect(cid.multihash).to.exist()
const mh = multihash.decode(cid.multihash)
expect(mh.name).to.equal('keccak-512')
})
})
})
{
"name": "ipld-ethereum",
"version": "2.0.3",
"version": "3.0.0",
"description": "JavaScript Implementation of All Ethereum IPLD formats",

@@ -24,17 +24,17 @@ "leadMaintainer": "Volker Mische <volker.mische@gmail.com>",

"dependencies": {
"async": "^2.6.0",
"cids": "~0.5.2",
"cids": "~0.6.0",
"ethereumjs-account": "^2.0.4",
"ethereumjs-block": "^2.1.0",
"ethereumjs-tx": "^1.3.3",
"ipfs-block": "~0.8.0",
"merkle-patricia-tree": "^3.0.0",
"multicodec": "~0.5.0",
"multihashes": "~0.4.12",
"multihashing-async": "~0.5.1",
"multihashing-async": "~0.7.0",
"rlp": "^2.0.0"
},
"devDependencies": {
"aegir": "^18.0.2",
"aegir": "^18.2.0",
"chai": "^4.1.2",
"dirty-chai": "^2.0.1"
"dirty-chai": "^2.0.1",
"promisify-es6": "^1.0.3"
},

@@ -41,0 +41,0 @@ "contributors": [

@@ -5,3 +5,5 @@ # js-ipld-ethereum

[![](https://img.shields.io/badge/project-IPLD-blue.svg?style=flat-square)](http://github.com/ipld/ipld)
[![](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23ipfs) [![Greenkeeper badge](https://badges.greenkeeper.io/ipld/js-ipld-ethereum.svg)](https://greenkeeper.io/)
[![](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23ipfs)
[![Travis CI](https://flat.badgen.net/travis/ipld/js-ipld-ethereum)](https://travis-ci.com/ipld/js-ipld-ethereum)
[![Greenkeeper badge](https://badges.greenkeeper.io/ipld/js-ipld-ethereum.svg)](https://greenkeeper.io/)

@@ -8,0 +10,0 @@ > JavaScript Implementation of the IPLD format - Ethereum Block

@@ -5,2 +5,3 @@ 'use strict'

const multihashes = require('multihashes')
const multicodec = require('multicodec')

@@ -10,2 +11,4 @@ module.exports = cidFromHash

function cidFromHash (codec, rawhash, options) {
// `CID` expects a string for the multicodec
const codecName = multicodec.print[codec]
options = options || {}

@@ -15,3 +18,3 @@ const hashAlg = options.hashAlg || 'keccak-256'

const multihash = multihashes.encode(rawhash, hashAlg)
return new CID(version, codec, multihash)
return new CID(version, codecName, multihash)
}
'use strict'
const waterfall = require('async/waterfall')
const createIsLink = require('../util/createIsLink')
const CID = require('cids')
const multicodec = require('multicodec')
const createUtil = require('../util/createUtil')
module.exports = createResolver
const createResolver = (codec, deserialize) => {
const util = createUtil(codec, deserialize)
function createResolver (multicodec, EthObjClass, mapFromEthObject) {
const util = createUtil(multicodec, EthObjClass)
const resolver = {
multicodec: multicodec,
defaultHashAlg: 'keccak-256',
resolve: resolve,
tree: tree,
isLink: createIsLink(resolve),
_resolveFromEthObject: resolveFromEthObject,
_treeFromEthObject: treeFromEthObject,
_mapFromEthObject: mapFromEthObject
}
/**
* Resolves a path within a Ethereum block.
*
* Returns the value or a link and the partial mising path. This way the
* IPLD Resolver can fetch the link and continue to resolve.
*
* @param {Buffer} binaryBlob - Binary representation of a Ethereum block
* @param {string} [path='/'] - Path that should be resolved
* @returns {Object} result - Result of the path it it was resolved successfully
* @returns {*} result.value - Value the path resolves to
* @returns {string} result.remainderPath - If the path resolves half-way to a
* link, then the `remainderPath` is the part after the link that can be used
* for further resolving
*/
const resolve = (binaryBlob, path) => {
let node = util.deserialize(binaryBlob)
return {
resolver: resolver,
util: util,
}
const parts = path.split('/').filter((x) => x)
while (parts.length) {
const key = parts.shift()
if (node[key] === undefined) {
throw new Error(`Object has no property '${key}'`)
}
/*
* tree: returns a flattened array with paths: values of the project. options
* are option (i.e. nestness)
*/
node = node[key]
if (CID.isCID(node)) {
return {
value: node,
remainderPath: parts.join('/')
}
}
}
function tree (binaryBlob, options, callback) {
// parse arguments
if (typeof options === 'function') {
callback = options
options = undefined
return {
value: node,
remainderPath: ''
}
if (!options) {
options = {}
}
waterfall([
(cb) => util.deserialize(binaryBlob, cb),
(ethObj, cb) => treeFromEthObject(ethObj, options, cb)
], callback)
}
function treeFromEthObject (ethObj, options, callback) {
waterfall([
(cb) => mapFromEthObject(ethObj, options, cb),
(tuples, cb) => cb(null, tuples.map((tuple) => tuple.path))
], callback)
const _traverse = function * (node, path) {
// Traverse only objects and arrays
if (Buffer.isBuffer(node) || CID.isCID(node) || typeof node === 'string' ||
node === null) {
return
}
for (const item of Object.keys(node)) {
const nextpath = path === undefined ? item : path + '/' + item
yield nextpath
yield * _traverse(node[item], nextpath)
}
}
/*
* resolve: receives a path and a binary blob and returns the value on path,
* throw if not possible. `binaryBlob`` is an Ethereum binary block.
/**
* Return all available paths of a block.
*
* @generator
* @param {Buffer} binaryBlob - Binary representation of a Bitcoin block
* @yields {string} - A single path
*/
const tree = function * (binaryBlob) {
const node = util.deserialize(binaryBlob)
function resolve (binaryBlob, path, callback) {
waterfall([
(cb) => util.deserialize(binaryBlob, cb),
(ethObj, cb) => resolveFromEthObject(ethObj, path, cb)
], callback)
yield * _traverse(node)
}
function resolveFromEthObject (ethObj, path, callback) {
// root
if (!path || path === '/') {
const result = { value: ethObj, remainderPath: '' }
return callback(null, result)
}
// check tree results
mapFromEthObject(ethObj, {}, (err, paths) => {
if (err) return callback(err)
// parse path
const pathParts = path.split('/')
// find potential matches
let matches = paths.filter((child) => child.path === path.slice(0, child.path.length))
// only match whole path chunks
matches = matches.filter((child) => child.path.split('/').every((part, index) => part === pathParts[index]))
// take longest match
const sortedMatches = matches.sort((a, b) => b.path.length - a.path.length)
const treeResult = sortedMatches[0]
if (!treeResult) {
let err = new Error('Path not found ("' + path + '").')
return callback(err)
}
// slice off remaining path (after match and following slash)
const remainderPath = path.slice(treeResult.path.length + 1)
const result = {
value: treeResult.value,
remainderPath: remainderPath
}
return callback(null, result)
})
return {
codec: codec,
defaultHashAlg: multicodec.KECCAK_256,
resolver: {
resolve: resolve,
tree: tree,
},
util: util,
}
}
module.exports = createResolver
'use strict'
const each = require('async/each')
const waterfall = require('async/waterfall')
const asyncify = require('async/asyncify')
const rlp = require('rlp')
const EthTrieNode = require('merkle-patricia-tree/trieNode')
const cidFromHash = require('./cidFromHash')
// const createBaseTrieResolver = require('./createBaseTrieResolver.js')
const createResolver = require('./createResolver')
const isExternalLink = require('./isExternalLink')
const createUtil = require('./createUtil')
const createIsLink = require('./createIsLink')
const cidFromEthObj = require('./cidFromEthObj')
// A `nibble` is an array of nested keys. So for example `[2, 1, 3]` would
// mean an item with value `"foo"` would be in an object like this:
// {
// "2": {
// "1": {
// "3": "foo"
// }
// }
// }
// This function converts such a nibble together with a `value` into such an
// object. As we want to combine multiple nibbles into a single object, we
// also pass in a `target` object where the value should be stored in.
const addNibbleToObject = (target, nibble, value) => {
// Make a reference to the target object that can be changed in the course
// of the algorithm
let current = target
for (const [ii, entry] of nibble.entries()) {
// Get the key the value should be stored in
const key = entry.toString(16)
module.exports = createTrieResolver
if (ii + 1 < nibble.length) {
// We haven't reached the last item yet
// There is no item with that key yet
if (!(key in current)) {
current[key] = {}
}
// Keep traversing deeper
current = current[key]
} else {
// Else we've reached the last item, hence adding the actual value
current[key] = value
return
}
}
}
function createTrieResolver(multicodec, leafResolver){
const baseTrie = createResolver(multicodec, EthTrieNode, mapFromEthObj)
baseTrie.util.deserialize = asyncify((serialized) => {
const rawNode = rlp.decode(serialized)
const trieNode = new EthTrieNode(rawNode)
return trieNode
})
const getLeafValue = (trieNode, leafResolver) => {
let value = trieNode.getValue()
return baseTrie
if (leafResolver !== undefined) {
value = leafResolver.util.deserialize(value)
}
// create map using both baseTrie and leafResolver
function mapFromEthObj (trieNode, options, callback) {
// expand from merkle-patricia-tree using leafResolver
mapFromBaseTrie(trieNode, options, (err, basePaths) => {
if (err) return callback(err)
if (!leafResolver) return callback(null, basePaths)
// expand children
let paths = basePaths.slice()
const leafTerminatingPaths = basePaths.filter(child => Buffer.isBuffer(child.value))
each(leafTerminatingPaths, (child, cb) => {
return waterfall([
(cb) => leafResolver.util.deserialize(child.value, cb),
(ethObj, cb) => leafResolver.resolver._mapFromEthObject(ethObj, options, cb)
], (err, grandChildren) => {
if (err) return cb(err)
// add prefix to grandchildren
grandChildren.forEach((grandChild) => {
paths.push({
path: child.path + '/' + grandChild.path,
value: grandChild.value,
})
})
cb()
})
}, (err) => {
if (err) return callback(err)
callback(null, paths)
})
})
return value
}
// create map from merkle-patricia-tree nodes
const mapFromBaseTrie = (codec, finalNode, trieNode, leafResolver) => {
if (trieNode.type === 'leaf') {
const value = getLeafValue(trieNode, leafResolver)
addNibbleToObject(finalNode, trieNode.getKey(), value)
return
}
// create map from merkle-patricia-tree nodes
function mapFromBaseTrie (trieNode, options, callback) {
let paths = []
trieNode.getChildren().forEach(([nibble, value]) => {
let valueToAdd
if (EthTrieNode.isRawNode(value)) {
// inline child root
const childNode = new EthTrieNode(value)
if (trieNode.type === 'leaf') {
// leaf nodes resolve to their actual value
paths.push({
path: nibbleToPath(trieNode.getKey()),
value: trieNode.getValue()
})
if (childNode.type === 'leaf') {
// Make sure the object is nested correctly
nibble.push(...childNode.getKey())
valueToAdd = getLeafValue(childNode, leafResolver)
} else {
valueToAdd = childNode
}
} else {
// other nodes link by hash
valueToAdd = cidFromHash(codec, value)
}
addNibbleToObject(finalNode, nibble, valueToAdd)
})
}
each(trieNode.getChildren(), (childData, next) => {
const key = nibbleToPath(childData[0])
const value = childData[1]
if (EthTrieNode.isRawNode(value)) {
// inline child root
const childNode = new EthTrieNode(value)
paths.push({
path: key,
value: childNode
})
// inline child non-leaf subpaths
mapFromBaseTrie(childNode, options, (err, subtree) => {
if (err) return next(err)
subtree.forEach((path) => {
path.path = key + '/' + path.path
})
paths = paths.concat(subtree)
next()
})
} else {
// other nodes link by hash
let link = { '/': cidFromHash(multicodec, value).toBaseEncodedString() }
paths.push({
path: key,
value: link
})
next()
}
}, (err) => {
if (err) return callback(err)
callback(null, paths)
})
// The `createUtilResolver` expects a constructor with a single parameter,
// hence wrap it in a creator function so that we can pass in the needed
// context
const createCustomEthTrieNode = function (codec, leafResolver) {
return function (serialized) {
const rawNode = rlp.decode(serialized)
const trieNode = new EthTrieNode(rawNode)
const finalNode = {}
mapFromBaseTrie(codec, finalNode, trieNode, leafResolver)
return finalNode
}
}
function nibbleToPath (data) {
return data.map((num) => num.toString(16)).join('/')
const createTrieResolver = (codec, leafResolver) => {
const customEthTrieNode = createCustomEthTrieNode(codec, leafResolver)
const baseTrie = createResolver(codec, customEthTrieNode)
return baseTrie
}
module.exports = createTrieResolver

@@ -1,12 +0,45 @@

const cidFromEthObj = require('./cidFromEthObj')
const asyncify = require('async/asyncify')
const CID = require('cids')
const multicodec = require('multicodec')
const multihashing = require('multihashing-async')
module.exports = createUtil
const DEFAULT_HASH_ALG = multicodec.KECCAK_256
function createUtil (multicodec, EthObjClass) {
const createUtil = (codec, deserialize) => {
return {
deserialize: asyncify((serialized) => new EthObjClass(serialized)),
serialize: asyncify((ethObj) => ethObj.serialize()),
cid: asyncify((ethObj, options) => cidFromEthObj(multicodec, ethObj, options))
/**
* Deserialize Ethereum block into the internal representation.
*
* @param {Buffer} serialized - Binary representation of a Ethereum block.
* @returns {Object}
*/
deserialize,
/**
* Serialize internal representation into a binary Ethereum block.
*
* @param {Object} deserialized - Internal representation of a Bitcoin block
* @returns {Buffer}
*/
serialize: (deserialized) => deserialized._ethObj.serialize(),
/**
* Calculate the CID of the binary blob.
*
* @param {Object} binaryBlob - Encoded IPLD Node
* @param {Object} [userOptions] - Options to create the CID
* @param {number} [userOptions.cidVersion=1] - CID version number
* @param {string} [UserOptions.hashAlg] - Defaults to the defaultHashAlg of the format
* @returns {Promise.<CID>}
*/
cid: async (binaryBlob, userOptions) => {
const defaultOptions = { cidVersion: 1, hashAlg: DEFAULT_HASH_ALG}
const options = Object.assign(defaultOptions, userOptions)
const multihash = await multihashing(binaryBlob, options.hashAlg)
const codecName = multicodec.print[codec]
const cid = new CID(options.cidVersion, codecName, multihash)
return cid
}
}
}
module.exports = createUtil
// this is the hash of the empty code (SHA3_NULL)
module.exports = new Buffer('c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470', 'hex')
module.exports = Buffer.from('c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470', 'hex')

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc