From 688d28d00fa6b5c426974e1006cdbca91e08dcc4 Mon Sep 17 00:00:00 2001 From: Matthew Dean Date: Wed, 7 Nov 2018 10:15:56 +0000 Subject: [PATCH] Make stateManager cache and trie private --- lib/stateManager.js | 56 ++++++++++++++++++--------------------- tests/api/index.js | 10 +++---- tests/api/runBlock.js | 8 +++--- tests/api/stateManager.js | 6 ++--- 4 files changed, 38 insertions(+), 42 deletions(-) diff --git a/lib/stateManager.js b/lib/stateManager.js index f606d80a4b..833eb046e6 100644 --- a/lib/stateManager.js +++ b/lib/stateManager.js @@ -14,16 +14,15 @@ module.exports = StateManager function StateManager (opts = {}) { var self = this - self.trie = opts.trie || new Trie() - var common = opts.common if (!common) { common = new Common('mainnet', 'byzantium') } self._common = common + self._trie = opts.trie || new Trie() self._storageTries = {} // the storage trie cache - self.cache = new Cache(self.trie) + self._cache = new Cache(self._trie) self._touched = new Set() self._touchedStack = [] self._checkpointCount = 0 @@ -32,13 +31,13 @@ function StateManager (opts = {}) { var proto = StateManager.prototype proto.copy = function () { - return new StateManager({ trie: this.trie.copy() }) + return new StateManager({ trie: this._trie.copy() }) } // gets the account from the cache, or triggers a lookup and stores // the result in the cache proto.getAccount = function (address, cb) { - this.cache.getOrLoad(address, cb) + this._cache.getOrLoad(address, cb) } // saves the account @@ -47,9 +46,9 @@ proto.putAccount = function (address, account, cb) { // TODO: dont save newly created accounts that have no balance // if (toAccount.balance.toString('hex') === '00') { // if they have money or a non-zero nonce or code, then write to tree - self.cache.put(address, account) + self._cache.put(address, account) self._touched.add(address.toString('hex')) - // self.trie.put(addressHex, account.serialize(), cb) + // self._trie.put(addressHex, account.serialize(), cb) cb() } @@ -84,7 +83,7 @@ proto.putContractCode = function (address, value, cb) { return cb(err) } // TODO: setCode use trie.setRaw which creates a storage leak - account.setCode(self.trie, value, function (err) { + account.setCode(self._trie, value, function (err) { if (err) { return cb(err) } @@ -100,7 +99,7 @@ proto.getContractCode = function (address, cb) { if (err) { return cb(err) } - account.getCode(self.trie, cb) + account.getCode(self._trie, cb) }) } @@ -112,7 +111,7 @@ proto._lookupStorageTrie = function (address, cb) { if (err) { return cb(err) } - var storageTrie = self.trie.copy() + var storageTrie = self._trie.copy() storageTrie.root = account.stateRoot storageTrie._checkpoints = [] cb(null, storageTrie) @@ -161,7 +160,7 @@ proto._modifyContractStorage = function (address, modifyTrie, cb) { // update storage cache self._storageTries[address.toString('hex')] = storageTrie // update contract stateRoot - var contract = self.cache.get(address) + var contract = self._cache.get(address) contract.stateRoot = storageTrie.root self.putAccount(address, contract, cb) self._touched.add(address.toString('hex')) @@ -196,8 +195,8 @@ proto.clearContractStorage = function (address, cb) { // proto.checkpoint = function () { var self = this - self.trie.checkpoint() - self.cache.checkpoint() + self._trie.checkpoint() + self._cache.checkpoint() self._touchedStack.push(new Set([...self._touched])) self._checkpointCount++ } @@ -205,13 +204,13 @@ proto.checkpoint = function () { proto.commit = function (cb) { var self = this // setup trie checkpointing - self.trie.commit(function () { + self._trie.commit(function () { // setup cache checkpointing - self.cache.commit() + self._cache.commit() self._touchedStack.pop() self._checkpointCount-- - if (self._checkpointCount === 0) self.cache.flush(cb) + if (self._checkpointCount === 0) self._cache.flush(cb) else cb() }) } @@ -219,40 +218,37 @@ proto.commit = function (cb) { proto.revert = function (cb) { var self = this // setup trie checkpointing - self.trie.revert() + self._trie.revert() // setup cache checkpointing - self.cache.revert() + self._cache.revert() self._storageTries = {} self._touched = self._touchedStack.pop() self._checkpointCount-- - if (self._checkpointCount === 0) self.cache.flush(cb) + if (self._checkpointCount === 0) self._cache.flush(cb) else cb() } -// -// cache stuff -// proto.getStateRoot = function (cb) { var self = this - self.cache.flush(function (err) { + self._cache.flush(function (err) { if (err) { return cb(err) } - var stateRoot = self.trie.root + var stateRoot = self._trie.root cb(null, stateRoot) }) } proto.setStateRoot = function (stateRoot, cb) { var self = this - self.cache.flush(function (err) { + self._cache.flush(function (err) { if (err) { return cb(err) } - self.trie.checkRoot(stateRoot, function (err, hasRoot) { + self._trie.checkRoot(stateRoot, function (err, hasRoot) { if (err || !hasRoot) { cb(err || new Error('State trie does not contain state root')) } else { - self.trie.root = stateRoot + self._trie.root = stateRoot cb() } }) @@ -278,7 +274,7 @@ proto.dumpStorage = function (address, cb) { proto.hasGenesisState = function (cb) { const root = this._common.genesis().stateRoot - this.trie.checkRoot(root, cb) + this._trie.checkRoot(root, cb) } proto.generateCanonicalGenesis = function (cb) { @@ -300,7 +296,7 @@ proto.generateGenesis = function (initState, cb) { var account = new Account() account.balance = new BN(initState[address]).toArrayLike(Buffer) address = Buffer.from(address, 'hex') - self.trie.put(address, account.serialize(), done) + self._trie.put(address, account.serialize(), done) }, cb) } @@ -327,7 +323,7 @@ proto.cleanupTouchedAccounts = function (cb) { } if (empty) { - self.cache.del(address) + self._cache.del(address) } next(null) }) diff --git a/tests/api/index.js b/tests/api/index.js index 26e3e10921..1f569f234a 100644 --- a/tests/api/index.js +++ b/tests/api/index.js @@ -11,14 +11,14 @@ tape('VM with fake blockchain', (t) => { t.test('should insantiate without params', (st) => { const vm = new VM() st.ok(vm.stateManager) - st.deepEqual(vm.stateManager.trie.root, util.KECCAK256_RLP, 'it has default trie') + st.deepEqual(vm.stateManager._trie.root, util.KECCAK256_RLP, 'it has default trie') st.ok(vm.blockchain.fake, 'it has fake blockchain by default') st.end() }) t.test('should be able to activate precompiles', (st) => { let vm = new VM({ activatePrecompiles: true }) - st.notEqual(vm.stateManager.trie.root, util.KECCAK256_RLP, 'it has different root') + st.notEqual(vm.stateManager._trie.root, util.KECCAK256_RLP, 'it has different root') st.end() }) @@ -47,7 +47,7 @@ tape('VM with fake blockchain', (t) => { tape('VM with blockchain', (t) => { t.test('should instantiate', (st) => { const vm = setupVM() - st.deepEqual(vm.stateManager.trie.root, util.KECCAK256_RLP, 'it has default trie') + st.deepEqual(vm.stateManager._trie.root, util.KECCAK256_RLP, 'it has default trie') st.notOk(vm.stateManager.fake, 'it doesn\'t have fake blockchain') st.end() }) @@ -74,7 +74,7 @@ tape('VM with blockchain', (t) => { ) const setupPreP = promisify(setupPreConditions) - await setupPreP(vm.stateManager.trie, testData) + await setupPreP(vm.stateManager._trie, testData) vm.runBlock = (block, cb) => cb(new Error('test')) runBlockchainP(vm) @@ -101,7 +101,7 @@ tape('VM with blockchain', (t) => { ) const setupPreP = promisify(setupPreConditions) - await setupPreP(vm.stateManager.trie, testData) + await setupPreP(vm.stateManager._trie, testData) await runBlockchainP(vm) diff --git a/tests/api/runBlock.js b/tests/api/runBlock.js index 1920376b35..47b8b68068 100644 --- a/tests/api/runBlock.js +++ b/tests/api/runBlock.js @@ -122,7 +122,7 @@ tape('should fail when runCall fails', async (t) => { // which always returns an error. // runTx is a full implementation that works. suite.vm.runTx = runTx - await suite.p.runBlock({ block, root: suite.vm.stateManager.trie.root }) + await suite.p.runBlock({ block, root: suite.vm.stateManager._trie.root }) .then(() => t.fail('should have returned error')) .catch((e) => t.equal(e.message, 'test')) @@ -137,15 +137,15 @@ tape('should run valid block', async (t) => { const block = new Block(util.rlp.decode(suite.data.blocks[0].rlp)) const setupPreP = promisify(setupPreConditions) - await setupPreP(suite.vm.stateManager.trie, suite.data) + await setupPreP(suite.vm.stateManager._trie, suite.data) t.equal( - suite.vm.stateManager.trie.root.toString('hex'), + suite.vm.stateManager._trie.root.toString('hex'), genesis.header.stateRoot.toString('hex'), 'genesis state root should match calculated state root' ) - let res = await suite.p.runBlock({ block, root: suite.vm.stateManager.trie.root }) + let res = await suite.p.runBlock({ block, root: suite.vm.stateManager._trie.root }) t.error(res.error, 'runBlock shouldn\'t have returned error') t.equal(res.results[0].gasUsed.toString('hex'), '5208', 'actual gas used should equal blockHeader gasUsed') diff --git a/tests/api/stateManager.js b/tests/api/stateManager.js index 839ed5129e..172790d862 100644 --- a/tests/api/stateManager.js +++ b/tests/api/stateManager.js @@ -8,7 +8,7 @@ tape('StateManager', (t) => { t.test('should instantiate', (st) => { const stateManager = new StateManager() - st.deepEqual(stateManager.trie.root, util.KECCAK256_RLP, 'it has default root') + st.deepEqual(stateManager._trie.root, util.KECCAK256_RLP, 'it has default root') stateManager.getStateRoot((err, res) => { st.error(err, 'getStateRoot returns no error') st.deepEqual(res, util.KECCAK256_RLP, 'it has default root') @@ -33,13 +33,13 @@ tape('StateManager', (t) => { st.equal(res.balance.toString('hex'), 'fff384') - stateManager.cache.clear() + stateManager._cache.clear() res = await promisify(stateManager.getAccount.bind(stateManager))( 'a94f5374fce5edbc8e2a8697c15331677e6ebf0b' ) - st.equal(stateManager.cache._cache.keys[0], 'a94f5374fce5edbc8e2a8697c15331677e6ebf0b') + st.equal(stateManager._cache._cache.keys[0], 'a94f5374fce5edbc8e2a8697c15331677e6ebf0b') st.end() })