Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
783 commits
Select commit Hold shift + click to select a range
851b26c
refactor(FlatDB): drop unused secondLen/allSameLenExceptFirst from BT…
asdacap May 27, 2026
3a4bd58
refactor(FlatDB): drop unused minLeafEntries/maxLeafEntries from Hsst…
asdacap May 27, 2026
8e146bc
refactor(FlatDB): drop unused IHsstByteReader.Bound, dead overloads, …
asdacap May 27, 2026
5fa1373
perf(FlatDB): cache address-BTree root descriptor per PersistedSnapshot
asdacap May 27, 2026
5a185f1
Merge branch 'cache-btree-root-index' into flat/long-finality
asdacap May 27, 2026
2a8b492
refactor(FlatDB): drop obvious labels and tighten stale-history comments
asdacap May 27, 2026
8ace70c
fix(FlatDB): honor PersistOnShutdown in ArenaReservation.CleanUp's pu…
asdacap May 28, 2026
5f1a4ff
test(FlatDB): cover persisted-tier prune on PersistenceManager tier-s…
asdacap May 28, 2026
386cf7c
refactor(FlatDB): migrate compact-size math to ICompactionSchedule
asdacap May 28, 2026
8a78319
fix(FlatDB): honor PersistOnShutdown in BlobArenaManager.TryResetOrph…
asdacap May 28, 2026
e5a3594
refactor(FlatDB): blob arena starts at length 0, truncates on reset
asdacap May 28, 2026
c14c0d0
feat(FlatDB): fsync arena (and blob if base) on persisted-snapshot co…
asdacap May 28, 2026
62d83b9
perf(FlatDB): swap fsync(2) to fdatasync(2) for the persisted-snapsho…
asdacap May 28, 2026
9829572
refactor(FlatDB): blob arena - pre-extend + 4-byte on-disk frontier m…
asdacap May 28, 2026
ba96706
Merge branch 'master' into flat/long-finality
asdacap May 28, 2026
e0b951a
refactor(FlatDB): AssembleSnapshots BFS prefers in-memory tier over p…
asdacap May 28, 2026
718b2dc
fix(FlatDB): DoCompactSnapshot startingBlockNumber must respect sched…
asdacap May 28, 2026
8435bf5
test(FlatDB): regression for DoCompactSnapshot startingBlockNumber of…
asdacap May 28, 2026
a21fc91
Revert "refactor(FlatDB): blob arena - pre-extend + 4-byte on-disk fr…
asdacap May 28, 2026
8fd05d6
fix(FlatDB): bundle bloom fetch must cover full snapshot range
asdacap May 29, 2026
95e4ae0
refactor(FlatDB): decouple bloom build from LoadFromCatalog, add Reco…
asdacap May 29, 2026
0d57b28
feat(FlatDB): catalog key adds depth — round-trip multi-size snapshot…
asdacap May 29, 2026
19fc543
Merge branch 'verify-snapshot-bloom-coverage' into flat/long-finality
asdacap May 29, 2026
d316b15
perf(FlatDB): parallelize LoadFromCatalog + ReconstructBloom, add pro…
asdacap May 29, 2026
f4064b7
docs(FlatDB): correct HSST FORMAT.md against the builders
asdacap May 29, 2026
9d74edc
Merge branch 'verify-format-accuracy' into flat/long-finality
asdacap May 29, 2026
9f98d90
Merge remote-tracking branch 'origin/master' into flat/long-finality
asdacap Jun 3, 2026
7b34e60
refactor(state): align persisted snapshot repo's remove-until method …
asdacap Jun 3, 2026
e9de159
fix(state): remove only converted in-memory snapshots in DoConvert Br…
asdacap Jun 3, 2026
2615034
perf(state): software-prefetch BTree node body during HSST descent
asdacap Jun 4, 2026
5760e96
Merge remote-tracking branch 'origin/master' into flat/long-finality
asdacap Jun 5, 2026
920ef2d
fix(test): update FlatSnapServerTests for 5-arg ReadOnlySnapshotBundl…
asdacap Jun 9, 2026
9d69e89
fix(test): convert TreePathTests FluentAssertions to NUnit
asdacap Jun 9, 2026
c882d61
perf(flat): remove single-source byte-copy fast path from compactor
asdacap Jun 9, 2026
a3db580
Merge branch 'remove-compactor-fast-path' into flat/long-finality
asdacap Jun 9, 2026
45fd339
Merge origin/master into flat/long-finality
asdacap Jun 9, 2026
b38ad7e
feat(flat): prune orphaned non-canonical forks from the persisted tier
asdacap Jun 9, 2026
71a2da5
refactor(flat): drop dead code and collapse TwoByteSlot u16/u24 fork
asdacap Jun 9, 2026
1210787
refactor(flat): drop the vestigial MaxLeafEntries HSST option
asdacap Jun 9, 2026
b21ee40
test(flat): make the two single-leaf HSST tests genuinely multi-leaf
asdacap Jun 9, 2026
c259a5c
docs(flat): trim HSST comments that duplicate FORMAT.md
asdacap Jun 9, 2026
6200bad
refactor(flat): revert no-op churn against master
asdacap Jun 10, 2026
e0a880e
chore(bench): drop standalone persisted-tier benchmarks
asdacap Jun 10, 2026
a74acce
refactor(flat): dedupe HSST search, reader and merge-callback internals
asdacap Jun 10, 2026
d54d2d8
fix(flat): gate persisted-probe skip metrics behind detailed-metrics …
asdacap Jun 10, 2026
e3f54b4
refactor(flat): drop single-value abstractions and dead persisted-tie…
asdacap Jun 10, 2026
25805be
refactor(flat): one edge-expansion seam for the snapshot graph walkers
asdacap Jun 10, 2026
5288eac
refactor(flat): encapsulate the persisted-snapshot probe in Persisted…
asdacap Jun 10, 2026
fb910a3
refactor(flat): move compaction orchestration behind IPersistedSnapsh…
asdacap Jun 10, 2026
0fd5067
refactor(flat): attach the persisted-snapshot bloom to PersistedSnapshot
asdacap Jun 10, 2026
01ababf
refactor(flat): drop the vestigial MinCompactSize knob
asdacap Jun 11, 2026
c3eef59
refactor(flat): address review feedback on HSST B-tree + DI wiring
asdacap Jun 11, 2026
b4e01c5
Merge branch 'remove-min-compact-size' into flat/long-finality
asdacap Jun 11, 2026
c8d91d4
refactor(flat): name the index-node key accessor GetSeparatorBytes
asdacap Jun 11, 2026
17a8fd9
refactor(flat): return BTreeNodeLayoutPlan struct from the layout pla…
asdacap Jun 11, 2026
25d168e
refactor(flat): rename EmitInlineLeaf to MaybeEmitInlineLeaf; trim re…
asdacap Jun 11, 2026
6171ccb
Merge branch 'btree-layout-plan-struct' into flat/long-finality
asdacap Jun 11, 2026
0fae1dd
refactor(flat): collapse CommonPrefixArr grow+write into Buffers.AddC…
asdacap Jun 11, 2026
a640770
refactor(flat): intent-named buffer-capacity methods; trim container doc
asdacap Jun 11, 2026
7f32649
refactor(flat): merge OnEntryAdded into EmitEntryBookkeeping
asdacap Jun 11, 2026
3e49a4b
refactor(flat): split index-region construction into HsstBTreeBuilder…
asdacap Jun 11, 2026
be4292e
test(flat): drive automatic u24 promotion in TwoByteSlot round-trip test
asdacap Jun 11, 2026
893688a
refactor(flat/hsst): TwoByteSlotValueBuilder ArrayPool -> NativeMemor…
asdacap Jun 11, 2026
8e78f8d
refactor(flat/hsst): DenseByteIndexBuilder ArrayPool -> NativeMemoryList
asdacap Jun 11, 2026
88d32c8
refactor(flat/hsst): BTreeNodeLayoutPlanner.Plan struct + buffers Nat…
asdacap Jun 11, 2026
73c461e
Merge branch 'twobyteprefix-large-variant-unit-test' into flat/long-f…
asdacap Jun 11, 2026
0bb7785
refactor(flat/hsst): drop dead 3-byte LE key search path
asdacap Jun 11, 2026
36deadd
refactor(flat/hsst): drop KeyValueEntry wrapper; expose CurrentValueB…
asdacap Jun 11, 2026
211d63b
refactor(flat): remove dead writer-side OpenReader read-back mechanism
asdacap Jun 11, 2026
922e69e
refactor(flat/hsst): simplify BTreeNodeLayoutPlanner.Compute
asdacap Jun 11, 2026
309d3f6
Merge branch 'investigate-twriter-openreader-usage' into flat/long-fi…
asdacap Jun 11, 2026
1035662
refactor(flat/hsst): widen the key slot after the common-prefix strip
asdacap Jun 11, 2026
ee66a9e
refactor(flat/hsst): drop HsstRefEnumerator wrapper, use HsstEnumerat…
asdacap Jun 11, 2026
eed46aa
refactor(flat/hsst): fold BTreeNodeLayoutPlanner into HsstBTreeBuilder
asdacap Jun 11, 2026
ef9d82e
Merge branch 'remove-hsst-ref-enumerator' into flat/long-finality
asdacap Jun 11, 2026
23e533c
refactor(flat/hsst): inline AddCore/Buffers, rename FinalizePendingNo…
asdacap Jun 11, 2026
eb36d36
refactor(flat): back ArenaBufferWriter with NativeMemoryList
asdacap Jun 11, 2026
da82793
refactor(flat/hsst): address index-builder review comments
asdacap Jun 11, 2026
8c1cf7a
refactor(flat/hsst): nest buffers container as HsstBTreeBuilderBuffer…
asdacap Jun 11, 2026
a398a44
refactor(flat): drop GetSpanWithoutTouch; pin then wrap in SpanByteRe…
asdacap Jun 11, 2026
b069c86
refactor(flat): tidy arena reader/file per review
asdacap Jun 11, 2026
880aa06
refactor(flat): wrap arena eviction logic in EvictionDispatcher inner…
asdacap Jun 11, 2026
fb61522
refactor(flat): back BlobArenaWriter with NativeMemoryList; drop writ…
asdacap Jun 11, 2026
4ae2eda
refactor(flat): nest storage helper enums/interface into their owners
asdacap Jun 11, 2026
f935af0
refactor(flat): trim IPersistedSnapshotCompactor to the external cont…
asdacap Jun 11, 2026
b89983b
refactor(flat): wrap address-bound cache in an AddressBoundCache struct
asdacap Jun 11, 2026
61af0ae
refactor(flat): group each snapshot bucket into a SnapshotBucket class
asdacap Jun 11, 2026
f5763ca
docs(flat/hsst): condense comments in HsstBTreeBuilder
asdacap Jun 11, 2026
82fa486
refactor(flat): move base-snapshot blob range into the HSST metadata …
asdacap Jun 11, 2026
9e97495
refactor(flat): add IHsstReaderSource reader-factory abstraction
asdacap Jun 11, 2026
a14ad9b
refactor(flat): make PersistedSnapshotScanner generic over the reader
asdacap Jun 11, 2026
f692bb1
refactor(flat): make the N-way merger generic over the reader
asdacap Jun 11, 2026
a988530
refactor(flat): make PersistedSnapshot.RefIdsEnumerator generic over …
asdacap Jun 11, 2026
58e7639
docs(flat): trim verbose/obvious comments, fix stale ones
asdacap Jun 11, 2026
9f365b6
perf(flat): resolve metadata column scope once per PersistedSnapshot
asdacap Jun 11, 2026
a8c9fb6
Merge remote-tracking branch 'origin/master' into flat/long-finality
asdacap Jun 12, 2026
1c22af1
refactor(flat/hsst): address index-builder review comments
asdacap Jun 12, 2026
a577005
refactor(flat/hsst): move Variable-node strip handling into the writer
asdacap Jun 12, 2026
1952081
refactor(flat/hsst): slice levelFirstKeys directly in ChooseIntermedi…
asdacap Jun 12, 2026
83e4936
refactor: extract SeparatorLength helper; condense MaybePadToNextPage…
asdacap Jun 12, 2026
f0cd1e8
refactor: dedup BuildIndex single-node path and carry committedSize
asdacap Jun 12, 2026
b404067
refactor: use BinaryPrimitives for u16 reads and Bound for entry regions
asdacap Jun 12, 2026
1f5fa89
refactor: drop the all-Entry fast leaf path in BTree enumerator
asdacap Jun 12, 2026
72aecbf
refactor(flat/hsst): take Bound in IHsstByteReader.PinBuffer
asdacap Jun 12, 2026
5df6045
Merge branch 'refactor-host-reader-bound' into flat/long-finality
asdacap Jun 12, 2026
b946c8a
refactor: page-bound the speculative node pin and drop scopeEnd
asdacap Jun 12, 2026
fa2f88a
refactor: move HsstOffset to PackedArray ns; thread entry pos; drop d…
asdacap Jun 12, 2026
7b969b4
feat(flat): RLP-wrap storage slot values in persisted snapshots
asdacap Jun 13, 2026
2d610d2
Merge branch 'master' into flat/long-finality
asdacap Jun 14, 2026
932c8c7
refactor(state-flat): read TryRead destinations into concrete values
asdacap Jun 14, 2026
c2759e1
refactor(flat/hsst): address review comments on HSST readers/mergers
asdacap Jun 14, 2026
1817812
Merge branch 'refactor-tryread-stackalloc-spans' into flat/long-finality
asdacap Jun 14, 2026
664c625
refactor(flat/hsst): value-merger opens its own value write
asdacap Jun 14, 2026
7c2b846
refactor(flat/storage): address review comments on arena/catalog
asdacap Jun 14, 2026
53296c9
refactor(flat/storage): WholeReadSession is its own reader source
asdacap Jun 14, 2026
b78ed17
refactor(flat/storage): drop test-only WholeReadSession.AsSpanIntBounded
asdacap Jun 14, 2026
d165201
refactor(flat/hsst): inline single-use PrimePerAddBuffers into ctor
asdacap Jun 14, 2026
1ffc615
refactor(flat): prune dead/test-only API surface from changed files
asdacap Jun 14, 2026
e299554
refactor(flat): SnapshotCatalog.Load returns the entries; drop in-mem…
asdacap Jun 14, 2026
0e3b199
refactor(flat): address persisted-snapshot review comments
asdacap Jun 14, 2026
2f1f24e
refactor(flat): per-bucket locking + self-contained SnapshotBucket
asdacap Jun 14, 2026
210a666
refactor(flat): fold SnapshotGraphWalker into SnapshotRepository
asdacap Jun 15, 2026
3653fbf
refactor(flat): move AssembleSnapshotsForCompaction to ISnapshotRepos…
asdacap Jun 15, 2026
63577d3
test(flat): consolidate HSST tests into parameterized cases
asdacap Jun 15, 2026
41ce18f
perf(flat): byte-copy slot-less single-source accounts in merge
asdacap Jun 15, 2026
d239edb
refactor(flat): merge persisted tier into SnapshotRepository; drop IP…
asdacap Jun 15, 2026
86801b2
Merge branch 'consolidate-parameterized-tests' into flat/long-finality
asdacap Jun 15, 2026
8a82a3f
refactor(flat): stream catalog Load + simplify persisted-snapshot DI
asdacap Jun 15, 2026
fd3d92e
refactor(flat): rename GetSnapshotBeforeStateId → GetStatesUpToBlock
asdacap Jun 15, 2026
f2821f2
docs(flat): trim verbose comments in FlatWorldStateModule and Persist…
asdacap Jun 15, 2026
0cc8152
refactor(flat): move AddressBoundCache to its own file
asdacap Jun 15, 2026
84fcbcf
refactor(flat): drop redundant boundary pre-filter in compactor
asdacap Jun 15, 2026
86022b6
refactor(flat): introduce SnapshotTier, collapse tier-paired snapshot…
asdacap Jun 15, 2026
76a6e40
refactor(flat): collapse persisted lease trio into TryLeasePersistedS…
asdacap Jun 15, 2026
64ed9e6
refactor(flat): hide compact sizes behind CompactionWindow schedule API
asdacap Jun 15, 2026
4ea6536
refactor(flat): move snapshot conversion into a PersistedSnapshotConv…
asdacap Jun 15, 2026
7a4bf5f
refactor(flat): move in-memory prune from FlatDbManager into AddToPer…
asdacap Jun 15, 2026
b94ef0a
refactor(flat): rename AssembleSnapshotsForCompaction → AssemblePersi…
asdacap Jun 15, 2026
3d89e9c
refactor(flat): unify the parent-edge graph walks onto one BFS driver
asdacap Jun 15, 2026
1d3b954
refactor(flat): name in-memory compaction-assemble to match its persi…
asdacap Jun 15, 2026
9819d83
refactor(flat): persisted compaction assembly uses the unified best-e…
asdacap Jun 15, 2026
877ac51
Merge branch 'list-snapshot-repo-methods' into flat/long-finality
asdacap Jun 15, 2026
27dfeff
refactor(flat): address snapshot repository/catalog review comments
asdacap Jun 15, 2026
ff8f8d2
refactor(flat): extract persisted snapshot loading into PersistedSnap…
asdacap Jun 15, 2026
f652c2b
refactor(flat): make PersistedSnapshotLoader a DI component owning ti…
asdacap Jun 15, 2026
b3a4f47
refactor(flat): fold PersistedSnapshotConverter into PersistedSnapsho…
asdacap Jun 15, 2026
f1ca9aa
refactor(flat): split persisted-tier mark vs dispose; let DI own disp…
asdacap Jun 15, 2026
90426db
refactor(flat): merge LoadPersistedSnapshot into AddPersistedSnapshot
asdacap Jun 15, 2026
9166ec5
test(flat): wire persisted-tier tests through FlatWorldStateModule co…
asdacap Jun 15, 2026
1e2642f
fix(flat): make FlushToPersistence drive the persisted tier
asdacap Jun 15, 2026
ccfe75a
test(flat): regression for persisted orphan above the in-memory tip
asdacap Jun 15, 2026
f341aa1
refactor(flat): address review comments (bloom dedup, catalog db, com…
asdacap Jun 15, 2026
9bd75cd
Merge branch 'fix-remove-siblings-snapshot' into flat/long-finality
asdacap Jun 15, 2026
ee760cd
refactor(flat): caller-built persisted snapshots; loader cleanups
asdacap Jun 15, 2026
4b2e85f
refactor(flat): inject SnapshotCatalog as a DI service
asdacap Jun 15, 2026
689ba0f
refactor(flat): rename Hierarchical compaction API to PersistedSnapshot
asdacap Jun 15, 2026
864d119
refactor(flat): split compaction boundary predicate; route by boundar…
asdacap Jun 15, 2026
f6878cc
refactor(flat): trim ICompactionSchedule to the predicates actually used
asdacap Jun 15, 2026
9cf1333
refactor(flat): address SnapshotRepository review comments
asdacap Jun 15, 2026
1230f72
Merge branch 'list-compaction-schedule-methods' into flat/long-finality
asdacap Jun 15, 2026
1bad813
refactor(flat): separate lock for last-registered tip; WalkParents ow…
asdacap Jun 15, 2026
090f6f2
refactor(flat): restore master comment wording to minimize review diff
asdacap Jun 15, 2026
c85f531
refactor(flat): address PersistedSnapshotCompactor review comments
asdacap Jun 15, 2026
eccd8d7
refactor(flat): let WalkParents visitors own their edge priority
asdacap Jun 15, 2026
9e893b3
refactor(flat): extract PersistedSnapshotBucket; pass WalkNode + tier…
asdacap Jun 15, 2026
101fcf0
refactor(flat): add WalkAction.Enqueue and move cycle detection into …
asdacap Jun 15, 2026
97ff2c7
refactor(flat): embed walk priorities in visitors; inline lease dispa…
asdacap Jun 16, 2026
2d6389f
refactor(flat): gather the assemble chain inside the BFS; hardcode ti…
asdacap Jun 16, 2026
c99d539
refactor(flat): drop redundant startViaPersisted from WalkAndAssemble
asdacap Jun 16, 2026
4288d8b
refactor(flat): move ResolveTrieRlp next to ReadBlobArenaRlp
asdacap Jun 16, 2026
694feab
refactor(flat): document ISnapshotRepository; prune + tier/size-label…
asdacap Jun 16, 2026
0b542b0
refactor(flat): query walk tries compacted edges first
asdacap Jun 16, 2026
f826f88
refactor(flat): group backward-walk infrastructure at end of Snapshot…
asdacap Jun 16, 2026
b54640e
docs(flat): rewrite FindSnapshotToPersist comment
asdacap Jun 16, 2026
d5663b2
refactor(flat): route FindSnapshotToPersist through the shared BFS
asdacap Jun 16, 2026
997505e
Merge remote-tracking branch 'origin/master' into flat/long-finality
asdacap Jun 16, 2026
5590df7
refactor(flat): rework ArenaManager page-residency machinery per review
asdacap Jun 16, 2026
f058751
refactor(flat): consolidate flush pruning in PersistenceManager; extr…
asdacap Jun 16, 2026
a1c7df4
test(flat): raise Hsst branch coverage; drop two dead branches
asdacap Jun 16, 2026
d850ced
refactor(flat): label compaction metrics by actual compacted size
asdacap Jun 16, 2026
74e86ea
test(flat): cover Hsst top-level corruption detection
asdacap Jun 16, 2026
83929c3
refactor(flat): convert lock statements to using Lock.Scope declarations
asdacap Jun 16, 2026
81467cb
test(flat): cover PersistedSnapshotScanner enumerators
asdacap Jun 16, 2026
f534134
refactor(flat): unify in-memory + persisted prune in RemoveStatesUntil
asdacap Jun 16, 2026
d9251d8
test(flat): cover PersistedSnapshot compactor + loader branches
asdacap Jun 16, 2026
ea3089d
test(flat): cover PersistedSnapshot(Reader) miss and advise paths
asdacap Jun 16, 2026
ae71b39
test(flat): cover PersistedSnapshotStack probe loops
asdacap Jun 16, 2026
f33547b
refactor(flat): move test-only ReadRefIdsFromMetadata out of production
asdacap Jun 16, 2026
219cfcc
refactor(flat): drop manager DisposeAsync, vestigial metric labels, f…
asdacap Jun 16, 2026
24983cf
refactor(flat): split DoConvert into two methods; revert PersistSnapshot
asdacap Jun 16, 2026
d644a98
refactor(flat): rename config to MaxReorgDepth and loader to ConvertA…
asdacap Jun 16, 2026
1c8956a
Merge branch 'check-snapshot-coverage' into flat/long-finality
asdacap Jun 16, 2026
1f6a511
refactor(flat): restore MaxReorgDepth location; use a metric label st…
asdacap Jun 16, 2026
947cbd3
chore(flat): trim redundant, obvious, and stale comments across the b…
asdacap Jun 16, 2026
7efd78f
chore(flat): restore comments matching master to avoid needless churn
asdacap Jun 16, 2026
f759d0c
refactor(flat): address review — restore comments, config tweaks, dro…
asdacap Jun 16, 2026
a9656b4
refactor(flat): inline IsPersistCandidate; remove fadvise-on-eviction…
asdacap Jun 16, 2026
9c6cbb3
feat(flat): add PersistedLargeCompacted snapshot tier
asdacap Jun 16, 2026
f124c4a
refactor(flat): rename "Persistable" snapshot term to "CompactSized"
asdacap Jun 16, 2026
f513d69
refactor(flat): rename PersistedCompacted to PersistedSmallCompacted
asdacap Jun 16, 2026
29076ea
feat(flat): isolate sub-CompactSize snapshots in their own arena files
asdacap Jun 16, 2026
1905b39
refactor(flat): persist-walk fixes — exact-target win, candidate set,…
asdacap Jun 16, 2026
85bc877
fix(flat): correct persist candidate set — CompactSized is the candidate
asdacap Jun 16, 2026
f2cd82f
Merge branch 'separate-small-arena-files' into flat/long-finality
asdacap Jun 16, 2026
44b85c9
refactor(flat): inline the edge-priority arrays into their policies
asdacap Jun 16, 2026
62d5da4
refactor(flat): size-based persist candidate rule; ReadOnlySpan edge …
asdacap Jun 16, 2026
306083d
Merge remote-tracking branch 'origin/master' into flat/long-finality
asdacap Jun 16, 2026
628bb41
fix(flat): simplify two using statements (IDE0063) after merging master
asdacap Jun 16, 2026
4f1ee41
refactor(flat): inert persisted tier when long finality is disabled
asdacap Jun 17, 2026
552e992
feat(flat): debug logs for persisted-snapshot and arena lifecycle
asdacap Jun 17, 2026
9ac13dd
feat(flat): exit with git-bisect-compatible code on persisted snapsho…
asdacap Jun 17, 2026
5af5c04
Merge branch 'validate-snapshot-bisect-exit' into flat/long-finality
asdacap Jun 17, 2026
f6cad27
fix(flat): page-bound speculative node pin must keep header readable
asdacap Jun 17, 2026
5bd6e29
Merge branch 'flat/long-finality' of github.com:NethermindEth/netherm…
asdacap Jun 17, 2026
1a8fd85
style(flat): remove unnecessary usings (IDE0005)
asdacap Jun 17, 2026
4cc7614
refactor(flat): cooperative shutdown for persistence and compaction
asdacap Jun 17, 2026
f289b80
test(flat): drop TempDirArenaManager wrapper for the real ArenaManager
asdacap Jun 17, 2026
d66f1b3
config(flat): default persisted-snapshot arena page cache to 4 GiB
asdacap Jun 17, 2026
8e84a2f
Merge branch 'master' into flat/long-finality
asdacap Jun 17, 2026
f9fb0fd
perf(flat): skip persisted-snapshot probe in reads when the tier is e…
asdacap Jun 17, 2026
3c62349
feat(flat): separate LongFinalityMaxReorgDepth from MaxReorgDepth
asdacap Jun 17, 2026
a55e0c5
config(flat): raise PersistedSnapshotMaxCompactSize to 1Mi blocks
asdacap Jun 17, 2026
33145a2
feat(flat): warn when the force-persist backstop forces persistence
asdacap Jun 17, 2026
8757e5d
refactor(flat): drop LastRegisteredState, use master's force-persist …
asdacap Jun 17, 2026
e05932b
fix(flat): raise force-persist backstop above MinReorgDepth
asdacap Jun 18, 2026
fa96d36
fix(flat): clamp persisted compaction window to the persistence point
asdacap Jun 18, 2026
c3276f8
fix(flat): make force-persist backstop an independent fallback
asdacap Jun 18, 2026
99468a2
perf(flat): use a non-padded ref-counter for PersistedSnapshot/ArenaR…
asdacap Jun 19, 2026
178a0e2
perf(flat): free demoted intermediate snapshot blooms
asdacap Jun 19, 2026
d0fd81a
Merge branch 'remove-bloom-on-demote' into flat/long-finality
asdacap Jun 19, 2026
aa7da18
perf(flat): share large-compaction bloom across contained snapshots
asdacap Jun 19, 2026
571269d
perf(flat): rebuild only the widest blooms on reload and share them
asdacap Jun 19, 2026
1ccfbdc
perf(flat): dedup shared blooms when sizing the merged compaction bloom
asdacap Jun 20, 2026
1dba23a
feat(flat): add detailed metric for live persisted-snapshot bloom count
asdacap Jun 20, 2026
b6e9552
refactor(flat): replace persisted-snapshot HSST with single-level sor…
asdacap Jun 23, 2026
173b15f
perf(flat): sparse sorted-table index, 1-byte sizes, per-id ref-ids
asdacap Jun 23, 2026
af4021e
perf(flat): front-code SortedTable keys (per-block prefix compression)
asdacap Jun 23, 2026
4683f92
refactor: remove unused Leb128 helper
asdacap Jun 23, 2026
a508dd6
Merge branch 'investigate-leb128-usage' into simplify-snapshot-format
asdacap Jun 23, 2026
b92bc1f
perf(flat): two-level SortedTable — 4KB blocks, in-block restarts, se…
asdacap Jun 23, 2026
a64980f
perf(flat): reusable Block format + 4K block-number addressing for So…
asdacap Jun 23, 2026
cd18172
fix(flat): address PR #12100 review findings
asdacap Jun 23, 2026
00779be
perf(flat): stream SortedTable build, lift 2 GiB record-buffer cap
asdacap Jun 23, 2026
86d8b99
refactor(flat): drop stale "Hsst" naming from the IO seam package
asdacap Jun 23, 2026
45051d2
refactor(flat): drop the page-residency tracker, keep OS demote/prewarm
asdacap Jun 23, 2026
93be7f7
refactor(flat): align snapshot trie-key encoding with persistence
asdacap Jun 23, 2026
4aa912e
refactor(flat): give persisted-snapshot slots their own column
asdacap Jun 24, 2026
4884ee3
perf(flat): clamp persisted-snapshot lookups to precalculated per-col…
asdacap Jun 24, 2026
8c0e85c
refactor(flat): fold per-address account and self-destruct into one v…
asdacap Jun 24, 2026
32b60b3
Merge branch 'remove-page-residency-tracker' into simplify-snapshot-f…
asdacap Jun 24, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
using Nethermind.Logging;
using Nethermind.State.Flat;
using Nethermind.State.Flat.Persistence;
using Nethermind.State.Flat.PersistedSnapshots;
using Nethermind.State.Flat.ScopeProvider;
using Nethermind.Trie;
using FlatSnapshot = Nethermind.State.Flat.Snapshot;
Expand Down Expand Up @@ -73,16 +74,17 @@ public void Setup()
int storageAccountCount = 20 * multiplier;
int slotsPerStorageAccount = 100 * multiplier;

// Build ReadOnlySnapshotBundle from previously captured snapshots
SnapshotPooledList prevSnapshots = new(allSnapshots.Count);
foreach (FlatSnapshot s in allSnapshots)
{
s.TryAcquire();
prevSnapshots.Add(s);
}

// Build ReadOnlySnapshotBundle from previously captured snapshots
ReadOnlySnapshotBundle readOnly = new(
prevSnapshots, new NoopPersistenceReader(), recordDetailedMetrics: false);
prevSnapshots, new NoopPersistenceReader(), recordDetailedMetrics: false,
PersistedSnapshotStack.Empty());
NullTrieNodeCache cache = new();
SnapshotBundle bundle = new(
readOnly, cache, resourcePool, ResourcePool.Usage.MainBlockProcessing);
Expand Down Expand Up @@ -154,16 +156,17 @@ public void Setup()
maxSlotsPerStorageAccount = slotsPerStorageAccount;
}

// Build final ReadOnlySnapshotBundle with all 8 snapshots
SnapshotPooledList finalSnapshots = new(allSnapshots.Count);
foreach (FlatSnapshot s in allSnapshots)
{
s.TryAcquire();
finalSnapshots.Add(s);
}

// Build final ReadOnlySnapshotBundle with all 8 snapshots
_bundle = new ReadOnlySnapshotBundle(
finalSnapshots, new NoopPersistenceReader(), recordDetailedMetrics: false);
finalSnapshots, new NoopPersistenceReader(), recordDetailedMetrics: false,
PersistedSnapshotStack.Empty());

// --- Hit arrays ---
_hitAccounts = new Address[ArraySize];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
using Nethermind.Logging;
using Nethermind.State.Flat;
using Nethermind.State.Flat.Persistence;
using Nethermind.State.Flat.PersistedSnapshots;
using Nethermind.State.Flat.ScopeProvider;
using Nethermind.Trie;
using FlatSnapshot = Nethermind.State.Flat.Snapshot;
Expand Down Expand Up @@ -65,7 +66,8 @@ public void GlobalSetup()
}

ReadOnlySnapshotBundle readOnly = new(
prevSnapshots, new NoopPersistenceReader(), recordDetailedMetrics: false);
prevSnapshots, new NoopPersistenceReader(), recordDetailedMetrics: false,
PersistedSnapshotStack.Empty());
NullTrieNodeCache cache = new();
SnapshotBundle bundle = new(
readOnly, cache, _resourcePool, ResourcePool.Usage.MainBlockProcessing);
Expand Down Expand Up @@ -147,7 +149,8 @@ public void IterationSetup()
}

ReadOnlySnapshotBundle readOnly = new(
prevSnapshots, new NoopPersistenceReader(), recordDetailedMetrics: false);
prevSnapshots, new NoopPersistenceReader(), recordDetailedMetrics: false,
PersistedSnapshotStack.Empty());
NullTrieNodeCache cache = new();
SnapshotBundle bundle = new(
readOnly, cache, _resourcePool, ResourcePool.Usage.MainBlockProcessing);
Expand Down
127 changes: 127 additions & 0 deletions src/Nethermind/Nethermind.Core/Utils/SmallRefCountingDisposable.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited
// SPDX-License-Identifier: LGPL-3.0-only

using System;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Threading;

namespace Nethermind.Core.Utils;

/// <summary>
/// Variant of <see cref="RefCountingDisposable"/> that stores its lease counter inline as a single
/// <see cref="long"/> instead of a cache-line-padded one, trading false-sharing protection for a much
/// smaller per-instance footprint. Prefer it for types that exist in large numbers and whose lease
/// counts are rarely contended across cores.
/// </summary>
public abstract class SmallRefCountingDisposable(int initialCount = 1) : IDisposable
{
private const int Single = 1;
private const int NoAccessors = 0;
private const int Disposing = -1;

private long _leases = initialCount;

public void AcquireLease()
{
if (!TryAcquireLease())
{
ThrowCouldNotAcquire();
}

[DoesNotReturn]
[StackTraceHidden]
static void ThrowCouldNotAcquire() => throw new InvalidOperationException("The lease cannot be acquired");
}

protected bool TryAcquireLease()
{
// Volatile read for starting value
long current = Volatile.Read(ref _leases);

while (true)
{
// Reject once the count has reached zero (NoAccessors) or gone to Disposing: the object is
// being torn down. Acquiring at NoAccessors would resurrect an object whose owner has
// already observed the zero count and begun teardown — the release path moves the count
// 1 → 0 and only then CASes 0 → Disposing, so a concurrent acquirer can briefly see 0.
// Checking inside the loop (not just on the initial read) also closes the window where a
// failed CAS hands back a now-zero count.
if (current <= NoAccessors)
{
return false;
}

long prev = Interlocked.CompareExchange(ref _leases, current + Single, current);
if (prev == current)
{
// Successfully acquired
return true;
}

// Try again with the observed value
current = prev;
// Add PAUSE instruction to reduce shared core contention
Thread.SpinWait(1);
}
}

/// <summary>
/// Disposes it once, decreasing the lease count by 1.
/// </summary>
public void Dispose() => ReleaseLeaseOnce();

private void ReleaseLeaseOnce()
{
// Volatile read for starting value
long current = Volatile.Read(ref _leases);
if (current <= NoAccessors)
{
// Mismatched Acquire/Release
ThrowOverDisposed();
}

while (true)
{
long prev = Interlocked.CompareExchange(ref _leases, current - Single, current);
if (prev != current)
{
current = prev;
// Add PAUSE instruction to reduce shared core contention
Thread.SpinWait(1);
continue;
}
if (prev == Single)
{
// Last use, try to dispose underlying
break;
}
if (prev <= NoAccessors)
{
// Mismatched Acquire/Release
ThrowOverDisposed();
}

// Successfully released
return;
}

if (Interlocked.CompareExchange(ref _leases, Disposing, NoAccessors) == NoAccessors)
{
// set to disposed by this Release
CleanUp();
}

[DoesNotReturn]
[StackTraceHidden]
static void ThrowOverDisposed() => throw new ObjectDisposedException("The lease has already been disposed");
}

protected abstract void CleanUp();

public override string ToString()
{
long leases = Volatile.Read(ref _leases);
return leases == Disposing ? "Disposed" : $"Leases: {leases}";
}
}
1 change: 1 addition & 0 deletions src/Nethermind/Nethermind.Db/DbNames.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,6 @@ public static class DbNames
public const string PeersDb = "peers";
public const string LogIndex = "logIndex";
public const string Preimage = "preimage";
public const string PersistedSnapshotCatalog = "persistedSnapshotCatalog";
}
}
9 changes: 9 additions & 0 deletions src/Nethermind/Nethermind.Db/FlatDbConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,13 @@ public class FlatDbConfig : IFlatDbConfig
public long BlockCacheSizeBudget { get; set; } = 1.GiB;
public long CompactionOffset { get; set; } = -1;
public long TrieCacheMemoryBudget { get; set; } = 512.MiB;
public bool EnableLongFinality { get; set; } = false;
public int LongFinalityMaxReorgDepth { get; set; } = 90000;
public int MaxInMemoryBaseSnapshotCount { get; set; } = 128;
public long ArenaFileSizeBytes { get; set; } = 1.GiB;
public long PersistedSnapshotDedicatedArenaThresholdBytes { get; set; } = 1.GiB;
public bool PersistedSnapshotPunchHoleOnReclaim { get; set; } = true;
public int PersistedSnapshotMaxCompactSize { get; set; } = 1024 * 1024;
public bool ValidatePersistedSnapshot { get; set; } = false;
public double PersistedSnapshotBloomBitsPerKey { get; set; } = 14.0;
}
29 changes: 28 additions & 1 deletion src/Nethermind/Nethermind.Db/IFlatDbConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public interface IFlatDbConfig : IConfig
[ConfigItem(Description = "Max in flight compact job", DefaultValue = "32")]
int MaxInFlightCompactJob { get; set; }

[ConfigItem(Description = "Max reorg depth", DefaultValue = "256")]
[ConfigItem(Description = "Max reorg depth — the force-persist backstop used when EnableLongFinality is off: once the in-memory depth exceeds it while finality is stalled, persistence is forced to bound memory.", DefaultValue = "256")]
int MaxReorgDepth { get; set; }

[ConfigItem(Description = "Minimum reorg depth", DefaultValue = "128")]
Expand All @@ -55,6 +55,33 @@ public interface IFlatDbConfig : IConfig
[ConfigItem(Description = "Verify with trie", DefaultValue = "false")]
bool VerifyWithTrie { get; set; }

[ConfigItem(Description = "Enable long finality support with persisted snapshots", DefaultValue = "false")]
bool EnableLongFinality { get; set; }

[ConfigItem(Description = "Force-persist backstop used when EnableLongFinality is on, in place of MaxReorgDepth. The persisted-snapshot tier serves deep reorgs, so this is much larger than the non-long-finality backstop.", DefaultValue = "90000")]
int LongFinalityMaxReorgDepth { get; set; }

[ConfigItem(Description = "Maximum number of in-memory base snapshots before conversion to the persisted-snapshot tier kicks in. Counted as `SnapshotCount` of the in-memory repository, not a block-distance depth.", DefaultValue = "128")]
int MaxInMemoryBaseSnapshotCount { get; set; }

[ConfigItem(Description = "Maximum size in bytes for a single arena file before a new one is started.", DefaultValue = "1073741824")]
long ArenaFileSizeBytes { get; set; }

[ConfigItem(Description = "Estimated-size threshold (bytes) at or above which a persisted-snapshot arena write goes to its own dedicated file instead of being packed into a shared arena.", DefaultValue = "1073741824")]
long PersistedSnapshotDedicatedArenaThresholdBytes { get; set; }

[ConfigItem(Description = "When reclaiming dead persisted-snapshot arena ranges — metadata reservation cleanup and blob-file frontier reset — call fallocate(FALLOC_FL_PUNCH_HOLE) to free the underlying disk blocks. Linux-only; automatically and permanently disabled per arena pool if the filesystem reports the operation unsupported. Set false to skip hole-punching entirely (the page-cache posix_fadvise still runs).", DefaultValue = "true")]
bool PersistedSnapshotPunchHoleOnReclaim { get; set; }

[ConfigItem(Description = "Max persisted snapshot compaction size (hierarchical compaction ceiling for persisted layer), in blocks", DefaultValue = "1048576")]
int PersistedSnapshotMaxCompactSize { get; set; }

[ConfigItem(Description = "Validate persisted snapshots against in-memory snapshots after conversion (debug/diagnostic only)", DefaultValue = "false")]
bool ValidatePersistedSnapshot { get; set; }

[ConfigItem(Description = "Bits per key for the per-snapshot in-memory bloom filter. One unified filter covers address/slot/self-destruct keys plus state-trie and storage-trie node paths. Higher = lower false-positive rate but more RAM. 0 disables the filter (lookups behave as full sweeps).", DefaultValue = "14.0")]
double PersistedSnapshotBloomBitsPerKey { get; set; }

[ConfigItem(Description = "Persistent dedicated reader threads used to resolve hinted BAL read sets into the pre-block cache. -1 for 4x logical processor count capped at 64. Values below 1 are clamped to 1. Use --Blocks.ParallelExecutionBatchRead=false to disable BAL warming entirely.", DefaultValue = "-1")]
int WarmReadConcurrency { get; set; }
}
49 changes: 49 additions & 0 deletions src/Nethermind/Nethermind.Init/Modules/FlatWorldStateModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// SPDX-License-Identifier: LGPL-3.0-only

using System;
using System.IO;
using Autofac;
using Nethermind.Api.Steps;
using Nethermind.Blockchain;
Expand All @@ -17,9 +18,12 @@
using Nethermind.JsonRpc.Modules.Admin;
using Nethermind.Logging;
using Nethermind.Monitoring.Config;
using Nethermind.Api;
using Nethermind.State.Flat;
using Nethermind.State.Flat.Persistence;
using Nethermind.State.Flat.PersistedSnapshots;
using Nethermind.State.Flat.ScopeProvider;
using Nethermind.State.Flat.PersistedSnapshots.Storage;
using Nethermind.State.Flat.Sync;
using Nethermind.State.Flat.Sync.Snap;

Expand All @@ -46,6 +50,7 @@ protected override void Load(ContainerBuilder builder)
ctx.Resolve<ISnapshotCompactor>(),
ctx.Resolve<ISnapshotRepository>(),
ctx.Resolve<IPersistenceManager>(),
ctx.Resolve<IPersistedSnapshotLoader>(),
ctx.Resolve<IFlatDbConfig>(),
ctx.Resolve<IBlocksConfig>(),
ctx.Resolve<ILogManager>(),
Expand All @@ -55,7 +60,26 @@ protected override void Load(ContainerBuilder builder)
.AddSingleton<ICompactionSchedule, CompactionSchedule>()
.AddSingleton<ISnapshotCompactor, SnapshotCompactor>()
.AddSingleton<IPersistenceManager, PersistenceManager>()
// Shared ArenaManager + BlobArenaManager singletons: the persisted-snapshot repo and
// the compactor MUST resolve the same instances, otherwise compaction would write
// through a different mmap than the repository reads from.
.AddSingleton<ArenaManager, IFlatDbConfig, IInitConfig, ILogManager>((cfg, initConfig, logManager) =>
{
string basePath = Path.Combine(initConfig.BaseDbPath, "persisted_snapshot");
return new ArenaManager(Path.Combine(basePath, "arena"), cfg, logManager);
})
.AddSingleton<IArenaManager>(ctx => ctx.Resolve<ArenaManager>())
.AddSingleton<BlobArenaManager, IFlatDbConfig, IInitConfig>((cfg, initConfig) =>
{
string basePath = Path.Combine(initConfig.BaseDbPath, "persisted_snapshot");
return new BlobArenaManager(
Path.Combine(basePath, "blob"),
cfg.ArenaFileSizeBytes);
})
.AddSingleton<IPersistedSnapshotCompactor, PersistedSnapshotCompactor>()
.AddSingleton<ISnapshotRepository, SnapshotRepository>()
// Registered after ISnapshotRepository so DI disposes it first.
.AddSingleton<IPersistedSnapshotLoader, PersistedSnapshotLoader>()
.AddSingleton<ITrieWarmer>(flatDbConfig.TrieWarmerWorkerCount == 0
? _ => new NoopTrieWarmer()
: ctx => ctx.Resolve<TrieWarmer>())
Expand All @@ -72,6 +96,17 @@ protected override void Load(ContainerBuilder builder)

// Persistences
.AddColumnDatabase<FlatDbColumns>(DbNames.Flat)
// Persisted snapshot catalog: dedicated RocksDB co-located with the arena/blob files it
// indexes under <BaseDbPath>/persisted_snapshot/catalog/. Wiping persisted_snapshot/
// therefore wipes the catalog alongside the data.
.AddKeyedSingleton<IDb>(DbNames.PersistedSnapshotCatalog, ctx => ctx
.Resolve<IDbFactory>()
.CreateDb(new DbSettings(
nameof(DbNames.PersistedSnapshotCatalog),
Path.Combine("persisted_snapshot", "catalog"))))
.AddSingleton<SnapshotCatalog>(ctx =>
new SnapshotCatalog(ctx.ResolveKeyed<IDb>(DbNames.PersistedSnapshotCatalog)))
.AddSingleton<ISnapshotCatalog>(ctx => ctx.Resolve<SnapshotCatalog>())
.AddSingleton<RocksDbPersistence>()
.AddSingleton<FlatInTriePersistence>()
.AddDecorator<IRocksDbConfigFactory, FlatRocksDbConfigAdjuster>()
Expand Down Expand Up @@ -99,6 +134,20 @@ protected override void Load(ContainerBuilder builder)
})
;

// EnableLongFinality off: inert the whole persisted tier. The Null loader skips loading any
// on-disk tier at startup and never converts in-memory snapshots into it; the Null catalog keeps
// it empty (nothing recorded or loaded); the Null compactor runs no background compaction. The
// conversion paths in PersistenceManager.DetermineSnapshotAction are also gated on this flag.
// SnapshotRepository still constructs its arena/blob/catalog stores under
// `<data-dir>/persisted_snapshot/`, but they stay empty and unread.
if (!flatDbConfig.EnableLongFinality)
{
builder
.AddSingleton<ISnapshotCatalog>(NullSnapshotCatalog.Instance)
.AddSingleton<IPersistedSnapshotLoader>(NullPersistedSnapshotLoader.Instance)
.AddSingleton<IPersistedSnapshotCompactor>(NullPersistedSnapshotCompactor.Instance);
}

if (flatDbConfig.ImportFromPruningTrieState)
{
builder
Expand Down
Loading
Loading