Skip to content

Commit 6561b9c

Browse files
committed
fix(trie): PopulateMerkleValues behavior
- Include Merkle value of the parent node passed as argument - Calculate missing Merkle values if needed - Add unit test
1 parent f033c35 commit 6561b9c

File tree

3 files changed

+130
-11
lines changed

3 files changed

+130
-11
lines changed

dot/state/offline_pruner.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,10 @@ func (p *OfflinePruner) SetBloomFilter() (err error) {
121121
return err
122122
}
123123

124-
tr.PopulateMerkleValues(tr.RootNode(), merkleValues)
124+
err = tr.PopulateMerkleValues(tr.RootNode(), merkleValues)
125+
if err != nil {
126+
return fmt.Errorf("populating Merkle values from trie: %w", err)
127+
}
125128

126129
// get parent header of current block
127130
header, err = p.blockState.GetHeader(header.ParentHash)

lib/trie/database.go

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -187,21 +187,44 @@ func (t *Trie) loadNode(db Database, n *Node) error {
187187

188188
// PopulateMerkleValues writes the Merkle value of each children of the node given
189189
// as keys to the map merkleValues.
190-
func (t *Trie) PopulateMerkleValues(n *Node, merkleValues map[string]struct{}) {
191-
if n.Kind() != node.Branch {
192-
return
190+
func (t *Trie) PopulateMerkleValues(n *Node,
191+
merkleValues map[string]struct{}) (err error) {
192+
if n == nil {
193+
return nil
193194
}
194195

195-
branch := n
196-
for _, child := range branch.Children {
197-
if child == nil {
198-
continue
196+
merkleValue := n.MerkleValue
197+
if len(merkleValue) == 0 {
198+
// Compute and cache node Merkle value if it is absent.
199+
if n == t.root {
200+
merkleValue, err = n.CalculateRootMerkleValue()
201+
if err != nil {
202+
return fmt.Errorf("calculating Merkle value for root node: %w", err)
203+
}
204+
} else {
205+
merkleValue, err = n.CalculateMerkleValue()
206+
if err != nil {
207+
return fmt.Errorf("calculating Merkle value for node: %w", err)
208+
}
199209
}
210+
}
200211

201-
merkleValues[string(child.MerkleValue)] = struct{}{}
212+
merkleValues[string(merkleValue)] = struct{}{}
213+
214+
if n.Kind() == node.Leaf {
215+
return nil
216+
}
202217

203-
t.PopulateMerkleValues(child, merkleValues)
218+
branch := n
219+
for _, child := range branch.Children {
220+
err = t.PopulateMerkleValues(child, merkleValues)
221+
if err != nil {
222+
// Note: do not wrap error since this is recursive.
223+
return err
224+
}
204225
}
226+
227+
return nil
205228
}
206229

207230
// GetFromDB retrieves a value at the given key from the trie using the database.

lib/trie/database_test.go

Lines changed: 94 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,100 @@ func Test_Trie_WriteDirty_ClearPrefix(t *testing.T) {
158158
assert.Equal(t, trie.String(), trieFromDB.String())
159159
}
160160

161-
func Test_Trie_GetFromDB(t *testing.T) {
161+
func Test_PopulateMerkleValues(t *testing.T) {
162+
t.Parallel()
163+
164+
someNode := &Node{Key: []byte{1}, SubValue: []byte{2}}
165+
166+
testCases := map[string]struct {
167+
trie *Trie
168+
node *Node
169+
merkleValues map[string]struct{}
170+
errSentinel error
171+
errMessage string
172+
}{
173+
"nil node": {
174+
trie: &Trie{},
175+
merkleValues: map[string]struct{}{},
176+
},
177+
"leaf node": {
178+
trie: &Trie{},
179+
node: &Node{MerkleValue: []byte("a")},
180+
merkleValues: map[string]struct{}{
181+
"a": {},
182+
},
183+
},
184+
"leaf node without Merkle value": {
185+
trie: &Trie{},
186+
node: &Node{Key: []byte{1}, SubValue: []byte{2}},
187+
merkleValues: map[string]struct{}{
188+
"A\x01\x04\x02": {},
189+
},
190+
},
191+
"root leaf node without Merkle value": {
192+
trie: &Trie{
193+
root: someNode,
194+
},
195+
node: someNode,
196+
merkleValues: map[string]struct{}{
197+
"`Qm\v\xb6\xe1\xbb\xfb\x12\x93\xf1\xb2v\xea\x95\x05\xe9\xf4\xa4\xe7ُb\r\x05\x11^\v\x85'J\xe1": {},
198+
},
199+
},
200+
"branch node": {
201+
trie: &Trie{},
202+
node: &Node{
203+
MerkleValue: []byte("a"),
204+
Children: padRightChildren([]*Node{
205+
{MerkleValue: []byte("b")},
206+
}),
207+
},
208+
merkleValues: map[string]struct{}{
209+
"a": {},
210+
"b": {},
211+
},
212+
},
213+
"nested branch node": {
214+
trie: &Trie{},
215+
node: &Node{
216+
MerkleValue: []byte("a"),
217+
Children: padRightChildren([]*Node{
218+
{MerkleValue: []byte("b")},
219+
{
220+
MerkleValue: []byte("c"),
221+
Children: padRightChildren([]*Node{
222+
{MerkleValue: []byte("d")},
223+
}),
224+
},
225+
}),
226+
},
227+
merkleValues: map[string]struct{}{
228+
"a": {},
229+
"b": {},
230+
"c": {},
231+
"d": {},
232+
},
233+
},
234+
}
235+
236+
for name, testCase := range testCases {
237+
testCase := testCase
238+
t.Run(name, func(t *testing.T) {
239+
t.Parallel()
240+
241+
merkleValues := make(map[string]struct{})
242+
243+
err := testCase.trie.PopulateMerkleValues(testCase.node, merkleValues)
244+
245+
assert.ErrorIs(t, err, testCase.errSentinel)
246+
if testCase.errSentinel != nil {
247+
assert.EqualError(t, err, testCase.errMessage)
248+
}
249+
assert.Equal(t, testCase.merkleValues, merkleValues)
250+
})
251+
}
252+
}
253+
254+
func Test_GetFromDB(t *testing.T) {
162255
t.Parallel()
163256

164257
const size = 1000

0 commit comments

Comments
 (0)