go-ethereum/triedb/pathdb
CPerezz fcc0587ec3
core/state,triedb/pathdb: fix bintrieFlatReader disk-layer shape via per-offset extraction
Addresses review finding C2 (+ I5, S5, T2, T3, T12).

Before this commit, bintrieFlatCodec.ReadAccount returned the FULL
variable-length stem blob from disk while the in-memory diff-layer
buffer stored per-offset 32-byte values. The consumer,
bintrieFlatReader.Account, enforced len(basicBlob)!=32 → error, so
every disk-layer hit produced "bintrie BasicData leaf invalid length"
in production the moment the write buffer flushed. TestBintrieFlatReaderEndToEnd
did not catch this because it never forced a buffer → disk flush.

Fix: make bintrieFlatCodec.ReadAccount extract the offset from the
stem blob (mirroring ReadStorage), so the disk path and the buffer
path return the same 32-byte per-offset shape. Update
AccountCacheKey/StorageCacheKey to embed the full 32-byte key
(prefix + 31-byte stem + 1-byte offset), since caching under a
stem-only key would collapse BasicData and CodeHash into the same
slot and return the wrong value on the second hit. Update
Flush's cache-update loop to store per-offset entries from the
aggregated write set.

Design note: I considered the alternative of introducing a new
StemBlob(stem) interface method that returns the full blob synthesized
from a stem-level lookup index. Rejected because (a) the index is a
new data structure with its own consistency invariants, (b) the
per-offset approach is strictly local to the codec + reader, and (c)
the "1 Pebble read per Account" locality benefit is preserved at the
OS page cache level — both offsets at the same stem live in the same
Pebble block, so the second read is effectively free.

bintrieFlatReader.Account still does two AccountRLP lookups; the
torn-read hazard is gated by a new load-bearing invariant test,
TestBinaryHasherWritesBothBasicAndCodeHash, which asserts that
binaryHasher.updateAccount always emits both BasicData and CodeHash
leaves together. A future code-only update that broke this invariant
would fail the test.

Tests added:
  * TestBintrieFlatReaderEndToEndAfterFlush — explicitly flushes via
    tdb.Commit(root, false) and re-reads through a fresh StateReader.
    This is the smoking-gun regression for C2.
  * TestBintrieFlatReaderMultipleOffsetsPerStem — multiple offsets at
    the same stem (BasicData, CodeHash, header storage slots) all
    round-trip post-flush.
  * TestBintrieCodecCrossFlushRMW — two Flush calls to the same stem
    from different "blocks" correctly merge on disk, with prior
    offsets preserved.
  * TestBinaryHasherWritesBothBasicAndCodeHash — locks down the hasher
    co-write invariant that bintrieFlatReader.Account relies on.

Existing tests updated to match the new per-offset ReadAccount
semantics:
  * TestBintrieCodecAccountRoundTrip, TestBintrieCodecMultipleWritesSameStem,
    TestBintrieCodecDeleteAccount — now read per-offset rather than
    calling extractStemOffset on the raw blob.
  * TestBintrieCodecCacheKeysDisjoint — additionally verifies two
    offsets at the same stem produce distinct cache keys.

Error messages in bintrieFlatReader now include address and length
context (S5).
2026-04-15 15:00:40 +02:00
..
buffer.go triedb/pathdb: thread flatStateCodec through internals 2026-04-15 15:00:39 +02:00
config.go triedb/pathdb: enhance history index initer (#33640) 2026-03-17 15:29:30 +01:00
context.go triedb/pathdb: thread flatStateCodec through internals 2026-04-15 15:00:39 +02:00
database.go core/state,triedb/pathdb: enable bintrie flat state reads end-to-end 2026-04-15 15:00:40 +02:00
database_test.go core, eth, ethclient, triedb: report trienode index progress (#34633) 2026-04-04 21:00:07 +08:00
difflayer.go triedb/pathdb: return nodeLoc by value to avoid heap allocation (#33819) 2026-02-11 22:14:43 +08:00
difflayer_test.go cmd, core, eth, triedb/pathdb: track node origins in the path database (#32418) 2025-09-05 10:37:05 +08:00
disklayer.go core/state,triedb/pathdb: enable bintrie flat state reads end-to-end 2026-04-15 15:00:40 +02:00
errors.go core, triedb/pathdb: final integration (snapshot integration pt 5) (#30661) 2025-05-16 18:29:38 +08:00
execute.go cmd, core, eth, triedb/pathdb: track node origins in the path database (#32418) 2025-09-05 10:37:05 +08:00
fileutils_unix.go triedb/pathdb: introduce file-based state journal (#32060) 2025-07-15 11:45:20 +08:00
fileutils_windows.go triedb/pathdb: introduce file-based state journal (#32060) 2025-07-15 11:45:20 +08:00
flat_codec.go core/state,triedb/pathdb: wire bintrie leaves through stateUpdate 2026-04-15 15:00:40 +02:00
flat_codec_bintrie.go core/state,triedb/pathdb: fix bintrieFlatReader disk-layer shape via per-offset extraction 2026-04-15 15:00:40 +02:00
flat_codec_bintrie_test.go core/state,triedb/pathdb: fix bintrieFlatReader disk-layer shape via per-offset extraction 2026-04-15 15:00:40 +02:00
flush.go core/state,triedb/pathdb: wire bintrie leaves through stateUpdate 2026-04-15 15:00:40 +02:00
generate.go core/state,triedb/pathdb: enable bintrie flat state reads end-to-end 2026-04-15 15:00:40 +02:00
generate_bintrie.go core/state,triedb/pathdb: enable bintrie flat state reads end-to-end 2026-04-15 15:00:40 +02:00
generate_bintrie_test.go triedb/pathdb: bintrie snapshot generator 2026-04-15 15:00:40 +02:00
generate_test.go triedb/pathdb, eth: use double-buffer mechanism in pathdb (#30464) 2025-06-22 20:40:54 +08:00
history.go core/rawdb, triedb/pathdb: enable trienode history alongside existing data (#33934) 2026-03-12 09:21:54 +08:00
history_index.go triedb/pathdb: improve trienode reader for searching (#33681) 2026-01-27 20:05:35 +08:00
history_index_block.go triedb/pathdb: improve trienode reader for searching (#33681) 2026-01-27 20:05:35 +08:00
history_index_block_test.go triedb/pathdb: introduce extension to history index structure (#33399) 2026-01-08 09:57:35 +01:00
history_index_iterator.go core, eth, internal, triedb/pathdb: enable eth_getProofs for history (#32727) 2026-01-22 09:19:27 +08:00
history_index_iterator_test.go core, eth, internal, triedb/pathdb: enable eth_getProofs for history (#32727) 2026-01-22 09:19:27 +08:00
history_index_pruner.go triedb/pathdb: implement history index pruner (#33999) 2026-04-02 00:21:58 +02:00
history_index_pruner_test.go triedb/pathdb: implement history index pruner (#33999) 2026-04-02 00:21:58 +02:00
history_index_test.go triedb/pathdb: introduce extension to history index structure (#33399) 2026-01-08 09:57:35 +01:00
history_indexer.go triedb/pathdb: implement history index pruner (#33999) 2026-04-02 00:21:58 +02:00
history_indexer_state.go triedb/pathdb: enhance history index initer (#33640) 2026-03-17 15:29:30 +01:00
history_indexer_test.go triedb/pathdb: enhance history index initer (#33640) 2026-03-17 15:29:30 +01:00
history_inspect.go triedb/pathdb: allow single-element history ranges (#33329) 2025-12-01 10:19:21 +08:00
history_reader.go triedb/pathdb: improve trienode reader for searching (#33681) 2026-01-27 20:05:35 +08:00
history_reader_test.go triedb/pathdb: implement trienode history indexing scheme (#33551) 2026-01-17 20:28:37 +08:00
history_state.go triedb/pathdb: implement trienode history indexing scheme (#33551) 2026-01-17 20:28:37 +08:00
history_state_test.go core/rawdb, triedb/pathdb: introduce trienode history (#32596) 2025-10-10 14:51:27 +08:00
history_trienode.go triedb/pathdb: preallocate slices in decodeRestartTrailer (#33715) 2026-01-30 21:14:15 +08:00
history_trienode_test.go triedb/pathdb: improve trienode reader for searching (#33681) 2026-01-27 20:05:35 +08:00
history_trienode_utils.go triedb/pathdb: implement trienode history indexing scheme (#33551) 2026-01-17 20:28:37 +08:00
history_trienode_utils_test.go triedb/pathdb: implement trienode history indexing scheme (#33551) 2026-01-17 20:28:37 +08:00
holdable_iterator.go trie/pathdb: state iterator (snapshot integration pt 4) (#30654) 2024-12-16 21:10:08 +08:00
holdable_iterator_test.go trie/pathdb: state iterator (snapshot integration pt 4) (#30654) 2024-12-16 21:10:08 +08:00
iterator.go triedb, triedb/internal, triedb/pathdb: add GenerateTrie + extract shared pipeline into triedb/internal (#34654) 2026-04-07 14:36:53 +08:00
iterator_binary.go triedb/pathdb, eth: use double-buffer mechanism in pathdb (#30464) 2025-06-22 20:40:54 +08:00
iterator_fast.go triedb/pathdb, eth: use double-buffer mechanism in pathdb (#30464) 2025-06-22 20:40:54 +08:00
iterator_test.go triedb/pathdb: thread flatStateCodec through internals 2026-04-15 15:00:39 +02:00
journal.go core/state,triedb/pathdb: enable bintrie flat state reads end-to-end 2026-04-15 15:00:40 +02:00
layertree.go triedb/pathdb: fix lookup sentinel collision with zero disk layer root (#34680) 2026-04-09 13:39:38 +08:00
layertree_test.go triedb/pathdb: fix lookup sentinel collision with zero disk layer root (#34680) 2026-04-09 13:39:38 +08:00
lookup.go triedb/pathdb: fix lookup sentinel collision with zero disk layer root (#34680) 2026-04-09 13:39:38 +08:00
metrics.go triedb/pathdb: implement history index pruner (#33999) 2026-04-02 00:21:58 +02:00
nodes.go core, eth, internal, triedb/pathdb: enable eth_getProofs for history (#32727) 2026-01-22 09:19:27 +08:00
nodes_test.go rlp, trie, triedb/pathdb: compress trienode history (#32913) 2026-01-08 21:58:02 +08:00
reader.go core/state,triedb/pathdb: enable bintrie flat state reads end-to-end 2026-04-15 15:00:40 +02:00
states.go triedb/pathdb: thread flatStateCodec through internals 2026-04-15 15:00:39 +02:00
states_test.go all: update license comments and AUTHORS (#31133) 2025-02-05 23:01:17 +01:00
stem_blob.go triedb/pathdb: implement bintrieFlatCodec + stem blob helpers 2026-04-15 15:00:40 +02:00
stem_blob_test.go triedb/pathdb: implement bintrieFlatCodec + stem blob helpers 2026-04-15 15:00:40 +02:00
verifier.go triedb, triedb/internal, triedb/pathdb: add GenerateTrie + extract shared pipeline into triedb/internal (#34654) 2026-04-07 14:36:53 +08:00