From 1bacc1e2e4c355ebcb1b88b240543025ccfc21b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ahmet=20Yaz=C4=B1c=C4=B1?= <75089142+yaziciahmet@users.noreply.github.com> Date: Tue, 20 Aug 2024 16:13:33 +0300 Subject: [PATCH] Enable verifying proofs based on the fork (#1011) * Partially rewrite fork manager * Add SpecId to the zk output * Lint * Verify proofs with the corresponding spec ids * Disable lint * Remove unused const * Remove std * Lint * Remove Receipt output type * Remove risc0 zkvm from mockvm * Lint * Rename to last_active_spec_id * Restore fork logs * Lint * Remove unused * Remove unnecessary allow clippy --------- Co-authored-by: yaziciahmet --- bin/citrea/src/rollup/bitcoin.rs | 8 +- bin/citrea/src/rollup/mock.rs | 8 +- bin/citrea/src/rollup/mod.rs | 22 +-- crates/citrea-stf/src/verifier.rs | 3 +- crates/fullnode/src/runner.rs | 63 ++++----- crates/fullnode/tests/hash_stf.rs | 5 +- .../tests/runner_initialization_tests.rs | 11 +- crates/primitives/src/fork/manager.rs | 98 ++++++------- crates/primitives/src/fork/migration.rs | 8 +- crates/primitives/src/fork/tests.rs | 54 +++++--- crates/primitives/src/forks.rs | 12 +- crates/prover/src/runner.rs | 40 +++--- crates/risc0-bonsai/src/host.rs | 15 +- crates/sequencer/src/sequencer.rs | 19 +-- .../adapters/mock-zkvm/src/lib.rs | 18 +-- .../adapters/risc0/src/guest/mod.rs | 6 +- .../sovereign-sdk/adapters/risc0/src/host.rs | 24 ++-- .../examples/demo-simple-stf/src/lib.rs | 5 +- .../full-node/db/sov-db/src/ledger_db/mod.rs | 14 +- .../db/sov-db/src/ledger_db/traits.rs | 4 - .../full-node/db/sov-db/src/schema/tables.rs | 7 - .../full-node/sov-stf-runner/src/mock/mod.rs | 5 +- crates/sovereign-sdk/fuzz/Cargo.lock | 129 +++++++++--------- .../sov-modules-rollup-blueprint/src/lib.rs | 6 +- .../sov-modules-stf-blueprint/src/lib.rs | 22 +-- .../sovereign-sdk/rollup-interface/Cargo.toml | 1 - .../rollup-interface/src/fork.rs | 20 +++ .../sovereign-sdk/rollup-interface/src/lib.rs | 3 + .../rollup-interface/src/spec.rs | 4 + .../rollup-interface/src/state_machine/stf.rs | 5 +- .../src/state_machine/zk/mod.rs | 12 +- 31 files changed, 338 insertions(+), 313 deletions(-) create mode 100644 crates/sovereign-sdk/rollup-interface/src/fork.rs diff --git a/bin/citrea/src/rollup/bitcoin.rs b/bin/citrea/src/rollup/bitcoin.rs index f07038c5f..0f07f9e3e 100644 --- a/bin/citrea/src/rollup/bitcoin.rs +++ b/bin/citrea/src/rollup/bitcoin.rs @@ -1,3 +1,4 @@ +use std::collections::HashMap; use std::sync::Arc; use async_trait::async_trait; @@ -18,6 +19,7 @@ use sov_modules_stf_blueprint::StfBlueprint; use sov_prover_storage_manager::ProverStorageManager; use sov_rollup_interface::da::DaVerifier; use sov_rollup_interface::services::da::SenderWithNotifier; +use sov_rollup_interface::spec::SpecId; use sov_rollup_interface::zk::{Zkvm, ZkvmHost}; use sov_state::{DefaultStorageSpec, Storage, ZkStorage}; use sov_stf_runner::{FullNodeConfig, ProverConfig}; @@ -90,8 +92,10 @@ impl RollupBlueprint for BitcoinRollup { } #[instrument(level = "trace", skip(self), ret)] - fn get_code_commitment(&self) -> ::CodeCommitment { - Digest::new(citrea_risc0::BITCOIN_DA_ID) + fn get_code_commitments_by_spec(&self) -> HashMap::CodeCommitment> { + let mut map = HashMap::new(); + map.insert(SpecId::Genesis, Digest::new(citrea_risc0::BITCOIN_DA_ID)); + map } #[instrument(level = "trace", skip_all, err)] diff --git a/bin/citrea/src/rollup/mock.rs b/bin/citrea/src/rollup/mock.rs index b2da31133..a0b9da83f 100644 --- a/bin/citrea/src/rollup/mock.rs +++ b/bin/citrea/src/rollup/mock.rs @@ -1,3 +1,4 @@ +use std::collections::HashMap; use std::sync::Arc; use async_trait::async_trait; @@ -13,6 +14,7 @@ use sov_modules_api::{Address, Spec}; use sov_modules_rollup_blueprint::RollupBlueprint; use sov_modules_stf_blueprint::StfBlueprint; use sov_prover_storage_manager::ProverStorageManager; +use sov_rollup_interface::spec::SpecId; use sov_rollup_interface::zk::{Zkvm, ZkvmHost}; use sov_state::{DefaultStorageSpec, Storage, ZkStorage}; use sov_stf_runner::{FullNodeConfig, ProverConfig}; @@ -81,8 +83,10 @@ impl RollupBlueprint for MockDemoRollup { Ok(rpc_methods) } - fn get_code_commitment(&self) -> ::CodeCommitment { - Digest::new(citrea_risc0::MOCK_DA_ID) + fn get_code_commitments_by_spec(&self) -> HashMap::CodeCommitment> { + let mut map = HashMap::new(); + map.insert(SpecId::Genesis, Digest::new(citrea_risc0::MOCK_DA_ID)); + map } async fn create_da_service( diff --git a/bin/citrea/src/rollup/mod.rs b/bin/citrea/src/rollup/mod.rs index b28973697..36a0292ea 100644 --- a/bin/citrea/src/rollup/mod.rs +++ b/bin/citrea/src/rollup/mod.rs @@ -11,7 +11,6 @@ use sov_modules_api::storage::HierarchicalStorageManager; use sov_modules_api::Spec; use sov_modules_rollup_blueprint::RollupBlueprint; use sov_modules_stf_blueprint::{Runtime as RuntimeTrait, StfBlueprint}; -use sov_rollup_interface::spec::SpecId; use sov_state::storage::NativeStorage; use sov_stf_runner::{FullNodeConfig, InitVariant, ProverConfig}; use tokio::sync::broadcast; @@ -92,10 +91,7 @@ pub trait CitreaRollupBlueprint: RollupBlueprint { .map(|(l2_height, _)| l2_height) .unwrap_or(BatchNumber(0)); - let active_spec: SpecId = ledger_db.get_active_fork()?; - - let mut fork_manager = - ForkManager::new(current_l2_height.into(), active_spec, FORKS.to_vec()); + let mut fork_manager = ForkManager::new(FORKS.to_vec(), current_l2_height.0); fork_manager.register_handler(Box::new(ledger_db.clone())); let seq = CitreaSequencer::new( @@ -180,7 +176,7 @@ pub trait CitreaRollupBlueprint: RollupBlueprint { }, }; - let code_commitment = self.get_code_commitment(); + let code_commitments_by_spec = self.get_code_commitments_by_spec(); let current_l2_height = ledger_db .get_head_soft_confirmation() @@ -188,9 +184,7 @@ pub trait CitreaRollupBlueprint: RollupBlueprint { .map(|(l2_height, _)| l2_height) .unwrap_or(BatchNumber(0)); - let active_spec: SpecId = ledger_db.get_active_fork()?; - let mut fork_manager = - ForkManager::new(current_l2_height.into(), active_spec, FORKS.to_vec()); + let mut fork_manager = ForkManager::new(FORKS.to_vec(), current_l2_height.0); fork_manager.register_handler(Box::new(ledger_db.clone())); let runner = CitreaFullnode::new( @@ -202,7 +196,7 @@ pub trait CitreaRollupBlueprint: RollupBlueprint { native_stf, storage_manager, init_variant, - code_commitment, + code_commitments_by_spec, rollup_config.sync_blocks_count, fork_manager, soft_confirmation_tx, @@ -286,7 +280,7 @@ pub trait CitreaRollupBlueprint: RollupBlueprint { }, }; - let code_commitment = self.get_code_commitment(); + let code_commitments_by_spec = self.get_code_commitments_by_spec(); let current_l2_height = ledger_db .get_head_soft_confirmation() @@ -294,9 +288,7 @@ pub trait CitreaRollupBlueprint: RollupBlueprint { .map(|(l2_height, _)| l2_height) .unwrap_or(BatchNumber(0)); - let active_spec: SpecId = ledger_db.get_active_fork()?; - let mut fork_manager = - ForkManager::new(current_l2_height.into(), active_spec, FORKS.to_vec()); + let mut fork_manager = ForkManager::new(FORKS.to_vec(), current_l2_height.0); fork_manager.register_handler(Box::new(ledger_db.clone())); let runner = CitreaProver::new( @@ -310,7 +302,7 @@ pub trait CitreaRollupBlueprint: RollupBlueprint { init_variant, Some(prover_service), Some(prover_config), - code_commitment, + code_commitments_by_spec, rollup_config.sync_blocks_count, fork_manager, soft_confirmation_tx, diff --git a/crates/citrea-stf/src/verifier.rs b/crates/citrea-stf/src/verifier.rs index d5a79b04a..8bdd22426 100644 --- a/crates/citrea-stf/src/verifier.rs +++ b/crates/citrea-stf/src/verifier.rs @@ -48,7 +48,7 @@ where )?; println!("going into apply_soft_confirmations_from_sequencer_commitments"); - let (final_state_root, state_diff) = self + let (final_state_root, state_diff, last_active_spec_id) = self .app .apply_soft_confirmations_from_sequencer_commitments( data.sequencer_public_key.as_ref(), @@ -83,6 +83,7 @@ where sequencer_public_key: data.sequencer_public_key, sequencer_da_public_key: data.sequencer_da_public_key, sequencer_commitments_range: data.sequencer_commitments_range, + last_active_spec_id, }; zkvm.commit(&out); diff --git a/crates/fullnode/src/runner.rs b/crates/fullnode/src/runner.rs index 278d4fa66..56fb02f7b 100644 --- a/crates/fullnode/src/runner.rs +++ b/crates/fullnode/src/runner.rs @@ -1,4 +1,4 @@ -use std::collections::VecDeque; +use std::collections::{HashMap, VecDeque}; use std::marker::PhantomData; use std::net::SocketAddr; use std::sync::Arc; @@ -7,7 +7,7 @@ use anyhow::{anyhow, bail}; use backoff::future::retry as retry_backoff; use backoff::ExponentialBackoffBuilder; use borsh::de::BorshDeserialize; -use citrea_primitives::fork::{Fork, ForkManager}; +use citrea_primitives::fork::ForkManager; use citrea_primitives::types::SoftConfirmationHash; use citrea_primitives::{get_da_block_at_height, L1BlockCache, SyncError}; use jsonrpsee::core::client::Error as JsonrpseeError; @@ -27,6 +27,7 @@ use sov_rollup_interface::da::{ }; use sov_rollup_interface::rpc::SoftConfirmationStatus; use sov_rollup_interface::services::da::{DaService, SlotData}; +use sov_rollup_interface::spec::SpecId; pub use sov_rollup_interface::stf::BatchReceipt; use sov_rollup_interface::stf::{SoftConfirmationReceipt, StateTransitionFunction}; use sov_rollup_interface::storage::HierarchicalStorageManager; @@ -65,7 +66,7 @@ where prover_da_pub_key: Vec, phantom: std::marker::PhantomData, include_tx_body: bool, - code_commitment: Vm::CodeCommitment, + code_commitments_by_spec: HashMap, accept_public_input_as_proven: bool, l1_block_cache: Arc>>, sync_blocks_count: u64, @@ -103,7 +104,7 @@ where stf: Stf, mut storage_manager: Sm, init_variant: InitVariant, - code_commitment: Vm::CodeCommitment, + code_commitments_by_spec: HashMap, sync_blocks_count: u64, fork_manager: ForkManager, soft_confirmation_tx: broadcast::Sender, @@ -151,7 +152,7 @@ where prover_da_pub_key: public_keys.prover_da_pub_key, phantom: std::marker::PhantomData, include_tx_body: runner_config.include_tx_body, - code_commitment, + code_commitments_by_spec, accept_public_input_as_proven: runner_config .accept_public_input_as_proven .unwrap_or(false), @@ -230,47 +231,37 @@ where l1_block.header().height() ); tracing::debug!("ZK proof: {:?}", proof); - let state_transition = match proof.clone() { - Proof::Full(proof) => { - let code_commitment = self.code_commitment.clone(); - tracing::warn!( - "using code commitment: {:?}", - serde_json::to_string(&code_commitment).unwrap() - ); + let state_transition = + Vm::extract_output::<::Spec, Stf::StateRoot>(&proof) + .expect("Proof should be deserializable"); + if state_transition.sequencer_da_public_key != self.sequencer_da_pub_key + || state_transition.sequencer_public_key != self.sequencer_pub_key + { + return Err(anyhow!( + "Proof verification: Sequencer public key or sequencer da public key mismatch. Skipping proof." + ).into()); + } - if let Ok(proof_data) = Vm::verify_and_extract_output::< - ::Spec, - Stf::StateRoot, - >(&proof, &code_commitment) - { - if proof_data.sequencer_da_public_key != self.sequencer_da_pub_key - || proof_data.sequencer_public_key != self.sequencer_pub_key - { - return Err(anyhow!( - "Proof verification: Sequencer public key or sequencer da public key mismatch. Skipping proof." - ).into()); - } - proof_data - } else { - return Err(anyhow!( - "Proof verification: SNARK verification failed. Skipping to next proof.." - ) - .into()); - } + match &proof { + Proof::Full(data) => { + let code_commitment = self + .code_commitments_by_spec + .get(&state_transition.last_active_spec_id) + .expect("Proof public input must contain valid spec id"); + Vm::verify(data, code_commitment) + .map_err(|err| anyhow!("Failed to verify proof: {:?}. Skipping it...", err))?; } Proof::PublicInput(_) => { if !self.accept_public_input_as_proven { return Err(anyhow!( - "Found public input in da block number: {:?}, Skipping to next proof..", + "Found public input in da block number: {}, Skipping to next proof..", l1_block.header().height(), ) .into()); } - // public input is accepted only in tests, so ok to expect - Vm::extract_output(&proof).expect("Proof should be deserializable") } - }; + } let stored_state_transition = StoredStateTransition { initial_state_root: state_transition.initial_state_root.as_ref().to_vec(), @@ -437,7 +428,7 @@ where .create_storage_on_l2_height(l2_height)?; let slot_result = self.stf.apply_soft_confirmation( - self.fork_manager.active_fork(), + self.fork_manager.active_fork().spec_id, self.sequencer_pub_key.as_slice(), // TODO(https://github.com/Sovereign-Labs/sovereign-sdk/issues/1247): incorrect pre-state root in case of re-org &self.state_root, diff --git a/crates/fullnode/tests/hash_stf.rs b/crates/fullnode/tests/hash_stf.rs index f26d01e41..800cec7a1 100644 --- a/crates/fullnode/tests/hash_stf.rs +++ b/crates/fullnode/tests/hash_stf.rs @@ -7,6 +7,7 @@ use sov_modules_api::Context; use sov_modules_stf_blueprint::StfBlueprintTrait; use sov_prover_storage_manager::{new_orphan_storage, SnapshotManager}; use sov_rollup_interface::da::{BlobReaderTrait, BlockHeaderTrait, DaSpec}; +use sov_rollup_interface::fork::Fork; use sov_rollup_interface::spec::SpecId; use sov_rollup_interface::stf::{SlotResult, StateTransitionFunction}; use sov_rollup_interface::zk::{CumulativeStateDiff, ValidityCondition, Zkvm}; @@ -245,8 +246,8 @@ impl StateTransitionFunction, >, _preproven_commitment_indicies: Vec, - _forks: Vec<(SpecId, u64)>, - ) -> (Self::StateRoot, CumulativeStateDiff) { + _forks: Vec, + ) -> (Self::StateRoot, CumulativeStateDiff, SpecId) { todo!() } } diff --git a/crates/fullnode/tests/runner_initialization_tests.rs b/crates/fullnode/tests/runner_initialization_tests.rs index 012bf699a..e4402ad57 100644 --- a/crates/fullnode/tests/runner_initialization_tests.rs +++ b/crates/fullnode/tests/runner_initialization_tests.rs @@ -1,3 +1,4 @@ +use std::collections::HashMap; use std::sync::Arc; use citrea_fullnode::CitreaFullnode; @@ -6,6 +7,7 @@ use sov_db::ledger_db::LedgerDB; use sov_mock_da::{MockAddress, MockDaConfig, MockDaService, MockDaSpec, MockValidityCond}; use sov_mock_zkvm::{MockCodeCommitment, MockZkvm}; use sov_prover_storage_manager::ProverStorageManager; +use sov_rollup_interface::fork::Fork; use sov_rollup_interface::spec::SpecId; use sov_state::DefaultStorageSpec; use sov_stf_runner::{ @@ -55,7 +57,7 @@ fn initialize_runner( sov_modules_api::default_context::DefaultContext, LedgerDB, > { - let specs = vec![(SpecId::Genesis, 0)]; + let forks = vec![Fork::new(SpecId::Genesis, 0)]; let da_storage_path = storage_path.join("da").to_path_buf(); let rollup_storage_path = storage_path.join("rollup").to_path_buf(); @@ -112,7 +114,10 @@ fn initialize_runner( // let vm = MockZkvm::new(MockValidityCond::default()); // let verifier = MockDaVerifier::default(); - let fork_manager = ForkManager::new(0, SpecId::Genesis, specs); + let fork_manager = ForkManager::new(forks, 0); + + let mut code_commitments_by_spec = HashMap::new(); + code_commitments_by_spec.insert(SpecId::Genesis, MockCodeCommitment([1u8; 32])); CitreaFullnode::new( rollup_config.runner.unwrap(), @@ -123,7 +128,7 @@ fn initialize_runner( stf, storage_manager, init_variant, - MockCodeCommitment([1u8; 32]), + code_commitments_by_spec, 10, fork_manager, broadcast::channel(1).0, diff --git a/crates/primitives/src/fork/manager.rs b/crates/primitives/src/fork/manager.rs index c8a5ac233..f944ddebf 100644 --- a/crates/primitives/src/fork/manager.rs +++ b/crates/primitives/src/fork/manager.rs @@ -1,41 +1,30 @@ -use std::collections::VecDeque; - -use sov_rollup_interface::spec::SpecId; -#[cfg(feature = "native")] -use tracing::info; +use sov_rollup_interface::fork::Fork; use super::ForkMigration; -/// Defines the interface which a fork manager needs to implement. -pub trait Fork { - /// Returns the currently active fork. - fn active_fork(&self) -> SpecId; - - /// Register a new L2 block with fork manager - fn register_block(&mut self, height: u64) -> anyhow::Result<()>; -} - -pub type SpecActivationBlockHeight = u64; - pub struct ForkManager { - active_spec: SpecId, - specs: VecDeque<(SpecId, SpecActivationBlockHeight)>, + forks: Vec, + active_fork_idx: usize, migration_handlers: Vec>, } impl ForkManager { - pub fn new( - current_l2_height: u64, - active_spec: SpecId, - mut specs: Vec<(SpecId, SpecActivationBlockHeight)>, - ) -> Self { - // Filter out specs which have already been activated. - specs.retain(|(spec, block)| *spec != active_spec && *block > current_l2_height); + pub fn new(mut forks: Vec, current_l2_height: u64) -> Self { // Make sure the list of specs is sorted by the block number at which they activate. - specs.sort_by_key(|(_, block_number)| *block_number); + forks.sort_by_key(|fork| fork.activation_height); + + let mut active_fork_idx = 0; + for (idx, fork) in forks.iter().enumerate() { + if current_l2_height >= fork.activation_height { + active_fork_idx = idx; + } else { + break; + } + } + Self { - specs: specs.into(), - active_spec, + forks, + active_fork_idx, migration_handlers: vec![], } } @@ -43,41 +32,42 @@ impl ForkManager { pub fn register_handler(&mut self, handler: Box) { self.migration_handlers.push(handler); } -} -impl Fork for ForkManager { - fn active_fork(&self) -> SpecId { - self.active_spec + pub fn active_fork(&self) -> &Fork { + &self.forks[self.active_fork_idx] } - fn register_block(&mut self, height: u64) -> anyhow::Result<()> { - if let Some((new_spec, activation_block_height)) = self.specs.front() { - if height == *activation_block_height { - #[cfg(feature = "native")] - info!("Activating fork {:?} at height: {}", *new_spec, height); + pub fn register_block(&mut self, height: u64) -> anyhow::Result<()> { + // Skip if we are already at the last fork + if self.active_fork_idx == self.forks.len() - 1 { + return Ok(()); + } - self.active_spec = *new_spec; - for handler in self.migration_handlers.iter() { - handler.spec_activated(self.active_spec)?; - } - self.specs.pop_front(); - } + let next_fork_idx = self.active_fork_idx + 1; + let next_fork = &self.forks[next_fork_idx]; + if height < next_fork.activation_height { + return Ok(()); + } + + #[cfg(feature = "native")] + tracing::info!( + "Activating fork {:?} at height: {}", + next_fork.spec_id, + height + ); + + for handler in self.migration_handlers.iter() { + handler.fork_activated(next_fork)?; } + + self.active_fork_idx = next_fork_idx; + Ok(()) } } /// Simple search for the fork to which a specific block number blongs. /// This assumes that the list of forks is sorted by block number in ascending fashion. -pub fn fork_from_block_number(forks: &[(SpecId, u64)], block_number: u64) -> SpecId { - let mut fork = forks[0].0; - if forks.len() == 1 { - return fork; - } - for (spec_id, activation_block) in &forks[1..] { - if block_number >= *activation_block { - fork = *spec_id; - } - } - fork +pub fn fork_from_block_number(forks: Vec, block_number: u64) -> Fork { + ForkManager::new(forks, block_number).active_fork().clone() } diff --git a/crates/primitives/src/fork/migration.rs b/crates/primitives/src/fork/migration.rs index f87783e15..4d95aa4ee 100644 --- a/crates/primitives/src/fork/migration.rs +++ b/crates/primitives/src/fork/migration.rs @@ -1,15 +1,15 @@ -use sov_rollup_interface::spec::SpecId; +use sov_rollup_interface::fork::Fork; /// Defines the interface of a migration pub trait ForkMigration { - /// Invoked when a spec is activated. - fn spec_activated(&self, spec_id: SpecId) -> anyhow::Result<()>; + /// Invoked when a fork is activated. + fn fork_activated(&self, fork: &Fork) -> anyhow::Result<()>; } pub struct NoOpMigration {} impl ForkMigration for NoOpMigration { - fn spec_activated(&self, _spec_id: SpecId) -> anyhow::Result<()> { + fn fork_activated(&self, _fork: &Fork) -> anyhow::Result<()> { // Do nothing Ok(()) } diff --git a/crates/primitives/src/fork/tests.rs b/crates/primitives/src/fork/tests.rs index 802697963..3194f32f6 100644 --- a/crates/primitives/src/fork/tests.rs +++ b/crates/primitives/src/fork/tests.rs @@ -1,60 +1,70 @@ use anyhow::anyhow; +use sov_rollup_interface::fork::Fork; use sov_rollup_interface::spec::SpecId; -use super::{Fork, ForkManager}; +use super::ForkManager; use crate::fork::{fork_from_block_number, ForkMigration}; #[test] fn test_fork_from_block_number() { let forks = vec![ - (SpecId::Genesis, 0), - (SpecId::Fork1, 100), - (SpecId::Fork2, 500), + Fork::new(SpecId::Genesis, 0), + Fork::new(SpecId::Fork1, 100), + Fork::new(SpecId::Fork2, 500), ]; - assert_eq!(fork_from_block_number(&forks, 5), SpecId::Genesis); - assert_eq!(fork_from_block_number(&forks, 105), SpecId::Fork1); - assert_eq!(fork_from_block_number(&forks, 350), SpecId::Fork1); - assert_eq!(fork_from_block_number(&forks, 505), SpecId::Fork2); + assert_eq!( + fork_from_block_number(forks.clone(), 5).spec_id, + SpecId::Genesis + ); + assert_eq!( + fork_from_block_number(forks.clone(), 105).spec_id, + SpecId::Fork1 + ); + assert_eq!( + fork_from_block_number(forks.clone(), 350).spec_id, + SpecId::Fork1 + ); + assert_eq!(fork_from_block_number(forks, 505).spec_id, SpecId::Fork2); } #[test] fn test_fork_manager() { let forks = vec![ - (SpecId::Genesis, 0), - (SpecId::Fork1, 100), - (SpecId::Fork2, 500), + Fork::new(SpecId::Genesis, 0), + Fork::new(SpecId::Fork1, 100), + Fork::new(SpecId::Fork2, 500), ]; - let mut fork_manager = ForkManager::new(0, SpecId::Genesis, forks); + let mut fork_manager = ForkManager::new(forks, 0); fork_manager.register_block(5).unwrap(); - assert_eq!(fork_manager.active_fork(), SpecId::Genesis); + assert_eq!(fork_manager.active_fork().spec_id, SpecId::Genesis); fork_manager.register_block(100).unwrap(); - assert_eq!(fork_manager.active_fork(), SpecId::Fork1); + assert_eq!(fork_manager.active_fork().spec_id, SpecId::Fork1); fork_manager.register_block(350).unwrap(); - assert_eq!(fork_manager.active_fork(), SpecId::Fork1); + assert_eq!(fork_manager.active_fork().spec_id, SpecId::Fork1); fork_manager.register_block(500).unwrap(); - assert_eq!(fork_manager.active_fork(), SpecId::Fork2); + assert_eq!(fork_manager.active_fork().spec_id, SpecId::Fork2); } #[test] fn test_fork_manager_callbacks() { let forks = vec![ - (SpecId::Genesis, 0), - (SpecId::Fork1, 100), - (SpecId::Fork2, 500), + Fork::new(SpecId::Genesis, 0), + Fork::new(SpecId::Fork1, 100), + Fork::new(SpecId::Fork2, 500), ]; struct Handler {} impl ForkMigration for Handler { - fn spec_activated(&self, spec_id: SpecId) -> anyhow::Result<()> { - if spec_id == SpecId::Fork1 { + fn fork_activated(&self, fork: &Fork) -> anyhow::Result<()> { + if fork.spec_id == SpecId::Fork1 { return Err(anyhow!("Called")); } Ok(()) } } let handler = Box::new(Handler {}); - let mut fork_manager = ForkManager::new(0, SpecId::Genesis, forks); + let mut fork_manager = ForkManager::new(forks, 0); fork_manager.register_handler(handler); let result = fork_manager.register_block(100); assert!(result.is_err()); diff --git a/crates/primitives/src/forks.rs b/crates/primitives/src/forks.rs index b5cba58db..7d84a5f43 100644 --- a/crates/primitives/src/forks.rs +++ b/crates/primitives/src/forks.rs @@ -1,10 +1,14 @@ +use sov_rollup_interface::fork::Fork; use sov_rollup_interface::spec::SpecId; /// This defines the list of forks which will be activated /// at specific heights. -pub const FORKS: [(SpecId, u64); 1] = [ - (SpecId::Genesis, 0), +pub const FORKS: [Fork; 1] = [ + Fork { + spec_id: SpecId::Genesis, + activation_height: 0, + }, // Examples of how we can define further forks - // (SpecId::Fork1, 100), - // (SpecId::Fork2, 200) + // Fork { spec_id: SpecId::Fork1, activation_height: 100 }, + // Fork { spec_id: SpecId::Fork2, activation_height: 1000 }, ]; diff --git a/crates/prover/src/runner.rs b/crates/prover/src/runner.rs index baf277438..941ef29e8 100644 --- a/crates/prover/src/runner.rs +++ b/crates/prover/src/runner.rs @@ -1,5 +1,5 @@ use core::panic; -use std::collections::{HashSet, VecDeque}; +use std::collections::{HashMap, HashSet, VecDeque}; use std::marker::PhantomData; use std::net::SocketAddr; use std::sync::Arc; @@ -9,7 +9,7 @@ use anyhow::{anyhow, bail}; use backoff::exponential::ExponentialBackoffBuilder; use backoff::future::retry as retry_backoff; use borsh::de::BorshDeserialize; -use citrea_primitives::fork::{Fork, ForkManager}; +use citrea_primitives::fork::ForkManager; use citrea_primitives::types::SoftConfirmationHash; use citrea_primitives::utils::merge_state_diffs; use citrea_primitives::{get_da_block_at_height, L1BlockCache, MAX_STATEDIFF_SIZE_PROOF_THRESHOLD}; @@ -26,6 +26,7 @@ use sov_modules_stf_blueprint::StfBlueprintTrait; use sov_rollup_interface::da::{BlockHeaderTrait, DaData, DaSpec, SequencerCommitment}; use sov_rollup_interface::rpc::SoftConfirmationStatus; use sov_rollup_interface::services::da::DaService; +use sov_rollup_interface::spec::SpecId; use sov_rollup_interface::stf::{SoftConfirmationReceipt, StateTransitionFunction}; use sov_rollup_interface::zk::{Proof, StateTransitionData, ZkvmHost}; use sov_stf_runner::{ @@ -71,7 +72,7 @@ where sequencer_da_pub_key: Vec, phantom: std::marker::PhantomData, prover_config: Option, - code_commitment: Vm::CodeCommitment, + code_commitments_by_spec: HashMap, l1_block_cache: Arc>>, sync_blocks_count: u64, fork_manager: ForkManager, @@ -111,7 +112,7 @@ where init_variant: InitVariant, prover_service: Option, prover_config: Option, - code_commitment: Vm::CodeCommitment, + code_commitments_by_spec: HashMap, sync_blocks_count: u64, fork_manager: ForkManager, soft_confirmation_tx: broadcast::Sender, @@ -158,7 +159,7 @@ where sequencer_da_pub_key: public_keys.sequencer_da_pub_key, phantom: std::marker::PhantomData, prover_config, - code_commitment, + code_commitments_by_spec, l1_block_cache: Arc::new(Mutex::new(L1BlockCache::new())), sync_blocks_count, fork_manager, @@ -347,7 +348,7 @@ where .create_storage_on_l2_height(l2_height)?; let slot_result = self.stf.apply_soft_confirmation( - self.fork_manager.active_fork(), + self.fork_manager.active_fork().spec_id, self.sequencer_pub_key.as_slice(), // TODO(https://github.com/Sovereign-Labs/sovereign-sdk/issues/1247): incorrect pre-state root in case of re-org &self.state_root, @@ -797,28 +798,21 @@ where // l1_height => (tx_id, proof, transition_data) // save proof along with tx id to db, should be queriable by slot number or slot hash - let transition_data: sov_modules_api::StateTransition< - ::Spec, - Stf::StateRoot, - > = Vm::extract_output(&proof).expect("Proof should be deserializable"); + let transition_data = Vm::extract_output::<::Spec, Stf::StateRoot>(&proof) + .expect("Proof should be deserializable"); - match proof { + match &proof { Proof::PublicInput(_) => { warn!("Proof is public input, skipping"); } - Proof::Full(ref proof) => { + Proof::Full(data) => { info!("Verifying proof!"); - let transition_data_from_proof = - Vm::verify_and_extract_output::<::Spec, Stf::StateRoot>( - &proof.clone(), - &self.code_commitment, - ) - .expect("Proof should be verifiable"); - - info!( - "transition data from proof: {:?}", - transition_data_from_proof - ); + let code_commitment = self + .code_commitments_by_spec + .get(&transition_data.last_active_spec_id) + .expect("Proof public input must contain valid spec id"); + Vm::verify(data, code_commitment) + .map_err(|err| anyhow!("Failed to verify proof: {:?}. Skipping it...", err))?; } } diff --git a/crates/risc0-bonsai/src/host.rs b/crates/risc0-bonsai/src/host.rs index b829e938d..eb34823a9 100644 --- a/crates/risc0-bonsai/src/host.rs +++ b/crates/risc0-bonsai/src/host.rs @@ -405,11 +405,16 @@ impl<'host> Zkvm for Risc0BonsaiHost<'host> { type Error = anyhow::Error; - fn verify<'a>( - _serialized_proof: &'a [u8], - _code_commitment: &Self::CodeCommitment, - ) -> Result<&'a [u8], Self::Error> { - unimplemented!(); + fn verify( + serialized_proof: &[u8], + code_commitment: &Self::CodeCommitment, + ) -> Result, Self::Error> { + let receipt: Receipt = bincode::deserialize(serialized_proof)?; + + #[allow(clippy::clone_on_copy)] + receipt.verify(code_commitment.clone())?; + + Ok(receipt.journal.bytes) } fn verify_and_extract_output( diff --git a/crates/sequencer/src/sequencer.rs b/crates/sequencer/src/sequencer.rs index 2c46529d2..16e959c87 100644 --- a/crates/sequencer/src/sequencer.rs +++ b/crates/sequencer/src/sequencer.rs @@ -10,7 +10,7 @@ use anyhow::anyhow; use borsh::BorshDeserialize; use citrea_evm::{CallMessage, Evm, RlpEvmTransaction, MIN_TRANSACTION_GAS}; use citrea_primitives::basefee::calculate_next_block_base_fee; -use citrea_primitives::fork::{Fork, ForkManager}; +use citrea_primitives::fork::ForkManager; use citrea_primitives::types::SoftConfirmationHash; use citrea_primitives::utils::merge_state_diffs; use citrea_primitives::MAX_STATEDIFF_SIZE_COMMITMENT_THRESHOLD; @@ -270,8 +270,9 @@ where mut signed_batch: SignedSoftConfirmationBatch, l2_block_mode: L2BlockMode, ) -> anyhow::Result<(Vec, Vec)> { + let active_fork_spec = self.fork_manager.active_fork().spec_id; match self.stf.begin_soft_confirmation( - self.fork_manager.active_fork(), + active_fork_spec, pub_key, &self.state_root, prestate.clone(), @@ -309,7 +310,7 @@ where let txs = vec![signed_blob.clone()]; let (batch_workspace, _) = self.stf.apply_soft_confirmation_txs( - self.fork_manager.active_fork(), + active_fork_spec, txs.clone(), working_set_to_discard, ); @@ -387,13 +388,15 @@ where .await .fetch_deposits(self.config.deposit_mempool_fetch_limit); + let active_fork_spec = self.fork_manager.active_fork().spec_id; + let batch_info = HookSoftConfirmationInfo { da_slot_height: da_block.header().height(), da_slot_hash: da_block.header().hash().into(), da_slot_txs_commitment: da_block.header().txs_commitment().into(), pre_state_root: self.state_root.clone().as_ref().to_vec(), deposit_data: deposit_data.clone(), - current_spec: self.fork_manager.active_fork(), + current_spec: active_fork_spec, pub_key, l1_fee_rate, timestamp, @@ -435,7 +438,7 @@ where // Execute the selected transactions match self.stf.begin_soft_confirmation( - self.fork_manager.active_fork(), + active_fork_spec, &pub_key, &self.state_root, prestate.clone(), @@ -458,7 +461,7 @@ where txs.push(signed_blob); (batch_workspace, tx_receipts) = self.stf.apply_soft_confirmation_txs( - self.fork_manager.active_fork(), + active_fork_spec, txs.clone(), batch_workspace, ); @@ -479,7 +482,7 @@ where self.sign_soft_confirmation_batch(unsigned_batch, self.batch_hash)?; let (batch_receipt, checkpoint) = self.stf.end_soft_confirmation( - self.fork_manager.active_fork(), + active_fork_spec, self.sequencer_pub_key.as_ref(), &mut signed_soft_confirmation, tx_receipts, @@ -488,7 +491,7 @@ where // Finalize soft confirmation let slot_result = self.stf.finalize_soft_confirmation( - self.fork_manager.active_fork(), + active_fork_spec, batch_receipt, checkpoint, prestate, diff --git a/crates/sovereign-sdk/adapters/mock-zkvm/src/lib.rs b/crates/sovereign-sdk/adapters/mock-zkvm/src/lib.rs index 620a20b57..e0955d3e1 100644 --- a/crates/sovereign-sdk/adapters/mock-zkvm/src/lib.rs +++ b/crates/sovereign-sdk/adapters/mock-zkvm/src/lib.rs @@ -9,6 +9,7 @@ use anyhow::ensure; use borsh::{BorshDeserialize, BorshSerialize}; use serde::{Deserialize, Serialize}; use sov_rollup_interface::da::BlockHeaderTrait; +use sov_rollup_interface::spec::SpecId; use sov_rollup_interface::zk::{Matches, Proof, StateTransitionData, ValidityCondition}; /// A mock commitment to a particular zkVM program. @@ -122,17 +123,17 @@ impl sov_rollup_interface::zk::Zkvm for MockZkv type Error = anyhow::Error; - fn verify<'a>( - serialized_proof: &'a [u8], + fn verify( + serialized_proof: &[u8], code_commitment: &Self::CodeCommitment, - ) -> Result<&'a [u8], Self::Error> { + ) -> Result, Self::Error> { let proof = MockProof::decode(serialized_proof)?; anyhow::ensure!( proof.program_id.matches(code_commitment), "Proof failed to verify against requested code commitment" ); anyhow::ensure!(proof.is_valid, "Proof is not valid"); - Ok(&serialized_proof[33..]) + Ok(serialized_proof[33..].to_vec()) } fn verify_and_extract_output( @@ -171,7 +172,7 @@ impl sov_rollup_interface::zk::ZkvmHost } fn extract_output( - proof: &sov_rollup_interface::zk::Proof, + proof: &Proof, ) -> Result, Self::Error> { match proof { sov_rollup_interface::zk::Proof::PublicInput(pub_input) => { @@ -189,6 +190,7 @@ impl sov_rollup_interface::zk::ZkvmHost sequencer_public_key: vec![], sequencer_da_public_key: vec![], sequencer_commitments_range: (0, 0), + last_active_spec_id: SpecId::Genesis, }) } sov_rollup_interface::zk::Proof::Full(_) => { @@ -210,10 +212,10 @@ impl sov_rollup_interface::zk::Zkvm for MockZkGuest { type Error = anyhow::Error; - fn verify<'a>( - _serialized_proof: &'a [u8], + fn verify( + _serialized_proof: &[u8], _code_commitment: &Self::CodeCommitment, - ) -> Result<&'a [u8], Self::Error> { + ) -> Result, Self::Error> { unimplemented!() } diff --git a/crates/sovereign-sdk/adapters/risc0/src/guest/mod.rs b/crates/sovereign-sdk/adapters/risc0/src/guest/mod.rs index 28e9e71b4..1d1e5429f 100644 --- a/crates/sovereign-sdk/adapters/risc0/src/guest/mod.rs +++ b/crates/sovereign-sdk/adapters/risc0/src/guest/mod.rs @@ -28,10 +28,10 @@ impl Zkvm for Risc0Guest { type Error = anyhow::Error; - fn verify<'a>( - _serialized_proof: &'a [u8], + fn verify( + _serialized_proof: &[u8], _code_commitment: &Self::CodeCommitment, - ) -> Result<&'a [u8], Self::Error> { + ) -> Result, Self::Error> { // Implement this method once risc0 supports recursion: issue #633 todo!("Implement once risc0 supports recursion: https://github.com/Sovereign-Labs/sovereign-sdk/issues/633") } diff --git a/crates/sovereign-sdk/adapters/risc0/src/host.rs b/crates/sovereign-sdk/adapters/risc0/src/host.rs index f1bcf2ce4..e6ecf955f 100644 --- a/crates/sovereign-sdk/adapters/risc0/src/host.rs +++ b/crates/sovereign-sdk/adapters/risc0/src/host.rs @@ -103,7 +103,7 @@ impl<'a> ZkvmHost for Risc0Host<'a> { receipt.journal } }; - Ok(BorshDeserialize::deserialize(&mut journal.bytes.as_ref())?) + Ok(BorshDeserialize::try_from_slice(&journal.bytes)?) } fn recover_proving_sessions(&self) -> Result, anyhow::Error> { @@ -116,10 +116,10 @@ impl<'host> Zkvm for Risc0Host<'host> { type Error = anyhow::Error; - fn verify<'a>( - serialized_proof: &'a [u8], + fn verify( + serialized_proof: &[u8], code_commitment: &Self::CodeCommitment, - ) -> Result<&'a [u8], Self::Error> { + ) -> Result, Self::Error> { verify_from_slice(serialized_proof, code_commitment) } @@ -140,10 +140,10 @@ impl Zkvm for Risc0Verifier { type Error = anyhow::Error; - fn verify<'a>( - serialized_proof: &'a [u8], + fn verify( + serialized_proof: &[u8], code_commitment: &Self::CodeCommitment, - ) -> Result<&'a [u8], Self::Error> { + ) -> Result, Self::Error> { verify_from_slice(serialized_proof, code_commitment) } @@ -156,11 +156,11 @@ impl Zkvm for Risc0Verifier { } } -fn verify_from_slice<'a>( - serialized_proof: &'a [u8], +fn verify_from_slice( + serialized_proof: &[u8], code_commitment: &Risc0MethodId, -) -> Result<&'a [u8], anyhow::Error> { - let Risc0Proof::<'a> { +) -> Result, anyhow::Error> { + let Risc0Proof { receipt, journal, .. } = bincode::deserialize(serialized_proof)?; @@ -170,7 +170,7 @@ fn verify_from_slice<'a>( receipt.verify(code_commitment.0)?; - Ok(journal) + Ok(journal.to_vec()) } /// A convenience type which contains the same data a Risc0 [`Receipt`] but borrows the journal diff --git a/crates/sovereign-sdk/examples/demo-simple-stf/src/lib.rs b/crates/sovereign-sdk/examples/demo-simple-stf/src/lib.rs index f6f72d5a8..4158a1348 100644 --- a/crates/sovereign-sdk/examples/demo-simple-stf/src/lib.rs +++ b/crates/sovereign-sdk/examples/demo-simple-stf/src/lib.rs @@ -4,6 +4,7 @@ use std::marker::PhantomData; use sha2::Digest; use sov_rollup_interface::da::{BlobReaderTrait, DaSpec}; +use sov_rollup_interface::fork::Fork; use sov_rollup_interface::soft_confirmation::SignedSoftConfirmationBatch; use sov_rollup_interface::spec::SpecId; use sov_rollup_interface::stf::{BatchReceipt, SlotResult, StateTransitionFunction}; @@ -146,8 +147,8 @@ impl StateTransitionFunction::ValidityCondition, _soft_confirmation: std::collections::VecDeque>, _preproven_commitment_indicies: Vec, - _forks: Vec<(SpecId, u64)>, - ) -> (Self::StateRoot, CumulativeStateDiff) { + _forks: Vec, + ) -> (Self::StateRoot, CumulativeStateDiff, SpecId) { todo!() } } diff --git a/crates/sovereign-sdk/full-node/db/sov-db/src/ledger_db/mod.rs b/crates/sovereign-sdk/full-node/db/sov-db/src/ledger_db/mod.rs index cd732f449..320cc4d0b 100644 --- a/crates/sovereign-sdk/full-node/db/sov-db/src/ledger_db/mod.rs +++ b/crates/sovereign-sdk/full-node/db/sov-db/src/ledger_db/mod.rs @@ -5,8 +5,8 @@ use citrea_primitives::fork::ForkMigration; use serde::de::DeserializeOwned; use serde::Serialize; use sov_rollup_interface::da::{DaSpec, SequencerCommitment}; +use sov_rollup_interface::fork::Fork; use sov_rollup_interface::services::da::SlotData; -use sov_rollup_interface::spec::SpecId; use sov_rollup_interface::stf::{BatchReceipt, Event, SoftConfirmationReceipt, StateDiff}; use sov_rollup_interface::zk::Proof; use sov_schema_db::{Schema, SchemaBatch, SeekKeyEncoder, DB}; @@ -14,7 +14,7 @@ use tracing::instrument; use crate::rocks_db_config::gen_rocksdb_options; use crate::schema::tables::{ - ActiveFork, BatchByNumber, CommitmentsByNumber, EventByKey, EventByNumber, L2GenesisStateRoot, + BatchByNumber, CommitmentsByNumber, EventByKey, EventByNumber, L2GenesisStateRoot, L2RangeByL1Height, L2Witness, LastSequencerCommitmentSent, LastStateDiff, MempoolTxs, PendingProvingSessions, PendingSequencerCommitmentL2Range, ProofBySlotNumber, ProverLastScannedSlot, ProverStateDiffs, SlotByHash, SlotByNumber, SoftConfirmationByHash, @@ -451,14 +451,6 @@ impl SharedLedgerOps for LedgerDB { self.db.get::(number) } - /// Gets the currently active fork - #[instrument(level = "trace", skip(self), err, ret)] - fn get_active_fork(&self) -> Result { - self.db - .get::(&()) - .map(|fork| fork.unwrap_or_default()) - } - /// Get the most recent committed batch /// Returns L2 height. #[instrument(level = "trace", skip(self), err, ret)] @@ -809,7 +801,7 @@ impl NodeLedgerOps for LedgerDB { } impl ForkMigration for LedgerDB { - fn spec_activated(&self, _spec_id: SpecId) -> anyhow::Result<()> { + fn fork_activated(&self, _fork: &Fork) -> anyhow::Result<()> { // TODO: Implement later Ok(()) } diff --git a/crates/sovereign-sdk/full-node/db/sov-db/src/ledger_db/traits.rs b/crates/sovereign-sdk/full-node/db/sov-db/src/ledger_db/traits.rs index 23ea633f6..01a8f405a 100644 --- a/crates/sovereign-sdk/full-node/db/sov-db/src/ledger_db/traits.rs +++ b/crates/sovereign-sdk/full-node/db/sov-db/src/ledger_db/traits.rs @@ -2,7 +2,6 @@ use anyhow::Result; use serde::de::DeserializeOwned; use serde::Serialize; use sov_rollup_interface::da::{DaSpec, SequencerCommitment}; -use sov_rollup_interface::spec::SpecId; use sov_rollup_interface::stf::{Event, SoftConfirmationReceipt, StateDiff}; use sov_rollup_interface::zk::Proof; use sov_schema_db::SchemaBatch; @@ -118,9 +117,6 @@ pub trait SharedLedgerOps { number: &BatchNumber, ) -> Result>; - /// Gets the currently active fork - fn get_active_fork(&self) -> Result; - /// Used by the sequencer to record that it has committed to soft confirmations on a given L2 height fn set_last_commitment_l2_height(&self, l2_height: BatchNumber) -> Result<()>; diff --git a/crates/sovereign-sdk/full-node/db/sov-db/src/schema/tables.rs b/crates/sovereign-sdk/full-node/db/sov-db/src/schema/tables.rs index 9bbcb1037..814b664af 100644 --- a/crates/sovereign-sdk/full-node/db/sov-db/src/schema/tables.rs +++ b/crates/sovereign-sdk/full-node/db/sov-db/src/schema/tables.rs @@ -30,7 +30,6 @@ use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt}; use jmt::storage::{NibblePath, Node, NodeKey}; use jmt::Version; use sov_rollup_interface::da::SequencerCommitment; -use sov_rollup_interface::spec::SpecId; use sov_rollup_interface::stf::{Event, EventKey, StateDiff}; use sov_schema_db::schema::{KeyDecoder, KeyEncoder, ValueCodec}; use sov_schema_db::{CodecError, SeekKeyEncoder}; @@ -52,7 +51,6 @@ pub const STATE_TABLES: &[&str] = &[ /// A list of all tables used by the LedgerDB. These tables store rollup "history" - meaning /// transaction, events, receipts, etc. pub const LEDGER_TABLES: &[&str] = &[ - ActiveFork::table_name(), SlotByNumber::table_name(), SlotByHash::table_name(), SoftConfirmationByNumber::table_name(), @@ -224,11 +222,6 @@ macro_rules! define_table_with_seek_key_codec { }; } -define_table_with_seek_key_codec!( - /// The currently active fork - (ActiveFork) () => SpecId -); - define_table_with_seek_key_codec!( /// The State diff storage (LastStateDiff) () => StateDiff diff --git a/crates/sovereign-sdk/full-node/sov-stf-runner/src/mock/mod.rs b/crates/sovereign-sdk/full-node/sov-stf-runner/src/mock/mod.rs index 6bad005a5..006d46222 100644 --- a/crates/sovereign-sdk/full-node/sov-stf-runner/src/mock/mod.rs +++ b/crates/sovereign-sdk/full-node/sov-stf-runner/src/mock/mod.rs @@ -1,6 +1,7 @@ use std::marker::PhantomData; use sov_rollup_interface::da::DaSpec; +use sov_rollup_interface::fork::Fork; use sov_rollup_interface::spec::SpecId; use sov_rollup_interface::stf::{BatchReceipt, SlotResult, StateTransitionFunction}; use sov_rollup_interface::zk::{CumulativeStateDiff, ValidityCondition, Zkvm}; @@ -101,8 +102,8 @@ impl StateTransitionFunction, >, _preproven_commitment_indicies: Vec, - _forks: Vec<(SpecId, u64)>, - ) -> (Self::StateRoot, CumulativeStateDiff) { + _forks: Vec, + ) -> (Self::StateRoot, CumulativeStateDiff, SpecId) { todo!() } } diff --git a/crates/sovereign-sdk/fuzz/Cargo.lock b/crates/sovereign-sdk/fuzz/Cargo.lock index 0fc8ddce8..36de11374 100644 --- a/crates/sovereign-sdk/fuzz/Cargo.lock +++ b/crates/sovereign-sdk/fuzz/Cargo.lock @@ -137,7 +137,7 @@ checksum = "4d0f2d905ebd295e7effec65e5f6868d153936130ae718352771de3e7d03c75c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.75", ] [[package]] @@ -363,9 +363,9 @@ checksum = "9d151e35f61089500b617991b791fc8bfd237ae50cd5950803758a179b41e67a" [[package]] name = "arrayvec" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "async-trait" @@ -375,7 +375,7 @@ checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.75", ] [[package]] @@ -392,7 +392,7 @@ checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.75", ] [[package]] @@ -482,7 +482,7 @@ dependencies = [ "regex", "rustc-hash 1.1.0", "shlex", - "syn 2.0.74", + "syn 2.0.75", ] [[package]] @@ -599,7 +599,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.75", "syn_derive", ] @@ -657,12 +657,13 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.10" +version = "1.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9e8aabfac534be767c909e0690571677d49f41bd8465ae876fe043d52ba5292" +checksum = "72db2f7947ecee9b03b510377e8bb9077afa27176fdbff55c51027e976fdcc48" dependencies = [ "jobserver", "libc", + "shlex", ] [[package]] @@ -715,9 +716,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.15" +version = "4.5.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11d8838454fda655dafd3accb2b6e2bea645b9e4078abe84a22ceb947235c5cc" +checksum = "ed6719fffa43d0d87e5fd8caeab59be1554fb028cd30edc88fc4369b17971019" dependencies = [ "clap_builder", "clap_derive", @@ -744,7 +745,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.75", ] [[package]] @@ -927,7 +928,7 @@ source = "git+https://github.com/risc0/curve25519-dalek?tag=curve25519-4.1.2-ris dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.75", ] [[package]] @@ -959,7 +960,7 @@ checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.75", ] [[package]] @@ -972,7 +973,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version 0.4.0", - "syn 2.0.74", + "syn 2.0.75", ] [[package]] @@ -1074,7 +1075,7 @@ checksum = "2f9ed6b3789237c8a0c1c505af1c7eb2c560df6186f01b098c3a1064ea532f38" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.75", ] [[package]] @@ -1216,7 +1217,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.75", ] [[package]] @@ -1525,9 +1526,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.3.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3fc2e30ba82dd1b3911c8de1ffc143c74a914a14e99514d7637e3099df5ea0" +checksum = "93ead53efc7ea8ed3cfb0c79fc8023fbb782a5432b52830b6518941cebe6505c" dependencies = [ "equivalent", "hashbrown 0.14.5", @@ -1634,9 +1635,9 @@ dependencies = [ [[package]] name = "jsonrpsee" -version = "0.24.2" +version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a1d83ae9ed70d8e3440db663e343a82f93913104744cd543bbcdd1dbc0e35d3" +checksum = "5ec465b607a36dc5dd45d48b7689bc83f679f66a3ac6b6b21cc787a11e0f8685" dependencies = [ "jsonrpsee-core", "jsonrpsee-http-client", @@ -1649,9 +1650,9 @@ dependencies = [ [[package]] name = "jsonrpsee-core" -version = "0.24.2" +version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83b772fb8aa2b511eeed75f7e19d8e5fa57be7e8202249470bf26210727399c7" +checksum = "e942c55635fbf5dc421938b8558a8141c7e773720640f4f1dbe1f4164ca4e221" dependencies = [ "async-trait", "bytes", @@ -1672,9 +1673,9 @@ dependencies = [ [[package]] name = "jsonrpsee-http-client" -version = "0.24.2" +version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d5f8f6ddb09312a9592ec9e21a3ccd6f61e51730d9d56321351eff971b0fe55" +checksum = "e33774602df12b68a2310b38a535733c477ca4a498751739f89fe8dbbb62ec4c" dependencies = [ "async-trait", "base64 0.22.1", @@ -1697,22 +1698,22 @@ dependencies = [ [[package]] name = "jsonrpsee-proc-macros" -version = "0.24.2" +version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "295d9b81496d1bef5bd34066d83c984388b6acb97620f468817bf46f67a1e9ab" +checksum = "6b07a2daf52077ab1b197aea69a5c990c060143835bf04c77070e98903791715" dependencies = [ "heck", "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.75", ] [[package]] name = "jsonrpsee-server" -version = "0.24.2" +version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85bf179199ad809157ceaab653f71cdb67f55d9e0093a6907c5765414a6b3bbb" +checksum = "038fb697a709bec7134e9ccbdbecfea0e2d15183f7140254afef7c5610a3f488" dependencies = [ "futures-util", "http", @@ -1737,9 +1738,9 @@ dependencies = [ [[package]] name = "jsonrpsee-types" -version = "0.24.2" +version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98deeee954567f75632fa40666ac93a66d4f9f4ed4ca15bd6b7ed0720b53e761" +checksum = "23b67d6e008164f027afbc2e7bb79662650158d26df200040282d2aa1cbb093b" dependencies = [ "http", "serde", @@ -1808,9 +1809,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.155" +version = "0.2.158" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" [[package]] name = "libfuzzer-sys" @@ -2035,7 +2036,7 @@ checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.75", ] [[package]] @@ -2170,7 +2171,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.75", ] [[package]] @@ -2333,7 +2334,7 @@ dependencies = [ "itertools 0.12.1", "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.75", ] [[package]] @@ -2478,7 +2479,7 @@ dependencies = [ "convert_case 0.6.0", "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.75", ] [[package]] @@ -2764,9 +2765,9 @@ dependencies = [ [[package]] name = "rustls-native-certs" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a88d6d420651b496bdd98684116959239430022a115c1240e6c3993be0b15fba" +checksum = "04182dffc9091a404e0fc069ea5cd60e5b866c3adf881eff99a32d048242dffa" dependencies = [ "openssl-probe", "rustls-pemfile", @@ -2892,7 +2893,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.74", + "syn 2.0.75", ] [[package]] @@ -2965,22 +2966,22 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.207" +version = "1.0.208" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5665e14a49a4ea1b91029ba7d3bca9f299e1f7cfa194388ccc20f14743e784f2" +checksum = "cff085d2cb684faa248efb494c39b68e522822ac0de72ccf08109abde717cfb2" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.207" +version = "1.0.208" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6aea2634c86b0e8ef2cfdc0c340baede54ec27b1e46febd7f80dffb2aa44a00e" +checksum = "24008e81ff7613ed8e5ba0cfaf24e2c2f1e5b8a0495711e44fcd4882fca62bcf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.75", ] [[package]] @@ -2991,14 +2992,14 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.75", ] [[package]] name = "serde_json" -version = "1.0.124" +version = "1.0.125" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66ad62847a56b3dba58cc891acd13884b9c61138d330c0d7b6181713d4fce38d" +checksum = "83c8e735a073ccf5be70aa8066aa984eaf2fa000db6c8d0100ae605b366d31ed" dependencies = [ "itoa", "memchr", @@ -3373,7 +3374,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.74", + "syn 2.0.75", ] [[package]] @@ -3395,9 +3396,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.74" +version = "2.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fceb41e3d546d0bd83421d3409b1460cc7444cd389341a4c880fe7a042cb3d7" +checksum = "f6af063034fc1935ede7be0122941bafa9bacb949334d090b77ca98b5817c7d9" dependencies = [ "proc-macro2", "quote", @@ -3413,7 +3414,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.75", ] [[package]] @@ -3452,7 +3453,7 @@ checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.75", ] [[package]] @@ -3510,9 +3511,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.39.2" +version = "1.39.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daa4fb1bc778bd6f04cbfc4bb2d06a7396a8f299dc33ea1900cedaa316f467b1" +checksum = "9babc99b9923bfa4804bd74722ff02c0381021eafa4db9949217e3be8e84fff5" dependencies = [ "backtrace", "bytes", @@ -3534,7 +3535,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.75", ] [[package]] @@ -3609,15 +3610,15 @@ dependencies = [ [[package]] name = "tower-layer" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" [[package]] name = "tower-service" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" @@ -3639,7 +3640,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.75", ] [[package]] @@ -3953,7 +3954,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.75", ] [[package]] @@ -3973,7 +3974,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn 2.0.75", ] [[package]] diff --git a/crates/sovereign-sdk/module-system/sov-modules-rollup-blueprint/src/lib.rs b/crates/sovereign-sdk/module-system/sov-modules-rollup-blueprint/src/lib.rs index 5fd0b8b74..c71583c99 100644 --- a/crates/sovereign-sdk/module-system/sov-modules-rollup-blueprint/src/lib.rs +++ b/crates/sovereign-sdk/module-system/sov-modules-rollup-blueprint/src/lib.rs @@ -4,6 +4,7 @@ mod runtime_rpc; mod wallet; +use std::collections::HashMap; use std::sync::Arc; use async_trait::async_trait; @@ -12,6 +13,7 @@ use sov_db::ledger_db::LedgerDB; use sov_modules_api::{Context, DaSpec, Spec}; use sov_modules_stf_blueprint::{GenesisParams, Runtime as RuntimeTrait}; use sov_rollup_interface::services::da::DaService; +use sov_rollup_interface::spec::SpecId; use sov_rollup_interface::storage::HierarchicalStorageManager; use sov_rollup_interface::zk::{Zkvm, ZkvmHost}; use sov_state::Storage; @@ -63,8 +65,8 @@ pub trait RollupBlueprint: Sized + Send + Sync { /// Creates a new instance of the blueprint. fn new() -> Self; - /// Get code commitment. - fn get_code_commitment(&self) -> ::CodeCommitment; + /// Get code commitments by fork. + fn get_code_commitments_by_spec(&self) -> HashMap::CodeCommitment>; /// Creates RPC methods for the rollup. fn create_rpc_methods( diff --git a/crates/sovereign-sdk/module-system/sov-modules-stf-blueprint/src/lib.rs b/crates/sovereign-sdk/module-system/sov-modules-stf-blueprint/src/lib.rs index 78704dfbf..13fef5ba1 100644 --- a/crates/sovereign-sdk/module-system/sov-modules-stf-blueprint/src/lib.rs +++ b/crates/sovereign-sdk/module-system/sov-modules-stf-blueprint/src/lib.rs @@ -2,7 +2,7 @@ #![doc = include_str!("../README.md")] use borsh::BorshDeserialize; -use citrea_primitives::fork::{fork_from_block_number, Fork, ForkManager}; +use citrea_primitives::fork::ForkManager; use itertools::Itertools; use rs_merkle::algorithms::Sha256; use rs_merkle::MerkleTree; @@ -17,6 +17,7 @@ use sov_modules_api::{ }; use sov_rollup_interface::da::{DaData, SequencerCommitment}; use sov_rollup_interface::digest::Digest; +use sov_rollup_interface::fork::Fork; use sov_rollup_interface::soft_confirmation::SignedSoftConfirmationBatch; use sov_rollup_interface::spec::SpecId; pub use sov_rollup_interface::stf::{BatchReceipt, TransactionReceipt}; @@ -505,8 +506,8 @@ where validity_condition: &::ValidityCondition, soft_confirmations: std::collections::VecDeque>, mut preproven_commitment_indicies: Vec, - forks: Vec<(SpecId, u64)>, - ) -> (Self::StateRoot, CumulativeStateDiff) { + forks: Vec, + ) -> (Self::StateRoot, CumulativeStateDiff, SpecId) { let mut state_diff = CumulativeStateDiff::default(); // First extract all sequencer commitments @@ -546,6 +547,8 @@ where let mut previous_batch_hash = initial_batch_hash; let mut last_commitment_end_height: Option = None; + let mut fork_manager = ForkManager::new(forks, sequencer_commitments_range.0 as u64); + // should panic if number of sequencer commitments, soft confirmations, slot headers and witnesses don't match for (((sequencer_commitment, soft_confirmations), da_block_headers), witnesses) in sequencer_commitments @@ -690,8 +693,6 @@ where let mut da_block_header = da_block_headers_iter.next().unwrap(); let mut l2_height = sequencer_commitment.l2_start_block_number; - let mut current_spec = fork_from_block_number(&forks, l2_height); - let mut fork_manager = ForkManager::new(l2_height, current_spec, forks.clone()); // now that we verified the claimed root, we can apply the soft confirmations // should panic if the number of witnesses and soft confirmations don't match @@ -702,7 +703,7 @@ where } let result = self.apply_soft_confirmation( - current_spec, + fork_manager.active_fork().spec_id, sequencer_public_key, ¤t_state_root, pre_state.clone(), @@ -721,14 +722,15 @@ where panic!("Fork transition failed {}", e); } l2_height += 1; - - // Update current spec for the next iteration - current_spec = fork_manager.active_fork(); } assert_eq!(sequencer_commitment.l2_end_block_number, l2_height - 1); } - (current_state_root, state_diff) + ( + current_state_root, + state_diff, + fork_manager.active_fork().spec_id, + ) } } diff --git a/crates/sovereign-sdk/rollup-interface/Cargo.toml b/crates/sovereign-sdk/rollup-interface/Cargo.toml index 476070f8e..81ee847db 100644 --- a/crates/sovereign-sdk/rollup-interface/Cargo.toml +++ b/crates/sovereign-sdk/rollup-interface/Cargo.toml @@ -14,7 +14,6 @@ exclude = [ "specs/assets/*", ] - [dependencies] anyhow = { workspace = true } async-trait = { workspace = true } diff --git a/crates/sovereign-sdk/rollup-interface/src/fork.rs b/crates/sovereign-sdk/rollup-interface/src/fork.rs new file mode 100644 index 000000000..b97aaf1b8 --- /dev/null +++ b/crates/sovereign-sdk/rollup-interface/src/fork.rs @@ -0,0 +1,20 @@ +use crate::spec::SpecId; + +/// Fork is a wrapper struct that contains spec id and it's activation height +#[derive(Debug, Clone)] +pub struct Fork { + /// Spec id for this fork + pub spec_id: SpecId, + /// Height to activate this spec + pub activation_height: u64, +} + +impl Fork { + /// Creates new Fork instance + pub fn new(spec_id: SpecId, activation_height: u64) -> Self { + Self { + spec_id, + activation_height, + } + } +} diff --git a/crates/sovereign-sdk/rollup-interface/src/lib.rs b/crates/sovereign-sdk/rollup-interface/src/lib.rs index 40c02a474..e06d79054 100644 --- a/crates/sovereign-sdk/rollup-interface/src/lib.rs +++ b/crates/sovereign-sdk/rollup-interface/src/lib.rs @@ -27,5 +27,8 @@ pub use alloc::sync::Arc as RefCount; pub use node::*; pub use {anyhow, digest}; +/// Fork module +pub mod fork; + /// Specs module pub mod spec; diff --git a/crates/sovereign-sdk/rollup-interface/src/spec.rs b/crates/sovereign-sdk/rollup-interface/src/spec.rs index d48c63ed0..11dfde63f 100644 --- a/crates/sovereign-sdk/rollup-interface/src/spec.rs +++ b/crates/sovereign-sdk/rollup-interface/src/spec.rs @@ -1,4 +1,6 @@ #![allow(clippy::module_inception)] +use core::hash::Hash; + use borsh::{BorshDeserialize, BorshSerialize}; use serde::{Deserialize, Serialize}; pub use spec::*; @@ -18,6 +20,7 @@ mod spec { BorshSerialize, Serialize, Deserialize, + Hash, )] #[borsh(use_discriminant = true)] pub enum SpecId { @@ -42,6 +45,7 @@ mod spec { BorshSerialize, Serialize, Deserialize, + Hash, )] #[borsh(use_discriminant = true)] pub enum SpecId { diff --git a/crates/sovereign-sdk/rollup-interface/src/state_machine/stf.rs b/crates/sovereign-sdk/rollup-interface/src/state_machine/stf.rs index 14ae748b0..c6af010d2 100644 --- a/crates/sovereign-sdk/rollup-interface/src/state_machine/stf.rs +++ b/crates/sovereign-sdk/rollup-interface/src/state_machine/stf.rs @@ -16,6 +16,7 @@ use serde::de::DeserializeOwned; use serde::{Deserialize, Serialize}; use crate::da::DaSpec; +use crate::fork::Fork; use crate::soft_confirmation::SignedSoftConfirmationBatch; use crate::spec::SpecId; use crate::zk::{CumulativeStateDiff, ValidityCondition, Zkvm}; @@ -268,8 +269,8 @@ pub trait StateTransitionFunction { validity_condition: &Da::ValidityCondition, soft_confirmations: VecDeque>, preproven_commitment_indicies: Vec, - forks: Vec<(SpecId, u64)>, - ) -> (Self::StateRoot, CumulativeStateDiff); + forks: Vec, + ) -> (Self::StateRoot, CumulativeStateDiff, SpecId); } /// A key-value pair representing a change to the rollup state diff --git a/crates/sovereign-sdk/rollup-interface/src/state_machine/zk/mod.rs b/crates/sovereign-sdk/rollup-interface/src/state_machine/zk/mod.rs index 2fbc5db41..e495fd944 100644 --- a/crates/sovereign-sdk/rollup-interface/src/state_machine/zk/mod.rs +++ b/crates/sovereign-sdk/rollup-interface/src/state_machine/zk/mod.rs @@ -11,6 +11,7 @@ extern crate alloc; use alloc::collections::{BTreeMap, VecDeque}; use alloc::vec::Vec; +use core::convert::Into; use core::fmt::Debug; use borsh::{BorshDeserialize, BorshSerialize}; @@ -20,6 +21,7 @@ use serde::{Deserialize, Serialize}; use crate::da::DaSpec; use crate::soft_confirmation::SignedSoftConfirmationBatch; +use crate::spec::SpecId; /// The ZK proof generated by the [`ZkvmHost::run`] method. #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, BorshSerialize, BorshDeserialize)] @@ -50,7 +52,7 @@ pub trait ZkvmHost: Zkvm + Clone { /// with some mild performance overhead and is not as easy to debug as [`simulate_with_hints`](ZkvmHost::simulate_with_hints). fn run(&mut self, with_proof: bool) -> Result; - /// Extracts public input form the proof. + /// Extracts public input and receipt from the proof. fn extract_output( proof: &Proof, ) -> Result, Self::Error>; @@ -70,10 +72,10 @@ pub trait Zkvm: Send + Sync { /// Interpret a sequence of a bytes as a proof and attempt to verify it against the code commitment. /// If the proof is valid, return a reference to the public outputs of the proof. - fn verify<'a>( - serialized_proof: &'a [u8], + fn verify( + serialized_proof: &[u8], code_commitment: &Self::CodeCommitment, - ) -> Result<&'a [u8], Self::Error>; + ) -> Result, Self::Error>; /// Same as [`verify`](Zkvm::verify), except that instead of returning the output /// as a serialized array, it returns a state transition structure. @@ -144,6 +146,8 @@ pub struct StateTransition { /// to be checked outside of the zkVM circuit. This typically corresponds to /// some claim about the DA layer history, such as (X) is a valid block on the DA layer pub validity_condition: Da::ValidityCondition, + /// The final spec id after state transition is completed. + pub last_active_spec_id: SpecId, } /// This trait expresses that a type can check a validity condition.