Skip to content

Validator chain invariants#1774

Open
sergerad wants to merge 11 commits intosergerad-validator-bootstrapfrom
sergerad-validator-chain
Open

Validator chain invariants#1774
sergerad wants to merge 11 commits intosergerad-validator-bootstrapfrom
sergerad-validator-chain

Conversation

@sergerad
Copy link
Collaborator

@sergerad sergerad commented Mar 11, 2026

Context

Closes #1773.

In #1764 we are adding a validator subcommand to construct and sign the genesis block. In this PR, we are building on top of that and storing the genesis block as the initial chain tip in the validator DB.

The validator is updated to maintain a chain tip as it continues to sign blocks. It uses this state to validate chain continuity (block number sequence, commitment references, etc).

Changes

  • Added a chain_tip table to the validator database to persist the last signed block header.
  • Bootstrap now initializes the validator database with the genesis block header as the chain tip (new --data-directory argument).
  • The validator server loads the chain tip on startup and requires it to be present (i.e., bootstrap must be run first).
  • validate_block now enforces chain continuity: sequential block numbers and matching previous block commitments.
  • validate_block handles retries by detecting when a proposed block matches the current chain tip and re-signing without advancing state (idempotence).
  • The chain tip is updated in-memory (behind a Mutex) and persisted to the database after each new block is signed.
  • Made the db module public so the bootstrap command can call save_chain_tip and load directly.

@sergerad sergerad added the no changelog This PR does not require an entry in the `CHANGELOG.md` file label Mar 11, 2026
@sergerad sergerad requested review from Mirko-von-Leipzig, bobbinth and mmagician and removed request for bobbinth March 11, 2026 00:47
@sergerad sergerad marked this pull request as ready for review March 11, 2026 00:48
Copy link
Collaborator

@Mirko-von-Leipzig Mirko-von-Leipzig left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor nits, but I think we need to allow for a single block fork.

/// block commitment).
///
/// On success, returns the signature and the new block header (which becomes the new chain tip).
#[instrument(target = COMPONENT, skip_all, err, fields(chain_tip = chain_tip.block_num().as_u32()))]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should also log block.number and block.commitment

Copy link
Collaborator Author

@sergerad sergerad Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

those aren't available from ProposedBlock, if thats what you mean. I could add an event in the fn? After

    let (proposed_header, _) = proposed_block

@sergerad sergerad changed the title Validator chain continuity check Validator chain invariants Mar 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

no changelog This PR does not require an entry in the `CHANGELOG.md` file

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants