anvil/eth/tempo_consensus.rs
1//! Native Tempo consensus RPC response types.
2//!
3//! `consensus_getFinalization` returns a [`TempoCertifiedBlock`]. `consensus_getLatest` returns a
4//! [`TempoConsensusState`] with nullable `finalized` and `notarized`; local mining only populates
5//! `finalized`. The certificate bytes are unprefixed hex.
6//!
7//! Identity rotation takes effect in the epoch after the next block's epoch, allowing its
8//! predecessor's boundary block to announce the new key before it signs. Snapshots restore pending
9//! rotations exactly; rollback restores the retained block's key schedule.
10//!
11//! Locally mined fork blocks commit to a partial trie of the accounts and storage slots cached
12//! when the block was mined, rather than the complete upstream state. Non-pending `eth_getProof`
13//! queries use that immutable trie, including at the current head after development state edits.
14//! Accounts and slots absent from it have exclusion proofs, even if they exist upstream. Later
15//! upstream reads cannot extend an already certified trie. Proof snapshots follow the configured
16//! state-history cache limits; evicted snapshots are unavailable rather than rebuilt from live
17//! state. The latest snapshot is retained even when historical state retention is disabled.
18
19use super::{
20 backend::tempo_consensus::TempoFinalization,
21 error::{BlockchainError, Result},
22};
23use anvil_core::eth::block::Block;
24use foundry_primitives::{FoundryHeader, FoundryTxEnvelope};
25use serde::{Deserialize, Serialize};
26use tempo_primitives::TempoTxEnvelope;
27
28/// A finalization certificate and the complete native Tempo block it authenticates.
29#[derive(Clone, Debug, Deserialize, Serialize)]
30pub struct TempoCertifiedBlock {
31 /// Certificate metadata and bytes for this block.
32 #[serde(flatten)]
33 pub finalization: TempoFinalization,
34 /// Native header and body, without Anvil transaction wrappers.
35 pub block: tempo_primitives::Block,
36}
37
38impl TryFrom<(TempoFinalization, Block)> for TempoCertifiedBlock {
39 type Error = BlockchainError;
40
41 fn try_from((finalization, block): (TempoFinalization, Block)) -> Result<Self> {
42 let block = block
43 .try_map_header(|header| match header {
44 FoundryHeader::Tempo(header) => Ok(header),
45 FoundryHeader::Ethereum(_) => {
46 Err(BlockchainError::Internal("expected a native Tempo header".into()))
47 }
48 })?
49 .try_map_transactions(|tx| match tx.into_inner() {
50 FoundryTxEnvelope::Legacy(tx) => Ok(TempoTxEnvelope::Legacy(tx)),
51 FoundryTxEnvelope::Eip2930(tx) => Ok(TempoTxEnvelope::Eip2930(tx)),
52 FoundryTxEnvelope::Eip1559(tx) => Ok(TempoTxEnvelope::Eip1559(tx)),
53 FoundryTxEnvelope::Eip7702(tx) => Ok(TempoTxEnvelope::Eip7702(tx)),
54 FoundryTxEnvelope::Tempo(tx) => Ok(TempoTxEnvelope::AA(tx)),
55 _ => Err(BlockchainError::Internal("expected a native Tempo transaction".into())),
56 })?;
57 Ok(Self { finalization, block })
58 }
59}
60
61/// Current consensus state, matching Tempo's `consensus_getLatest` response.
62#[derive(Clone, Debug, Serialize)]
63pub struct TempoConsensusState {
64 /// Latest local finalization, or the pinned upstream finalization before local mining.
65 pub finalized: Option<TempoCertifiedBlock>,
66 /// Reserved by Tempo; local mining only produces finalizations.
67 pub notarized: Option<TempoCertifiedBlock>,
68}