mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-25 22:26:42 +00:00
trie, light: Rename Storage to PersistentMap
This commit is contained in:
parent
de5a818baa
commit
5b73f9aacd
5 changed files with 58 additions and 59 deletions
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
12
trie/trie.go
12
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
|
||||
|
|
|
|||
Loading…
Reference in a new issue