Follow-ups from PR review, bundled together because they are all
non-functional documentation and helper polish:
- Move accountDeletedMarkerKey to key_encoding.go alongside the
other leaf-key constants, and drop the stale "Keep this in sync"
directive. After this PR both GetAccount and DeleteAccount
reference the constant by name, so there is nothing left to
manually keep in sync.
- Replace the hard-coded "trie.go:219" line references in the
DeleteAccount doc and body comments with function-name references
("GetAccount's deletion-detection branch"). Line references rot
on any edit above the target line.
- Clarify what protects header storage from DeleteAccount: it shares
the same stem as BasicData/CodeHash, so the safety comes from
non-colliding offsets plus the nil-means-"do not overwrite"
semantics of StemNode.InsertValuesAtStem, not from living at a
different stem. Mirror the clarification in the
TestDeleteAccountDoesNotAffectMainStorage comment and
cross-reference the header-storage test.
- Rename newTestTrie to newEmptyTestTrie so readers can pick between
"empty" (this helper) and "pre-populated with entries" (makeTrie
in iterator_test.go) without guessing.
TestDeleteAccountDoesNotAffectMainStorage was using `if got, _ :=
tr.GetAccount(addr); got != nil` to assert deletion. If GetAccount
ever returns a non-nil error on this path (a future change to
GetValuesAtStem, a resolver-error case), `got` is nil and the
assertion passes silently — exactly the kind of suppression the
broader fix is designed to eliminate.
Match the error-checking pattern used four lines earlier in the
same test, and rename the now-shadowed `got` for the GetStorage
result to `stored`.
Two independent tries running the same UpdateAccount → DeleteAccount
sequence must produce identical root hashes. Deletion does not
return the trie to a pristine-empty root (zero blobs hash to
non-zero leaves under the tombstone model), but the post-delete
root must be deterministic across runs — any non-determinism in
the tombstone-write path would silently fork the network on the
first self-destruct after enabling flat state.
Also pin the post-delete root != empty root invariant so a future
change to the tombstone semantics surfaces here instead of in
GetAccount's deletion-detection branch.
Header-range storage slots (key[31] < 64) live at the same stem as
BasicData and CodeHash, at offsets 64-127. The existing
TestDeleteAccountDoesNotAffectMainStorage uses a main-storage slot
(key[31] = 0x80) which lives at a different stem, giving zero
coverage of the same-stem case.
DeleteAccount's safety against header storage relies on
StemNode.InsertValuesAtStem treating nil entries as "do not
overwrite". Pin that invariant so a future change filling the values
slice with zeroBlob[:] instead of leaving nils cannot silently
corrupt slots 0-63 of any contract.
BinaryTrie.DeleteAccount was a no-op, silently ignoring the caller's
deletion request and leaving the old BasicData and CodeHash in the trie.
The GetAccount deletion-detection branch (trie.go:219) already expected
a tombstone convention — "BasicData and CodeHash are 32-byte zero blobs
AND a non-nil 32-byte sentinel is present at a reserved offset" — but
nothing was writing that sentinel, so the check was effectively dead
code.
Implement the deletion as an InsertValuesAtStem that:
- writes a 32-byte zero blob to BasicData (offset 0)
- writes a 32-byte zero blob to CodeHash (offset 1)
- writes a 32-byte zero blob to a deletion sentinel offset in the
EIP-7864 reserved range (offset 10, promoted to the named constant
accountDeletedMarkerKey for cross-referencing with GetAccount)
This matches the bintrie's existing "write zeros to delete" convention
seen in DeleteStorage, keeps GetAccount's deletion branch consistent,
and still distinguishes "deleted" from "never existed" (the latter has
all-nil slots so the empty-account check fires first).
Storage slots and code chunks are intentionally left untouched. Wiping
storage on self-destruct is a separate concern handled at the StateDB
level — the bintrie's unified keyspace has no cheap way to enumerate
every slot of a given account, so a blanket wipe is not possible here.
Regression tests cover:
- round-trip: UpdateAccount -> GetAccount -> DeleteAccount -> GetAccount nil
- delete on missing account: no panic, subsequent read still nil
- unrelated accounts at different stems are preserved
- delete + recreate: second read sees the new values, not the old ones
- main storage slots at different stems survive DeleteAccount
GetStorage and DeleteStorage used GetBinaryTreeKey to compute the tree
key, while UpdateStorage used GetBinaryTreeKeyStorageSlot. The latter
applies storage slot remapping (header offset for slots <64, main
storage prefix for the rest), so reads and deletes were targeting
different tree locations than writes.
Replace GetBinaryTreeKey with GetBinaryTreeKeyStorageSlot in both
GetStorage and DeleteStorage to match UpdateStorage. Add a regression
test that verifies the write→read→delete→read round-trip for main
storage slots.
The `Witness` method was not implemented for the binary tree, which
caused `debug_excutionWitness` to panic. This PR fixes that.
Note that the `TransitionTrie` version isn't implemented, and that's on
purpose: more thought must be given to what should go in the global
witness.
This is broken off of #31730 to only focus on testing networks that
start with verkle at genesis.
The PR has seen a lot of work since its creation, and it now targets
creating and re-executing tests for a binary tree testnet without the
transition (so it starts at genesis). The transition tree has been moved
to its own package. It also replaces verkle with the binary tree for
this specific application.
---------
Co-authored-by: Gary Rong <garyrong0905@gmail.com>
Implement the binary tree as specified in [eip-7864](https://eips.ethereum.org/EIPS/eip-7864).
This will gradually replace verkle trees in the codebase. This is only
running the tests and will not be executed in production, but will help
me rebase some of my work, so that it doesn't bitrot as much.
---------
Signed-off-by: Guillaume Ballet
Co-authored-by: Parithosh Jayanthi <parithosh.jayanthi@ethereum.org>
Co-authored-by: rjl493456442 <garyrong0905@gmail.com>