mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-05-24 08:49:29 +00:00
trie/bintrie: mark promoted stem dirty during splitStemValuesInsert
When splitStemValuesInsert inserts a new stem that shares a prefix with an existing stem, it increments the existing stem's depth and inserts a new internal node above it. The existing stem's on-disk path is derived from its depth via collectChildGroups + extendPathToGroupLeaf, so promoting its depth means it should be flushed at a new path. Previously, only the new stem (created in the divergence branch) was marked dirty. The promoted existing stem retained whatever dirty value it had — false if it was just deserialized from disk via a HashedNode resolve. collectNodes would then skip flushing the existing stem at its new path, while the new ancestor internal blob (also dirty) overwrites the existing stem's old blob at the prior path. The stem's data is left with no on-disk home, breaking subsequent reads with "missing trie node". The bug surfaces in the integration-test harness (state-actor builds a DB with single-stem-per-slot at depth 8, geth then mutates by adding a new stem that shares ≥8 prefix bits with the existing stem). After mutation, geth's `getValuesAtStem` resolves a HashedNode whose blob should be at the extended-depth path but isn't on disk. Mark `existing.dirty = true` when promoting the depth so collectNodes re-flushes the stem at its new path. Verification: the 100MB integration-test harness (which previously failed at block 9-10 with "missing trie node bdaf89... (path c96010)") now runs cleanly through 200+ blocks of ERC20 deploys and bloat transactions without any missing-trie-node errors.
This commit is contained in:
parent
a1eaa21f24
commit
bdb7b64173
1 changed files with 6 additions and 0 deletions
|
|
@ -263,6 +263,12 @@ func (s *nodeStore) splitStemValuesInsert(existingRef nodeRef, newStem []byte, v
|
|||
nRef := s.newInternalRef(int(existing.depth))
|
||||
nNode := s.getInternal(nRef.Index())
|
||||
existing.depth++
|
||||
// The existing stem's on-disk path is derived from its depth via
|
||||
// extendPathToGroupLeaf. Promoting its depth changes that path, so the
|
||||
// stem must be re-flushed at the new path; otherwise the old blob (at
|
||||
// the prior path) gets overwritten by the new ancestor internal blob
|
||||
// and the stem's data has no on-disk home.
|
||||
existing.dirty = true
|
||||
|
||||
bitKey := newStem[nNode.depth/8] >> (7 - (nNode.depth % 8)) & 1
|
||||
if bitKey == bitStem {
|
||||
|
|
|
|||
Loading…
Reference in a new issue