Skip to content
This repository was archived by the owner on Aug 3, 2026. It is now read-only.

Commit 2d86210

Browse files
committed
fix: always include Shasta parent checkpoint proof
1 parent 16f0ee4 commit 2d86210

2 files changed

Lines changed: 89 additions & 22 deletions

File tree

core/src/preflight/mod.rs

Lines changed: 40 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ use raiko_lib::{
2121
Measurement,
2222
};
2323
use reth_primitives::TransactionSigned;
24-
use reth_revm::Database;
2524
use tracing::{debug, info};
2625

2726
use util::{
@@ -81,12 +80,13 @@ impl PreflightData {
8180
}
8281
}
8382

84-
fn load_shasta_parent_checkpoint_storage<BDP: BlockDataProvider>(
85-
db: &mut ProviderDb<BDP>,
83+
fn shasta_parent_checkpoint_storage_slots(
8684
input: &GuestInput,
87-
) -> RaikoResult<()> {
85+
) -> RaikoResult<Vec<(raiko_lib::primitives::Address, raiko_lib::primitives::U256)>> {
8886
let Some(last_anchor_block_number) = input.taiko.prover_data.last_anchor_block_number else {
89-
return Ok(());
87+
return Err(RaikoError::Preflight(
88+
"cannot load shasta parent checkpoint: missing last_anchor_block_number".to_owned(),
89+
));
9090
};
9191
let Some(signal_service) =
9292
shasta_signal_service_address_from_l2_contract(input.chain_spec.l2_contract)
@@ -97,15 +97,17 @@ fn load_shasta_parent_checkpoint_storage<BDP: BlockDataProvider>(
9797
};
9898
let (block_hash_slot, state_root_slot) =
9999
shasta_checkpoint_storage_slots(last_anchor_block_number);
100-
for slot in [block_hash_slot, state_root_slot] {
101-
db.storage(signal_service, slot).map_err(|e| {
102-
RaikoError::Preflight(format!(
103-
"failed to load shasta parent checkpoint slot {slot:?} at block {}: {e:?}",
104-
db.block_number
105-
))
106-
})?;
107-
}
108-
Ok(())
100+
Ok(vec![
101+
(signal_service, block_hash_slot),
102+
(signal_service, state_root_slot),
103+
])
104+
}
105+
106+
fn should_load_shasta_parent_checkpoint_storage(
107+
input: &GuestInput,
108+
_batch_block_idx: usize,
109+
) -> bool {
110+
matches!(input.taiko.block_proposed, BlockProposedFork::Shasta(_))
109111
}
110112

111113
pub async fn preflight<BDP: BlockDataProvider>(
@@ -465,14 +467,16 @@ pub async fn batch_preflight<BDP: BlockDataProvider>(
465467
return Err(RaikoError::Preflight("No db in builder".to_owned()));
466468
};
467469

468-
if batch_block_idx == 0
469-
&& matches!(
470-
taiko_guest_batch_input.batch_proposed,
471-
BlockProposedFork::Shasta(_)
472-
)
473-
&& taiko_guest_batch_input.l1_ancestor_headers.is_empty()
474-
{
475-
load_shasta_parent_checkpoint_storage(db, &input)?;
470+
if should_load_shasta_parent_checkpoint_storage(&input, batch_block_idx) {
471+
let checkpoint_slots = shasta_parent_checkpoint_storage_slots(&input)?;
472+
db.load_initial_storage_values(&checkpoint_slots)
473+
.await
474+
.map_err(|e| {
475+
RaikoError::Preflight(format!(
476+
"failed to load shasta parent checkpoint storage at block {}: {e:?}",
477+
db.block_number
478+
))
479+
})?;
476480
}
477481

478482
// Gather inclusion proofs for the initial and final state
@@ -555,11 +559,25 @@ mod test {
555559
use ethers_core::types::Transaction;
556560
use raiko_lib::{
557561
consts::{Network, SupportedChainSpecs},
562+
input::{BlockProposedFork, GuestInput},
558563
utils::txs::decode_transactions,
559564
};
560565

566+
use super::should_load_shasta_parent_checkpoint_storage;
561567
use crate::preflight::util::{blob_to_bytes, block_time_to_block_slot};
562568

569+
#[test]
570+
fn shasta_parent_checkpoint_storage_is_loaded_for_every_batch_block() {
571+
let mut input = GuestInput::default();
572+
input.taiko.block_proposed = BlockProposedFork::Shasta(Default::default());
573+
574+
assert!(should_load_shasta_parent_checkpoint_storage(&input, 0));
575+
assert!(should_load_shasta_parent_checkpoint_storage(&input, 1));
576+
577+
input.taiko.block_proposed = BlockProposedFork::Nothing;
578+
assert!(!should_load_shasta_parent_checkpoint_storage(&input, 0));
579+
}
580+
563581
#[test]
564582
fn test_new_blob_decode() {
565583
let valid_blob_str = "\

core/src/provider/db.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,55 @@ impl<'a, BDP: BlockDataProvider> ProviderDb<'a, BDP> {
144144
Ok((initial_proofs, latest_proofs, num_storage_proofs))
145145
}
146146

147+
pub async fn load_initial_storage_values(
148+
&mut self,
149+
slots: &[(Address, U256)],
150+
) -> RaikoResult<()> {
151+
if slots.is_empty() {
152+
return Ok(());
153+
}
154+
155+
let mut addresses = slots
156+
.iter()
157+
.map(|(address, _)| *address)
158+
.collect::<Vec<_>>();
159+
addresses.sort_unstable();
160+
addresses.dedup();
161+
162+
let accounts = self
163+
.provider
164+
.get_accounts(self.block_number, &addresses)
165+
.await?;
166+
if accounts.len() != addresses.len() {
167+
return Err(RaikoError::RPC(format!(
168+
"expected {} accounts, got {}",
169+
addresses.len(),
170+
accounts.len()
171+
)));
172+
}
173+
for (address, account) in addresses.into_iter().zip(accounts) {
174+
self.initial_db.insert_account_info(address, account);
175+
}
176+
177+
let values = self
178+
.provider
179+
.get_storage_values(self.block_number, slots)
180+
.await?;
181+
if values.len() != slots.len() {
182+
return Err(RaikoError::RPC(format!(
183+
"expected {} storage values, got {}",
184+
slots.len(),
185+
values.len()
186+
)));
187+
}
188+
for ((address, slot), value) in slots.iter().zip(values) {
189+
self.initial_db
190+
.insert_account_storage(address, *slot, value);
191+
}
192+
193+
Ok(())
194+
}
195+
147196
pub async fn get_ancestor_headers(&mut self) -> RaikoResult<Vec<Header>> {
148197
let earliest_block = &self.block_number.saturating_sub(255);
149198
let mut headers = Vec::with_capacity(

0 commit comments

Comments
 (0)