aboutsummaryrefslogtreecommitdiffstats
path: root/core/state/journal.go
diff options
context:
space:
mode:
authorMartin Holst Swende <martin@swende.se>2017-10-02 03:07:30 +0800
committerPéter Szilágyi <peterke@gmail.com>2018-03-28 14:29:28 +0800
commit958ed4f3d977b08465915e475e11aaab3d2dc574 (patch)
tree177e7bf727a11cc18237c5299bfceffe56ccee88 /core/state/journal.go
parent1a8894b3d59bdf592244b91b6a629f7cf25dcdde (diff)
downloadgo-tangerine-958ed4f3d977b08465915e475e11aaab3d2dc574.tar.gz
go-tangerine-958ed4f3d977b08465915e475e11aaab3d2dc574.tar.zst
go-tangerine-958ed4f3d977b08465915e475e11aaab3d2dc574.zip
core/state: rework dirty handling to avoid quadratic overhead
Diffstat (limited to 'core/state/journal.go')
-rw-r--r--core/state/journal.go75
1 files changed, 68 insertions, 7 deletions
diff --git a/core/state/journal.go b/core/state/journal.go
index a89bb3d13..b00a46224 100644
--- a/core/state/journal.go
+++ b/core/state/journal.go
@@ -24,9 +24,40 @@ import (
type journalEntry interface {
undo(*StateDB)
+ getAccount() *common.Address
}
-type journal []journalEntry
+type journal struct {
+ entries []journalEntry
+ dirtyOverrides []common.Address
+}
+
+func (j *journal) append(entry journalEntry) {
+ j.entries = append(j.entries, entry)
+}
+
+func (j *journal) flatten() map[common.Address]struct{} {
+
+ dirtyObjects := make(map[common.Address]struct{})
+ for _, journalEntry := range j.entries {
+ if addr := journalEntry.getAccount(); addr != nil {
+ dirtyObjects[*addr] = struct{}{}
+ }
+ }
+ for _, addr := range j.dirtyOverrides {
+ dirtyObjects[addr] = struct{}{}
+ }
+ return dirtyObjects
+}
+
+// Length returns the number of journal entries in the journal
+func (j *journal) Length() int {
+ return len(j.entries)
+}
+
+func (j *journal) dirtyOverride(address common.Address) {
+ j.dirtyOverrides = append(j.dirtyOverrides, address)
+}
type (
// Changes to the account trie.
@@ -82,10 +113,18 @@ func (ch createObjectChange) undo(s *StateDB) {
delete(s.stateObjectsDirty, *ch.account)
}
+func (ch createObjectChange) getAccount() *common.Address {
+ return ch.account
+}
+
func (ch resetObjectChange) undo(s *StateDB) {
s.setStateObject(ch.prev)
}
+func (ch resetObjectChange) getAccount() *common.Address {
+ return nil
+}
+
func (ch suicideChange) undo(s *StateDB) {
obj := s.getStateObject(*ch.account)
if obj != nil {
@@ -93,37 +132,52 @@ func (ch suicideChange) undo(s *StateDB) {
obj.setBalance(ch.prevbalance)
}
}
+func (ch suicideChange) getAccount() *common.Address {
+ return ch.account
+}
var ripemd = common.HexToAddress("0000000000000000000000000000000000000003")
func (ch touchChange) undo(s *StateDB) {
- if !ch.prev && *ch.account != ripemd {
- s.getStateObject(*ch.account).touched = ch.prev
- if !ch.prevDirty {
- delete(s.stateObjectsDirty, *ch.account)
- }
- }
+}
+func (ch touchChange) getAccount() *common.Address {
+ return ch.account
}
func (ch balanceChange) undo(s *StateDB) {
s.getStateObject(*ch.account).setBalance(ch.prev)
}
+func (ch balanceChange) getAccount() *common.Address {
+ return ch.account
+}
func (ch nonceChange) undo(s *StateDB) {
s.getStateObject(*ch.account).setNonce(ch.prev)
}
+func (ch nonceChange) getAccount() *common.Address {
+ return ch.account
+}
func (ch codeChange) undo(s *StateDB) {
s.getStateObject(*ch.account).setCode(common.BytesToHash(ch.prevhash), ch.prevcode)
}
+func (ch codeChange) getAccount() *common.Address {
+ return ch.account
+}
func (ch storageChange) undo(s *StateDB) {
s.getStateObject(*ch.account).setState(ch.key, ch.prevalue)
}
+func (ch storageChange) getAccount() *common.Address {
+ return ch.account
+}
func (ch refundChange) undo(s *StateDB) {
s.refund = ch.prev
}
+func (ch refundChange) getAccount() *common.Address {
+ return nil
+}
func (ch addLogChange) undo(s *StateDB) {
logs := s.logs[ch.txhash]
@@ -134,7 +188,14 @@ func (ch addLogChange) undo(s *StateDB) {
}
s.logSize--
}
+func (ch addLogChange) getAccount() *common.Address {
+ return nil
+}
func (ch addPreimageChange) undo(s *StateDB) {
delete(s.preimages, ch.hash)
}
+
+func (ch addPreimageChange) getAccount() *common.Address {
+ return nil
+}