From 9683a38895254dabd5d53d402769dbba310984fb Mon Sep 17 00:00:00 2001 From: Nick Johnson Date: Mon, 24 Oct 2016 11:42:16 +0100 Subject: [PATCH] core/state, light, trie: Rename Trie to Storage; remove Hash() and Root() methods --- core/state/dump.go | 8 ++--- core/state/state_object.go | 24 +++++++------ core/state/statedb.go | 30 ++++++++-------- light/trie.go | 30 ++++++++-------- trie/secure_trie.go | 70 ++++++++++++++++---------------------- trie/secure_trie_test.go | 18 +++++----- trie/trie.go | 4 +-- 7 files changed, 86 insertions(+), 98 deletions(-) diff --git a/core/state/dump.go b/core/state/dump.go index 8294d61b9f..49569ac9fd 100644 --- a/core/state/dump.go +++ b/core/state/dump.go @@ -44,9 +44,9 @@ func (self *StateDB) RawDump() Dump { Accounts: make(map[string]DumpAccount), } - it := self.trie.Iterator() + it := self.storage.Iterator() for it.Next() { - addr := self.trie.GetKey(it.Key) + addr := self.storage.GetKey(it.Key) var data Account if err := rlp.DecodeBytes(it.Value, &data); err != nil { panic(err) @@ -61,9 +61,9 @@ func (self *StateDB) RawDump() Dump { Code: common.Bytes2Hex(obj.Code(self.db)), Storage: make(map[string]string), } - storageIt := obj.getTrie(self.db).Iterator() + storageIt := obj.getStorage(self.db).Iterator() for storageIt.Next() { - account.Storage[common.Bytes2Hex(self.trie.GetKey(storageIt.Key))] = common.Bytes2Hex(storageIt.Value) + account.Storage[common.Bytes2Hex(self.storage.GetKey(storageIt.Key))] = common.Bytes2Hex(storageIt.Value) } dump.Accounts[common.Bytes2Hex(addr)] = account } diff --git a/core/state/state_object.go b/core/state/state_object.go index e770aac254..1817299493 100644 --- a/core/state/state_object.go +++ b/core/state/state_object.go @@ -76,7 +76,8 @@ type StateObject struct { dbErr error // Write caches. - trie *trie.SecureTrie // storage trie, which becomes non-nil on first access + trie *trie.SimpleTrie // storage trie, which becomes non-nil on first access + storage *trie.SecureTrie // Interface to storage code Code // contract bytecode, which gets set when code is loaded cachedStorage Storage // Storage entry cache to avoid duplicate reads @@ -134,17 +135,17 @@ func (self *StateObject) markSuicided() { } } -func (c *StateObject) getTrie(db trie.Database) *trie.SecureTrie { +func (c *StateObject) getStorage(db trie.Database) *trie.SecureTrie { if c.trie == nil { var err error - t, err := trie.New(c.data.Root, db, 0) + c.trie, err = trie.New(c.data.Root, db, 0) if err != nil { - t, _ = trie.New(common.Hash{}, nil, 0) + c.trie, _ = trie.New(common.Hash{}, nil, 0) c.setError(fmt.Errorf("can't create storage trie: %v", err)) } - c.trie = trie.NewSecure(t, db) + c.storage = trie.NewSecure(c.trie, db) } - return c.trie + return c.storage } // GetState returns a value in account storage. @@ -154,7 +155,7 @@ func (self *StateObject) GetState(db trie.Database, key common.Hash) common.Hash return value } // Load from DB in case it is missing. - if enc := self.getTrie(db).Get(key[:]); len(enc) > 0 { + if enc := self.getStorage(db).Get(key[:]); len(enc) > 0 { _, content, _, err := rlp.Split(enc) if err != nil { self.setError(err) @@ -189,7 +190,7 @@ func (self *StateObject) setState(key, value common.Hash) { // updateTrie writes cached storage modifications into the object's storage trie. func (self *StateObject) updateTrie(db trie.Database) { - tr := self.getTrie(db) + tr := self.getStorage(db) for key, value := range self.dirtyStorage { delete(self.dirtyStorage, key) if (value == common.Hash{}) { @@ -215,7 +216,7 @@ func (self *StateObject) CommitTrie(db trie.Database, dbw trie.DatabaseWriter) e if self.dbErr != nil { return self.dbErr } - root, err := self.trie.CommitTo(dbw) + root, err := self.storage.CommitTo(dbw) if err == nil { self.data.Root = root } @@ -266,6 +267,7 @@ func (c *StateObject) ReturnGas(gas, price *big.Int) {} func (self *StateObject) deepCopy(db *StateDB, onDirty func(addr common.Address)) *StateObject { stateObject := newObject(db, self.address, self.data, onDirty) stateObject.trie = self.trie + stateObject.storage = self.storage stateObject.code = self.code stateObject.dirtyStorage = self.dirtyStorage.Copy() stateObject.cachedStorage = self.dirtyStorage.Copy() @@ -361,10 +363,10 @@ func (self *StateObject) ForEachStorage(cb func(key, value common.Hash) bool) { cb(h, value) } - it := self.getTrie(self.db.db).Iterator() + it := self.getStorage(self.db.db).Iterator() for it.Next() { // ignore cached values - key := common.BytesToHash(self.trie.GetKey(it.Key)) + key := common.BytesToHash(self.storage.GetKey(it.Key)) if _, ok := self.cachedStorage[key]; !ok { cb(key, common.BytesToHash(it.Value)) } diff --git a/core/state/statedb.go b/core/state/statedb.go index 394df93904..2fd41e6180 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -62,8 +62,9 @@ type revision struct { // * Accounts type StateDB struct { db ethdb.Database - trie *trie.SecureTrie - pastTries []*trie.SecureTrie + trie *trie.SimpleTrie + storage *trie.SecureTrie + pastTries []*trie.SimpleTrie codeSizeCache *lru.Cache // This map holds 'live' objects, which will get modified while processing a state transition. @@ -93,11 +94,11 @@ func New(root common.Hash, db ethdb.Database) (*StateDB, error) { if err != nil { return nil, err } - st := trie.NewSecure(tr, db) csc, _ := lru.New(codeSizeCacheSize) return &StateDB{ db: db, - trie: st, + trie: tr, + storage: trie.NewSecure(tr, db), codeSizeCache: csc, stateObjects: make(map[common.Address]*StateObject), stateObjectsDirty: make(map[common.Address]struct{}), @@ -119,6 +120,7 @@ func (self *StateDB) New(root common.Hash) (*StateDB, error) { return &StateDB{ db: self.db, trie: tr, + storage: trie.NewSecure(tr, self.db), codeSizeCache: self.codeSizeCache, stateObjects: make(map[common.Address]*StateObject), stateObjectsDirty: make(map[common.Address]struct{}), @@ -138,6 +140,7 @@ func (self *StateDB) Reset(root common.Hash) error { return err } self.trie = tr + self.storage = trie.NewSecure(tr, self.db) self.stateObjects = make(map[common.Address]*StateObject) self.stateObjectsDirty = make(map[common.Address]struct{}) self.thash = common.Hash{} @@ -152,21 +155,17 @@ func (self *StateDB) Reset(root common.Hash) error { // openTrie creates a trie. It uses an existing trie if one is available // from the journal if available. -func (self *StateDB) openTrie(root common.Hash) (*trie.SecureTrie, error) { +func (self *StateDB) openTrie(root common.Hash) (*trie.SimpleTrie, error) { for i := len(self.pastTries) - 1; i >= 0; i-- { if self.pastTries[i].Hash() == root { tr := *self.pastTries[i] return &tr, nil } } - t, err := trie.New(root, self.db, MaxTrieCacheGen) - if err != nil { - return nil, err - } - return trie.NewSecure(t, self.db), nil + return trie.New(root, self.db, MaxTrieCacheGen) } -func (self *StateDB) pushTrie(t *trie.SecureTrie) { +func (self *StateDB) pushTrie(t *trie.SimpleTrie) { self.lock.Lock() defer self.lock.Unlock() @@ -361,14 +360,14 @@ func (self *StateDB) updateStateObject(stateObject *StateObject) { if err != nil { panic(fmt.Errorf("can't encode object at %x: %v", addr[:], err)) } - self.trie.Update(addr[:], data) + self.storage.Update(addr[:], data) } // deleteStateObject removes the given object from the state trie. func (self *StateDB) deleteStateObject(stateObject *StateObject) { stateObject.deleted = true addr := stateObject.Address() - self.trie.Delete(addr[:]) + self.storage.Delete(addr[:]) } // Retrieve a state object given my the address. Returns nil if not found. @@ -382,7 +381,7 @@ func (self *StateDB) GetStateObject(addr common.Address) (stateObject *StateObje } // Load the object from the database. - enc := self.trie.Get(addr[:]) + enc := self.storage.Get(addr[:]) if len(enc) == 0 { return nil } @@ -462,6 +461,7 @@ func (self *StateDB) Copy() *StateDB { state := &StateDB{ db: self.db, trie: self.trie, + storage: self.storage, pastTries: self.pastTries, codeSizeCache: self.codeSizeCache, stateObjects: make(map[common.Address]*StateObject, len(self.stateObjectsDirty)), @@ -607,7 +607,7 @@ func (s *StateDB) commit(dbw trie.DatabaseWriter) (root common.Hash, err error) delete(s.stateObjectsDirty, addr) } // Write trie changes. - root, err = s.trie.CommitTo(dbw) + root, err = s.storage.CommitTo(dbw) if err == nil { s.pushTrie(s.trie) } diff --git a/light/trie.go b/light/trie.go index 3436a37bdd..9e2d067ce6 100644 --- a/light/trie.go +++ b/light/trie.go @@ -25,7 +25,7 @@ import ( // LightTrie is an ODR-capable wrapper around trie.SecureTrie type LightTrie struct { - trie *trie.SecureTrie + storage *trie.SecureTrie originalRoot common.Hash odr OdrBackend db ethdb.Database @@ -74,26 +74,26 @@ func (t *LightTrie) do(ctx context.Context, fallbackKey []byte, fn func() error) return err } -func (t *LightTrie) getTrie() (ret *trie.SecureTrie, err error) { - if t.trie == nil { - var tr trie.Trie +func (t *LightTrie) getStorage() (ret *trie.SecureTrie, err error) { + if t.storage == nil { + var tr trie.Storage tr, err = trie.New(t.originalRoot, t.db, 0) if err != nil { return nil, err } - t.trie = trie.NewSecure(tr, t.db) + t.storage = trie.NewSecure(tr, t.db) } - return t.trie, nil + return t.storage, nil } // Get returns the value for key stored in the trie. // The value bytes must not be modified by the caller. func (t *LightTrie) Get(ctx context.Context, key []byte) (res []byte, err error) { err = t.do(ctx, key, func() (err error) { - var tr *trie.SecureTrie - tr, err = t.getTrie() + var st *trie.SecureTrie + st, err = t.getStorage() if err == nil { - res, err = tr.TryGet(key) + res, err = st.TryGet(key) } return }) @@ -108,10 +108,10 @@ func (t *LightTrie) Get(ctx context.Context, key []byte) (res []byte, err error) // stored in the trie. func (t *LightTrie) Update(ctx context.Context, key, value []byte) (err error) { err = t.do(ctx, key, func() (err error) { - var tr *trie.SecureTrie - tr, err = t.getTrie() + var st *trie.SecureTrie + st, err = t.getStorage() if err == nil { - err = tr.TryUpdate(key, value) + err = st.TryUpdate(key, value) } return }) @@ -121,10 +121,10 @@ func (t *LightTrie) Update(ctx context.Context, key, value []byte) (err error) { // Delete removes any existing value for key from the trie. func (t *LightTrie) Delete(ctx context.Context, key []byte) (err error) { err = t.do(ctx, key, func() (err error) { - var tr *trie.SecureTrie - tr, err = t.getTrie() + var st *trie.SecureTrie + st, err = t.getStorage() if err == nil { - err = tr.TryDelete(key) + err = st.TryDelete(key) } return }) diff --git a/trie/secure_trie.go b/trie/secure_trie.go index 00160fd62c..f17704effc 100644 --- a/trie/secure_trie.go +++ b/trie/secure_trie.go @@ -37,7 +37,7 @@ const secureKeyLength = 11 + 32 // Length of the above prefix + 32byte hash // // SecureTrie is not safe for concurrent use. type SecureTrie struct { - trie Trie + storage Storage db Database hashKeyBuf [secureKeyLength]byte secKeyBuf [200]byte @@ -45,57 +45,57 @@ type SecureTrie struct { secKeyCacheOwner *SecureTrie // Pointer to self, replace the key cache on mismatch } -// NewSecure creates a secure trie from an existing trie. -func NewSecure(t Trie, db Database) *SecureTrie { - if t == nil { - panic("NewSecure called with nil trie") +// NewSecure creates a secure Storage from an existing Storage. +func NewSecure(s Storage, db Database) *SecureTrie { + if s == nil { + panic("NewSecure called with nil storage") } if db == nil { panic("NewSecure called with nil database") } - return &SecureTrie{trie: t, db: db} + return &SecureTrie{storage: s, db: db} } -// Get returns the value for key stored in the trie. +// Get returns the value for key stored in the storage. // The value bytes must not be modified by the caller. func (t *SecureTrie) Get(key []byte) []byte { res, err := t.TryGet(key) if err != nil && glog.V(logger.Error) { - glog.Errorf("Unhandled trie error: %v", err) + glog.Errorf("Unhandled storage error: %v", err) } return res } -// TryGet returns the value for key stored in the trie. +// TryGet returns the value for key stored in the storage. // The value bytes must not be modified by the caller. // If a node was not found in the database, a MissingNodeError is returned. func (t *SecureTrie) TryGet(key []byte) ([]byte, error) { - return t.trie.TryGet(t.hashKey(key)) + return t.storage.TryGet(t.hashKey(key)) } -// Update associates key with value in the trie. Subsequent calls to +// Update associates key with value in the storage. Subsequent calls to // Get will return value. If value has length zero, any existing value -// is deleted from the trie and calls to Get will return nil. +// is deleted from the storage and calls to Get will return nil. // // The value bytes must not be modified by the caller while they are -// stored in the trie. +// stored in the storage. func (t *SecureTrie) Update(key, value []byte) { if err := t.TryUpdate(key, value); err != nil && glog.V(logger.Error) { - glog.Errorf("Unhandled trie error: %v", err) + glog.Errorf("Unhandled storage error: %v", err) } } -// TryUpdate associates key with value in the trie. Subsequent calls to +// TryUpdate associates key with value in the storage. Subsequent calls to // Get will return value. If value has length zero, any existing value -// is deleted from the trie and calls to Get will return nil. +// is deleted from the storage and calls to Get will return nil. // // The value bytes must not be modified by the caller while they are -// stored in the trie. +// stored in the storage. // // If a node was not found in the database, a MissingNodeError is returned. func (t *SecureTrie) TryUpdate(key, value []byte) error { hk := t.hashKey(key) - err := t.trie.TryUpdate(hk, value) + err := t.storage.TryUpdate(hk, value) if err != nil { return err } @@ -103,19 +103,19 @@ func (t *SecureTrie) TryUpdate(key, value []byte) error { return nil } -// Delete removes any existing value for key from the trie. +// Delete removes any existing value for key from the storage. func (t *SecureTrie) Delete(key []byte) { if err := t.TryDelete(key); err != nil && glog.V(logger.Error) { - glog.Errorf("Unhandled trie error: %v", err) + glog.Errorf("Unhandled storage error: %v", err) } } -// TryDelete removes any existing value for key from the trie. +// TryDelete removes any existing value for key from the storage. // If a node was not found in the database, a MissingNodeError is returned. func (t *SecureTrie) TryDelete(key []byte) error { hk := t.hashKey(key) delete(t.getSecKeyCache(), string(hk)) - return t.trie.TryDelete(hk) + return t.storage.TryDelete(hk) } // GetKey returns the sha3 preimage of a hashed key that was @@ -128,7 +128,7 @@ func (t *SecureTrie) GetKey(shaKey []byte) []byte { return key } -// Commit writes all nodes and the secure hash pre-images to the trie's database. +// Commit writes all nodes and the secure hash pre-images to the database. // Nodes are stored with their sha3 hash as the key. // // Committing flushes nodes from memory. Subsequent Get calls will load nodes @@ -137,36 +137,24 @@ func (t *SecureTrie) Commit() (root common.Hash, err error) { if err := t.CommitPreimages(); err != nil { return common.Hash{}, err } - return t.trie.Commit() -} - -func (t *SecureTrie) Hash() common.Hash { - return t.trie.Hash() -} - -func (t *SecureTrie) Root() []byte { - return t.trie.Root() + return t.storage.Commit() } func (t *SecureTrie) Iterator() *Iterator { - return t.trie.Iterator() -} - -func (t *SecureTrie) NodeIterator() *NodeIterator { - return t.trie.NodeIterator() + return t.storage.Iterator() } // CommitTo writes all nodes and the secure hash pre-images to the given database. // Nodes are stored with their sha3 hash as the key. // // Committing flushes nodes from memory. Subsequent Get calls will load nodes from -// the trie's database. Calling code must ensure that the changes made to db are -// written back to the trie's attached database before using the trie. +// the database. Calling code must ensure that the changes made to db are +// written back to the attached database before using the storage. func (t *SecureTrie) CommitTo(db DatabaseWriter) (root common.Hash, err error) { if err := t.CommitPreimages(); err != nil { return common.Hash{}, err } - return t.trie.CommitTo(db) + return t.storage.CommitTo(db) } func (t *SecureTrie) CommitPreimages() error { @@ -203,7 +191,7 @@ func (t *SecureTrie) hashKey(key []byte) []byte { } // getSecKeyCache returns the current secure key cache, creating a new one if -// ownership changed (i.e. the current secure trie is a copy of another owning +// ownership changed (i.e. the current secure storage is a copy of another owning // the actual cache). func (t *SecureTrie) getSecKeyCache() map[string][]byte { if t != t.secKeyCacheOwner { diff --git a/trie/secure_trie_test.go b/trie/secure_trie_test.go index a0d04ac7f3..a595c2f1ea 100644 --- a/trie/secure_trie_test.go +++ b/trie/secure_trie_test.go @@ -27,11 +27,11 @@ import ( "github.com/ethereum/go-ethereum/ethdb" ) -func newEmptySecure() *SecureTrie { +func newEmptySecure() (*SimpleTrie, *SecureTrie) { db, _ := ethdb.NewMemDatabase() tr, _ := New(common.Hash{}, db, 0) st := NewSecure(tr, db) - return st + return tr, st } // makeTestSecureTrie creates a large enough secure trie for testing. @@ -67,7 +67,7 @@ func makeTestSecureTrie() (ethdb.Database, *SecureTrie, map[string][]byte) { } func TestSecureDelete(t *testing.T) { - trie := newEmptySecure() + trie, st := newEmptySecure() vals := []struct{ k, v string }{ {"do", "verb"}, {"ether", "wookiedoo"}, @@ -80,9 +80,9 @@ func TestSecureDelete(t *testing.T) { } for _, val := range vals { if val.v != "" { - trie.Update([]byte(val.k), []byte(val.v)) + st.Update([]byte(val.k), []byte(val.v)) } else { - trie.Delete([]byte(val.k)) + st.Delete([]byte(val.k)) } } hash := trie.Hash() @@ -93,17 +93,17 @@ func TestSecureDelete(t *testing.T) { } func TestSecureGetKey(t *testing.T) { - trie := newEmptySecure() - trie.Update([]byte("foo"), []byte("bar")) + _, st := newEmptySecure() + st.Update([]byte("foo"), []byte("bar")) key := []byte("foo") value := []byte("bar") seckey := crypto.Keccak256(key) - if !bytes.Equal(trie.Get(key), value) { + if !bytes.Equal(st.Get(key), value) { t.Errorf("Get did not return bar") } - if k := trie.GetKey(seckey); !bytes.Equal(k, key) { + if k := st.GetKey(seckey); !bytes.Equal(k, key) { t.Errorf("GetKey returned %q, want %q", k, key) } } diff --git a/trie/trie.go b/trie/trie.go index 4427e523ae..f9eae6053e 100644 --- a/trie/trie.go +++ b/trie/trie.go @@ -78,7 +78,7 @@ type DatabaseWriter interface { // Use New to create a trie that sits on top of a database. // // trie is not safe for concurrent use. -type Trie interface { +type Storage interface { Iterator() *Iterator NodeIterator() *NodeIterator Get(key []byte) []byte @@ -87,8 +87,6 @@ type Trie interface { TryUpdate(key, value []byte) error Delete(key []byte) TryDelete(key []byte) error - Root() []byte - Hash() common.Hash Commit() (root common.Hash, err error) CommitTo(db DatabaseWriter) (root common.Hash, err error) }