Skip to content

Commit

Permalink
feat(migration): fix issue where the path of a deleted trie node cou…
Browse files Browse the repository at this point in the history
…ld not be retrieved in certain situations
  • Loading branch information
0xbenyun committed Dec 11, 2024
1 parent 8d10579 commit fdc45ca
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 93 deletions.
2 changes: 1 addition & 1 deletion migration/migrator_newstate.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ func (m *StateMigrator) applyAccountChanges(tr *trie.StateTrie, bn uint64, root
}
// if set is nil, it means there are no changes, so we skip verification in that case.
if set != nil {
if err := m.validateStorage(storageTr, id, addr, set, bn); err != nil {
if err := m.validateStorage(storageTr, addr, set, bn); err != nil {
return err
}
}
Expand Down
135 changes: 50 additions & 85 deletions migration/migrator_validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"sync/atomic"
"time"

"github.com/status-im/keycard-go/hexutils"
"golang.org/x/sync/errgroup"

"github.com/ethereum/go-ethereum/common"
Expand Down Expand Up @@ -175,61 +174,49 @@ func (m *StateMigrator) validateState(tr *trie.StateTrie, set *trienode.NodeSet,
if err != nil {
return err
}
originTrie, err := trie.NewStateTrie(trie.StateTrieID(prevRoot), m.mptdb)
if err != nil {
return err
}
updatedRootNode := set.Nodes[""].Blob
originRootNode, _, err := originTrie.GetNode([]byte(""))

rootNode := set.Nodes[""].Blob
if err != nil {
return err
}

var deletedLeaves []*StateAccount
var updatedLeaves []*StateAccount

for hk := range set.DeletedKeys {
preimage := tr.GetKey(hk.Bytes())
if preimage == nil {
return fmt.Errorf("failed to get preimage for hashKey: %x", hk)
} else {
addr := common.BytesToAddress(preimage)
deletedLeaves = append(deletedLeaves, &StateAccount{addr, nil})
}
}

for path, node := range set.Nodes {
if node.IsDeleted() {
blob, _, err := originTrie.GetNode(trie.HexToCompact(path))
if !node.IsDeleted() {
hk, err := trie.GetKeyFromPath(rootNode, m.db, []byte(path))
if err != nil {
return err
}
if blob != nil && trie.IsLeafNode(blob) {
hk, err := trie.GetKeyFromPath(originRootNode, m.db, []byte(path))
if err != nil {
return err
}
preimage := tr.GetKey(hk)
if preimage == nil {
return fmt.Errorf("failed to get preimage for hashKey: %x", hk)
}
addr := common.BytesToAddress(preimage)
deletedLeaves = append(deletedLeaves, &StateAccount{addr, nil})
preimage := tr.GetKey(hk)
if preimage == nil {
return fmt.Errorf("failed to get preimage for hashKey: %x", hk)
}
} else {
if trie.IsLeafNode(node.Blob) {
hk, err := trie.GetKeyFromPath(updatedRootNode, m.db, []byte(path))
if err != nil {
return err
}
preimage := tr.GetKey(hk)
if preimage == nil {
return fmt.Errorf("failed to get preimage for hashKey: %x", hk)
}
addr := common.BytesToAddress(preimage)
acc, err := trie.NodeBlobToAccount(node.Blob)
if err != nil {
return err
}
// StorageRoot is already validated in storage verification stage
if zkAcc, err := zkTr.GetAccount(addr); err != nil {
return err
} else if zkAcc == nil {
acc.Root = common.Hash{}
} else {
acc.Root = zkAcc.Root
}
updatedLeaves = append(updatedLeaves, &StateAccount{addr, acc})
addr := common.BytesToAddress(preimage)
acc, err := trie.NodeBlobToAccount(node.Blob)
if err != nil {
return err
}
// StorageRoot is already validated in storage verification stage
if zkAcc, err := zkTr.GetAccount(addr); err != nil {
return err
} else if zkAcc == nil {
acc.Root = common.Hash{}
} else {
acc.Root = zkAcc.Root
}
updatedLeaves = append(updatedLeaves, &StateAccount{addr, acc})
}
}

Expand All @@ -256,7 +243,7 @@ func (m *StateMigrator) validateState(tr *trie.StateTrie, set *trienode.NodeSet,
return nil
}

func (m *StateMigrator) validateStorage(tr *trie.StateTrie, id *trie.ID, addr common.Address, set *trienode.NodeSet, bn uint64) error {
func (m *StateMigrator) validateStorage(tr *trie.StateTrie, addr common.Address, set *trienode.NodeSet, bn uint64) error {
if set == nil {
return nil
}
Expand All @@ -283,46 +270,29 @@ func (m *StateMigrator) validateStorage(tr *trie.StateTrie, id *trie.ID, addr co
if err != nil {
return err
}
originTrie, err := trie.NewStateTrie(id, m.mptdb)
if err != nil {
return err
}
updatedRootNode := set.Nodes[""].Blob
originRootNode, _, err := originTrie.GetNode([]byte(""))
rootNode := set.Nodes[""].Blob
if err != nil {
return err
}

var deletedLeaves []*Slot
var updatedLeaves []*Slot
for path, node := range set.Nodes {
if node.IsDeleted() {
blob, _, err := originTrie.GetNode(trie.HexToCompact(path))
if err != nil {
return err
}

if blob != nil && trie.IsLeafNode(blob) {
hk, err := trie.GetKeyFromPath(originRootNode, m.db, []byte(path))
if err != nil {
return err
}
preimage := tr.GetKey(hk)
if preimage == nil {
return fmt.Errorf("failed to get preimage for hashKey: %x", hk)
}
slot := common.BytesToHash(preimage).Bytes()
deletedLeaves = append(deletedLeaves, &Slot{slot, nil})
if addr.Cmp(common.HexToAddress("0x51901916b0a8A67b18299bb6fA16da4D7428f9cA")) == 0 {
if bytes.Compare(slot, hexutils.HexToBytes("5be7a1449cff78980bfa293037675a1770f220327e9386d49ba469c7210536a4")) == 0 {
fmt.Printf("[DeleteStorage]\n")
}
}

}
for hk := range set.DeletedKeys {
preimage := tr.GetKey(hk.Bytes())
if preimage == nil {
return fmt.Errorf("failed to get preimage for hashKey: %x", hk)
} else {
slot := common.BytesToHash(preimage).Bytes()
deletedLeaves = append(deletedLeaves, &Slot{slot, nil})

}
}

for path, node := range set.Nodes {
if !node.IsDeleted() {
if trie.IsLeafNode(node.Blob) {
hk, err := trie.GetKeyFromPath(updatedRootNode, m.db, []byte(path))
hk, err := trie.GetKeyFromPath(rootNode, m.db, []byte(path))
if err != nil {
return err
}
Expand All @@ -336,11 +306,6 @@ func (m *StateMigrator) validateStorage(tr *trie.StateTrie, id *trie.ID, addr co
return err
}
updatedLeaves = append(updatedLeaves, &Slot{slot, val})
if addr.Cmp(common.HexToAddress("0x51901916b0a8A67b18299bb6fA16da4D7428f9cA")) == 0 {
if bytes.Compare(slot, hexutils.HexToBytes("5be7a1449cff78980bfa293037675a1770f220327e9386d49ba469c7210536a4")) == 0 {
fmt.Printf("[UpdateStorage] path %x slot %x\n", []byte(path), slot)
}
}
}
}
}
Expand Down Expand Up @@ -376,10 +341,10 @@ func (m *StateMigrator) validateStorage(tr *trie.StateTrie, id *trie.ID, addr co
return fmt.Errorf("account doesn't exist: %s", addr.Hex())
} else {
if zktRoot.Cmp(zkAcc.Root) != 0 {
//err := m.printStoragesForDebug(zkAcc.Root, parentZkt)
//if err != nil {
// panic(err)
//}
err := m.printStoragesForDebug(zkAcc.Root, parentZkt)
if err != nil {
panic(err)
}
return fmt.Errorf("invalid migrated storage of account: %s", addr.Hex())
}
}
Expand Down
16 changes: 16 additions & 0 deletions trie/tracer.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ type tracer struct {
inserts map[string]struct{}
deletes map[string]struct{}
accessList map[string][]byte
// [Kroma: START]
deletedKeys map[common.Hash]bool
// [Kroma: ENd]
}

// newTracer initializes the tracer for capturing trie changes.
Expand All @@ -51,6 +54,9 @@ func newTracer() *tracer {
inserts: make(map[string]struct{}),
deletes: make(map[string]struct{}),
accessList: make(map[string][]byte),
// [Kroma: START]
deletedKeys: make(map[common.Hash]bool),
// [Kroma: END]
}
}

Expand Down Expand Up @@ -88,6 +94,9 @@ func (t *tracer) reset() {
t.inserts = make(map[string]struct{})
t.deletes = make(map[string]struct{})
t.accessList = make(map[string][]byte)
// [Kroma: START]
t.deletedKeys = make(map[common.Hash]bool)
// [Kroma: END]
}

// copy returns a deep copied tracer instance.
Expand Down Expand Up @@ -128,3 +137,10 @@ func (t *tracer) deletedNodes() []string {
}
return paths
}

// [Kroma: START]
func (t *tracer) onDeleteKroma(key []byte) {
t.deletedKeys[common.BytesToHash(key)] = true
}

// [Kroma: END]
11 changes: 10 additions & 1 deletion trie/trie.go
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,9 @@ func (t *Trie) delete(n node, prefix, key []byte) (bool, node, error) {
// need to be tracked at all since it's always embedded.
t.tracer.onDelete(prefix)

// [Kroma: START]
t.tracer.onDeleteKroma(hexToKeybytes(append(prefix, key...)))
// [Kroma: END]
return true, nil, nil // remove n entirely for whole matches
}
// The key is longer than n.Key. Remove the remaining suffix
Expand Down Expand Up @@ -528,8 +531,8 @@ func (t *Trie) delete(n node, prefix, key []byte) (bool, node, error) {
// Replace the entire full node with the short node.
// Mark the original short node as deleted since the
// value is embedded into the parent now.
t.tracer.onDelete(append(prefix, byte(pos)))

t.tracer.onDelete(append(prefix, byte(pos)))
k := append([]byte{byte(pos)}, cnode.Key...)
return true, &shortNode{k, cnode.Val, t.newFlag()}, nil
}
Expand Down Expand Up @@ -625,6 +628,9 @@ func (t *Trie) Commit(collectLeaf bool) (common.Hash, *trienode.NodeSet, error)
for _, path := range paths {
nodes.AddNode([]byte(path), trienode.NewDeleted())
}
// [Kroma: START]
nodes.DeletedKeys = t.tracer.deletedKeys
// [Kroma: END]
return types.EmptyRootHash, nodes, nil // case (b)
}
// Derive the hash for all dirty nodes first. We hold the assumption
Expand All @@ -643,6 +649,9 @@ func (t *Trie) Commit(collectLeaf bool) (common.Hash, *trienode.NodeSet, error)
for _, path := range t.tracer.deletedNodes() {
nodes.AddNode([]byte(path), trienode.NewDeleted())
}
// [Kroma: START]
nodes.DeletedKeys = t.tracer.deletedKeys
// [Kroma: END]
t.root = newCommitter(nodes, t.tracer, collectLeaf).Commit(t.root)
return rootHash, nodes, nil
}
Expand Down
13 changes: 7 additions & 6 deletions trie/trienode/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,12 @@ type leaf struct {
// NodeSet contains a set of nodes collected during the commit operation.
// Each node is keyed by path. It's not thread-safe to use.
type NodeSet struct {
Owner common.Hash
Leaves []*leaf
Nodes map[string]*Node
updates int // the count of updated and inserted nodes
deletes int // the count of deleted nodes
Owner common.Hash
Leaves []*leaf
Nodes map[string]*Node
updates int // the count of updated and inserted nodes
deletes int // the count of deleted nodes
DeletedKeys map[common.Hash]bool
}

// NewNodeSet initializes a node set. The owner is zero for the account trie and
Expand Down Expand Up @@ -142,7 +143,7 @@ func (set *NodeSet) Hashes() []common.Hash {

// Summary returns a string-representation of the NodeSet.
func (set *NodeSet) Summary() string {
var out = new(strings.Builder)
out := new(strings.Builder)
fmt.Fprintf(out, "nodeset owner: %v\n", set.Owner)
if set.Nodes != nil {
for path, n := range set.Nodes {
Expand Down

0 comments on commit fdc45ca

Please sign in to comment.