Skip to content

Commit 5327e6f

Browse files
Clean-up state-manager.touched
1 parent 01b7f37 commit 5327e6f

File tree

4 files changed

+84
-63
lines changed

4 files changed

+84
-63
lines changed

lib/runCall.js

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,10 @@ module.exports = function (opts, cb) {
5252
stateManager.checkpoint()
5353

5454
// run and parse
55-
subTxValue()
56-
5755
async.series([
56+
subTxValue,
5857
loadToAccount,
58+
addTxValue,
5959
loadCode,
6060
runCode,
6161
saveCode
@@ -83,26 +83,29 @@ module.exports = function (opts, cb) {
8383
}
8484
}
8585

86-
function subTxValue () {
86+
function subTxValue (cb) {
8787
if (delegatecall) {
88+
cb()
8889
return
8990
}
90-
account.balance = new BN(account.balance).sub(txValue)
91-
stateManager.cache.put(caller, account)
91+
var newBalance = new BN(account.balance).sub(txValue)
92+
account.balance = newBalance
93+
stateManager.putAccountBalance(ethUtil.toBuffer(caller), newBalance, cb)
9294
}
9395

94-
function addTxValue () {
96+
function addTxValue (cb) {
9597
if (delegatecall) {
98+
cb()
9699
return
97100
}
98101
// add the amount sent to the `to` account
99-
toAccount.balance = new BN(toAccount.balance).add(txValue)
100-
stateManager.cache.put(toAddress, toAccount)
101-
stateManager.touched.push(toAddress)
102+
var newBalance = new BN(toAccount.balance).add(txValue)
103+
toAccount.balance = newBalance
104+
// putAccount as the nonce may have changed for contract creation
105+
stateManager.putAccount(ethUtil.toBuffer(toAddress), toAccount, cb)
102106
}
103107

104108
function loadCode (cb) {
105-
addTxValue()
106109
// loads the contract's code if the account is a contract
107110
if (code || !(toAccount.isContract() || self._precompiled[toAddress.toString('hex')])) {
108111
cb()

lib/runCode.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,6 @@ module.exports = function (opts, cb) {
248248
if (results.exceptionError) {
249249
delete results.gasRefund
250250
delete results.selfdestruct
251-
self.stateManager.touched = []
252251
}
253252

254253
if (err && err.error !== ERROR.REVERT) {

lib/runTx.js

Lines changed: 39 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@ module.exports = function (opts, cb) {
6969

7070
if (tx.to.toString('hex') !== '') {
7171
accounts.add(tx.to.toString('hex'))
72-
self.stateManager.touched.push(tx.to)
7372
}
7473

7574
if (opts.populateCache === false) {
@@ -148,53 +147,50 @@ module.exports = function (opts, cb) {
148147
}
149148

150149
results.amountSpent = results.gasUsed.mul(new BN(tx.gasPrice))
151-
// refund the leftover gas amount
152-
fromAccount.balance = new BN(tx.gasLimit).sub(results.gasUsed)
153-
.mul(new BN(tx.gasPrice))
154-
.add(new BN(fromAccount.balance))
155-
156-
self.stateManager.cache.put(tx.from, fromAccount)
157-
self.stateManager.touched.push(tx.from)
158-
159-
var minerAccount = self.stateManager.cache.get(block.header.coinbase)
160-
// add the amount spent on gas to the miner's account
161-
minerAccount.balance = new BN(minerAccount.balance)
162-
.add(results.amountSpent)
163-
164-
// save the miner's account
165-
if (!(new BN(minerAccount.balance).isZero())) {
166-
self.stateManager.cache.put(block.header.coinbase, minerAccount)
150+
151+
async.series([
152+
updateFromAccount,
153+
updateMinerAccount,
154+
cleanupAccounts
155+
], cb)
156+
157+
function updateFromAccount (next) {
158+
// refund the leftover gas amount
159+
var finalFromBalance = new BN(tx.gasLimit).sub(results.gasUsed)
160+
.mul(new BN(tx.gasPrice))
161+
.add(new BN(fromAccount.balance))
162+
fromAccount.balance = finalFromBalance
163+
164+
self.stateManager.putAccountBalance(utils.toBuffer(tx.from), finalFromBalance, next)
167165
}
168166

169-
if (!results.vm.selfdestruct) {
170-
results.vm.selfdestruct = {}
167+
function updateMinerAccount (next) {
168+
var minerAccount = self.stateManager.cache.get(block.header.coinbase)
169+
// add the amount spent on gas to the miner's account
170+
minerAccount.balance = new BN(minerAccount.balance)
171+
.add(results.amountSpent)
172+
173+
// save the miner's account
174+
if (!(new BN(minerAccount.balance).isZero())) {
175+
self.stateManager.cache.put(block.header.coinbase, minerAccount)
176+
}
177+
178+
next(null)
171179
}
172180

173-
var keys = Object.keys(results.vm.selfdestruct)
174-
175-
keys.forEach(function (s) {
176-
self.stateManager.cache.del(Buffer.from(s, 'hex'))
177-
})
178-
179-
// delete all touched accounts
180-
var touched = self.stateManager.touched
181-
async.forEach(touched, function (address, next) {
182-
self.stateManager.accountIsEmpty(address, function (err, empty) {
183-
if (err) {
184-
next(err)
185-
return
186-
}
187-
188-
if (empty) {
189-
self.stateManager.cache.del(address)
190-
}
191-
next(null)
181+
function cleanupAccounts (next) {
182+
if (!results.vm.selfdestruct) {
183+
results.vm.selfdestruct = {}
184+
}
185+
186+
var keys = Object.keys(results.vm.selfdestruct)
187+
188+
keys.forEach(function (s) {
189+
self.stateManager.cache.del(Buffer.from(s, 'hex'))
192190
})
193-
},
194-
function () {
195-
self.stateManager.touched = []
196-
cb()
197-
})
191+
192+
self.stateManager.cleanupTouchedAccounts(next)
193+
}
198194
}
199195
}
200196

lib/stateManager.js

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ function StateManager (opts) {
2828
self.trie = trie
2929
self._storageTries = {} // the storage trie cache
3030
self.cache = new Cache(trie)
31-
self.touched = []
31+
self._touched = new Set()
3232
}
3333

3434
var proto = StateManager.prototype
@@ -47,14 +47,13 @@ proto.exists = function (address, cb) {
4747
}
4848

4949
// saves the account
50-
proto._putAccount = function (address, account, cb) {
50+
proto.putAccount = function (address, account, cb) {
5151
var self = this
52-
var addressHex = Buffer.from(address, 'hex')
5352
// TODO: dont save newly created accounts that have no balance
5453
// if (toAccount.balance.toString('hex') === '00') {
5554
// if they have money or a non-zero nonce or code, then write to tree
56-
self.cache.put(addressHex, account)
57-
self.touched.push(address)
55+
self.cache.put(address, account)
56+
self._touched.add(address.toString('hex'))
5857
// self.trie.put(addressHex, account.serialize(), cb)
5958
cb()
6059
}
@@ -82,7 +81,7 @@ proto.putAccountBalance = function (address, balance, cb) {
8281
}
8382

8483
account.balance = balance
85-
self._putAccount(address, account, cb)
84+
self.putAccount(address, account, cb)
8685
})
8786
}
8887

@@ -98,7 +97,7 @@ proto.putContractCode = function (address, value, cb) {
9897
if (err) {
9998
return cb(err)
10099
}
101-
self._putAccount(address, account, cb)
100+
self.putAccount(address, account, cb)
102101
})
103102
})
104103
}
@@ -180,8 +179,8 @@ proto.putContractStorage = function (address, key, value, cb) {
180179
// update contract stateRoot
181180
var contract = self.cache.get(address)
182181
contract.stateRoot = storageTrie.root
183-
self._putAccount(address, contract, cb)
184-
self.touched.push(address)
182+
self.putAccount(address, contract, cb)
183+
self._touched.add(address.toString('hex'))
185184
}
186185
})
187186
}
@@ -204,6 +203,7 @@ proto.commitContracts = function (cb) {
204203
proto.revertContracts = function () {
205204
var self = this
206205
self._storageTries = {}
206+
self._touched.clear()
207207
}
208208

209209
//
@@ -325,3 +325,26 @@ proto.accountIsEmpty = function (address, cb) {
325325
cb(null, account.nonce.toString('hex') === '' && account.balance.toString('hex') === '' && account.codeHash.toString('hex') === utils.SHA3_NULL_S)
326326
})
327327
}
328+
329+
proto.cleanupTouchedAccounts = function (cb) {
330+
var self = this
331+
var touchedArray = Array.from(self._touched)
332+
async.forEach(touchedArray, function (addressHex, next) {
333+
var address = Buffer.from(addressHex, 'hex')
334+
self.accountIsEmpty(address, function (err, empty) {
335+
if (err) {
336+
next(err)
337+
return
338+
}
339+
340+
if (empty) {
341+
self.cache.del(address)
342+
}
343+
next(null)
344+
})
345+
},
346+
function () {
347+
self._touched.clear()
348+
cb()
349+
})
350+
}

0 commit comments

Comments
 (0)