Skip to content

feat(validator): return signed block commitment from SignBlock#2204

Merged
Mirko-von-Leipzig merged 4 commits into
0xMiden:nextfrom
mmagician:mmagician-claude/return-signed-commitment
Jun 5, 2026
Merged

feat(validator): return signed block commitment from SignBlock#2204
Mirko-von-Leipzig merged 4 commits into
0xMiden:nextfrom
mmagician:mmagician-claude/return-signed-commitment

Conversation

@mmagician
Copy link
Copy Markdown
Contributor

Why

Block 1 is being rejected by the block producer with InvalidSignature
(signature.verify(header.commitment(), header.validator_key())). #2203 rules out the validator-key mismatch. The remaining unverified suspect is that the validator and the block producer derive a different block commitment from the same ProposedBlock (e.g. an architecture-dependent difference - the validator runs on ARM, dev/CI on amd64), so the signature is valid for the validator's commitment but not the producer's.

Today the SignBlock response carries only the signature, so the producer cannot tell a commitment mismatch from a key/algorithm problem. This PR has the validator return the commitment it actually signed, and the block producer compares it against its own. It is a deliberately small, easily revertible diagnostic, separate from #2203.

What

  • Proto: new SignBlockResponse { BlockSignature signature; primitives.Digest block_commitment; }, and SignBlock now returns it. BlockSignature is left unchanged (it is also embedded in the persisted SignedBlock, where the commitment would be redundant with the header), so the existing conversions are untouched.
  • Validator handler (bin/validator/src/server/sign_block.rs): returns (Signature, Word); the signed commitment is captured from the validated header before it is moved into the persistence step.
  • Block producer client (crates/block-producer/src/validator/mod.rs): sign_block returns (Signature, Word).
  • Block producer (crates/block-producer/src/block_builder/mod.rs): before the signature check, compares the validator's signed commitment against the locally built header.commitment() and returns the new BuildBlockError::BlockCommitmentMismatch { validator, block_producer } on divergence. This cleanly separates the cases: commitment mismatch -> BlockCommitmentMismatch; commitment matches but verify fails -> key/algorithm problem (InvalidSignature).

A hard error (not assert!/panic) is used, matching the existing InvalidSignature style: on a real mismatch the signature check would fail anyway, so the explicit error is strictly more informative without crashing the process.

Tests

sign_block_returns_signed_commitment (validator server suite) asserts the response carries the commitment of the block the validator signed and that it matches the commitment derived from the same proposed block.

Verification

  • cargo build -p miden-node-proto -p miden-validator -p miden-node-block-producer (regenerates proto).
  • cargo test -p miden-validator --lib: 14 passed, 1 ignored.
  • cargo clippy --locked -p miden-node-proto -p miden-validator -p miden-node-block-producer --all-targets --all-features -- -D warnings: clean.
  • Nightly rustfmt + comment reflow: clean.

(Note: mempool::tests::add_transaction_traces_are_correct is flaky under parallel runs - passes in isolation - and is unrelated to this change.)

🤖 Generated with Claude Code

claude added 2 commits June 4, 2026 17:29
To diagnose block-1 `InvalidSignature` rejections, the block producer needs to
distinguish a block-hash mismatch (validator and block producer derive a
different commitment from the same proposed block) from a key/algorithm problem.

The `SignBlock` RPC now returns a `SignBlockResponse` carrying both the signature
and the commitment the validator actually signed. The block producer compares
that commitment against its own locally built `header.commitment()` and fails
with a distinct `BuildBlockError::BlockCommitmentMismatch` (naming both
commitments) before the signature check, so the two failure modes are
disambiguated.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@bobbinth bobbinth left a comment

Choose a reason for hiding this comment

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

Looks good! Thank you! (I reviewed non-test code)

@Mirko-von-Leipzig Mirko-von-Leipzig marked this pull request as ready for review June 5, 2026 10:55
@Mirko-von-Leipzig Mirko-von-Leipzig merged commit fe2a83e into 0xMiden:next Jun 5, 2026
20 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants