Skip to content
This repository was archived by the owner on Jun 6, 2025. It is now read-only.

Commit 8de85b0

Browse files
committed
trie: fix issue insert wrong path in stack trie and remove the offset when inserting in stack trie reference by 86fe359 (#604)
1 parent 351ac1e commit 8de85b0

File tree

1 file changed

+37
-44
lines changed

1 file changed

+37
-44
lines changed

trie/stacktrie.go

Lines changed: 37 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -58,13 +58,12 @@ func returnToPool(st *StackTrie) {
5858
// in order. Once it determines that a subtree will no longer be inserted
5959
// into, it will hash it and free up the memory it uses.
6060
type StackTrie struct {
61-
owner common.Hash // the owner of the trie
62-
nodeType uint8 // node type (as in branch, ext, leaf)
63-
val []byte // value contained by this node if it's a leaf
64-
key []byte // key chunk covered by this (full|ext) node
65-
keyOffset int // offset of the key chunk inside a full key
66-
children [16]*StackTrie // list of children (for fullnodes and exts)
67-
writeFn NodeWriteFunc // function for commiting nodes, can be nil
61+
owner common.Hash // the owner of the trie
62+
nodeType uint8 // node type (as in branch, ext, leaf)
63+
val []byte // value contained by this node if it's a leaf
64+
key []byte // key chunk covered by this (full|ext) node
65+
children [16]*StackTrie // list of children (for fullnodes and exts)
66+
writeFn NodeWriteFunc // function for commiting nodes, can be nil
6867
}
6968

7069
// NewStackTrie allocates and initializes an empty trie.
@@ -105,17 +104,15 @@ func (st *StackTrie) MarshalBinary() (data []byte, err error) {
105104
w = bufio.NewWriter(&b)
106105
)
107106
if err := gob.NewEncoder(w).Encode(struct {
108-
Owner common.Hash
109-
NodeType uint8
110-
Val []byte
111-
Key []byte
112-
KeyOffset uint8
107+
Owner common.Hash
108+
NodeType uint8
109+
Val []byte
110+
Key []byte
113111
}{
114112
st.owner,
115113
st.nodeType,
116114
st.val,
117115
st.key,
118-
uint8(st.keyOffset),
119116
}); err != nil {
120117
return nil, err
121118
}
@@ -143,18 +140,16 @@ func (st *StackTrie) UnmarshalBinary(data []byte) error {
143140

144141
func (st *StackTrie) unmarshalBinary(r io.Reader) error {
145142
var dec struct {
146-
Owner common.Hash
147-
NodeType uint8
148-
Val []byte
149-
Key []byte
150-
KeyOffset uint8
143+
Owner common.Hash
144+
NodeType uint8
145+
Val []byte
146+
Key []byte
151147
}
152148
gob.NewDecoder(r).Decode(&dec)
153149
st.owner = dec.Owner
154150
st.nodeType = dec.NodeType
155151
st.val = dec.Val
156152
st.key = dec.Key
157-
st.keyOffset = int(dec.KeyOffset)
158153

159154
var hasChild = make([]byte, 1)
160155
for i := range st.children {
@@ -179,20 +174,18 @@ func (st *StackTrie) setWriteFunc(writeFn NodeWriteFunc) {
179174
}
180175
}
181176

182-
func newLeaf(owner common.Hash, ko int, key, val []byte, writeFn NodeWriteFunc) *StackTrie {
177+
func newLeaf(owner common.Hash, key, val []byte, writeFn NodeWriteFunc) *StackTrie {
183178
st := stackTrieFromPool(writeFn, owner)
184179
st.nodeType = leafNode
185-
st.keyOffset = ko
186-
st.key = append(st.key, key[ko:]...)
180+
st.key = append(st.key, key...)
187181
st.val = val
188182
return st
189183
}
190184

191-
func newExt(owner common.Hash, ko int, key []byte, child *StackTrie, writeFn NodeWriteFunc) *StackTrie {
185+
func newExt(owner common.Hash, key []byte, child *StackTrie, writeFn NodeWriteFunc) *StackTrie {
192186
st := stackTrieFromPool(writeFn, owner)
193187
st.nodeType = extNode
194-
st.keyOffset = ko
195-
st.key = append(st.key, key[ko:]...)
188+
st.key = append(st.key, key...)
196189
st.children[0] = child
197190
return st
198191
}
@@ -231,25 +224,26 @@ func (st *StackTrie) Reset() {
231224
st.children[i] = nil
232225
}
233226
st.nodeType = emptyNode
234-
st.keyOffset = 0
235227
}
236228

237229
// Helper function that, given a full key, determines the index
238230
// at which the chunk pointed by st.keyOffset is different from
239231
// the same chunk in the full key.
240232
func (st *StackTrie) getDiffIndex(key []byte) int {
241-
diffindex := 0
242-
for ; diffindex < len(st.key) && st.key[diffindex] == key[st.keyOffset+diffindex]; diffindex++ {
233+
for idx, nibble := range st.key {
234+
if nibble != key[idx] {
235+
return idx
236+
}
243237
}
244-
return diffindex
238+
return len(st.key)
245239
}
246240

247241
// Helper function to that inserts a (key, value) pair into
248242
// the trie. Adding the prefix when inserting too.
249-
func (st *StackTrie) insert(key, value []byte, prefix []byte) {
243+
func (st *StackTrie) insert(key, value, prefix []byte) {
250244
switch st.nodeType {
251245
case branchNode: /* Branch */
252-
idx := int(key[st.keyOffset])
246+
idx := int(key[0])
253247
// Unresolve elder siblings
254248
for i := idx - 1; i >= 0; i-- {
255249
if st.children[i] != nil {
@@ -261,10 +255,11 @@ func (st *StackTrie) insert(key, value []byte, prefix []byte) {
261255
}
262256
// Add new child
263257
if st.children[idx] == nil {
264-
st.children[idx] = stackTrieFromPool(st.writeFn, st.owner)
265-
st.children[idx].keyOffset = st.keyOffset + 1
258+
st.children[idx] = newLeaf(st.owner, key[1:], value, st.writeFn)
259+
} else {
260+
st.children[idx].insert(key[1:], value, append(prefix, key[0]))
266261
}
267-
st.children[idx].insert(key, value, append(prefix, key[st.keyOffset]))
262+
268263
case extNode: /* Ext */
269264
// Compare both key chunks and see where they differ
270265
diffidx := st.getDiffIndex(key)
@@ -277,7 +272,7 @@ func (st *StackTrie) insert(key, value []byte, prefix []byte) {
277272
if diffidx == len(st.key) {
278273
// Ext key and key segment are identical, recurse into
279274
// the child node.
280-
st.children[0].insert(key, value, append(prefix, key[:diffidx]...))
275+
st.children[0].insert(key[diffidx:], value, append(prefix, key[:diffidx]...))
281276
return
282277
}
283278
// Save the original part. Depending if the break is
@@ -289,7 +284,7 @@ func (st *StackTrie) insert(key, value []byte, prefix []byte) {
289284
// Break on the non-last byte, insert an intermediate
290285
// extension. The path prefix of the newly-inserted
291286
// extension should also contain the different byte.
292-
n = newExt(st.owner, diffidx+1, st.key, st.children[0], st.writeFn)
287+
n = newExt(st.owner, st.key[diffidx+1:], st.children[0], st.writeFn)
293288
n.hash(append(prefix, st.key[:diffidx+1]...))
294289
} else {
295290
// an extension node: reuse the current node.
@@ -313,15 +308,14 @@ func (st *StackTrie) insert(key, value []byte, prefix []byte) {
313308
// node.
314309
st.children[0] = stackTrieFromPool(st.writeFn, st.owner)
315310
st.children[0].nodeType = branchNode
316-
st.children[0].keyOffset = st.keyOffset + diffidx
317311
p = st.children[0]
318312
}
319313
// Create a leaf for the inserted part
320-
o := newLeaf(st.owner, st.keyOffset+diffidx+1, key, value, st.writeFn)
314+
o := newLeaf(st.owner, key[diffidx+1:], value, st.writeFn)
321315

322316
// Insert both child leaves where they belong:
323317
origIdx := st.key[diffidx]
324-
newIdx := key[diffidx+st.keyOffset]
318+
newIdx := key[diffidx]
325319
p.children[origIdx] = n
326320
p.children[newIdx] = o
327321
st.key = st.key[:diffidx]
@@ -355,7 +349,6 @@ func (st *StackTrie) insert(key, value []byte, prefix []byte) {
355349
st.nodeType = extNode
356350
st.children[0] = NewStackTrieWithOwner(st.writeFn, st.owner)
357351
st.children[0].nodeType = branchNode
358-
st.children[0].keyOffset = st.keyOffset + diffidx
359352
p = st.children[0]
360353
}
361354

@@ -364,19 +357,19 @@ func (st *StackTrie) insert(key, value []byte, prefix []byte) {
364357
// The child leave will be hashed directly in order to
365358
// free up some memory.
366359
origIdx := st.key[diffidx]
367-
p.children[origIdx] = newLeaf(st.owner, diffidx+1, st.key, st.val, st.writeFn)
360+
p.children[origIdx] = newLeaf(st.owner, st.key[diffidx+1:], st.val, st.writeFn)
368361
p.children[origIdx].hash(append(prefix, st.key[:diffidx+1]...))
369362

370-
newIdx := key[diffidx+st.keyOffset]
371-
p.children[newIdx] = newLeaf(st.owner, p.keyOffset+1, key, value, st.writeFn)
363+
newIdx := key[diffidx]
364+
p.children[newIdx] = newLeaf(st.owner, key[diffidx+1:], value, st.writeFn)
372365

373366
// Finally, cut off the key part that has been passed
374367
// over to the children.
375368
st.key = st.key[:diffidx]
376369
st.val = nil
377370
case emptyNode: /* Empty */
378371
st.nodeType = leafNode
379-
st.key = key[st.keyOffset:]
372+
st.key = key
380373
st.val = value
381374
case hashedNode:
382375
panic("trying to insert into hash")

0 commit comments

Comments
 (0)