Skip to content

Commit

Permalink
Merge branch 'master' into patch-2
Browse files Browse the repository at this point in the history
  • Loading branch information
yann300 authored Apr 17, 2018
2 parents d0c7079 + 1cbba0a commit 8f721bb
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 63 deletions.
23 changes: 13 additions & 10 deletions lib/runCall.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,10 @@ module.exports = function (opts, cb) {
stateManager.checkpoint()

// run and parse
subTxValue()

async.series([
subTxValue,
loadToAccount,
addTxValue,
loadCode,
runCode,
saveCode
Expand Down Expand Up @@ -83,26 +83,29 @@ module.exports = function (opts, cb) {
}
}

function subTxValue () {
function subTxValue (cb) {
if (delegatecall) {
cb()
return
}
account.balance = new BN(account.balance).sub(txValue)
stateManager.cache.put(caller, account)
var newBalance = new BN(account.balance).sub(txValue)
account.balance = newBalance
stateManager.putAccountBalance(ethUtil.toBuffer(caller), newBalance, cb)
}

function addTxValue () {
function addTxValue (cb) {
if (delegatecall) {
cb()
return
}
// add the amount sent to the `to` account
toAccount.balance = new BN(toAccount.balance).add(txValue)
stateManager.cache.put(toAddress, toAccount)
stateManager.touched.push(toAddress)
var newBalance = new BN(toAccount.balance).add(txValue)
toAccount.balance = newBalance
// putAccount as the nonce may have changed for contract creation
stateManager.putAccount(ethUtil.toBuffer(toAddress), toAccount, cb)
}

function loadCode (cb) {
addTxValue()
// loads the contract's code if the account is a contract
if (code || !(toAccount.isContract() || self._precompiled[toAddress.toString('hex')])) {
cb()
Expand Down
1 change: 0 additions & 1 deletion lib/runCode.js
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,6 @@ module.exports = function (opts, cb) {
if (results.exceptionError) {
delete results.gasRefund
delete results.selfdestruct
self.stateManager.touched = []
}

if (err && err.error !== ERROR.REVERT) {
Expand Down
82 changes: 39 additions & 43 deletions lib/runTx.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ module.exports = function (opts, cb) {

if (tx.to.toString('hex') !== '') {
accounts.add(tx.to.toString('hex'))
self.stateManager.touched.push(tx.to)
}

if (opts.populateCache === false) {
Expand Down Expand Up @@ -148,53 +147,50 @@ module.exports = function (opts, cb) {
}

results.amountSpent = results.gasUsed.mul(new BN(tx.gasPrice))
// refund the leftover gas amount
fromAccount.balance = new BN(tx.gasLimit).sub(results.gasUsed)
.mul(new BN(tx.gasPrice))
.add(new BN(fromAccount.balance))

self.stateManager.cache.put(tx.from, fromAccount)
self.stateManager.touched.push(tx.from)

var minerAccount = self.stateManager.cache.get(block.header.coinbase)
// add the amount spent on gas to the miner's account
minerAccount.balance = new BN(minerAccount.balance)
.add(results.amountSpent)

// save the miner's account
if (!(new BN(minerAccount.balance).isZero())) {
self.stateManager.cache.put(block.header.coinbase, minerAccount)

async.series([
updateFromAccount,
updateMinerAccount,
cleanupAccounts
], cb)

function updateFromAccount (next) {
// refund the leftover gas amount
var finalFromBalance = new BN(tx.gasLimit).sub(results.gasUsed)
.mul(new BN(tx.gasPrice))
.add(new BN(fromAccount.balance))
fromAccount.balance = finalFromBalance

self.stateManager.putAccountBalance(utils.toBuffer(tx.from), finalFromBalance, next)
}

if (!results.vm.selfdestruct) {
results.vm.selfdestruct = {}
function updateMinerAccount (next) {
var minerAccount = self.stateManager.cache.get(block.header.coinbase)
// add the amount spent on gas to the miner's account
minerAccount.balance = new BN(minerAccount.balance)
.add(results.amountSpent)

// save the miner's account
if (!(new BN(minerAccount.balance).isZero())) {
self.stateManager.cache.put(block.header.coinbase, minerAccount)
}

next(null)
}

var keys = Object.keys(results.vm.selfdestruct)

keys.forEach(function (s) {
self.stateManager.cache.del(Buffer.from(s, 'hex'))
})

// delete all touched accounts
var touched = self.stateManager.touched
async.forEach(touched, function (address, next) {
self.stateManager.accountIsEmpty(address, function (err, empty) {
if (err) {
next(err)
return
}

if (empty) {
self.stateManager.cache.del(address)
}
next(null)
function cleanupAccounts (next) {
if (!results.vm.selfdestruct) {
results.vm.selfdestruct = {}
}

var keys = Object.keys(results.vm.selfdestruct)

keys.forEach(function (s) {
self.stateManager.cache.del(Buffer.from(s, 'hex'))
})
},
function () {
self.stateManager.touched = []
cb()
})

self.stateManager.cleanupTouchedAccounts(next)
}
}
}

Expand Down
41 changes: 32 additions & 9 deletions lib/stateManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ function StateManager (opts) {
self.trie = trie
self._storageTries = {} // the storage trie cache
self.cache = new Cache(trie)
self.touched = []
self._touched = new Set()
}

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

// saves the account
proto._putAccount = function (address, account, cb) {
proto.putAccount = function (address, account, cb) {
var self = this
var addressHex = Buffer.from(address, 'hex')
// 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(addressHex, account)
self.touched.push(address)
self.cache.put(address, account)
self._touched.add(address.toString('hex'))
// self.trie.put(addressHex, account.serialize(), cb)
cb()
}
Expand Down Expand Up @@ -82,7 +81,7 @@ proto.putAccountBalance = function (address, balance, cb) {
}

account.balance = balance
self._putAccount(address, account, cb)
self.putAccount(address, account, cb)
})
}

Expand All @@ -98,7 +97,7 @@ proto.putContractCode = function (address, value, cb) {
if (err) {
return cb(err)
}
self._putAccount(address, account, cb)
self.putAccount(address, account, cb)
})
})
}
Expand Down Expand Up @@ -180,8 +179,8 @@ proto.putContractStorage = function (address, key, value, cb) {
// update contract stateRoot
var contract = self.cache.get(address)
contract.stateRoot = storageTrie.root
self._putAccount(address, contract, cb)
self.touched.push(address)
self.putAccount(address, contract, cb)
self._touched.add(address.toString('hex'))
}
})
}
Expand All @@ -204,6 +203,7 @@ proto.commitContracts = function (cb) {
proto.revertContracts = function () {
var self = this
self._storageTries = {}
self._touched.clear()
}

//
Expand Down Expand Up @@ -325,3 +325,26 @@ proto.accountIsEmpty = function (address, cb) {
cb(null, account.nonce.toString('hex') === '' && account.balance.toString('hex') === '' && account.codeHash.toString('hex') === utils.SHA3_NULL_S)
})
}

proto.cleanupTouchedAccounts = function (cb) {
var self = this
var touchedArray = Array.from(self._touched)
async.forEach(touchedArray, function (addressHex, next) {
var address = Buffer.from(addressHex, 'hex')
self.accountIsEmpty(address, function (err, empty) {
if (err) {
next(err)
return
}

if (empty) {
self.cache.del(address)
}
next(null)
})
},
function () {
self._touched.clear()
cb()
})
}

0 comments on commit 8f721bb

Please sign in to comment.