Skip to content

expired nodes: rebuild the subtree on reads #561

@gballet

Description

@gballet

I decided not to rebuild the tree on reads, in order to make a potential resurrection attack more expensive.

If it turns out this is necessary, here is the diff:

@@ -272,8 +238,22 @@ func (t *Trie) get(origNode node, key []byte, pos int) (value []byte, newnode no
                        return nil, n, false, fmt.Errorf("failed to resolve expired node: %w", err)
                }
                newnode, err := archiveRecordsToNode(records)
-               value, newnode, _, err = t.get(newnode, key, pos)
-               return value, newnode, true, err
+               for _, record := range records {
+                       // make sure that the path up to the node matches
+                       if bytes.HasPrefix(key[pos:], record.Path) {
+                               resolved, err := decodeNodeUnsafe(nil, record.Value)
+                               if err != nil {
+                                       return nil, n, false, fmt.Errorf("failed to deserialize RLP node: %w", err)
+                               }
+                               if leaf, ok := resolved.(*shortNode); ok {
+                                       // make sure that the key to the leaf also matches
+                                       if bytes.Equal(key[pos+len(record.Path):], leaf.Key) {
+                                               return leaf.Val.(valueNode), newnode, true, nil
+                                       }
+                               }
+                       }
+               }
+               return value, newnode, false, err

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions