From c3916ef2c35c61b21063ebecb137273e3ce9f6eb Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Thu, 6 Mar 2025 15:48:27 +0300 Subject: [PATCH] mpt: introduce DummySTTempStoragePrefix Use this constant as a dummy contract storage item prefix for those situations when Billet is used as an MPT search wrapper. Otherwise it's confusing to see `0` passed as a storage prefix to the billet constructor and then panic inside the Billet's code if this prefix is `0`. Ref. https://github.com/nspcc-dev/neo-go/pull/2201. Signed-off-by: Anna Shaleva --- pkg/core/mpt/billet.go | 10 +++++++++- pkg/core/mpt/trie.go | 2 +- pkg/core/mpt/trie_store.go | 2 +- pkg/core/statesync/module.go | 2 +- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/pkg/core/mpt/billet.go b/pkg/core/mpt/billet.go index e6495beaf..021f634ea 100644 --- a/pkg/core/mpt/billet.go +++ b/pkg/core/mpt/billet.go @@ -11,6 +11,14 @@ import ( "github.com/nspcc-dev/neo-go/pkg/util" ) +// DummySTTempStoragePrefix is a dummy contract storage item prefix that may be +// passed to Billet constructor when Billet's restoring functionality is not +// used, i.e. for those situations when only traversal functionality is used. +// Note that using this prefix for MPT restoring is an error which will lead to +// a panic since Billet must have the ability to save contract storage items to +// the underlying DB during MPT restore process. +const DummySTTempStoragePrefix = 0x00 + var ( // ErrRestoreFailed is returned when replacing HashNode by its "unhashed" // candidate fails. @@ -68,7 +76,7 @@ func (b *Billet) RestoreHashNode(path []byte, node Node) error { // If it's a leaf, then put into temporary contract storage. if leaf, ok := node.(*LeafNode); ok { - if b.TempStoragePrefix == 0 { + if b.TempStoragePrefix == DummySTTempStoragePrefix { panic("invalid storage prefix") } k := append([]byte{byte(b.TempStoragePrefix)}, fromNibbles(path)...) diff --git a/pkg/core/mpt/trie.go b/pkg/core/mpt/trie.go index f0e807c0b..d8b9a3af7 100644 --- a/pkg/core/mpt/trie.go +++ b/pkg/core/mpt/trie.go @@ -612,7 +612,7 @@ func (t *Trie) Find(prefix, from []byte, maxNum int) ([]storage.KeyValue, error) res []storage.KeyValue count int ) - b := NewBillet(t.root.Hash(), t.mode, 0, t.Store) + b := NewBillet(t.root.Hash(), t.mode, DummySTTempStoragePrefix, t.Store) process := func(pathToNode []byte, node Node, _ []byte) bool { if leaf, ok := node.(*LeafNode); ok { if from == nil || !bytes.Equal(pathToNode, from) { // (*Billet).traverse includes `from` path into result if so. Need to filter out manually. diff --git a/pkg/core/mpt/trie_store.go b/pkg/core/mpt/trie_store.go index 3ab800088..e98859e06 100644 --- a/pkg/core/mpt/trie_store.go +++ b/pkg/core/mpt/trie_store.go @@ -94,7 +94,7 @@ func (m *TrieStore) Seek(rng storage.SeekRange, f func(k, v []byte) bool) { } } - b := NewBillet(m.trie.root.Hash(), m.trie.mode, 0, m.trie.Store) + b := NewBillet(m.trie.root.Hash(), m.trie.mode, DummySTTempStoragePrefix, m.trie.Store) process := func(pathToNode []byte, node Node, _ []byte) bool { if leaf, ok := node.(*LeafNode); ok { // (*Billet).traverse includes `from` path into the result if so. It's OK for Seek, so shouldn't be filtered out. diff --git a/pkg/core/statesync/module.go b/pkg/core/statesync/module.go index b129bf67f..770c63d58 100644 --- a/pkg/core/statesync/module.go +++ b/pkg/core/statesync/module.go @@ -551,7 +551,7 @@ func (s *Module) Traverse(root util.Uint256, process func(node mpt.Node, nodeByt if s.bc.GetConfig().Ledger.KeepOnlyLatestState || s.bc.GetConfig().Ledger.RemoveUntraceableBlocks { mode |= mpt.ModeLatest } - b := mpt.NewBillet(root, mode, 0, storage.NewMemCachedStore(s.dao.Store)) + b := mpt.NewBillet(root, mode, mpt.DummySTTempStoragePrefix, storage.NewMemCachedStore(s.dao.Store)) return b.Traverse(func(pathToNode []byte, node mpt.Node, nodeBytes []byte) bool { return process(node, nodeBytes) }, false)