trie, light: Rename Storage to PersistentMap

This commit is contained in:
Nick Johnson 2016-10-25 11:05:59 +01:00
parent de5a818baa
commit 5b73f9aacd
5 changed files with 58 additions and 59 deletions

View file

@ -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)
}

View file

@ -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)
}

View file

@ -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)
}

View file

@ -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 {

View file

@ -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