Skip to content

Commit a5550a9

Browse files
authored
feat: OpenVmHalo2Verifier (#1549)
This PR adds a new verifier contract generation that wraps the original `snark-verifier` output (via inheritance). The goal of this wrapper `OpenVmHalo2Verifier` is to expose a more friendly interface to users that cleanly separates out the guest program public values. `OpenVmHalo2Verifier` exposes the following interface: ```solidity interface IOpenVmHalo2Verifier { function verify(bytes calldata publicValues, bytes calldata proofData, bytes32 appExeCommit, bytes32 appVmCommit) external view; } ``` - `publicValues`: The bytes revealed in the OpenVM guest program packed together. - `proofData`: Defined as `abi.encodePacked(KZG accumulators, publicValuesSuffix)` - `appExeCommit`: The commitment to the OpenVM application executable whose execution is being verified. - `appVmCommit`: The commitment to the VM configuration (aka `leaf_exe_commit`) Once received, the proof is constructed into the format expected by `snark-verifier`. The expected format is `abi.encodePacked(proofData[0:0x180], appExeCommit, appVmExeCommit, publicValuesPayload, proofData[0x180:])` where `publicValuesPayload` is a memory payload with each byte in `publicValues` separated into its own `bytes32` word. Since `OpenVmHalo2Verifier` inherits the `snark-verifier` output, the proof is forwarded via self-call. ## Verifier Generation The smart contract is written as a template that does not compile in isolation. During generation, the OpenVM SDK will fill out the maximum amount of public values and the OpenVM version with which the generation happened. Given an output folder, the relevant contracts are written into the following folder structure: ``` halo2/ ├── interfaces/ │ └── IOpenVmHalo2Verifier.sol ├── OpenVmHalo2Verifier.sol ├── Halo2Verifier.sol ``` `cargo openvm setup` will now generate this output directly into the `~/.openvm/` dir. Closes INT-3710
1 parent a9f68e0 commit a5550a9

File tree

25 files changed

+2637
-78
lines changed

25 files changed

+2637
-78
lines changed

.github/workflows/sdk.yml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ jobs:
3939
- name: Install solc # svm should support arm64 linux
4040
run: (hash svm 2>/dev/null || cargo install --version 0.2.23 svm-rs) && svm install 0.8.19 && solc --version
4141

42+
- name: Install Foundry
43+
uses: foundry-rs/foundry-toolchain@v1
44+
4245
- name: Install architecture specific tools
4346
run: |
4447
arch=$(uname -m)
@@ -74,8 +77,24 @@ jobs:
7477
run: |
7578
bash ../../extensions/native/recursion/trusted_setup_s3.sh
7679
80+
- name: Run openvm-sdk contracts/ tests
81+
working-directory: crates/sdk/contracts
82+
run: |
83+
forge fmt --check
84+
forge build --sizes
85+
forge test
86+
87+
- name: Check IOpenVmHalo2Verifier.sol abi correctness
88+
working-directory: crates/sdk/contracts
89+
run: |
90+
forge build
91+
jq -S '.abi' ./out/IOpenVmHalo2Verifier.sol/IOpenVmHalo2Verifier.json > compiled_abi.json
92+
jq -S . ./abi/IOpenVmHalo2Verifier.json > expected_abi_sorted.json
93+
diff -u expected_abi_sorted.json compiled_abi.json
94+
7795
- name: Run openvm-sdk crate tests
7896
working-directory: crates/sdk
7997
run: |
8098
export RUST_BACKTRACE=1
8199
cargo nextest run --cargo-profile=fast --test-threads=2 --features parallel
100+

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
[submodule "toolchain/tests/rv32im-test-vectors/riscv-tests"]
22
path = crates/toolchain/tests/rv32im-test-vectors/riscv-tests
33
url = https://github.com/riscv-software-src/riscv-tests.git
4+
[submodule "crates/sdk/contracts/lib/forge-std"]
5+
path = crates/sdk/contracts/lib/forge-std
6+
url = https://github.com/foundry-rs/forge-std

Cargo.lock

Lines changed: 151 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,9 +184,12 @@ snark-verifier-sdk = { version = "0.2.0", default-features = false, features = [
184184
"loader_halo2",
185185
"halo2-axiom",
186186
] }
187+
snark-verifier = { version = "0.2.0", default-features = false }
187188
halo2curves-axiom = "0.7.0"
188189

189190
cargo_metadata = "0.18"
191+
alloy-primitives = "0.8.25"
192+
alloy-sol-types = "0.8.25"
190193
tracing = "0.1.40"
191194
bon = "3.2.0"
192195
serde_json = "1.0.117"

crates/cli/src/commands/build.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use std::{
2-
fs::{read, write},
2+
fs::{create_dir_all, read, write},
33
path::PathBuf,
44
};
55

@@ -146,6 +146,9 @@ pub(crate) fn build(build_args: &BuildArgs) -> Result<Option<PathBuf>> {
146146
let exe = Sdk::new().transpile(elf, transpiler)?;
147147
let committed_exe = commit_app_exe(app_config.app_fri_params.fri_params, exe.clone());
148148
write_exe_to_file(exe, output_path)?;
149+
if let Some(parent) = build_args.committed_exe_output.parent() {
150+
create_dir_all(parent)?;
151+
}
149152
write(
150153
&build_args.committed_exe_output,
151154
committed_exe_as_bn254(&committed_exe).value.to_bytes(),

crates/cli/src/commands/setup.rs

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@ use openvm_native_recursion::halo2::utils::CacheHalo2ParamsReader;
1111
use openvm_sdk::{
1212
config::AggConfig,
1313
fs::{
14-
write_agg_pk_to_file, write_evm_verifier_to_folder, EVM_VERIFIER_ARTIFACT_FILENAME,
15-
EVM_VERIFIER_SOL_FILENAME,
14+
write_agg_pk_to_file, write_evm_halo2_verifier_to_folder, EVM_HALO2_VERIFIER_BASE_NAME,
15+
EVM_HALO2_VERIFIER_INTERFACE_NAME, EVM_HALO2_VERIFIER_PARENT_NAME,
1616
},
1717
DefaultStaticVerifierPvHandler, Sdk,
1818
};
1919

20-
use crate::default::{DEFAULT_AGG_PK_PATH, DEFAULT_PARAMS_DIR, DEFAULT_VERIFIER_FOLDER};
20+
use crate::default::{DEFAULT_AGG_PK_PATH, DEFAULT_EVM_HALO2_VERIFIER_PATH, DEFAULT_PARAMS_DIR};
2121

2222
#[derive(Parser)]
2323
#[command(
@@ -29,11 +29,15 @@ pub struct EvmProvingSetupCmd {}
2929
impl EvmProvingSetupCmd {
3030
pub async fn run(&self) -> Result<()> {
3131
if PathBuf::from(DEFAULT_AGG_PK_PATH).exists()
32-
&& PathBuf::from(DEFAULT_VERIFIER_FOLDER)
33-
.join(EVM_VERIFIER_ARTIFACT_FILENAME)
32+
&& PathBuf::from(DEFAULT_EVM_HALO2_VERIFIER_PATH)
33+
.join(EVM_HALO2_VERIFIER_PARENT_NAME)
3434
.exists()
35-
&& PathBuf::from(DEFAULT_VERIFIER_FOLDER)
36-
.join(EVM_VERIFIER_SOL_FILENAME)
35+
&& PathBuf::from(DEFAULT_EVM_HALO2_VERIFIER_PATH)
36+
.join(EVM_HALO2_VERIFIER_BASE_NAME)
37+
.exists()
38+
&& PathBuf::from(DEFAULT_EVM_HALO2_VERIFIER_PATH)
39+
.join("interfaces")
40+
.join(EVM_HALO2_VERIFIER_INTERFACE_NAME)
3741
.exists()
3842
{
3943
println!("Aggregation proving key and verifier contract already exist");
@@ -53,13 +57,13 @@ impl EvmProvingSetupCmd {
5357
let agg_pk = sdk.agg_keygen(agg_config, &params_reader, &DefaultStaticVerifierPvHandler)?;
5458

5559
println!("Generating verifier contract...");
56-
let verifier = sdk.generate_snark_verifier_contract(&params_reader, &agg_pk)?;
60+
let verifier = sdk.generate_halo2_verifier_solidity(&params_reader, &agg_pk)?;
5761

5862
println!("Writing proving key to file...");
5963
write_agg_pk_to_file(agg_pk, DEFAULT_AGG_PK_PATH)?;
6064

6165
println!("Writing verifier contract to file...");
62-
write_evm_verifier_to_folder(verifier, DEFAULT_VERIFIER_FOLDER)?;
66+
write_evm_halo2_verifier_to_folder(verifier, DEFAULT_EVM_HALO2_VERIFIER_PATH)?;
6367

6468
Ok(())
6569
}

0 commit comments

Comments
 (0)