diff --git a/core/state/statedb.go b/core/state/statedb.go index dc5323f2b1..013e330a5c 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -191,7 +191,7 @@ func (self *StateDB) SetTxContext(blockHash common.Hash, blockNum uint64, txHash if validator == nil { validator = &trie.NullCacheValidator{} } - storage := trie.NewDirectCache(self.trie, self.db, CachePrefix, validator, true) + storage := trie.NewDirectCache(self.trie, self.db, CachePrefix, &trie.NullCacheValidator{}, true) self.storage = trie.NewSecure(storage, self.db) } diff --git a/light/trie.go b/light/trie.go index 9e2d067ce6..e526d6b2c6 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 { - storage *trie.SecureTrie + data *trie.SecureTrie originalRoot common.Hash odr OdrBackend db ethdb.Database @@ -74,16 +74,16 @@ func (t *LightTrie) do(ctx context.Context, fallbackKey []byte, fn func() error) return err } -func (t *LightTrie) getStorage() (ret *trie.SecureTrie, err error) { - if t.storage == nil { - var tr trie.Storage +func (t *LightTrie) getMap() (ret *trie.SecureTrie, err error) { + if t.data == nil { + var tr trie.PersistentMap tr, err = trie.New(t.originalRoot, t.db, 0) if err != nil { return nil, err } - t.storage = trie.NewSecure(tr, t.db) + t.data = trie.NewSecure(tr, t.db) } - return t.storage, nil + return t.data, nil } // Get returns the value for key stored in the trie. @@ -91,7 +91,7 @@ func (t *LightTrie) getStorage() (ret *trie.SecureTrie, err error) { func (t *LightTrie) Get(ctx context.Context, key []byte) (res []byte, err error) { err = t.do(ctx, key, func() (err error) { var st *trie.SecureTrie - st, err = t.getStorage() + st, err = t.getMap() if err == nil { res, err = st.TryGet(key) } @@ -109,7 +109,7 @@ func (t *LightTrie) Get(ctx context.Context, key []byte) (res []byte, err error) func (t *LightTrie) Update(ctx context.Context, key, value []byte) (err error) { err = t.do(ctx, key, func() (err error) { var st *trie.SecureTrie - st, err = t.getStorage() + st, err = t.getMap() if err == nil { err = st.TryUpdate(key, value) } @@ -122,7 +122,7 @@ func (t *LightTrie) Update(ctx context.Context, key, value []byte) (err error) { func (t *LightTrie) Delete(ctx context.Context, key []byte) (err error) { err = t.do(ctx, key, func() (err error) { var st *trie.SecureTrie - st, err = t.getStorage() + st, err = t.getMap() if err == nil { err = st.TryDelete(key) } diff --git a/trie/directcache.go b/trie/directcache.go index 25d3d6e305..8beaf666e0 100644 --- a/trie/directcache.go +++ b/trie/directcache.go @@ -42,7 +42,7 @@ type CacheValidator interface { } type DirectCache struct { - storage Storage + data PersistentMap db Database keyPrefix []byte blockNum uint64 @@ -58,9 +58,9 @@ func (cv *NullCacheValidator) IsCanonChainBlock(num uint64, hash common.Hash) bo return false } -func NewDirectCache(s Storage, db Database, keyPrefix []byte, validator CacheValidator, complete bool) *DirectCache { +func NewDirectCache(pm PersistentMap, db Database, keyPrefix []byte, validator CacheValidator, complete bool) *DirectCache { return &DirectCache{ - storage: s, + data: pm, db: db, keyPrefix: keyPrefix, validator: validator, @@ -71,7 +71,7 @@ func NewDirectCache(s Storage, db Database, keyPrefix []byte, validator CacheVal func (dc *DirectCache) Iterator() *Iterator { // Todo: If complete is true, implement an iterator over the DB instead. - return dc.storage.Iterator() + return dc.data.Iterator() } func (dc *DirectCache) makeKey(key []byte) []byte { @@ -87,7 +87,6 @@ func (dc *DirectCache) Get(key []byte) []byte { } func (dc *DirectCache) TryGet(key []byte) ([]byte, error) { - return dc.storage.TryGet(key) start := time.Now() // Use the underlying object for dirty keys @@ -99,7 +98,7 @@ func (dc *DirectCache) TryGet(key []byte) ([]byte, error) { } } - value, err := dc.storage.TryGet(key) + value, err := dc.data.TryGet(key) if err != nil { return value, err } @@ -146,7 +145,7 @@ func (dc *DirectCache) Update(key, value []byte) { func (dc *DirectCache) TryUpdate(key, value []byte) error { dc.dirty[string(key)] = true - return dc.storage.TryUpdate(key, value) + return dc.data.TryUpdate(key, value) } func (dc *DirectCache) Delete(key []byte) { @@ -157,7 +156,7 @@ func (dc *DirectCache) Delete(key []byte) { func (dc *DirectCache) TryDelete(key []byte) error { dc.dirty[string(key)] = true - return dc.storage.TryDelete(key) + return dc.data.TryDelete(key) } func (dc *DirectCache) Commit() (root common.Hash, err error) { @@ -167,7 +166,7 @@ func (dc *DirectCache) Commit() (root common.Hash, err error) { func (dc *DirectCache) CommitTo(dbw DatabaseWriter) (root common.Hash, err error) { directCacheWrites.Inc(int64(len(dc.dirty))) for k, _ := range dc.dirty { - v, err := dc.storage.TryGet([]byte(k)) + v, err := dc.data.TryGet([]byte(k)) if err, ok := err.(*MissingNodeError); err != nil && !ok { return common.Hash{}, err } @@ -176,5 +175,5 @@ func (dc *DirectCache) CommitTo(dbw DatabaseWriter) (root common.Hash, err error } } dc.dirty = make(map[string]bool) - return dc.storage.CommitTo(dbw) + return dc.data.CommitTo(dbw) } diff --git a/trie/secure_trie.go b/trie/secure_trie.go index f17704effc..4f8af02cef 100644 --- a/trie/secure_trie.go +++ b/trie/secure_trie.go @@ -26,6 +26,18 @@ var secureKeyPrefix = []byte("secure-key-") const secureKeyLength = 11 + 32 // Length of the above prefix + 32byte hash +type PersistentMap interface { + Iterator() *Iterator + Get(key []byte) []byte + TryGet(key []byte) ([]byte, error) + Update(key, value []byte) + TryUpdate(key, value []byte) error + Delete(key []byte) + TryDelete(key []byte) error + Commit() (root common.Hash, err error) + CommitTo(db DatabaseWriter) (root common.Hash, err error) +} + // SecureTrie wraps a trie with key hashing. In a secure trie, all // access operations hash the key using keccak256. This prevents // calling code from creating long chains of nodes that @@ -37,7 +49,7 @@ const secureKeyLength = 11 + 32 // Length of the above prefix + 32byte hash // // SecureTrie is not safe for concurrent use. type SecureTrie struct { - storage Storage + data PersistentMap db Database hashKeyBuf [secureKeyLength]byte secKeyBuf [200]byte @@ -45,57 +57,57 @@ type SecureTrie struct { secKeyCacheOwner *SecureTrie // Pointer to self, replace the key cache on mismatch } -// 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") +// NewSecure creates a secure persistent map from an existing map. +func NewSecure(pm PersistentMap, db Database) *SecureTrie { + if pm == nil { + panic("NewSecure called with nil persistent map") } if db == nil { panic("NewSecure called with nil database") } - return &SecureTrie{storage: s, db: db} + return &SecureTrie{data: pm, db: db} } -// Get returns the value for key stored in the storage. +// Get returns the value for key stored in the map. // 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 storage error: %v", err) + glog.Errorf("Unhandled persistent map error: %v", err) } return res } -// TryGet returns the value for key stored in the storage. +// TryGet returns the value for key stored in the map. // 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.storage.TryGet(t.hashKey(key)) + return t.data.TryGet(t.hashKey(key)) } -// Update associates key with value in the storage. Subsequent calls to +// Update associates key with value in the map. Subsequent calls to // Get will return value. If value has length zero, any existing value -// is deleted from the storage and calls to Get will return nil. +// is deleted from the map and calls to Get will return nil. // // The value bytes must not be modified by the caller while they are -// stored in the storage. +// stored in the map. func (t *SecureTrie) Update(key, value []byte) { if err := t.TryUpdate(key, value); err != nil && glog.V(logger.Error) { - glog.Errorf("Unhandled storage error: %v", err) + glog.Errorf("Unhandled persistent map error: %v", err) } } -// TryUpdate associates key with value in the storage. Subsequent calls to +// TryUpdate associates key with value in the map. Subsequent calls to // Get will return value. If value has length zero, any existing value -// is deleted from the storage and calls to Get will return nil. +// is deleted from the map and calls to Get will return nil. // // The value bytes must not be modified by the caller while they are -// stored in the storage. +// stored in the map. // // 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.storage.TryUpdate(hk, value) + err := t.data.TryUpdate(hk, value) if err != nil { return err } @@ -103,19 +115,19 @@ func (t *SecureTrie) TryUpdate(key, value []byte) error { return nil } -// Delete removes any existing value for key from the storage. +// Delete removes any existing value for key from the map. func (t *SecureTrie) Delete(key []byte) { if err := t.TryDelete(key); err != nil && glog.V(logger.Error) { - glog.Errorf("Unhandled storage error: %v", err) + glog.Errorf("Unhandled persistent map error: %v", err) } } -// TryDelete removes any existing value for key from the storage. +// TryDelete removes any existing value for key from the map. // 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.storage.TryDelete(hk) + return t.data.TryDelete(hk) } // GetKey returns the sha3 preimage of a hashed key that was @@ -137,11 +149,11 @@ func (t *SecureTrie) Commit() (root common.Hash, err error) { if err := t.CommitPreimages(); err != nil { return common.Hash{}, err } - return t.storage.Commit() + return t.data.Commit() } func (t *SecureTrie) Iterator() *Iterator { - return t.storage.Iterator() + return t.data.Iterator() } // CommitTo writes all nodes and the secure hash pre-images to the given database. @@ -149,12 +161,12 @@ func (t *SecureTrie) Iterator() *Iterator { // // Committing flushes nodes from memory. Subsequent Get calls will load nodes from // the database. Calling code must ensure that the changes made to db are -// written back to the attached database before using the storage. +// written back to the attached database before using the map. func (t *SecureTrie) CommitTo(db DatabaseWriter) (root common.Hash, err error) { if err := t.CommitPreimages(); err != nil { return common.Hash{}, err } - return t.storage.CommitTo(db) + return t.data.CommitTo(db) } func (t *SecureTrie) CommitPreimages() error { @@ -191,7 +203,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 storage is a copy of another owning +// ownership changed (i.e. the current secure map is a copy of another owning // the actual cache). func (t *SecureTrie) getSecKeyCache() map[string][]byte { if t != t.secKeyCacheOwner { diff --git a/trie/trie.go b/trie/trie.go index e186fc1d7c..2e0ecf9692 100644 --- a/trie/trie.go +++ b/trie/trie.go @@ -78,18 +78,6 @@ type DatabaseWriter interface { // Use New to create a trie that sits on top of a database. // // trie is not safe for concurrent use. -type Storage interface { - Iterator() *Iterator - Get(key []byte) []byte - TryGet(key []byte) ([]byte, error) - Update(key, value []byte) - TryUpdate(key, value []byte) error - Delete(key []byte) - TryDelete(key []byte) error - Commit() (root common.Hash, err error) - CommitTo(db DatabaseWriter) (root common.Hash, err error) -} - type Trie struct { root node db Database