mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-12 09:51:36 +00:00
trie/bintrie: test DeleteAccount produces a deterministic root
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.
This commit is contained in:
parent
2a7effb6ca
commit
d38689e4ed
1 changed files with 42 additions and 0 deletions
|
|
@ -555,6 +555,48 @@ func TestDeleteAccountPreservesHeaderStorage(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// TestDeleteAccountHashIsDeterministic verifies that two independent tries
|
||||
// running the same UpdateAccount → DeleteAccount sequence produce identical
|
||||
// root hashes. This is the consensus-critical property of the tombstone
|
||||
// model: deletion may not produce a pristine-empty root (zero blobs hash to
|
||||
// non-zero leaves), but it MUST be deterministic across independent runs.
|
||||
//
|
||||
// A regression that introduced any non-determinism into the tombstone write
|
||||
// path (e.g. relying on map iteration order, randomized offsets) would
|
||||
// silently fork the network on the first self-destruct after enabling flat
|
||||
// state.
|
||||
func TestDeleteAccountHashIsDeterministic(t *testing.T) {
|
||||
addr := common.HexToAddress("0x1234567890abcdef1234567890abcdef12345678")
|
||||
codeHash := common.HexToHash("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")
|
||||
acc := makeAccount(42, 1000, codeHash)
|
||||
|
||||
run := func() common.Hash {
|
||||
tr := newTestTrie(t)
|
||||
if err := tr.UpdateAccount(addr, acc, 0); err != nil {
|
||||
t.Fatalf("UpdateAccount: %v", err)
|
||||
}
|
||||
if err := tr.DeleteAccount(addr); err != nil {
|
||||
t.Fatalf("DeleteAccount: %v", err)
|
||||
}
|
||||
return tr.Hash()
|
||||
}
|
||||
|
||||
first := run()
|
||||
second := run()
|
||||
if first != second {
|
||||
t.Fatalf("non-deterministic root after Update+Delete: first=%x second=%x", first, second)
|
||||
}
|
||||
|
||||
// Sanity check the tombstone model itself: the post-delete root is NOT
|
||||
// the empty-trie root, because zero blobs hash to non-zero leaves. If
|
||||
// this assertion ever flips, the tombstone semantics have silently
|
||||
// changed and the deletion-detection branch in GetAccount needs review.
|
||||
empty := newTestTrie(t).Hash()
|
||||
if first == empty {
|
||||
t.Fatalf("post-delete root unexpectedly equals empty-trie root %x; tombstone semantics changed", empty)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBinaryTrieWitness(t *testing.T) {
|
||||
tracer := trie.NewPrevalueTracer()
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue