diff --git a/.gitignore b/.gitignore index 8635b6d93..cc847937e 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ fuzz/Cargo.lock demo_data/ sequencer-db/ full-node-db/ +prover-db/ /.vscode/* /docker/credentials/* diff --git a/Cargo.lock b/Cargo.lock index 14a1b61e9..89418a923 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1661,7 +1661,7 @@ dependencies = [ "ethers-middleware", "ethers-signers", "hex", - "itertools 0.11.0", + "itertools 0.13.0", "jsonrpsee", "lazy_static", "rand 0.8.5", @@ -4468,6 +4468,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.11" @@ -9156,6 +9165,7 @@ dependencies = [ "anyhow", "borsh", "hex", + "itertools 0.13.0", "jmt", "jsonrpsee", "risc0-zkvm", diff --git a/Cargo.toml b/Cargo.toml index ab9f07ee5..95a02b30b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -74,7 +74,7 @@ async-trait = "0.1.71" anyhow = { version = "1.0.68", default-features = false } arbitrary = { version = "1.3.1", features = ["derive"] } alloy-rlp = "0.3" -backoff = { version = "0.4.0", features = [ "futures", "tokio" ] } +backoff = { version = "0.4.0", features = ["futures", "tokio"] } borsh = { version = "0.10.3", default-features = false } # TODO: Consider replacing this serialization format # https://github.com/Sovereign-Labs/sovereign-sdk/issues/283 @@ -93,6 +93,7 @@ hex = { version = "0.4.3", default-features = false, features = [ "alloc", "serde", ] } +itertools = { version = "0.13.0", default-features = false } log-panics = { version = "2", features = ["with-backtrace"] } once_cell = { version = "1.19.0", default-features = false, features = [ "alloc", diff --git a/Makefile b/Makefile index 67b223ac6..b4a95ad17 100644 --- a/Makefile +++ b/Makefile @@ -16,6 +16,7 @@ clean: ## Cleans compiled clean-node: ## Cleans local dbs needed for sequencer and nodes sudo rm -rf data/postgres rm -rf sequencer-db + rm -rf prover-db rm -rf full-node-db rm test-da-dbs/*.db diff --git a/bin/citrea/configs/bitcoin-regtest/prover_config.toml b/bin/citrea/configs/bitcoin-regtest/prover_config.toml new file mode 100644 index 000000000..f22d841e5 --- /dev/null +++ b/bin/citrea/configs/bitcoin-regtest/prover_config.toml @@ -0,0 +1,2 @@ +proving_mode = "execute" +proof_sampling_number = 500 diff --git a/bin/citrea/configs/bitcoin-regtest/prover_rollup_config.toml b/bin/citrea/configs/bitcoin-regtest/prover_rollup_config.toml new file mode 100644 index 000000000..75e3cacac --- /dev/null +++ b/bin/citrea/configs/bitcoin-regtest/prover_rollup_config.toml @@ -0,0 +1,28 @@ +[public_keys] +sequencer_public_key = "204040e364c10f2bec9c1fe500a1cd4c247c89d650a01ed7e82caba867877c21" +sequencer_da_pub_key = "02588d202afcc1ee4ab5254c7847ec25b9a135bbda0f2bc69ee1a714749fd77dc9" +prover_da_pub_key = "" + +[da] +# fill here +node_url = "" +# fill here +node_username = "" +# fill here +node_password = "" +network = "regtest" + +[storage] +# The path to the rollup's data directory. Paths that do not begin with `/` are interpreted as relative paths. +path = "prover-db" + +[rpc] +# the host and port to bind the rpc server for +bind_host = "127.0.0.1" +bind_port = 12346 + +# We define the rollup's genesis to occur at block number `start_height`. The rollup will ignore +# any blocks before this height +[runner] +sequencer_client_url = "http://0.0.0.0:12345" +include_tx_body = false diff --git a/bin/citrea/configs/mock/prover_config.toml b/bin/citrea/configs/mock/prover_config.toml index 427c4f634..105b60c4e 100644 --- a/bin/citrea/configs/mock/prover_config.toml +++ b/bin/citrea/configs/mock/prover_config.toml @@ -1,4 +1,5 @@ proving_mode = "execute" +proof_sampling_number = 500 [db_config] db_host = "localhost" diff --git a/bin/citrea/provers/risc0/guest-bitcoin/Cargo.lock b/bin/citrea/provers/risc0/guest-bitcoin/Cargo.lock index 7ccd028fb..a2085571c 100644 --- a/bin/citrea/provers/risc0/guest-bitcoin/Cargo.lock +++ b/bin/citrea/provers/risc0/guest-bitcoin/Cargo.lock @@ -1686,6 +1686,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.11" @@ -2985,6 +2994,7 @@ dependencies = [ "anyhow", "borsh", "hex", + "itertools 0.13.0", "jmt", "risc0-zkvm", "risc0-zkvm-platform", diff --git a/bin/citrea/provers/risc0/guest-mock/Cargo.lock b/bin/citrea/provers/risc0/guest-mock/Cargo.lock index 9ec8c65a7..84c179ac6 100644 --- a/bin/citrea/provers/risc0/guest-mock/Cargo.lock +++ b/bin/citrea/provers/risc0/guest-mock/Cargo.lock @@ -1463,6 +1463,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.11" @@ -2773,6 +2782,7 @@ dependencies = [ "anyhow", "borsh", "hex", + "itertools 0.13.0", "jmt", "risc0-zkvm", "risc0-zkvm-platform", diff --git a/bin/citrea/src/bitcoin_rollup.rs b/bin/citrea/src/bitcoin_rollup.rs index 793e4225f..89a6f9472 100644 --- a/bin/citrea/src/bitcoin_rollup.rs +++ b/bin/citrea/src/bitcoin_rollup.rs @@ -80,8 +80,8 @@ impl RollupBlueprint for BitcoinRollup { #[instrument(level = "trace", skip(self), ret)] fn get_code_commitment(&self) -> ::CodeCommitment { Digest::from([ - 1860130309, 3212374340, 1571693462, 196802355, 3242449784, 3924610482, 1760955211, - 1058326957, + 3965686256, 604444860, 1238257798, 1624929768, 3378693295, 3187615180, 1121902498, + 1170832510, ]) } diff --git a/crates/evm/Cargo.toml b/crates/evm/Cargo.toml index c3786cb7a..dd711aad9 100644 --- a/crates/evm/Cargo.toml +++ b/crates/evm/Cargo.toml @@ -52,7 +52,7 @@ reth-rpc-types-compat = { workspace = true, optional = true } reth-rpc = { workspace = true, optional = true } revm-inspectors = { workspace = true, optional = true } secp256k1 = { workspace = true, optional = true } -itertools = { version = "0.11.0", optional = true } +itertools = { workspace = true, optional = true } [dev-dependencies] revm = { workspace = true, features = [ 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 d9273ab2e..f4646f705 100644 --- a/crates/sovereign-sdk/examples/demo-simple-stf/src/lib.rs +++ b/crates/sovereign-sdk/examples/demo-simple-stf/src/lib.rs @@ -5,8 +5,8 @@ use std::marker::PhantomData; use sha2::Digest; use sov_rollup_interface::da::{BlobReaderTrait, DaSpec}; use sov_rollup_interface::soft_confirmation::SignedSoftConfirmationBatch; -use sov_rollup_interface::stf::{BatchReceipt, SlotResult, StateDiff, StateTransitionFunction}; -use sov_rollup_interface::zk::{ValidityCondition, Zkvm}; +use sov_rollup_interface::stf::{BatchReceipt, SlotResult, StateTransitionFunction}; +use sov_rollup_interface::zk::{CumulativeStateDiff, ValidityCondition, Zkvm}; /// An implementation of the [`StateTransitionFunction`] /// that is specifically designed to check if someone knows a preimage of a specific hash. @@ -138,7 +138,7 @@ impl StateTransitionFunction::BlockHeader>>, _validity_condition: &::ValidityCondition, _soft_batch: std::collections::VecDeque>, - ) -> (Self::StateRoot, StateDiff) { + ) -> (Self::StateRoot, CumulativeStateDiff) { todo!() } } 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 e8e155d98..34d683a52 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,9 +1,8 @@ use std::marker::PhantomData; -use sov_modules_api::StateDiff; use sov_rollup_interface::da::DaSpec; use sov_rollup_interface::stf::{BatchReceipt, SlotResult, StateTransitionFunction}; -use sov_rollup_interface::zk::{ValidityCondition, Zkvm}; +use sov_rollup_interface::zk::{CumulativeStateDiff, ValidityCondition, Zkvm}; /// A mock implementation of the [`StateTransitionFunction`] #[derive(PartialEq, Debug, Clone, Eq, serde::Serialize, serde::Deserialize, Default)] @@ -95,7 +94,7 @@ impl StateTransitionFunction, >, - ) -> (Self::StateRoot, StateDiff) { + ) -> (Self::StateRoot, CumulativeStateDiff) { todo!() } } diff --git a/crates/sovereign-sdk/full-node/sov-stf-runner/src/runner.rs b/crates/sovereign-sdk/full-node/sov-stf-runner/src/runner.rs index 935167a85..b371cd632 100644 --- a/crates/sovereign-sdk/full-node/sov-stf-runner/src/runner.rs +++ b/crates/sovereign-sdk/full-node/sov-stf-runner/src/runner.rs @@ -844,9 +844,11 @@ where Proof::Full(proof) => { // hotfix for devnet deployment // TODO: handle these deployed bug fixes better - let code_commitment = if serde_json::to_string(&self.code_commitment)? == "[1860130309,3212374340,1571693462,196802355,3242449784,3924610482,1760955211,1058326957]" && soft_batch.da_slot_height <= 6787 + let code_commitment = if serde_json::to_string(&self.code_commitment)? == "[3965686256,604444860,1238257798,1624929768,3378693295,3187615180,1121902498,1170832510]" && soft_batch.da_slot_height <= 6787 { serde_json::from_str("[3565622432,3167720487,554880044,1689168947,3495902722,3638273228,1798052366,4175296332]").unwrap() + } else if serde_json::to_string(&self.code_commitment)? == "[3965686256,604444860,1238257798,1624929768,3378693295,3187615180,1121902498,1170832510]" && soft_batch.da_slot_height > 6786 && soft_batch.da_slot_height <= 11075 { + serde_json::from_str("[1860130309,3212374340,1571693462,196802355,3242449784,3924610482,1760955211,1058326957]").unwrap() } else { self.code_commitment.clone() }; diff --git a/crates/sovereign-sdk/full-node/sov-stf-runner/src/verifier.rs b/crates/sovereign-sdk/full-node/sov-stf-runner/src/verifier.rs index 778d7a2db..43e2ea16b 100644 --- a/crates/sovereign-sdk/full-node/sov-stf-runner/src/verifier.rs +++ b/crates/sovereign-sdk/full-node/sov-stf-runner/src/verifier.rs @@ -2,9 +2,7 @@ use std::marker::PhantomData; use sov_rollup_interface::da::{BlockHeaderTrait, DaVerifier}; use sov_rollup_interface::stf::StateTransitionFunction; -use sov_rollup_interface::zk::{ - CumulativeStateDiff, StateTransition, StateTransitionData, Zkvm, ZkvmGuest, -}; +use sov_rollup_interface::zk::{StateTransition, StateTransitionData, Zkvm, ZkvmGuest}; /// Verifies a state transition pub struct StateTransitionVerifier @@ -82,12 +80,6 @@ where "Invalid final state root" ); - // Collect state diffs into a BtreeMap - let state_diff: CumulativeStateDiff = state_diff - .into_iter() - // .map(|(k, v)| (k, v)) - .collect(); - let out: StateTransition = StateTransition { initial_state_root: data.initial_state_root, final_state_root, diff --git a/crates/sovereign-sdk/full-node/sov-stf-runner/tests/hash_stf.rs b/crates/sovereign-sdk/full-node/sov-stf-runner/tests/hash_stf.rs index 536b53047..259914737 100644 --- a/crates/sovereign-sdk/full-node/sov-stf-runner/tests/hash_stf.rs +++ b/crates/sovereign-sdk/full-node/sov-stf-runner/tests/hash_stf.rs @@ -3,12 +3,12 @@ use sov_mock_da::{ MockAddress, MockBlob, MockBlock, MockBlockHeader, MockDaSpec, MockValidityCond, }; use sov_mock_zkvm::MockZkvm; -use sov_modules_api::{Context, StateDiff}; +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::stf::{SlotResult, StateTransitionFunction}; -use sov_rollup_interface::zk::{ValidityCondition, Zkvm}; +use sov_rollup_interface::zk::{CumulativeStateDiff, ValidityCondition, Zkvm}; use sov_state::storage::{NativeStorage, StorageKey, StorageValue}; use sov_state::{ ArrayWitness, DefaultStorageSpec, OrderedReadsAndWrites, Prefix, ProverStorage, Storage, @@ -234,7 +234,7 @@ impl StateTransitionFunction, >, - ) -> (Self::StateRoot, StateDiff) { + ) -> (Self::StateRoot, CumulativeStateDiff) { todo!() } } diff --git a/crates/sovereign-sdk/module-system/sov-modules-stf-blueprint/Cargo.toml b/crates/sovereign-sdk/module-system/sov-modules-stf-blueprint/Cargo.toml index 21088f27e..731a6c290 100644 --- a/crates/sovereign-sdk/module-system/sov-modules-stf-blueprint/Cargo.toml +++ b/crates/sovereign-sdk/module-system/sov-modules-stf-blueprint/Cargo.toml @@ -19,7 +19,7 @@ serde = { workspace = true, features = ["derive"] } tracing = { workspace = true, optional = true } jmt = { workspace = true } hex = { workspace = true } - +itertools = { workspace = true } sov-rollup-interface = { path = "../../rollup-interface" } sov-state = { path = "../sov-state" } sov-modules-api = { path = "../sov-modules-api", default-features = false } @@ -35,7 +35,12 @@ jsonrpsee = { workspace = true, features = ["server"], optional = true } [features] bench = ["sov-zk-cycle-macros", "risc0-zkvm", "risc0-zkvm-platform"] default = [] -native = ["sov-state/native", "sov-modules-api/native", "dep:tracing", "jsonrpsee"] +native = [ + "sov-state/native", + "sov-modules-api/native", + "dep:tracing", + "jsonrpsee", +] [package.metadata.cargo-udeps.ignore] normal = [ 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 768a1b4a5..17c3005c4 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 @@ -7,6 +7,7 @@ mod tx_verifier; pub use batch::Batch; use borsh::{BorshDeserialize, BorshSerialize}; +use itertools::Itertools; use rs_merkle::algorithms::Sha256; use rs_merkle::MerkleTree; use sov_modules_api::da::BlockHeaderTrait; @@ -16,14 +17,15 @@ use sov_modules_api::hooks::{ }; use sov_modules_api::{ native_debug, native_info, native_warn, BasicAddress, BlobReaderTrait, Context, DaSpec, - DispatchCall, Genesis, Signature, Spec, StateCheckpoint, StateDiff, - UnsignedSoftConfirmationBatch, WorkingSet, Zkvm, + DispatchCall, Genesis, Signature, Spec, StateCheckpoint, UnsignedSoftConfirmationBatch, + WorkingSet, Zkvm, }; use sov_rollup_interface::da::{DaData, SequencerCommitment}; use sov_rollup_interface::digest::Digest; use sov_rollup_interface::soft_confirmation::SignedSoftConfirmationBatch; pub use sov_rollup_interface::stf::{BatchReceipt, TransactionReceipt}; use sov_rollup_interface::stf::{SlotResult, StateTransitionFunction}; +use sov_rollup_interface::zk::CumulativeStateDiff; use sov_state::Storage; pub use stf_blueprint::StfBlueprint; pub use tx_verifier::RawTx; @@ -472,18 +474,18 @@ where sequencer_da_public_key: &[u8], initial_state_root: &Self::StateRoot, pre_state: Self::PreState, - mut da_data: Vec<::BlobTransaction>, - mut witnesses: std::collections::VecDeque>, - mut slot_headers: std::collections::VecDeque::BlockHeader>>, + da_data: Vec<::BlobTransaction>, + witnesses: std::collections::VecDeque>, + slot_headers: std::collections::VecDeque::BlockHeader>>, validity_condition: &::ValidityCondition, - mut soft_confirmations: std::collections::VecDeque>, - ) -> (Self::StateRoot, StateDiff) { - let mut state_diff = vec![]; + soft_confirmations: std::collections::VecDeque>, + ) -> (Self::StateRoot, CumulativeStateDiff) { + let mut state_diff = CumulativeStateDiff::default(); // First extract all sequencer commitments // Ignore broken DaData and zk proofs. Also ignore ForcedTransaction's (will be implemented in the future). let mut sequencer_commitments: Vec = vec![]; - for blob in da_data.iter_mut() { + for blob in da_data { // TODO: get sequencer da pub key if blob.sender().as_ref() == sequencer_da_public_key { let da_data = DaData::try_from_slice(blob.verified_data()); @@ -498,16 +500,14 @@ where let mut current_state_root = initial_state_root.clone(); - for sequencer_commitment in sequencer_commitments.iter() { - // should panic if number of sequencer commitments and soft confirmations don't match - let mut soft_confirmations = soft_confirmations.pop_front().unwrap(); - - // should panic if number of sequencer commitments and set of DA block headers don't match - let da_block_headers = slot_headers.pop_front().unwrap(); - - // should panic if number of sequencer commitments and set of witnesses don't match - let witnesses = witnesses.pop_front().unwrap(); - + // 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 + .into_iter() + .zip_eq(soft_confirmations) + .zip_eq(slot_headers) + .zip_eq(witnesses) + { // we must verify given DA headers match the commitments let mut index_headers = 0; let mut index_soft_confirmation = 0; @@ -601,11 +601,13 @@ where "Invalid merkle root" ); - let mut witness_iter = witnesses.into_iter(); let mut da_block_headers_iter = da_block_headers.into_iter().peekable(); let mut da_block_header = da_block_headers_iter.next().unwrap(); + // now that we verified the claimed root, we can apply the soft confirmations - for soft_confirmation in soft_confirmations.iter_mut() { + // should panic if the number of witnesses and soft confirmations don't match + for (mut soft_confirmation, witness) in soft_confirmations.into_iter().zip_eq(witnesses) + { if soft_confirmation.da_slot_height() != da_block_header.height() { da_block_header = da_block_headers_iter.next().unwrap(); } @@ -613,12 +615,11 @@ where let result = self.apply_soft_batch( sequencer_public_key, ¤t_state_root, - // TODO: either somehow commit to the prestate after each soft confirmation and pass the correct prestate here, or run every soft confirmation all at once. pre_state.clone(), - witness_iter.next().unwrap(), // should panic if the number of witnesses and soft confirmations don't match + witness, &da_block_header, validity_condition, - soft_confirmation, + &mut soft_confirmation, ); current_state_root = result.state_root; @@ -626,7 +627,6 @@ where } } - // TODO: implement state diff extraction (current_state_root, state_diff) } } 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 deeff9ea2..8774b1d2d 100644 --- a/crates/sovereign-sdk/rollup-interface/src/state_machine/stf.rs +++ b/crates/sovereign-sdk/rollup-interface/src/state_machine/stf.rs @@ -14,7 +14,7 @@ use serde::{Deserialize, Serialize}; use crate::da::DaSpec; use crate::maybestd::vec::Vec; use crate::soft_confirmation::SignedSoftConfirmationBatch; -use crate::zk::{ValidityCondition, Zkvm}; +use crate::zk::{CumulativeStateDiff, ValidityCondition, Zkvm}; #[cfg(any(all(test, feature = "sha2"), feature = "fuzzing"))] pub mod fuzzing; @@ -250,7 +250,7 @@ pub trait StateTransitionFunction { slot_headers: VecDeque>, validity_condition: &Da::ValidityCondition, soft_confirmations: VecDeque>, - ) -> (Self::StateRoot, Vec<(Vec, Option>)>); + ) -> (Self::StateRoot, CumulativeStateDiff); } /// A key-value pair representing a change to the rollup state