diem/diem · error
We must not accept genesis from others
Error message
We must not accept genesis from others
What it means
Block::verify_well_formed() performs state-independent sanity checks and first ensures the block is not a genesis block (via is_genesis_block()). Genesis must come from local configuration, not from peers, so a genesis check here fails with 'We must not accept genesis from others'.
Source
Thrown at consensus/consensus-types/src/block.rs:240
pub fn validate_signature(&self, validator: &ValidatorVerifier) -> anyhow::Result<()> {
match self.block_data.block_type() {
BlockType::Genesis => bail!("We should not accept genesis from others"),
BlockType::NilBlock => self.quorum_cert().verify(validator),
BlockType::Proposal { author, .. } => {
let signature = self
.signature
.as_ref()
.ok_or_else(|| format_err!("Missing signature in Proposal"))?;
validator.verify(*author, &self.block_data, signature)?;
self.quorum_cert().verify(validator)
}
}
}
/// Makes sure that the proposal makes sense, independently of the current state.
/// If this is the genesis block, we skip these checks.
pub fn verify_well_formed(&self) -> anyhow::Result<()> {
ensure!(
!self.is_genesis_block(),
"We must not accept genesis from others"
);
let parent = self.quorum_cert().certified_block();
ensure!(
parent.round() < self.round(),
"Block must have a greater round than parent's block"
);
ensure!(
parent.epoch() == self.epoch(),
"block's parent should be in the same epoch"
);
if parent.has_reconfiguration() {
ensure!(
self.payload().map_or(true, |p| p.is_empty()),
"Reconfiguration suffix should not carry payload"
);
}View on GitHub (pinned to fc4714a8ea)
Solutions
- Filter out genesis blocks before calling verify_well_formed; initialize from the local genesis/waypoint instead.
- Reject the offending message and penalize/disconnect the peer sending genesis.
- Fix sync logic to source the parent chain head from local storage rather than network payloads.
- Ensure tests construct fresh proposal blocks rather than reusing genesis.
Example fix
// before block.verify_well_formed()?; // after ensure!(!block.is_genesis_block(), "genesis must come from local config"); block.verify_well_formed()?;
Defensive patterns
Strategy: validation
Validate before calling
if block.is_genesis_block() {
return Err(anyhow::anyhow!("genesis must be loaded locally, not from peers"));
}
block.verify_well_formed()?; Type guard
fn is_network_block(block: &Block) -> bool {
!block.is_genesis_block()
} Try / catch
match block.verify_well_formed() {
Ok(()) => { /* continue processing */ }
Err(e) if e.to_string().contains("genesis") => {
drop_peer(peer_id);
metrics.genesis_offenses.inc();
}
Err(e) => return Err(e),
} Prevention
- Filter genesis blocks at the network ingress boundary.
- Bootstrap chain state only from local genesis/waypoint files.
- Write tests that assert genesis is never serialized over the wire.
- Reject and log peers that send genesis blocks.
When it happens
Trigger: Calling block.verify_well_formed() when is_genesis_block() is true — the QC/block being checked wraps the genesis block received or constructed as an incoming proposal.
Common situations: A peer proposes/syncs genesis, test harness reusing the genesis block as a proposal, initial sync pulling a block that should be loaded from the local genesis file.
Related errors
- We should not accept genesis from others
- Block must have a greater round than parent's block
- block's parent should be in the same epoch
- Reconfiguration suffix should not carry payload
- Nil/reconfig suffix block must have same timestamp as parent
AI-assisted analysis of diem/diem@fc4714a8ea (2026-09-04).
Data as JSON: /api/errors/f431f0b8a7ef08f1.
Report an issue: GitHub.