Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update merkle-patricia-tree to v4, move account trie-related methods to StateManager #787

Merged
merged 1 commit into from
Jun 26, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
410 changes: 0 additions & 410 deletions packages/account/package-lock.json

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion packages/account/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@
"@types/bn.js": "^4.11.6",
"@types/node": "^11.13.4",
"@types/tape": "^4.13.0",
"merkle-patricia-tree": "^3.0.0",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

"nyc": "^14.0.0",
"prettier": "^2.0.5",
"tape": "^4.10.1",
Expand Down
149 changes: 6 additions & 143 deletions packages/account/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,7 @@
import * as rlp from 'rlp'

const ethUtil = require('ethereumjs-util')
import { KECCAK256_NULL, KECCAK256_NULL_S, KECCAK256_RLP, defineProperties } from 'ethereumjs-util'
const Buffer = require('safe-buffer').Buffer

interface TrieGetCb {
(err: any, value: Buffer | null): void
}
interface TriePutCb {
(err?: any): void
}

interface Trie {
root: Buffer
copy(): Trie
getRaw(key: Buffer, cb: TrieGetCb): void
putRaw(key: Buffer | string, value: Buffer, cb: TriePutCb): void
get(key: Buffer | string, cb: TrieGetCb): void
put(key: Buffer | string, value: Buffer | string, cb: TriePutCb): void
}

export default class Account {
/**
* The account's nonce.
Expand Down Expand Up @@ -80,160 +63,40 @@ export default class Account {
{
name: 'stateRoot',
length: 32,
default: ethUtil.KECCAK256_RLP,
default: KECCAK256_RLP,
},
{
name: 'codeHash',
length: 32,
default: ethUtil.KECCAK256_NULL,
default: KECCAK256_NULL,
},
]

ethUtil.defineProperties(this, fields, data)
defineProperties(this, fields, data)
}

/**
* Returns the RLP serialization of the account as a `Buffer`.
*
*/
serialize(): Buffer {
return rlp.encode([this.nonce, this.balance, this.stateRoot, this.codeHash])
}

/**
* Returns a `Boolean` deteremining if the account is a contract.
*
*/
isContract(): boolean {
return this.codeHash.toString('hex') !== ethUtil.KECCAK256_NULL_S
}

/**
* Fetches the code from the trie.
* @param trie The [trie](https://github.com/ethereumjs/merkle-patricia-tree) storing the accounts
* @param cb The callback
*/
getCode(trie: Trie, cb: TrieGetCb): void {
if (!this.isContract()) {
cb(null, Buffer.alloc(0))
return
}

trie.getRaw(this.codeHash, cb)
}

/**
* Stores the code in the trie.
*
* ~~~
* // Requires manual merkle-patricia-tree install
* const SecureTrie = require('merkle-patricia-tree/secure')
* const Account = require('./index.js').default
*
* let code = Buffer.from(
* '73095e7baea6a6c7c4c2dfeb977efac326af552d873173095e7baea6a6c7c4c2dfeb977efac326af552d873157',
* 'hex',
* )
*
* let raw = {
* nonce: '0x0',
* balance: '0x03e7',
* stateRoot: '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421',
* codeHash: '0xb30fb32201fe0486606ad451e1a61e2ae1748343cd3d411ed992ffcc0774edd4',
* }
* let account = new Account(raw)
* let trie = new SecureTrie()
*
* account.setCode(trie, code, function(err, codeHash) {
* console.log(`Code with hash 0x${codeHash.toString('hex')} set to trie`)
* account.getCode(trie, function(err, code) {
* console.log(`Code ${code.toString('hex')} read from trie`)
* })
* })
* ~~~
*
* @param trie The [trie](https://github.com/ethereumjs/merkle-patricia-tree) storing the accounts.
* @param {Buffer} code
* @param cb The callback.
*
*/
setCode(trie: Trie, code: Buffer, cb: (err: any, codeHash: Buffer) => void): void {
this.codeHash = ethUtil.keccak256(code)

if (this.codeHash.toString('hex') === ethUtil.KECCAK256_NULL_S) {
cb(null, Buffer.alloc(0))
return
}

trie.putRaw(this.codeHash, code, (err: any) => {
cb(err, this.codeHash)
})
}

/**
* Fetches `key` from the account's storage.
* @param trie
* @param key
* @param cb
*/
getStorage(trie: Trie, key: Buffer | string, cb: TrieGetCb) {
const t = trie.copy()
t.root = this.stateRoot
t.get(key, cb)
}

/**
* Stores a `val` at the `key` in the contract's storage.
*
* Example for `getStorage` and `setStorage`:
*
* ~~~
* // Requires manual merkle-patricia-tree install
* const SecureTrie = require('merkle-patricia-tree/secure')
* const Account = require('./index.js').default
*
* let raw = {
* nonce: '0x0',
* balance: '0x03e7',
* stateRoot: '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421',
* codeHash: '0xb30fb32201fe0486606ad451e1a61e2ae1748343cd3d411ed992ffcc0774edd4',
* }
* let account = new Account(raw)
* let trie = new SecureTrie()
* let key = Buffer.from('0000000000000000000000000000000000000000', 'hex')
* let value = Buffer.from('01', 'hex')
*
* account.setStorage(trie, key, value, function(err) {
* account.getStorage(trie, key, function(err, value) {
* console.log(`Value ${value.toString('hex')} set and retrieved from trie.`)
* })
* })
* ~~~
*
* @param trie
* @param key
* @param val
* @param cb
*/
setStorage(trie: Trie, key: Buffer | string, val: Buffer | string, cb: TriePutCb) {
const t = trie.copy()
t.root = this.stateRoot
t.put(key, val, (err: any) => {
if (err) return cb(err)
this.stateRoot = t.root
cb()
})
return this.codeHash.toString('hex') !== KECCAK256_NULL_S
}

/**
* Returns a `Boolean` determining if the account is empty.
*
*/
isEmpty(): boolean {
return (
this.balance.toString('hex') === '' &&
this.nonce.toString('hex') === '' &&
this.codeHash.toString('hex') === ethUtil.KECCAK256_NULL_S
this.codeHash.toString('hex') === KECCAK256_NULL_S
)
}
}
75 changes: 0 additions & 75 deletions packages/account/test/index.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import * as tape from 'tape'
import * as rlp from 'rlp'
import Account from '../src/index'
const SecureTrie = require('merkle-patricia-tree/secure')

tape('empty constructor', function (tester) {
const it = tester.test
Expand Down Expand Up @@ -132,80 +131,6 @@ tape('isContract', function (tester) {
})
})

tape('setCode && getCode', (tester) => {
const it = tester.test
it('should set and get code', (t) => {
const code = Buffer.from(
'73095e7baea6a6c7c4c2dfeb977efac326af552d873173095e7baea6a6c7c4c2dfeb977efac326af552d873157',
'hex',
)

const raw = {
nonce: '0x0',
balance: '0x03e7',
stateRoot: '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421',
codeHash: '0xb30fb32201fe0486606ad451e1a61e2ae1748343cd3d411ed992ffcc0774edd4',
}
const account = new Account(raw)
const trie = new SecureTrie()

account.setCode(trie, code, function (err, codeHash) {
account.getCode(trie, function (err, codeRetrieved) {
t.equals(Buffer.compare(code, codeRetrieved!), 0)
t.end()
})
})
})
it('should not get code if is not contract', (t) => {
const raw = {
nonce: '0x0',
balance: '0x03e7',
}
const account = new Account(raw)
const trie = new SecureTrie()
account.getCode(trie, function (err, code) {
t.equals(Buffer.compare(code!, Buffer.alloc(0)), 0)
t.end()
})
})
it('should set empty code', (t) => {
const raw = {
nonce: '0x0',
balance: '0x03e7',
}
const account = new Account(raw)
const trie = new SecureTrie()
const code = Buffer.alloc(0)
account.setCode(trie, code, function (err, codeHash) {
t.equals(Buffer.compare(codeHash, Buffer.alloc(0)), 0)
t.end()
})
})
})

tape('setStorage && getStorage', (tester) => {
const it = tester.test
it('should set and get storage', (t) => {
const raw = {
nonce: '0x0',
balance: '0x03e7',
stateRoot: '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421',
codeHash: '0xb30fb32201fe0486606ad451e1a61e2ae1748343cd3d411ed992ffcc0774edd4',
}
const account = new Account(raw)
const trie = new SecureTrie()
const key = Buffer.from('0000000000000000000000000000000000000000', 'hex')
const value = Buffer.from('01', 'hex')

account.setStorage(trie, key, value, (err) => {
account.getStorage(trie, key, (err, valueRetrieved) => {
t.equals(Buffer.compare(value, valueRetrieved!), 0)
t.end()
})
})
})
})

tape('isEmpty', (tester) => {
const it = tester.test
it('should return true for an empty account', (t) => {
Expand Down
Loading