Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ resolver = "2"
default-members = ["node"]

[workspace.package]
version = "1.41.0"
version = "1.41.1"
edition = "2024"
repository = "https://github.com/NethermindEth/Catalyst"
license = "MIT"
Expand Down
85 changes: 66 additions & 19 deletions shasta/src/node/proposal_manager/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ use crate::node::L2SlotInfoV2;
use block_advancer::BlockAdvancer;
use proposal::Proposals;

pub struct RecoveredBlockInfo {
proposal_id: u64,
timestamp: u64,
}

pub struct ProposalManager {
proposal_builder: ProposalBuilder,
ethereum_l1: Arc<EthereumL1<ExecutionLayer>>,
Expand Down Expand Up @@ -464,32 +469,57 @@ impl ProposalManager {
pub async fn recover_from_l2_block(
&mut self,
block_height: u64,
parent_timestamp: Option<u64>,
) -> Result<u64, Error> {
parent_info: Option<RecoveredBlockInfo>,
) -> Result<RecoveredBlockInfo, Error> {
debug!("Recovering from L2 block {}", block_height);

let parent_timestamp = if let Some(ts) = parent_timestamp {
ts
let block = self
.taiko
.get_l2_block_by_number(block_height, true)
.await?;

let proposal_id =
crate::l2::extra_data::ExtraData::decode(block.header.extra_data())?.proposal_id;

let parent_info = if let Some(info) = parent_info {
info
} else {
if block_height == 0 {
return Err(anyhow::anyhow!(
"recover_from_l2_block: parent_timestamp must be provided for genesis (block_height == 0)"
"recover_from_l2_block: parent_info must be provided for genesis (block_height == 0)"
));
}

self.taiko
let parent_block = self
.taiko
.get_l2_block_by_number(block_height - 1, false)
.await?
.header
.timestamp()
};
.await?;

let block = self
.taiko
.get_l2_block_by_number(block_height, true)
.await?;
let parent_proposal_id =
crate::l2::extra_data::ExtraData::decode(parent_block.header.extra_data())?
.proposal_id;

self.validate_block_timestamp(block_height, block.header.timestamp(), parent_timestamp)?;
if proposal_id != parent_proposal_id + 1 {
return Err(anyhow::anyhow!(
"recover_from_l2_block: proposal ID validation failed at the first recovered block {}: proposal_id={} parent_proposal_id={}",
block_height,
proposal_id,
parent_proposal_id,
));
}

RecoveredBlockInfo {
proposal_id: parent_proposal_id,
timestamp: parent_block.header.timestamp(),
}
};

self.validate_block_timestamp(
block_height,
block.header.timestamp(),
parent_info.timestamp,
)?;
self.validate_block_proposal_id(block_height, proposal_id, parent_info.proposal_id)?;

let (anchor_tx, txs) = match block.transactions.as_transactions() {
Some(txs) => txs.split_first().ok_or_else(|| {
Expand Down Expand Up @@ -517,9 +547,6 @@ impl ProposalManager {

let coinbase = block.header.beneficiary();

let proposal_id =
crate::l2::extra_data::ExtraData::decode(block.header.extra_data())?.proposal_id;

let anchor_tx_data = Taiko::get_anchor_tx_data(anchor_tx.input())?;
let anchor_info = AnchorBlockInfo::from_precomputed_data(
self.ethereum_l1.execution_layer.common(),
Expand Down Expand Up @@ -557,7 +584,27 @@ impl ProposalManager {
is_forced_inclusion,
)
.await?;
Ok(block.header.timestamp())
Ok(RecoveredBlockInfo {
proposal_id,
timestamp: block.header.timestamp(),
})
}

fn validate_block_proposal_id(
&self,
block_height: u64,
proposal_id: u64,
parent_proposal_id: u64,
) -> Result<(), Error> {
match proposal_id.checked_sub(parent_proposal_id) {
Some(diff) if diff <= 1 => Ok(()),
Comment thread
mikhailUshakoff marked this conversation as resolved.
_ => Err(anyhow::anyhow!(
"Proposal ID validation failed at block {}: proposal_id={} parent_proposal_id={}",
block_height,
proposal_id,
parent_proposal_id,
)),
}
}

fn validate_block_timestamp(
Expand Down
6 changes: 3 additions & 3 deletions shasta/src/node/verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -220,16 +220,16 @@ impl VerifierThread {

// Sync FI with L1 chain
self.proposal_manager.reset_builder().await?;
let mut parent_timestamp = None;
let mut parent_info = None;

for current_height in first_block..=l2_height {
if self.cancel_token.is_cancelled() {
return Err(anyhow::anyhow!("Verification cancelled"));
}

parent_timestamp = Some(
parent_info = Some(
self.proposal_manager
.recover_from_l2_block(current_height, parent_timestamp)
.recover_from_l2_block(current_height, parent_info)
.await?,
);
}
Expand Down
Loading