Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable verifying proofs based on the fork #1011

Merged
merged 16 commits into from
Aug 20, 2024
8 changes: 6 additions & 2 deletions bin/citrea/src/rollup/bitcoin.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use std::collections::HashMap;
use std::sync::Arc;

use async_trait::async_trait;
Expand All @@ -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};
Expand Down Expand Up @@ -90,8 +92,10 @@ impl RollupBlueprint for BitcoinRollup {
}

#[instrument(level = "trace", skip(self), ret)]
fn get_code_commitment(&self) -> <Self::Vm as Zkvm>::CodeCommitment {
Digest::new(citrea_risc0::BITCOIN_DA_ID)
fn get_code_commitments_by_spec(&self) -> HashMap<SpecId, <Self::Vm as Zkvm>::CodeCommitment> {
let mut map = HashMap::new();
map.insert(SpecId::Genesis, Digest::new(citrea_risc0::BITCOIN_DA_ID));
map
}

#[instrument(level = "trace", skip_all, err)]
Expand Down
8 changes: 6 additions & 2 deletions bin/citrea/src/rollup/mock.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use std::collections::HashMap;
use std::sync::Arc;

use async_trait::async_trait;
Expand All @@ -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};
Expand Down Expand Up @@ -81,8 +83,10 @@ impl RollupBlueprint for MockDemoRollup {
Ok(rpc_methods)
}

fn get_code_commitment(&self) -> <Self::Vm as Zkvm>::CodeCommitment {
Digest::new(citrea_risc0::MOCK_DA_ID)
fn get_code_commitments_by_spec(&self) -> HashMap<SpecId, <Self::Vm as Zkvm>::CodeCommitment> {
let mut map = HashMap::new();
map.insert(SpecId::Genesis, Digest::new(citrea_risc0::MOCK_DA_ID));
map
}

async fn create_da_service(
Expand Down
22 changes: 7 additions & 15 deletions bin/citrea/src/rollup/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -180,17 +176,15 @@ 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()
.map_err(|e| anyhow!("Failed to get head soft confirmation: {}", e))?
.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(
Expand All @@ -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,
Expand Down Expand Up @@ -286,17 +280,15 @@ 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()
.map_err(|e| anyhow!("Failed to get head soft confirmation: {}", e))?
.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(
Expand All @@ -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,
Expand Down
3 changes: 2 additions & 1 deletion crates/citrea-stf/src/verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down Expand Up @@ -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);
Expand Down
63 changes: 27 additions & 36 deletions crates/fullnode/src/runner.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -65,7 +66,7 @@ where
prover_da_pub_key: Vec<u8>,
phantom: std::marker::PhantomData<C>,
include_tx_body: bool,
code_commitment: Vm::CodeCommitment,
code_commitments_by_spec: HashMap<SpecId, Vm::CodeCommitment>,
accept_public_input_as_proven: bool,
l1_block_cache: Arc<Mutex<L1BlockCache<Da>>>,
sync_blocks_count: u64,
Expand Down Expand Up @@ -103,7 +104,7 @@ where
stf: Stf,
mut storage_manager: Sm,
init_variant: InitVariant<Stf, Vm, Da::Spec>,
code_commitment: Vm::CodeCommitment,
code_commitments_by_spec: HashMap<SpecId, Vm::CodeCommitment>,
sync_blocks_count: u64,
fork_manager: ForkManager,
soft_confirmation_tx: broadcast::Sender<u64>,
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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::<<Da as DaService>::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::<
<Da as DaService>::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")
}
eyusufatik marked this conversation as resolved.
Show resolved Hide resolved
};
}

let stored_state_transition = StoredStateTransition {
initial_state_root: state_transition.initial_state_root.as_ref().to_vec(),
Expand Down Expand Up @@ -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,
Expand Down
5 changes: 3 additions & 2 deletions crates/fullnode/tests/hash_stf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -245,8 +246,8 @@ impl<Vm: Zkvm, Cond: ValidityCondition, Da: DaSpec> StateTransitionFunction<Vm,
Vec<sov_modules_api::SignedSoftConfirmationBatch>,
>,
_preproven_commitment_indicies: Vec<usize>,
_forks: Vec<(SpecId, u64)>,
) -> (Self::StateRoot, CumulativeStateDiff) {
_forks: Vec<Fork>,
) -> (Self::StateRoot, CumulativeStateDiff, SpecId) {
todo!()
}
}
Expand Down
11 changes: 8 additions & 3 deletions crates/fullnode/tests/runner_initialization_tests.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use std::collections::HashMap;
use std::sync::Arc;

use citrea_fullnode::CitreaFullnode;
Expand All @@ -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::{
Expand Down Expand Up @@ -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();

Expand Down Expand Up @@ -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(),
Expand All @@ -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,
Expand Down
Loading
Loading