diff options
Diffstat (limited to 'core/state/statedb.go')
-rw-r--r-- | core/state/statedb.go | 104 |
1 files changed, 56 insertions, 48 deletions
diff --git a/core/state/statedb.go b/core/state/statedb.go index 24f97e32a..4233c763b 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -35,7 +35,6 @@ import ( type StateDB struct { db ethdb.Database trie *trie.SecureTrie - root common.Hash stateObjects map[string]*StateObject @@ -49,12 +48,19 @@ type StateDB struct { // Create a new state from a given trie func New(root common.Hash, db ethdb.Database) *StateDB { - trie := trie.NewSecure(root[:], db) - return &StateDB{root: root, db: db, trie: trie, stateObjects: make(map[string]*StateObject), refund: new(big.Int), logs: make(map[common.Hash]Logs)} -} - -func (self *StateDB) PrintRoot() { - self.trie.Trie.PrintRoot() + tr, err := trie.NewSecure(root, db) + if err != nil { + // TODO: bubble this up + tr, _ = trie.NewSecure(common.Hash{}, db) + glog.Errorf("can't create state trie with root %x: %v", root[:], err) + } + return &StateDB{ + db: db, + trie: tr, + stateObjects: make(map[string]*StateObject), + refund: new(big.Int), + logs: make(map[common.Hash]Logs), + } } func (self *StateDB) StartRecord(thash, bhash common.Hash, ti int) { @@ -196,7 +202,6 @@ func (self *StateDB) UpdateStateObject(stateObject *StateObject) { if len(stateObject.CodeHash()) > 0 { self.db.Put(stateObject.CodeHash(), stateObject.code) } - addr := stateObject.Address() self.trie.Update(addr[:], stateObject.RlpEncode()) } @@ -207,6 +212,7 @@ func (self *StateDB) DeleteStateObject(stateObject *StateObject) { addr := stateObject.Address() self.trie.Delete(addr[:]) + //delete(self.stateObjects, addr.Str()) } // Retrieve a state object given my the address. Nil if not found @@ -303,65 +309,67 @@ func (self *StateDB) Set(state *StateDB) { self.logSize = state.logSize } -func (s *StateDB) Root() common.Hash { - return common.BytesToHash(s.trie.Root()) -} - -// Syncs the trie and all siblings -func (s *StateDB) Sync() { - // Sync all nested states +// IntermediateRoot computes the current root hash of the state trie. +// It is called in between transactions to get the root hash that +// goes into transaction receipts. +func (s *StateDB) IntermediateRoot() common.Hash { + s.refund = new(big.Int) for _, stateObject := range s.stateObjects { - stateObject.trie.Commit() - } - - s.trie.Commit() - - s.Empty() -} - -func (self *StateDB) Empty() { - self.stateObjects = make(map[string]*StateObject) - self.refund = new(big.Int) -} - -func (self *StateDB) Refunds() *big.Int { - return self.refund -} - -// SyncIntermediate updates the intermediate state and all mid steps -func (self *StateDB) SyncIntermediate() { - self.refund = new(big.Int) - - for _, stateObject := range self.stateObjects { if stateObject.dirty { if stateObject.remove { - self.DeleteStateObject(stateObject) + s.DeleteStateObject(stateObject) } else { stateObject.Update() - - self.UpdateStateObject(stateObject) + s.UpdateStateObject(stateObject) } stateObject.dirty = false } } + return s.trie.Hash() } -// SyncObjects syncs the changed objects to the trie -func (self *StateDB) SyncObjects() { - self.trie = trie.NewSecure(self.root[:], self.db) +// Commit commits all state changes to the database. +func (s *StateDB) Commit() (root common.Hash, err error) { + return s.commit(s.db) +} - self.refund = new(big.Int) +// CommitBatch commits all state changes to a write batch but does not +// execute the batch. It is used to validate state changes against +// the root hash stored in a block. +func (s *StateDB) CommitBatch() (root common.Hash, batch ethdb.Batch) { + batch = s.db.NewBatch() + root, _ = s.commit(batch) + return root, batch +} - for _, stateObject := range self.stateObjects { +func (s *StateDB) commit(db trie.DatabaseWriter) (common.Hash, error) { + s.refund = new(big.Int) + + for _, stateObject := range s.stateObjects { if stateObject.remove { - self.DeleteStateObject(stateObject) + // If the object has been removed, don't bother syncing it + // and just mark it for deletion in the trie. + s.DeleteStateObject(stateObject) } else { + // Write any storage changes in the state object to its trie. stateObject.Update() - - self.UpdateStateObject(stateObject) + // Commit the trie of the object to the batch. + // This updates the trie root internally, so + // getting the root hash of the storage trie + // through UpdateStateObject is fast. + if _, err := stateObject.trie.CommitTo(db); err != nil { + return common.Hash{}, err + } + // Update the object in the account trie. + s.UpdateStateObject(stateObject) } stateObject.dirty = false } + return s.trie.CommitTo(db) +} + +func (self *StateDB) Refunds() *big.Int { + return self.refund } // Debug stuff |