Skip to content

Commit

Permalink
core/state: move slot RLP encoding into the MPT implementation (ether…
Browse files Browse the repository at this point in the history
…eum#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.
  • Loading branch information
gballet authored and devopsbo3 committed Nov 10, 2023
1 parent c51cd2d commit 797c100
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 21 deletions.
33 changes: 18 additions & 15 deletions core/state/state_object.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,15 +183,23 @@ func (s *stateObject) GetCommittedState(db Database, key common.Hash) common.Has
}
// If no live objects are available, attempt to use snapshots
var (
enc []byte
err error
enc []byte
err error
value common.Hash
)
if s.db.snap != nil {
start := time.Now()
enc, err = s.db.snap.Storage(s.addrHash, crypto.Keccak256Hash(key.Bytes()))
if metrics.EnabledExpensive {
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 s.db.snap == nil || err != nil {
Expand All @@ -201,22 +209,15 @@ func (s *stateObject) GetCommittedState(db Database, key common.Hash) common.Has
s.db.setError(err)
return common.Hash{}
}
enc, err = tr.GetStorage(s.address, key.Bytes())
val, err := tr.GetStorage(s.address, key.Bytes())
if metrics.EnabledExpensive {
s.db.StorageReads += time.Since(start)
}
if err != nil {
s.db.setError(err)
return common.Hash{}
}
}
var value common.Hash
if len(enc) > 0 {
_, content, _, err := rlp.Split(enc)
if err != nil {
s.db.setError(err)
}
value.SetBytes(content)
value.SetBytes(val)
}
s.originStorage[key] = value
return value
Expand Down Expand Up @@ -292,17 +293,19 @@ func (s *stateObject) updateTrie(db Database) (Trie, error) {
}
s.originStorage[key] = value

var v []byte
// rlp-encoded value to be used by the snapshot
var snapshotVal []byte
if (value == common.Hash{}) {
if err := tr.DeleteStorage(s.address, key[:]); err != nil {
s.db.setError(err)
return nil, err
}
s.db.StorageDeleted += 1
} else {
trimmedVal := common.TrimLeftZeroes(value[:])
// Encoding []byte cannot fail, ok to ignore the error.
v, _ = rlp.EncodeToBytes(common.TrimLeftZeroes(value[:]))
if err := tr.UpdateStorage(s.address, key[:], v); err != nil {
snapshotVal, _ = rlp.EncodeToBytes(trimmedVal)
if err := tr.UpdateStorage(s.address, key[:], trimmedVal); err != nil {
s.db.setError(err)
return nil, err
}
Expand All @@ -317,7 +320,7 @@ func (s *stateObject) updateTrie(db Database) (Trie, error) {
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
}
Expand Down
13 changes: 9 additions & 4 deletions light/trie.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,12 +108,16 @@ type odrTrie struct {

func (t *odrTrie) GetStorage(_ common.Address, key []byte) ([]byte, error) {
key = crypto.Keccak256(key)
var res []byte
var enc []byte
err := t.do(key, func() (err error) {
res, err = t.trie.Get(key)
enc, err = t.trie.Get(key)
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) {
Expand Down Expand Up @@ -145,8 +149,9 @@ func (t *odrTrie) UpdateAccount(address common.Address, acc *types.StateAccount)

func (t *odrTrie) UpdateStorage(_ common.Address, key, value []byte) error {
key = crypto.Keccak256(key)
v, _ := rlp.EncodeToBytes(value)
return t.do(key, func() error {
return t.trie.Update(key, value)
return t.trie.Update(key, v)
})
}

Expand Down
10 changes: 8 additions & 2 deletions trie/secure_trie.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 a trie node is not found in the database, a MissingNodeError is returned.
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.
Expand Down Expand Up @@ -148,7 +153,8 @@ func (t *StateTrie) MustUpdate(key, value []byte) {
// If a node is not found in the database, a MissingNodeError is returned.
func (t *StateTrie) UpdateStorage(_ common.Address, key, value []byte) error {
hk := t.hashKey(key)
err := t.trie.Update(hk, value)
v, _ := rlp.EncodeToBytes(value)
err := t.trie.Update(hk, v)
if err != nil {
return err
}
Expand Down

0 comments on commit 797c100

Please sign in to comment.