feat(hot)!: add table for journal hashes#70
Conversation
| /// Set the journal hash (keccak256 of the wire-encoded `Journal::V1`). | ||
| /// Leave the method uncalled for block-only nodes that do not produce | ||
| /// a journal - the field defaults to `None`. | ||
| pub const fn journal_hash(mut self, hash: B256) -> Self { |
There was a problem hiding this comment.
nit: usually with_journal_hash or some other verb that indicates mutating
There was a problem hiding this comment.
I prefer the with_ prefix too, but all other setters don't have it.
I'd be OK with adding it to all of them. It'd be a breaking change to the API, but this PR already has other breaking changes, so now might be a good time to make that change if we want it?
There was a problem hiding this comment.
let's go ahead and make the change :)
| /// [`queue_raw_create`](crate::model::HotKvWrite::queue_raw_create) so the | ||
| /// same record drives both table creation and backend-side FSI inference. | ||
| #[derive(Debug, Clone, Copy, PartialEq, Eq)] | ||
| pub struct StandardTable { |
There was a problem hiding this comment.
I don't mind this complexity addition
prestwich
left a comment
There was a problem hiding this comment.
[Claude Code]
Approved. Reviewed for correctness and CLAUDE.md compliance — no bugs found and no convention violations.
Verified sound:
- `unwind_above` `checked_add(1)` overflow guard and the `JournalHashes` range-delete ordering.
- `queue_raw_create` flag refactor via `from_create_args`/`is_dupsort`/`is_dup_fixed` is equivalent to the prior inline behavior.
- `append_blocks` persists journal hashes atomically in the same writer/transaction as headers/bundle.
- `NUM_TABLES` (now `STANDARD_TABLES.len()`) — all consumers derive from the const, no drift.
One optional follow-up, not blocking: the agreed-upon `with_` prefix rename on the `ExecutedBlockBuilder` setters wasn't applied. Fraser can update the naming before merging if he wants.
Minor: the PR description still mentions the pre-upgrade FSI fallback and `open_tolerates_pre_upgrade_db` test that were removed in `ae5e263`; worth tidying the description before merge.

Summary
Adds a
JournalHashes<BlockNumber => B256>hot table so nodes can re-seed the rolling previous-journal hash across restarts and reorgs (ENG-2017). Hot-only, opt-in per block.Changes
JournalHashes<BlockNumber => B256>plusHotDbRead::get_journal_hashandUnsafeDbWrite::put_journal_hash.ExecutedBlock.journal_hash: Option<B256>+ builder setter.UnifiedStorage::append_blockspersists it in the same hot transaction as headers/bundle.HistoryWrite::unwind_abovedeletes journal hashes alongside change-sets/headers, independent oflast_block_number().STANDARD_TABLESconst insignet-hotas the single source of truth for table creation and MDBX FSI cache seeding.queue_db_initandread_known_fsiboth iterate it.unwind_above(u64::MAX)now short-circuits viachecked_addinstead of overflowingblock + 1(wraps to0in release, panics in debug).From<ExecutedBlock> for BlockDatadestructures explicitly so new fields trip a compile error on the cold side.API breakages
ExecutedBlock::new()removed - useExecutedBlockBuilderinstead.ExecutedBlockgains a new publicjournal_hashfield. Struct-literal construction (ExecutedBlock { header, .. }) and exhaustive destructuring without..will no longer compile.Test plan
cargo t -p signet-hot -p signet-hot-mdbx -p signet-storage --all-featurescargo clippy --workspace --all-targets --all-features -- -D warningscargo clippy --workspace --all-targets --no-default-features -- -D warningscargo +nightly fmt -- --checktest_journal_hash_roundtrip(conformance),append_blocks_persists_journal_hashes/unwind_above_drops_journal_hashes(integration),unwind_above_u64_max_is_noop/unwind_above_below_u64_max_deletes_max_entry(overflow boundary).test_unwind_conformanceupdated to coverJournalHashes.Notes
put_journal_hashhas no consistent-trait wrapper; callers are responsible for pairing writes with a header.unwind_abovecleans both regardless.replay_to_coldsilently discardsjournal_hash(hot-only).PR description drafted by Claude (Opus 4.7, 1M context) via Claude Code.