Unverified Commit 45a3ab42 authored by Guillaume Ballet's avatar Guillaume Ballet Committed by GitHub

core/state: move slot RLP encoding into the MPT implementation (#27000)

Continuing with a series of PRs to make the Trie interface more generic, this PR moves
the RLP encoding of storage slots inside the StateTrie and light.Trie implementations,
as other types of tries don't use RLP.
parent ac86547b
...@@ -183,8 +183,9 @@ func (s *stateObject) GetCommittedState(db Database, key common.Hash) common.Has ...@@ -183,8 +183,9 @@ func (s *stateObject) GetCommittedState(db Database, key common.Hash) common.Has
} }
// If no live objects are available, attempt to use snapshots // If no live objects are available, attempt to use snapshots
var ( var (
enc []byte enc []byte
err error err error
value common.Hash
) )
if s.db.snap != nil { if s.db.snap != nil {
start := time.Now() start := time.Now()
...@@ -192,6 +193,13 @@ func (s *stateObject) GetCommittedState(db Database, key common.Hash) common.Has ...@@ -192,6 +193,13 @@ func (s *stateObject) GetCommittedState(db Database, key common.Hash) common.Has
if metrics.EnabledExpensive { if metrics.EnabledExpensive {
s.db.SnapshotStorageReads += time.Since(start) s.db.SnapshotStorageReads += time.Since(start)
} }
if len(enc) > 0 {
_, content, _, err := rlp.Split(enc)
if err != nil {
s.db.setError(err)
}
value.SetBytes(content)
}
} }
// If the snapshot is unavailable or reading from it fails, load from the database. // If the snapshot is unavailable or reading from it fails, load from the database.
if s.db.snap == nil || err != nil { if s.db.snap == nil || err != nil {
...@@ -201,7 +209,7 @@ func (s *stateObject) GetCommittedState(db Database, key common.Hash) common.Has ...@@ -201,7 +209,7 @@ func (s *stateObject) GetCommittedState(db Database, key common.Hash) common.Has
s.db.setError(err) s.db.setError(err)
return common.Hash{} return common.Hash{}
} }
enc, err = tr.GetStorage(s.address, key.Bytes()) val, err := tr.GetStorage(s.address, key.Bytes())
if metrics.EnabledExpensive { if metrics.EnabledExpensive {
s.db.StorageReads += time.Since(start) s.db.StorageReads += time.Since(start)
} }
...@@ -209,14 +217,7 @@ func (s *stateObject) GetCommittedState(db Database, key common.Hash) common.Has ...@@ -209,14 +217,7 @@ func (s *stateObject) GetCommittedState(db Database, key common.Hash) common.Has
s.db.setError(err) s.db.setError(err)
return common.Hash{} return common.Hash{}
} }
} value.SetBytes(val)
var value common.Hash
if len(enc) > 0 {
_, content, _, err := rlp.Split(enc)
if err != nil {
s.db.setError(err)
}
value.SetBytes(content)
} }
s.originStorage[key] = value s.originStorage[key] = value
return value return value
...@@ -292,7 +293,8 @@ func (s *stateObject) updateTrie(db Database) (Trie, error) { ...@@ -292,7 +293,8 @@ func (s *stateObject) updateTrie(db Database) (Trie, error) {
} }
s.originStorage[key] = value s.originStorage[key] = value
var v []byte // rlp-encoded value to be used by the snapshot
var snapshotVal []byte
if (value == common.Hash{}) { if (value == common.Hash{}) {
if err := tr.DeleteStorage(s.address, key[:]); err != nil { if err := tr.DeleteStorage(s.address, key[:]); err != nil {
s.db.setError(err) s.db.setError(err)
...@@ -300,9 +302,10 @@ func (s *stateObject) updateTrie(db Database) (Trie, error) { ...@@ -300,9 +302,10 @@ func (s *stateObject) updateTrie(db Database) (Trie, error) {
} }
s.db.StorageDeleted += 1 s.db.StorageDeleted += 1
} else { } else {
trimmedVal := common.TrimLeftZeroes(value[:])
// Encoding []byte cannot fail, ok to ignore the error. // Encoding []byte cannot fail, ok to ignore the error.
v, _ = rlp.EncodeToBytes(common.TrimLeftZeroes(value[:])) snapshotVal, _ = rlp.EncodeToBytes(trimmedVal)
if err := tr.UpdateStorage(s.address, key[:], v); err != nil { if err := tr.UpdateStorage(s.address, key[:], trimmedVal); err != nil {
s.db.setError(err) s.db.setError(err)
return nil, err return nil, err
} }
...@@ -317,7 +320,7 @@ func (s *stateObject) updateTrie(db Database) (Trie, error) { ...@@ -317,7 +320,7 @@ func (s *stateObject) updateTrie(db Database) (Trie, error) {
s.db.snapStorage[s.addrHash] = storage s.db.snapStorage[s.addrHash] = storage
} }
} }
storage[crypto.HashData(hasher, key[:])] = v // v will be nil if it's deleted storage[crypto.HashData(hasher, key[:])] = snapshotVal // will be nil if it's deleted
} }
usedStorage = append(usedStorage, common.CopyBytes(key[:])) // Copy needed for closure usedStorage = append(usedStorage, common.CopyBytes(key[:])) // Copy needed for closure
} }
......
...@@ -108,12 +108,16 @@ type odrTrie struct { ...@@ -108,12 +108,16 @@ type odrTrie struct {
func (t *odrTrie) GetStorage(_ common.Address, key []byte) ([]byte, error) { func (t *odrTrie) GetStorage(_ common.Address, key []byte) ([]byte, error) {
key = crypto.Keccak256(key) key = crypto.Keccak256(key)
var res []byte var enc []byte
err := t.do(key, func() (err error) { err := t.do(key, func() (err error) {
res, err = t.trie.Get(key) enc, err = t.trie.Get(key)
return err return err
}) })
return res, err if err != nil || len(enc) == 0 {
return nil, err
}
_, content, _, err := rlp.Split(enc)
return content, err
} }
func (t *odrTrie) GetAccount(address common.Address) (*types.StateAccount, error) { func (t *odrTrie) GetAccount(address common.Address) (*types.StateAccount, error) {
...@@ -145,8 +149,9 @@ func (t *odrTrie) UpdateAccount(address common.Address, acc *types.StateAccount) ...@@ -145,8 +149,9 @@ func (t *odrTrie) UpdateAccount(address common.Address, acc *types.StateAccount)
func (t *odrTrie) UpdateStorage(_ common.Address, key, value []byte) error { func (t *odrTrie) UpdateStorage(_ common.Address, key, value []byte) error {
key = crypto.Keccak256(key) key = crypto.Keccak256(key)
v, _ := rlp.EncodeToBytes(value)
return t.do(key, func() error { return t.do(key, func() error {
return t.trie.Update(key, value) return t.trie.Update(key, v)
}) })
} }
......
...@@ -86,7 +86,12 @@ func (t *StateTrie) MustGet(key []byte) []byte { ...@@ -86,7 +86,12 @@ func (t *StateTrie) MustGet(key []byte) []byte {
// If the specified storage slot is not in the trie, nil will be returned. // If the specified storage slot is not in the trie, nil will be returned.
// If a trie node is not found in the database, a MissingNodeError is returned. // If a trie node is not found in the database, a MissingNodeError is returned.
func (t *StateTrie) GetStorage(_ common.Address, key []byte) ([]byte, error) { func (t *StateTrie) GetStorage(_ common.Address, key []byte) ([]byte, error) {
return t.trie.Get(t.hashKey(key)) enc, err := t.trie.Get(t.hashKey(key))
if err != nil || len(enc) == 0 {
return nil, err
}
_, content, _, err := rlp.Split(enc)
return content, err
} }
// GetAccount attempts to retrieve an account with provided account address. // GetAccount attempts to retrieve an account with provided account address.
...@@ -148,7 +153,8 @@ func (t *StateTrie) MustUpdate(key, value []byte) { ...@@ -148,7 +153,8 @@ func (t *StateTrie) MustUpdate(key, value []byte) {
// If a node is not found in the database, a MissingNodeError is returned. // If a node is not found in the database, a MissingNodeError is returned.
func (t *StateTrie) UpdateStorage(_ common.Address, key, value []byte) error { func (t *StateTrie) UpdateStorage(_ common.Address, key, value []byte) error {
hk := t.hashKey(key) hk := t.hashKey(key)
err := t.trie.Update(hk, value) v, _ := rlp.EncodeToBytes(value)
err := t.trie.Update(hk, v)
if err != nil { if err != nil {
return err return err
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment