From 090b757dc1f2fd797f481f9fb4251010bd63804b Mon Sep 17 00:00:00 2001 From: CPerezz Date: Wed, 8 Apr 2026 12:09:23 +0200 Subject: [PATCH] trie/bintrie: assign t.root only on successful DeleteAccount DeleteAccount was assigning t.root unconditionally and then returning the error, matching UpdateAccount but diverging from the safer pattern in UpdateStorage/DeleteStorage (assign to a temp, return on error, mutate t.root only on success). This is a partial fix to a broader footgun: InternalNode.Insert- ValuesAtStem mutates its receiver in place on error paths, so the root pointer is already shared and the mutation has already leaked by the time we return. The proper fix is either rewriting that function or documenting the contract; both are out of scope here. At minimum, stop pointing t.root at whatever InsertValuesAtStem returned on error (which could be nil or a different node altogether), and bring DeleteAccount in line with its DeleteStorage sibling. --- trie/bintrie/trie.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/trie/bintrie/trie.go b/trie/bintrie/trie.go index db680e3b15..6e965db0e0 100644 --- a/trie/bintrie/trie.go +++ b/trie/bintrie/trie.go @@ -317,7 +317,6 @@ func (t *BinaryTrie) UpdateStorage(address common.Address, key, value []byte) er // enumerate every slot of a given account. func (t *BinaryTrie) DeleteAccount(addr common.Address) error { var ( - err error zeroBlob [HashSize]byte values = make([][]byte, StemNodeWidth) stem = GetBinaryTreeKey(addr, zero[:]) @@ -330,10 +329,11 @@ func (t *BinaryTrie) DeleteAccount(addr common.Address) error { // subsequent read. See GetAccount's deletion branch around trie.go:219. values[accountDeletedMarkerKey] = zeroBlob[:] - t.root, err = t.root.InsertValuesAtStem(stem, values, t.nodeResolver, 0) + root, err := t.root.InsertValuesAtStem(stem, values, t.nodeResolver, 0) if err != nil { return fmt.Errorf("DeleteAccount (%x) error: %v", addr, err) } + t.root = root return nil }