From 27b0beeaace5b93d1d32ac9b13da0722793fafeb Mon Sep 17 00:00:00 2001 From: Brecht Devos Date: Thu, 9 May 2024 01:07:48 +0200 Subject: [PATCH] feat(raiko): run general tests on all targets (#164) * Run general tests on all targets * fix risc0 * fix SGX + temp disable driver tests * typo * increase timeout on ci for SP1 * disable slow test on SP1 so ci can handle it * decrease sp1 timeout again on ci * temp disable sp1 driver test * use more recent taiko a7 block * small improvements + run standard tests with native prover * update prove_block with working holesky endpoint * increase timeout * fix ci env vars * more fixes to features * Fix build error propegation * skip kzg check on SP1 because out of memory problems * fix sgx compile error * fix default skip value --- .github/workflows/ci.yml | 63 +++++++++++++---- README.md | 22 +++--- host/src/preflight.rs | 1 + host/src/raiko.rs | 108 ++++++++++++++++++++---------- lib/src/input.rs | 1 + lib/src/protocol_instance.rs | 26 ++++--- provers/risc0/driver/src/lib.rs | 14 +--- provers/sgx/guest/src/one_shot.rs | 5 +- provers/sgx/prover/src/lib.rs | 8 ++- script/build.sh | 50 +++++++++++--- script/install.sh | 2 + script/prove-block.sh | 6 +- 12 files changed, 211 insertions(+), 95 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 22aab3374..f68eb6e35 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,18 +8,45 @@ on: env: CARGO_TERM_COLOR: always GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - RISC0_VERSION: 0.20.1 - RISC0_TOOLCHAIN_VERSION: test-release-2 concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true jobs: + build-test: + name: Build and test native + runs-on: ubuntu-latest + timeout-minutes: 120 + env: + TARGET: native + CI: 1 + MOCK: 1 + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + - uses: actions-rs/toolchain@v1 + with: + toolchain: nightly-2024-04-17 + profile: minimal + - name: Install cargo-binstall + uses: cargo-bins/cargo-binstall@v1.6.4 + - name: Install native + run: make install + - name: Build native prover + run: make build + - name: Test native prover + run: make test + build-test-risc0: name: Build and test risc0 runs-on: ubuntu-latest - timeout-minutes: 60 + timeout-minutes: 120 + env: + TARGET: risc0 + CI: 1 + MOCK: 1 steps: - uses: actions/checkout@v4 with: @@ -32,16 +59,20 @@ jobs: uses: cargo-bins/cargo-binstall@v1.6.4 - uses: risc0/risc0/.github/actions/sccache@release-0.19 - name: Install risc0 - run: TARGET="risc0" CI=1 make install + run: make install - name: Build risc0 prover - run: TARGET="risc0" make build + run: make build - name: Test risc0 prover - run: MOCK=1 TARGET="risc0" make test + run: make test build-test-sp1: name: Build and test sp1 runs-on: ubuntu-latest - timeout-minutes: 60 + timeout-minutes: 120 + env: + TARGET: sp1 + CI: 1 + MOCK: 1 steps: - uses: actions/checkout@v4 with: @@ -53,16 +84,20 @@ jobs: - name: Install cargo-binstall uses: cargo-bins/cargo-binstall@v1.6.4 - name: Install sp1 - run: TARGET="sp1" CI=1 make install + run: make install - name: Build sp1 prover - run: TARGET="sp1" make build + run: make build - name: Test sp1 prover - run: MOCK=1 TARGET="sp1" make test + run: make test build-test-sgx: name: Build and test sgx runs-on: ubuntu-latest - timeout-minutes: 60 + timeout-minutes: 120 + env: + TARGET: sgx + CI: 1 + MOCK: 1 steps: - uses: actions/checkout@v4 with: @@ -74,11 +109,11 @@ jobs: - name: Install cargo-binstall uses: cargo-bins/cargo-binstall@v1.6.4 - name: Install sgx - run: TARGET="sgx" CI=1 make install + run: make install - name: Build sgx prover - run: TARGET="sgx" make build + run: make build - name: Test sgx prover - run: TARGET="sgx" make test + run: make test build-test-sgx-with-docker: name: Build and test sgx with Docker diff --git a/README.md b/README.md index 702d157c6..b462255b8 100644 --- a/README.md +++ b/README.md @@ -15,13 +15,13 @@ $ make install You can also download all required dependencies for each prover separately, for example to install SP1: ```console -$ TARGET="sp1" make install +$ TARGET=sp1 make install ``` ### Building After installing dependencies of selected prover, the following command internally calls cargo to build the prover's guest target with the `--release` profile by default, for example: ```console -$ TARGET="sp1" make build +$ TARGET=sp1 make build ``` If you set `DEBUG=1` then the target will be compiled without optimization (not recomended for ZkVM elfs). @@ -29,7 +29,7 @@ If you set `DEBUG=1` then the target will be compiled without optimization (not Note that you have to `make build` first before running ZkVM provers, otherwise the guest elf may not be up to date and can result in poof failures. ```console -$ TARGET="sp1" make run +$ TARGET=sp1 make run ``` Just for development with the native prover which runs through the block execution without producing any ZK/SGX proof: ``` @@ -49,12 +49,12 @@ Look into `prove-block.sh` for the available options or run the script without i ### Risc zero To install, build, and run in one step: ```console -$ export TARGET="risc0" +$ export TARGET=risc0 $ make install && make build && make run ``` To build and run test on Risc0 Zkvm: ```console -$ TARGET="risc0" make test +$ TARGET=risc0 make test ``` #### Bonsai If you are using Bonsai service, edit `run-bonsai.sh` to setup your API key, endpoint and on-chain verifier address. @@ -74,29 +74,29 @@ $ cargo run -F metal --release --features risc0 Note that CUDA needs to be installed when using `cuda`: https://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html -### SP1 +### SP1 To install, build, and run in one step: ```console -$ export TARGET="sp1" +$ export TARGET=sp1 $ make install && make build && make run ``` To build and run test on Sp1 Zkvm: ```console -$ TARGET="sp1" make test +$ TARGET=sp1 make test ``` ### SGX: To install, build, and run in one step: ```console -$ export TARGET="sgx" +$ export TARGET=sgx $ make install && make build && make run ``` To build and run test related SGX provers: ```console -$ TARGET="sgx" make test +$ TARGET=sgx make test ``` If your CPU doesn't support SGX, you can still run the SGX code through gramine like it would on an SGX machine: ```console -$ SGX_DIRECT=1 TARGET="sgx" make run +$ MOCK=1 TARGET=sgx make run ``` \ No newline at end of file diff --git a/host/src/preflight.rs b/host/src/preflight.rs index 14c5095bf..c48f08bb8 100644 --- a/host/src/preflight.rs +++ b/host/src/preflight.rs @@ -144,6 +144,7 @@ pub async fn preflight( tx_blob_hash, block_proposed: proposal_event, prover_data, + skip_verify_blob: false, } } else { // For Ethereum blocks we just convert the block transactions in a tx_list diff --git a/host/src/raiko.rs b/host/src/raiko.rs index 59a4f38b6..80e069684 100644 --- a/host/src/raiko.rs +++ b/host/src/raiko.rs @@ -210,74 +210,114 @@ fn check_eq(expected: T, actual: T, me #[cfg(test)] mod tests { - use crate::raiko::{ChainSpec, NativeResponse, Raiko}; + use crate::raiko::{ChainSpec, Raiko}; use crate::request::{ProofRequest, ProofType}; use crate::rpc_provider::RpcBlockDataProvider; use alloy_primitives::Address; - use raiko_lib::{ - consts::{get_network_spec, Network}, - input::GuestOutput, - }; + use clap::ValueEnum; + use raiko_lib::consts::{get_network_spec, Network}; use raiko_primitives::B256; + use serde_json::{json, Value}; use std::collections::HashMap; + use std::env; + + fn get_proof_type_from_env() -> ProofType { + let proof_type = env::var("TARGET").unwrap_or("native".to_string()); + ProofType::from_str(&proof_type, true).unwrap() + } + + fn is_ci() -> bool { + let ci = env::var("CI").unwrap_or("0".to_string()); + ci == "1" + } + + fn test_proof_params() -> HashMap { + let mut prover_args = HashMap::new(); + prover_args.insert( + "risc0".to_string(), + json! { + { + "bonsai": false, + "snark": false, + "profile": true, + "execution_po2": 18 + } + }, + ); + prover_args.insert( + "sgx".to_string(), + json! { + { + "instance_id": 121, + "setup": true, + "bootstrap": true, + "prove": true, + } + }, + ); + prover_args + } async fn prove_block(chain_spec: ChainSpec, proof_request: ProofRequest) { let provider = RpcBlockDataProvider::new(&proof_request.rpc.clone(), proof_request.block_number - 1); - let raiko = Raiko::new(chain_spec, proof_request); - let input = raiko + let raiko = Raiko::new(chain_spec, proof_request.clone()); + let mut input = raiko .generate_input(provider) .await .expect("input generation failed"); + if is_ci() && proof_request.proof_type == ProofType::Sp1 { + input.taiko.skip_verify_blob = true; + } let output = raiko.get_output(&input).expect("output generation failed"); - let proof = raiko + let _proof = raiko .prove(input, &output) .await .expect("proof generation failed"); - let response: NativeResponse = serde_json::from_value(proof).unwrap(); - match response.output { - GuestOutput::Success(_) => {} - GuestOutput::Failure => unreachable!(), - }; } #[tokio::test(flavor = "multi_thread")] async fn test_prove_block_taiko_a7() { + let proof_type = get_proof_type_from_env(); let network = Network::TaikoA7; - let block_number = 39367; + let block_number = 105987; let chain_spec = get_network_spec(network); let proof_request = ProofRequest { block_number, - rpc: "https://rpc.hekla.taiko.xyz/".to_string(), - l1_rpc: "https://l1rpc.hekla.taiko.xyz/".to_string(), + rpc: "https://rpc.hekla.taiko.xyz".to_string(), + l1_rpc: "https://ethereum-holesky-rpc.publicnode.com".to_string(), beacon_rpc: "https://l1beacon.hekla.taiko.xyz".to_string(), network, graffiti: B256::ZERO, prover: Address::ZERO, l1_network: Network::Ethereum.to_string(), - proof_type: ProofType::Native, - prover_args: HashMap::new(), + proof_type, + prover_args: test_proof_params(), }; prove_block(chain_spec, proof_request).await; } #[tokio::test(flavor = "multi_thread")] async fn test_prove_block_ethereum() { - let network = Network::Ethereum; - let block_number = 19707175; - let chain_spec = get_network_spec(network); - let proof_request = ProofRequest { - block_number, - rpc: "https://rpc.ankr.com/eth".to_string(), - l1_rpc: String::new(), - beacon_rpc: String::new(), - network, - graffiti: B256::ZERO, - prover: Address::ZERO, - l1_network: Network::Ethereum.to_string(), - proof_type: ProofType::Native, - prover_args: HashMap::new(), - }; - prove_block(chain_spec, proof_request).await; + let proof_type = get_proof_type_from_env(); + // Skip test on SP1 for now because it's too slow on CI + if proof_type != ProofType::Sp1 { + let network = Network::Ethereum; + let block_number = 19707175; + let chain_spec = get_network_spec(network); + let proof_request = ProofRequest { + block_number, + rpc: "https://rpc.ankr.com/eth".to_string(), + l1_rpc: String::new(), + beacon_rpc: String::new(), + network, + graffiti: B256::ZERO, + prover: Address::ZERO, + l1_network: Network::Ethereum.to_string(), + proof_type, + prover_args: test_proof_params(), + }; + prove_block(chain_spec, proof_request).await; + } } } diff --git a/lib/src/input.rs b/lib/src/input.rs index 99f548863..7c67706e6 100644 --- a/lib/src/input.rs +++ b/lib/src/input.rs @@ -94,6 +94,7 @@ pub struct TaikoGuestInput { pub block_proposed: BlockProposed, pub prover_data: TaikoProverData, pub tx_blob_hash: Option, + pub skip_verify_blob: bool, } #[derive(Clone, Default, Debug, Serialize, Deserialize)] diff --git a/lib/src/protocol_instance.rs b/lib/src/protocol_instance.rs index a248979f2..a63a2b201 100644 --- a/lib/src/protocol_instance.rs +++ b/lib/src/protocol_instance.rs @@ -94,16 +94,22 @@ pub fn assemble_protocol_instance( ) -> Result { let blob_used = input.taiko.block_proposed.meta.blobUsed; let tx_list_hash = if blob_used { - let mut data = Vec::from(KZG_TRUST_SETUP_DATA); - let kzg_settings = KzgSettings::from_u8_slice(&mut data); - let kzg_commit = KzgCommitment::blob_to_kzg_commitment( - &Blob::from_bytes(&input.taiko.tx_data.as_slice()).unwrap(), - &kzg_settings, - ) - .unwrap(); - let versioned_hash = kzg_to_versioned_hash(kzg_commit); - assert_eq!(versioned_hash, input.taiko.tx_blob_hash.unwrap()); - versioned_hash + if !input.taiko.skip_verify_blob { + println!("kzg check enabled!"); + let mut data = Vec::from(KZG_TRUST_SETUP_DATA); + let kzg_settings = KzgSettings::from_u8_slice(&mut data); + let kzg_commit = KzgCommitment::blob_to_kzg_commitment( + &Blob::from_bytes(&input.taiko.tx_data.as_slice()).unwrap(), + &kzg_settings, + ) + .unwrap(); + let versioned_hash = kzg_to_versioned_hash(kzg_commit); + assert_eq!(versioned_hash, input.taiko.tx_blob_hash.unwrap()); + versioned_hash + } else { + println!("kzg check disabled!"); + input.taiko.tx_blob_hash.unwrap() + } } else { TxHash::from(keccak(input.taiko.tx_data.as_slice())) }; diff --git a/provers/risc0/driver/src/lib.rs b/provers/risc0/driver/src/lib.rs index c381f45aa..ccbe4245f 100644 --- a/provers/risc0/driver/src/lib.rs +++ b/provers/risc0/driver/src/lib.rs @@ -51,18 +51,7 @@ impl Prover for Risc0Prover { output: &GuestOutput, config: &ProverConfig, ) -> ProverResult { - println!("config: {:?}", config); - - let config_risc0 = json! { - { - "bonsai": false, - "snark": false, - "profile": true, - "execution_po2": 18 - } - }; - - let config = Risc0Param::deserialize(config_risc0).unwrap(); + let config = Risc0Param::deserialize(config.get("risc0").unwrap()).unwrap(); println!("elf code length: {}", RISC0_GUEST_ELF.len()); let encoded_input = to_vec(&input).expect("Could not serialize proving input!"); @@ -106,6 +95,7 @@ impl Prover for Risc0Prover { } } +#[ignore] #[test] fn test_guest() { use risc0_zkvm::{default_prover, ExecutorEnv}; diff --git a/provers/sgx/guest/src/one_shot.rs b/provers/sgx/guest/src/one_shot.rs index 9fa8fd3ce..1edf69ebc 100644 --- a/provers/sgx/guest/src/one_shot.rs +++ b/provers/sgx/guest/src/one_shot.rs @@ -9,6 +9,7 @@ use anyhow::{anyhow, bail, Context, Error, Result}; use base64_serde::base64_serde_type; use raiko_lib::{ builder::{BlockBuilderStrategy, TaikoStrategy}, + input::GuestInput, protocol_instance::{assemble_protocol_instance, EvidenceType}, }; use raiko_primitives::Address; @@ -121,7 +122,9 @@ pub async fn one_shot(global_opts: GlobalOpts, args: OneShotArgs) -> Result<()> let new_pubkey = public_key(&prev_privkey); let new_instance = public_key_to_address(&new_pubkey); - let input = bincode::deserialize_from(std::io::stdin()).expect("unable to deserialize input"); + let input: GuestInput = + bincode::deserialize_from(std::io::stdin()).expect("unable to deserialize input"); + assert!(!input.taiko.skip_verify_blob); // Process the block let (header, _mpt_node) = diff --git a/provers/sgx/prover/src/lib.rs b/provers/sgx/prover/src/lib.rs index c7ea9ef2b..7b3c234ae 100644 --- a/provers/sgx/prover/src/lib.rs +++ b/provers/sgx/prover/src/lib.rs @@ -80,11 +80,17 @@ impl Prover for SgxProver { ); // The working directory - let cur_dir = env::current_exe() + let mut cur_dir = env::current_exe() .expect("Fail to get current directory") .parent() .unwrap() .to_path_buf(); + + // When running in tests we might be in a child folder + if cur_dir.ends_with("deps") { + cur_dir = cur_dir.parent().unwrap().to_path_buf(); + } + println!("Current directory: {cur_dir:?}\n"); // Working paths PRIVATE_KEY diff --git a/script/build.sh b/script/build.sh index 0c3333580..06eb06fca 100755 --- a/script/build.sh +++ b/script/build.sh @@ -1,15 +1,17 @@ #!/usr/bin/env bash +# Any error will result in failure +set -e + TOOLCHAIN_RISC0=+nightly-2024-02-06 TOOLCHAIN_SP1=+nightly-2024-02-06 TOOLCHAIN_SGX=+nightly-2024-02-06 - check_toolchain() { local TOOLCHAIN=$1 # Remove the plus sign from the toolchain name - TOOLCHAIN=${TOOLCHAIN#+} + TOOLCHAIN=${TOOLCHAIN#+} # Function to check if the toolchain is installed exist() { @@ -23,11 +25,11 @@ check_toolchain() { echo "Installing Rust toolchain: $TOOLCHAIN" rustup install "$TOOLCHAIN" fi -} +} if [ -z "${DEBUG}" ]; then FLAGS=--release -else +else echo "Warning: in debug mode" fi @@ -37,23 +39,53 @@ else COMMAND=run fi +# NATIVE +if [ -z "$1" ] || [ "$1" == "native" ]; then + if [ -z "${RUN}" ]; then + if [ -z "${TEST}" ]; then + echo "Building native prover" + cargo build ${FLAGS} + else + echo "Building native tests" + cargo test ${FLAGS} --no-run + fi + else + if [ -z "${TEST}" ]; then + echo "Running native prover" + cargo run ${FLAGS} + else + echo "Running native tests" + cargo test ${FLAGS} + fi + fi +fi + # SGX if [ -z "$1" ] || [ "$1" == "sgx" ]; then check_toolchain $TOOLCHAIN_SGX + if [ "$MOCK" = "1" ]; then + export SGX_DIRECT=1 + echo "SGX_DIRECT is set to $SGX_DIRECT" + fi if [ -z "${RUN}" ]; then if [ -z "${TEST}" ]; then + echo "Building SGX prover" cargo ${TOOLCHAIN_SGX} build ${FLAGS} --features sgx else - cargo ${TOOLCHAIN_SGX} test ${FLAGS} -p sgx-prover --features enable --no-run + echo "Building SGX tests" + cargo ${TOOLCHAIN_SGX} test ${FLAGS} -p raiko-host -p sgx-prover --features "sgx enable" --no-run fi else if [ -z "${TEST}" ]; then + echo "Running SGX prover" cargo ${TOOLCHAIN_SGX} run ${FLAGS} --features sgx else - cargo ${TOOLCHAIN_SGX} test ${FLAGS} -p sgx-prover --features enable + echo "Running SGX tests" + cargo ${TOOLCHAIN_SGX} test ${FLAGS} -p raiko-host -p sgx-prover --features "sgx enable" fi fi fi + # RISC0 if [ -z "$1" ] || [ "$1" == "risc0" ]; then check_toolchain $TOOLCHAIN_RISC0 @@ -77,7 +109,7 @@ if [ -z "$1" ] || [ "$1" == "risc0" ]; then cargo ${TOOLCHAIN_RISC0} run ${FLAGS} --features risc0 else echo "Running Sp1 tests" - RISC0_DEV_MODE=1 cargo ${TOOLCHAIN_RISC0} test ${FLAGS} -p risc0-driver --features enable + cargo ${TOOLCHAIN_RISC0} test ${FLAGS} -p raiko-host -p risc0-driver --features "risc0 enable" fi fi fi @@ -85,7 +117,7 @@ fi # SP1 if [ -z "$1" ] || [ "$1" == "sp1" ]; then check_toolchain $TOOLCHAIN_SP1 - if [ "$MOCK" = "1" ]; then + if [ "$MOCK" = "1" ]; then export SP1_PROVER=mock echo "SP1_PROVER is set to $SP1_PROVER" fi @@ -104,7 +136,7 @@ if [ -z "$1" ] || [ "$1" == "sp1" ]; then cargo ${TOOLCHAIN_SP1} run ${FLAGS} --features sp1 else echo "Running Sp1 tests" - cargo ${TOOLCHAIN_SP1} test ${FLAGS} -p sp1-driver --features enable + cargo ${TOOLCHAIN_SP1} test ${FLAGS} -p raiko-host -p sp1-driver --features "sp1 enable" fi fi fi \ No newline at end of file diff --git a/script/install.sh b/script/install.sh index 836b34377..a60b55b56 100755 --- a/script/install.sh +++ b/script/install.sh @@ -1,4 +1,6 @@ #!/usr/bin/env bash + +# Any error will result in failure set -e # toolchain necessary to compile c-kzg in SP1/risc0 diff --git a/script/prove-block.sh b/script/prove-block.sh index bdc780c05..5e72c7996 100755 --- a/script/prove-block.sh +++ b/script/prove-block.sh @@ -30,11 +30,11 @@ elif [ "$chain" == "holesky" ]; then rpc="https://ethereum-holesky-rpc.publicnode.com" elif [ "$chain" == "taiko_a6" ]; then rpc="https://rpc.katla.taiko.xyz" - l1Rpc="https://l1rpc.katla.taiko.xyz" + l1Rpc="https://ethereum-holesky-rpc.publicnode.com" beaconRpc="https://l1beacon.hekla.taiko.xyz" elif [ "$chain" == "taiko_a7" ]; then - rpc="https://rpc.hekla.taiko.xyz/" - l1Rpc="https://l1rpc.hekla.taiko.xyz/" + rpc="https://rpc.hekla.taiko.xyz" + l1Rpc="https://ethereum-holesky-rpc.publicnode.com" beaconRpc="https://l1beacon.hekla.taiko.xyz" else echo "Invalid chain name. Please use 'ethereum', 'taiko_a6' or 'taiko_a7'."