Skip to content

Commit 7131290

Browse files
authored
fix(lib/trie): PopulateMerkleValues functionality changes and fixes (#2871)
- Include Merkle value of the parent node passed as argument - Update comment all nodes are expected to have their Merkle value computed - Enforce all nodes to have their Merkle value computed with a `panic`
1 parent ace6b32 commit 7131290

File tree

3 files changed

+122
-13
lines changed

3 files changed

+122
-13
lines changed

dot/state/offline_pruner.go

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

124-
tr.PopulateMerkleValues(tr.RootNode(), merkleValues)
124+
trie.PopulateNodeHashes(tr.RootNode(), merkleValues)
125125

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

lib/trie/database.go

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -185,22 +185,35 @@ func (t *Trie) loadNode(db Database, n *Node) error {
185185
return nil
186186
}
187187

188-
// PopulateMerkleValues writes the Merkle value of each children of the node given
189-
// as keys to the map merkleValues.
190-
func (t *Trie) PopulateMerkleValues(n *Node, merkleValues map[string]struct{}) {
191-
if n.Kind() != node.Branch {
188+
// PopulateNodeHashes writes the node hash values of the node given and of
189+
// all its descendant nodes as keys to the nodeHashes map.
190+
// It is assumed the node and its descendant nodes have their Merkle value already
191+
// computed.
192+
func PopulateNodeHashes(n *Node, nodeHashes map[string]struct{}) {
193+
if n == nil {
192194
return
193195
}
194196

195-
branch := n
196-
for _, child := range branch.Children {
197-
if child == nil {
198-
continue
199-
}
197+
switch {
198+
case len(n.MerkleValue) == 0:
199+
// TODO remove once lazy loading of nodes is implemented
200+
// https://github.com/ChainSafe/gossamer/issues/2838
201+
panic(fmt.Sprintf("node with key 0x%x has no Merkle value computed", n.Key))
202+
case len(n.MerkleValue) < 32:
203+
// Inlined node where its Merkle value is its
204+
// encoding and not the encoding hash digest.
205+
return
206+
}
200207

201-
merkleValues[string(child.MerkleValue)] = struct{}{}
208+
nodeHashes[string(n.MerkleValue)] = struct{}{}
202209

203-
t.PopulateMerkleValues(child, merkleValues)
210+
if n.Kind() == node.Leaf {
211+
return
212+
}
213+
214+
branch := n
215+
for _, child := range branch.Children {
216+
PopulateNodeHashes(child, nodeHashes)
204217
}
205218
}
206219

lib/trie/database_test.go

Lines changed: 97 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,103 @@ 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_PopulateNodeHashes(t *testing.T) {
162+
t.Parallel()
163+
164+
const (
165+
merkleValue32Zeroes = "00000000000000000000000000000000"
166+
merkleValue32Ones = "11111111111111111111111111111111"
167+
merkleValue32Twos = "22222222222222222222222222222222"
168+
merkleValue32Threes = "33333333333333333333333333333333"
169+
)
170+
171+
testCases := map[string]struct {
172+
node *Node
173+
nodeHashes map[string]struct{}
174+
panicValue interface{}
175+
}{
176+
"nil node": {
177+
nodeHashes: map[string]struct{}{},
178+
},
179+
"inlined leaf node": {
180+
node: &Node{MerkleValue: []byte("a")},
181+
nodeHashes: map[string]struct{}{},
182+
},
183+
"leaf node": {
184+
node: &Node{MerkleValue: []byte(merkleValue32Zeroes)},
185+
nodeHashes: map[string]struct{}{
186+
merkleValue32Zeroes: {},
187+
},
188+
},
189+
"leaf node without Merkle value": {
190+
node: &Node{Key: []byte{1}, SubValue: []byte{2}},
191+
panicValue: "node with key 0x01 has no Merkle value computed",
192+
},
193+
"inlined branch node": {
194+
node: &Node{
195+
MerkleValue: []byte("a"),
196+
Children: padRightChildren([]*Node{
197+
{MerkleValue: []byte("b")},
198+
}),
199+
},
200+
nodeHashes: map[string]struct{}{},
201+
},
202+
"branch node": {
203+
node: &Node{
204+
MerkleValue: []byte(merkleValue32Zeroes),
205+
Children: padRightChildren([]*Node{
206+
{MerkleValue: []byte(merkleValue32Ones)},
207+
}),
208+
},
209+
nodeHashes: map[string]struct{}{
210+
merkleValue32Zeroes: {},
211+
merkleValue32Ones: {},
212+
},
213+
},
214+
"nested branch node": {
215+
node: &Node{
216+
MerkleValue: []byte(merkleValue32Zeroes),
217+
Children: padRightChildren([]*Node{
218+
{MerkleValue: []byte(merkleValue32Ones)},
219+
{
220+
MerkleValue: []byte(merkleValue32Twos),
221+
Children: padRightChildren([]*Node{
222+
{MerkleValue: []byte(merkleValue32Threes)},
223+
}),
224+
},
225+
}),
226+
},
227+
nodeHashes: map[string]struct{}{
228+
merkleValue32Zeroes: {},
229+
merkleValue32Ones: {},
230+
merkleValue32Twos: {},
231+
merkleValue32Threes: {},
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+
nodeHashes := make(map[string]struct{})
242+
243+
if testCase.panicValue != nil {
244+
assert.PanicsWithValue(t, testCase.panicValue, func() {
245+
PopulateNodeHashes(testCase.node, nodeHashes)
246+
})
247+
return
248+
}
249+
250+
PopulateNodeHashes(testCase.node, nodeHashes)
251+
252+
assert.Equal(t, testCase.nodeHashes, nodeHashes)
253+
})
254+
}
255+
}
256+
257+
func Test_GetFromDB(t *testing.T) {
162258
t.Parallel()
163259

164260
const size = 1000

0 commit comments

Comments
 (0)