diff --git a/Cargo.lock b/Cargo.lock index c054b8bf7..66a39cfaa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2516,9 +2516,9 @@ checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" [[package]] name = "bytemuck" -version = "1.18.0" +version = "1.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94bbb0ad554ad961ddc5da507a12a29b14e4ae5bda06b19f575a3e6079d2e2ae" +checksum = "ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3" dependencies = [ "bytemuck_derive", ] @@ -13057,12 +13057,14 @@ dependencies = [ "argh", "bech32 0.11.0", "bitcoin", + "bytemuck", "hex", "rand_core", "secp256k1", "serde_json", "strata-key-derivation", "strata-primitives", + "strata-risc0-guest-builder", "strata-sp1-guest-builder", "terrors", "zeroize", diff --git a/bin/datatool/Cargo.toml b/bin/datatool/Cargo.toml index 95bd4449f..2a6e605c3 100644 --- a/bin/datatool/Cargo.toml +++ b/bin/datatool/Cargo.toml @@ -10,15 +10,22 @@ path = "src/main.rs" [dependencies] strata-key-derivation.workspace = true strata-primitives.workspace = true -strata-sp1-guest-builder = { path = "../../provers/sp1" } +strata-risc0-guest-builder = { path = "../../provers/risc0", optional = true } +strata-sp1-guest-builder = { path = "../../provers/sp1", optional = true } anyhow.workspace = true argh.workspace = true bech32 = "0.11.0" bitcoin = { workspace = true, features = ["std"] } +bytemuck = { version = "1.21.0", optional = true } hex.workspace = true rand_core.workspace = true secp256k1 = { workspace = true, features = ["global-context", "std"] } serde_json.workspace = true terrors = "0.3.0" zeroize.workspace = true + +[features] +default = [] +sp1 = ["strata-sp1-guest-builder"] +risc0 = ["strata-risc0-guest-builder", "bytemuck"] diff --git a/bin/datatool/src/util.rs b/bin/datatool/src/util.rs index 1c454a2e4..d9e1421ac 100644 --- a/bin/datatool/src/util.rs +++ b/bin/datatool/src/util.rs @@ -27,7 +27,6 @@ use strata_primitives::{ params::{ProofPublishMode, RollupParams}, proof::RollupVerifyingKey, }; -use strata_sp1_guest_builder::GUEST_CHECKPOINT_VK_HASH_STR; use zeroize::Zeroize; use crate::args::{ @@ -66,6 +65,55 @@ pub(super) fn exec_subc(cmd: Subcommand, ctx: &mut CmdContext) -> anyhow::Result } } +/// Returns the appropriate [`RollupVerifyingKey`] based on the enabled features. +/// +/// # Behavior +/// +/// - If the **sp1** feature is exclusively enabled, returns an `SP1VerifyingKey`. +/// - If the **risc0** feature is exclusively enabled, returns a `Risc0VerifyingKey`. +/// - If **both** `sp1` and `risc0` are enabled at once, this function will **panic**. +/// - If **neither** `sp1` nor `risc0` is enabled, returns a `NativeVerifyingKey`. +/// +/// # Panics +/// +/// Panics if both `sp1` and `risc0` features are enabled simultaneously, since +/// only one ZKVM can be supported at a time. +fn resolve_rollup_vk() -> RollupVerifyingKey { + // Use SP1 if only `sp1` feature is enabled + #[cfg(all(feature = "sp1", not(feature = "risc0")))] + { + use strata_sp1_guest_builder::GUEST_CHECKPOINT_VK_HASH_STR; + let vk_buf32: Buf32 = GUEST_CHECKPOINT_VK_HASH_STR + .parse() + .expect("invalid sp1 checkpoint verifier key hash"); + RollupVerifyingKey::SP1VerifyingKey(vk_buf32) + } + + // Use Risc0 if only `risc0` feature is enabled + #[cfg(all(feature = "risc0", not(feature = "sp1")))] + { + use strata_risc0_guest_builder::GUEST_RISC0_CHECKPOINT_ID; + let vk_u8: [u8; 32] = bytemuck::cast(GUEST_RISC0_CHECKPOINT_ID); + let vk_buf32 = vk_u8.into(); + RollupVerifyingKey::Risc0VerifyingKey(vk_buf32) + } + + // Panic if both `sp1` and `risc0` feature are enabled + #[cfg(all(feature = "risc0", feature = "sp1"))] + { + panic!( + "Conflicting ZKVM features: both 'sp1' and 'risc0' are enabled. \ + Please disable one of them, as only a single ZKVM can be supported at a time." + ) + } + + // If neither `risc0` nor `sp1` is enabled, use the Native verifying key + #[cfg(all(not(feature = "risc0"), not(feature = "sp1")))] + { + RollupVerifyingKey::NativeVerifyingKey(Buf32::zero()) + } +} + /// Executes the `genxpriv` subcommand. /// /// Generates a new [`Xpriv`] that will [`Zeroize`](zeroize) on [`Drop`] and writes it to a file. @@ -200,9 +248,7 @@ fn exec_genparams(cmd: SubcParams, ctx: &mut CmdContext) -> anyhow::Result<()> { .unwrap_or(1_000_000_000); // Parse the checkpoint verification key. - let rollup_vk: Buf32 = GUEST_CHECKPOINT_VK_HASH_STR - .parse() - .expect("invalid checkpoint verifier key hash"); + let rollup_vk = resolve_rollup_vk(); let config = ParamsConfig { name: cmd.name.unwrap_or_else(|| "strata-testnet".to_string()), @@ -357,7 +403,7 @@ pub struct ParamsConfig { /// Operators' keys. opkeys: Vec, /// Verifier's key. - rollup_vk: Buf32, + rollup_vk: RollupVerifyingKey, /// Amount of sats to deposit. deposit_sats: u64, /// Timeout for proofs. @@ -407,7 +453,7 @@ fn construct_params(config: ParamsConfig) -> RollupParams { target_l2_batch_size: config.epoch_slots as u64, address_length: 20, deposit_amount: config.deposit_sats, - rollup_vk: RollupVerifyingKey::SP1VerifyingKey(config.rollup_vk), + rollup_vk: config.rollup_vk, // TODO make configurable dispatch_assignment_dur: 64, proof_publish_mode: config diff --git a/crates/consensus-logic/Cargo.toml b/crates/consensus-logic/Cargo.toml index 012c74ce7..16a7ab644 100644 --- a/crates/consensus-logic/Cargo.toml +++ b/crates/consensus-logic/Cargo.toml @@ -12,7 +12,7 @@ strata-eectl.workspace = true strata-primitives.workspace = true strata-risc0-adapter.workspace = true strata-rpc-types.workspace = true -strata-sp1-adapter = { workspace = true, features = ["prover"] } +strata-sp1-adapter.workspace = true strata-state.workspace = true strata-status.workspace = true strata-storage.workspace = true diff --git a/crates/consensus-logic/src/l1_handler.rs b/crates/consensus-logic/src/l1_handler.rs index 3395e3158..bb93b8ed2 100644 --- a/crates/consensus-logic/src/l1_handler.rs +++ b/crates/consensus-logic/src/l1_handler.rs @@ -187,6 +187,9 @@ pub fn verify_proof(checkpoint: &BatchCheckpoint, rollup_params: &RollupParams) RollupVerifyingKey::SP1VerifyingKey(vk) => { strata_sp1_adapter::verify_groth16(proof, vk.as_ref(), &public_params_raw) } + // In Native Execution mode, we do not actually generate the proof to verify. Checking + // public parameters is sufficient. + RollupVerifyingKey::NativeVerifyingKey(_) => Ok(()), } } diff --git a/crates/primitives/src/proof.rs b/crates/primitives/src/proof.rs index 12838e795..45f3c28ea 100644 --- a/crates/primitives/src/proof.rs +++ b/crates/primitives/src/proof.rs @@ -8,6 +8,7 @@ use crate::{buf::Buf32, l1::L1BlockId, l2::L2BlockId}; /// This enum encapsulates verifying keys for different ZKVMs: /// - `SP1VerifyingKey`: Used for verifying proofs generated using SP1. /// - `Risc0VerifyingKey`: Used for verifying proofs generated using Risc0. +/// - `Native`: For functional testing purposes without ZKVM overhead. #[derive(Clone, Debug, Copy, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] pub enum RollupVerifyingKey { @@ -18,6 +19,15 @@ pub enum RollupVerifyingKey { /// Verifying Key for proofs generated by Risc0. #[serde(rename = "risc0")] Risc0VerifyingKey(Buf32), + + /// Placeholder variant for functional testing. + /// + /// This variant allows skipping guest code compilation (e.g., ELFs for SP1 or Risc0) and is + /// used to test the prover-client and proof logic without the overhead of ZKVM + /// compilation. It is strictly for internal testing and must not be used in production + /// deployments. + #[serde(rename = "native")] + NativeVerifyingKey(Buf32), } /// Represents a context for different types of proofs. diff --git a/functional-tests/rollup_params_cfg.py b/functional-tests/rollup_params_cfg.py index 286c23028..bf7c8d3ae 100644 --- a/functional-tests/rollup_params_cfg.py +++ b/functional-tests/rollup_params_cfg.py @@ -1,13 +1,18 @@ -from pydantic import BaseModel +from typing import Annotated, Union + +from pydantic import BaseModel, StringConstraints + +# A string that optionally starts with 0x, followed by exactly 64 hex characters +StrBuf32 = Annotated[str, StringConstraints(pattern=r"^(0x)?[0-9A-Fa-f]{64}$")] class CredRule(BaseModel): - schnorr_key: str + schnorr_key: StrBuf32 class OperatorConfigItem(BaseModel): - signing_pk: str - wallet_pk: str + signing_pk: StrBuf32 + wallet_pk: StrBuf32 class OperatorConfig(BaseModel): @@ -17,8 +22,19 @@ def get_operators_pubkeys(self) -> list[str]: return [operator.wallet_pk for operator in self.static] -class RollupVk(BaseModel): - sp1: str +class Sp1RollupVk(BaseModel): + sp1: StrBuf32 + + +class Risc0RollupVk(BaseModel): + risc0: StrBuf32 + + +class NativeRollupVk(BaseModel): + native: StrBuf32 + + +RollupVk = Union[Sp1RollupVk, Risc0RollupVk, NativeRollupVk] class ProofPublishMode(BaseModel): @@ -37,8 +53,8 @@ class RollupConfig(BaseModel): horizon_l1_height: int genesis_l1_height: int operator_config: OperatorConfig - evm_genesis_block_hash: str - evm_genesis_block_state_root: str + evm_genesis_block_hash: StrBuf32 + evm_genesis_block_state_root: StrBuf32 l1_reorg_safe_depth: int target_l2_batch_size: int address_length: int diff --git a/provers/risc0/Cargo.toml b/provers/risc0/Cargo.toml index afbf04135..52855bae9 100644 --- a/provers/risc0/Cargo.toml +++ b/provers/risc0/Cargo.toml @@ -41,5 +41,5 @@ methods = [ ] [features] -default = [] +default = ["prover"] prover = ["dep:strata-risc0-adapter"] diff --git a/provers/risc0/build.rs b/provers/risc0/build.rs index 25606a114..c3612963c 100644 --- a/provers/risc0/build.rs +++ b/provers/risc0/build.rs @@ -18,22 +18,22 @@ fn main() { let elf = r#" pub const GUEST_RISC0_EVM_EE_STF_ELF: &[u8] = &[]; - pub const GUEST_RISC0_EVM_EE_STF_ID: &[u8] = &[]; + pub const GUEST_RISC0_EVM_EE_STF_ID: &[u32; 8] = &[0u32; 8]; pub const GUEST_RISC0_CL_STF_ELF: &[u8] = &[]; - pub const GUEST_RISC0_CL_STF_ID: &[u8] = &[]; + pub const GUEST_RISC0_CL_STF_ID: [u32; 8] = [0u32; 8]; pub const GUEST_RISC0_CL_AGG_ELF: &[u8] = &[]; - pub const GUEST_RISC0_CL_AGG_ID: &[u32; 8] = &[0u32; 8]; + pub const GUEST_RISC0_CL_AGG_ID: [u32; 8] = [0u32; 8]; pub const GUEST_RISC0_BTC_BLOCKSPACE_ELF: &[u8] = &[]; - pub const GUEST_RISC0_BTC_BLOCKSPACE_ID: &[u8] = &[]; + pub const GUEST_RISC0_BTC_BLOCKSPACE_ID: [u32; 8] = [0u32; 8]; pub const GUEST_RISC0_L1_BATCH_ELF: &[u8] = &[]; - pub const GUEST_RISC0_L1_BATCH_ID: &[u8] = &[]; + pub const GUEST_RISC0_L1_BATCH_ID: [u32; 8] = [0u32; 8]; pub const GUEST_RISC0_CHECKPOINT_ELF: &[u8] = &[]; - pub const GUEST_RISC0_CHECKPOINT_ID: &[u8] = &[]; + pub const GUEST_RISC0_CHECKPOINT_ID: [u32; 8] = [0u32; 8]; "#; std::fs::write(methods_path, elf).expect("Failed to write mock rollup elf"); diff --git a/provers/risc0/guest-checkpoint/Cargo.lock b/provers/risc0/guest-checkpoint/Cargo.lock index 03346e87b..bb3142c60 100644 --- a/provers/risc0/guest-checkpoint/Cargo.lock +++ b/provers/risc0/guest-checkpoint/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "addr2line" @@ -3800,8 +3800,10 @@ dependencies = [ "rlp", "serde", "serde_with", + "strata-primitives", "strata-reth-evm", "strata-reth-primitives", + "strata-state", "strata-zkvm", "thiserror", ] diff --git a/provers/risc0/guest-cl-agg/Cargo.lock b/provers/risc0/guest-cl-agg/Cargo.lock index d8d9b1313..5b56a1d2e 100644 --- a/provers/risc0/guest-cl-agg/Cargo.lock +++ b/provers/risc0/guest-cl-agg/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "addr2line" @@ -3780,8 +3780,10 @@ dependencies = [ "rlp", "serde", "serde_with", + "strata-primitives", "strata-reth-evm", "strata-reth-primitives", + "strata-state", "strata-zkvm", "thiserror 1.0.69", ] diff --git a/provers/risc0/guest-cl-stf/Cargo.lock b/provers/risc0/guest-cl-stf/Cargo.lock index 3e37e6cf4..5cccda727 100644 --- a/provers/risc0/guest-cl-stf/Cargo.lock +++ b/provers/risc0/guest-cl-stf/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "addr2line" @@ -3770,8 +3770,10 @@ dependencies = [ "rlp", "serde", "serde_with", + "strata-primitives", "strata-reth-evm", "strata-reth-primitives", + "strata-state", "strata-zkvm", "thiserror", ] diff --git a/provers/risc0/guest-evm-ee-stf/Cargo.lock b/provers/risc0/guest-evm-ee-stf/Cargo.lock index 756b4c046..6d861fb55 100644 --- a/provers/risc0/guest-evm-ee-stf/Cargo.lock +++ b/provers/risc0/guest-evm-ee-stf/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "addr2line" @@ -638,6 +638,16 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" +[[package]] +name = "base58ck" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c8d66485a3a2ea485c1913c4572ce0256067a5377ac8c75c4960e1cda98605f" +dependencies = [ + "bitcoin-internals", + "bitcoin_hashes", +] + [[package]] name = "base64" version = "0.22.1" @@ -650,6 +660,12 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +[[package]] +name = "bech32" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d965446196e3b7decd44aa7ee49e31d630118f90ef12f97900f262eb915c951d" + [[package]] name = "bincode" version = "1.3.3" @@ -674,6 +690,60 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" +[[package]] +name = "bitcoin" +version = "0.32.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6bc65742dea50536e35ad42492b234c27904a27f0abdcbce605015cb4ea026" +dependencies = [ + "base58ck", + "bech32", + "bitcoin-internals", + "bitcoin-io", + "bitcoin-units", + "bitcoin_hashes", + "hex-conservative", + "hex_lit", + "secp256k1", + "serde", +] + +[[package]] +name = "bitcoin-internals" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30bdbe14aa07b06e6cfeffc529a1f099e5fbe249524f8125358604df99a4bed2" +dependencies = [ + "serde", +] + +[[package]] +name = "bitcoin-io" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b47c4ab7a93edb0c7198c5535ed9b52b63095f4e9b45279c6736cec4b856baf" + +[[package]] +name = "bitcoin-units" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5285c8bcaa25876d07f37e3d30c303f2609179716e11d688f51e8f1fe70063e2" +dependencies = [ + "bitcoin-internals", + "serde", +] + +[[package]] +name = "bitcoin_hashes" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb18c03d0db0247e147a21a6faafd5a7eb851c743db062de72018b6b7e8e4d16" +dependencies = [ + "bitcoin-io", + "hex-conservative", + "serde", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -1293,6 +1363,12 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "ethnum" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b90ca2580b73ab6a1f724b76ca11ab632df820fd6040c336200d2c1df7b3c82c" + [[package]] name = "fastrand" version = "2.1.0" @@ -1553,12 +1629,27 @@ dependencies = [ "serde", ] +[[package]] +name = "hex-conservative" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5313b072ce3c597065a808dbf612c4c8e8590bdbf8b579508bf7a762c5eae6cd" +dependencies = [ + "arrayvec", +] + [[package]] name = "hex-literal" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" +[[package]] +name = "hex_lit" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3011d1213f159867b13cfd6ac92d2cd5f1345762c63be3554e84092d85a50bbd" + [[package]] name = "hmac" version = "0.12.1" @@ -2115,6 +2206,23 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "musig2" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c89bee285da6010ad76c3467c4de8265bb4fa46fba0017df95ae55cad4436528" +dependencies = [ + "base16ct", + "hmac", + "once_cell", + "secp", + "secp256k1", + "serde", + "serdect", + "sha2", + "subtle", +] + [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -2230,6 +2338,7 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" dependencies = [ + "proc-macro-crate", "proc-macro2", "quote", "syn 2.0.75", @@ -3287,14 +3396,30 @@ dependencies = [ "zeroize", ] +[[package]] +name = "secp" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd426921f62c7e334ca27173743cd90a7263566a3be76ef0b47773d631633cf9" +dependencies = [ + "base16ct", + "once_cell", + "secp256k1", + "serde", + "serdect", + "subtle", +] + [[package]] name = "secp256k1" -version = "0.29.0" +version = "0.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e0cc0f1cf93f4969faf3ea1c7d8a9faed25918d96affa959720823dfe86d4f3" +checksum = "9465315bc9d4566e1724f0fffcbcc446268cb522e60f9a27bcded6b19c108113" dependencies = [ + "bitcoin_hashes", "rand", "secp256k1-sys", + "serde", ] [[package]] @@ -3408,6 +3533,16 @@ dependencies = [ "syn 2.0.75", ] +[[package]] +name = "serdect" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a84f14a19e9a014bb9f4512488d9829a68e04ecabffb0f9904cd1ace94598177" +dependencies = [ + "base16ct", + "serde", +] + [[package]] name = "sha2" version = "0.10.8" @@ -3530,6 +3665,49 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "strata-bridge-tx-builder" +version = "0.1.0" +dependencies = [ + "bitcoin", + "musig2", + "serde", + "strata-primitives", + "thiserror", +] + +[[package]] +name = "strata-crypto" +version = "0.1.0" +dependencies = [ + "secp256k1", + "sha2", + "strata-primitives", +] + +[[package]] +name = "strata-primitives" +version = "0.1.0" +dependencies = [ + "anyhow", + "arbitrary", + "bincode", + "bitcoin", + "borsh", + "digest 0.10.7", + "hex", + "musig2", + "rand", + "reth-primitives", + "secp256k1", + "serde", + "serde_json", + "sha2", + "thiserror", + "tracing", + "zeroize", +] + [[package]] name = "strata-proofimpl-evm-ee-stf" version = "0.1.0" @@ -3549,8 +3727,10 @@ dependencies = [ "rlp", "serde", "serde_with", + "strata-primitives", "strata-reth-evm", "strata-reth-primitives", + "strata-state", "strata-zkvm", "thiserror", ] @@ -3589,6 +3769,26 @@ dependencies = [ "tracing-subscriber 0.3.18", ] +[[package]] +name = "strata-state" +version = "0.1.0" +dependencies = [ + "arbitrary", + "bitcoin", + "borsh", + "digest 0.10.7", + "ethnum", + "hex", + "num_enum", + "serde", + "sha2", + "strata-bridge-tx-builder", + "strata-crypto", + "strata-primitives", + "strata-zkvm", + "tracing", +] + [[package]] name = "strata-zkvm" version = "0.1.0"