linera-io/linera-protocol · critical · ChainError
Justification chain must lie in rounds strictly below the ce
Error message
Justification chain must lie in rounds strictly below the certificate's round
What it means
For validated certificates, after matching the signed unlocking round to the chain top, LiteCertificate::check enforces at linera-chain/src/certificate/lite.rs:181 that the justification chain lies strictly below the certificate's own round (top.is_none_or(|top| top < self.round), else ChainError::JustificationChainNotBelowCertificate). A chain reaching the certified round or beyond is nonsensical: a certificate cannot be justified by evidence from its own or a higher round, which would enable circular justification and double-confirmation.
Source
Thrown at linera-chain/src/certificate/lite.rs:181
let value = VoteValue(
self.value.value_hash,
self.round,
self.value.kind,
self.unlocking_round,
self.first_round,
self.justification_commitment,
);
check_signatures(&value, &self.signatures, committee)?;
let top = self.justification.top_unlocking_round();
match self.value.kind {
CertificateKind::Validated => {
// The signed unlocking round must be the top of the chain, which must lie strictly
// below the certified round.
ensure!(
self.unlocking_round == top,
ChainError::JustificationUnlockingRoundMismatch
);
ensure!(
top.is_none_or(|top| top < self.round),
ChainError::JustificationChainNotBelowCertificate
);
}
CertificateKind::Confirmed => {
// The first-round attestation can only be set in a round that could be a chain's
// first one.
if self.first_round {
ensure!(
matches!(
self.round,
Round::Fast
| Round::MultiLeader(0)
| Round::SingleLeader(0)
| Round::Validator(0)
),
ChainError::FalseFirstRoundAttestation
);View on GitHub (pinned to 6c226ddcb3)
Solutions
- Reject the certificate; per protocol this can only be malformed or malicious input.
- If produced by your own node, audit where full_justification/append is called: the appended quorum's round must be strictly below the new certificate's round.
- Add invariant tests over round monotonicity when constructing justification chains.
- Alert on frequency: sporadic failures point to a faulty peer, sustained failures to an adversarial one or a version bug.
Defensive patterns
Strategy: try-catch
Try / catch
match certificate.check(&committee) {
Ok(value) => value,
Err(ChainError::JustificationChainNotBelowCertificate) => {
// Impossible for honest participants: chain at/above the certified round.
tracing::error!(round = ?certificate.round, "justification chain not below certificate round; flagging peer");
self.penalize_peer(peer_id);
return Err(ChainError::JustificationChainNotBelowCertificate.into());
}
Err(e) => return Err(e),
} Prevention
- Assert round monotonicity wherever justification chains are constructed or appended.
- Do not splice chains during view change; rebuild from the current round's validation.
- Fuzz certificate round combinations to prove the builder cannot emit non-monotonic chains.
When it happens
Trigger: A crafted certificate whose justification chain includes a link with round >= the certificate's round; a bug merging chains during view change that splices a same-round validation below a new certificate; replay of an old certificate with a chain refreshed by later-round evidence.
Common situations: Byzantine validators attempting to justify a value with fabricated future-round evidence; logic errors in view-change/retry code that append the wrong chain; test fixtures building chains with non-monotonic rounds.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- Certificate justification commitment does not match its just
- Certificate unlocking round does not match the top of its ju
- Certificate carries the first-round attestation but was not
- FalseFirstRoundAttestation
- CannotRejectMessage
AI-assisted analysis of linera-io/linera-protocol@6c226ddcb3 (2026-08-22).
Data as JSON: /api/errors/ac4399b94e58683a.
Report an issue: GitHub.