Skip to content

Commit 6d01946

Browse files
chore(refactor): separate openvm-continuations from SDK (#1447)
A refactor to split the security critical recursion programs necessary for the continuations framework outside of the SDK. The recursion programs are now in a separate `openvm-continuations` crate. I wanted to keep keygen together with the recursion programs, but that was too difficult to separate because the proving key types are very tied to the SDK, and also the requirement of a dummy proof ties keygen to some prover implementation. This is not ideal and could be reworked with more refactoring, which is out of scope for now. No major logic was changed. Most files changed are import changes. - The `static_verifier` module was split between `sdk/keygen` and `continuations/verifier`, with some minor changes to remove dependence on proving key in the verifier (which is weird for a verifier anyways). - `ContinuationVmProof` is moved into `openvm-circuit` crate to remove a dependency issue and also because it is core to the framework.
1 parent 18096f4 commit 6d01946

File tree

42 files changed

+413
-330
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+413
-330
lines changed

.github/workflows/recursion.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,8 @@ jobs:
4141
working-directory: extensions/native/recursion
4242
run: |
4343
cargo nextest run --features parallel,static-verifier
44+
45+
- name: Run continuations verifier crate tests
46+
working-directory: crates/continuations
47+
run: |
48+
cargo nextest run --no-tests=pass

Cargo.lock

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

Cargo.toml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ members = [
2525
"crates/toolchain/macros",
2626
"crates/toolchain/platform",
2727
"crates/toolchain/tests",
28+
"crates/continuations",
2829
"crates/vm",
2930
"extensions/rv32im/circuit",
3031
"extensions/rv32im/transpiler",
@@ -122,10 +123,11 @@ openvm-instructions-derive = { path = "crates/toolchain/instructions/derive", de
122123
openvm-macros-common = { path = "crates/toolchain/macros", default-features = false }
123124
openvm-platform = { path = "crates/toolchain/platform", default-features = false }
124125
openvm-transpiler = { path = "crates/toolchain/transpiler", default-features = false }
125-
openvm-circuit = { path = "crates/vm", default-features = false }
126-
openvm-circuit-derive = { path = "crates/vm/derive", default-features = false }
127126
openvm-toolchain-tests = { path = "crates/toolchain/tests", default-features = false }
128127
openvm-custom-insn = { path = "crates/toolchain/custom_insn", default-features = false }
128+
openvm-circuit = { path = "crates/vm", default-features = false }
129+
openvm-circuit-derive = { path = "crates/vm/derive", default-features = false }
130+
openvm-continuations = { path = "crates/continuations", default-features = false }
129131

130132
# Extensions
131133
openvm-rv32im-circuit = { path = "extensions/rv32im/circuit", default-features = false }

benchmarks/src/bin/fib_e2e.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use openvm_rv32im_transpiler::{
1010
Rv32ITranspilerExtension, Rv32IoTranspilerExtension, Rv32MTranspilerExtension,
1111
};
1212
use openvm_sdk::{
13-
commit::commit_app_exe, keygen::RootVerifierProvingKey, prover::ContinuationProver, Sdk, StdIn,
13+
commit::commit_app_exe, prover::ContinuationProver, DefaultStaticVerifierPvHandler, Sdk, StdIn,
1414
};
1515
use openvm_stark_sdk::bench::run_with_metric_collection;
1616
use openvm_transpiler::{transpiler::Transpiler, FromElf};
@@ -40,7 +40,7 @@ async fn main() -> Result<()> {
4040
let full_agg_pk = sdk.agg_keygen(
4141
agg_config,
4242
&halo2_params_reader,
43-
None::<&RootVerifierProvingKey>,
43+
&DefaultStaticVerifierPvHandler,
4444
)?;
4545
let elf = args.build_bench_program("fibonacci")?;
4646
let exe = VmExe::from_elf(

crates/cli/src/commands/setup.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@ use openvm_native_recursion::halo2::utils::CacheHalo2ParamsReader;
1111
use openvm_sdk::{
1212
config::AggConfig,
1313
fs::{write_agg_pk_to_file, write_evm_verifier_to_file},
14-
keygen::RootVerifierProvingKey,
15-
Sdk,
14+
DefaultStaticVerifierPvHandler, Sdk,
1615
};
1716

1817
use crate::default::{DEFAULT_AGG_PK_PATH, DEFAULT_PARAMS_DIR, DEFAULT_VERIFIER_PATH};
@@ -42,7 +41,7 @@ impl EvmProvingSetupCmd {
4241
let agg_config = AggConfig::default();
4342

4443
println!("Generating proving key...");
45-
let agg_pk = Sdk.agg_keygen(agg_config, &params_reader, None::<&RootVerifierProvingKey>)?;
44+
let agg_pk = Sdk.agg_keygen(agg_config, &params_reader, &DefaultStaticVerifierPvHandler)?;
4645

4746
println!("Generating verifier contract...");
4847
let verifier = Sdk.generate_snark_verifier_contract(&params_reader, &agg_pk)?;

crates/continuations/Cargo.toml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
[package]
2+
name = "openvm-continuations"
3+
version.workspace = true
4+
authors.workspace = true
5+
edition.workspace = true
6+
homepage.workspace = true
7+
repository.workspace = true
8+
license.workspace = true
9+
10+
[dependencies]
11+
openvm-native-circuit = { workspace = true }
12+
openvm-native-compiler = { workspace = true }
13+
openvm-native-recursion = { workspace = true, features = ["static-verifier"] }
14+
openvm-stark-backend = { workspace = true }
15+
openvm-stark-sdk = { workspace = true }
16+
openvm-circuit = { workspace = true }
17+
18+
derivative = { workspace = true }
19+
serde = { workspace = true }
20+
static_assertions.workspace = true
21+
22+
[features]
23+
default = ["parallel"]
24+
parallel = ["openvm-circuit/parallel"]
25+
test-utils = ["openvm-circuit/test-utils"]

crates/continuations/src/lib.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
use openvm_native_recursion::types::InnerConfig;
2+
use openvm_stark_sdk::{
3+
config::{
4+
baby_bear_poseidon2::BabyBearPoseidon2Config,
5+
baby_bear_poseidon2_root::BabyBearPoseidon2RootConfig,
6+
},
7+
p3_baby_bear::BabyBear,
8+
};
9+
10+
pub mod static_verifier;
11+
pub mod verifier;
12+
13+
pub type SC = BabyBearPoseidon2Config;
14+
pub type C = InnerConfig;
15+
pub type F = BabyBear;
16+
pub type RootSC = BabyBearPoseidon2RootConfig;
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
use openvm_circuit::arch::PROGRAM_CACHED_TRACE_INDEX;
2+
use openvm_native_compiler::prelude::*;
3+
use openvm_native_recursion::{
4+
challenger::multi_field32::MultiField32ChallengerVariable,
5+
config::outer::{new_from_outer_multi_vk, OuterConfig},
6+
digest::DigestVariable,
7+
fri::TwoAdicFriPcsVariable,
8+
halo2::DslOperations,
9+
stark::StarkVerifier,
10+
utils::const_fri_config,
11+
vars::StarkProofVariable,
12+
witness::Witnessable,
13+
};
14+
use openvm_stark_backend::keygen::types::MultiStarkVerifyingKey;
15+
use openvm_stark_sdk::{
16+
config::FriParameters, openvm_stark_backend::proof::Proof, p3_bn254_fr::Bn254Fr,
17+
};
18+
19+
use crate::{
20+
verifier::{
21+
common::{
22+
assert_single_segment_vm_exit_successfully_with_connector_air_id, types::SpecialAirIds,
23+
},
24+
root::types::RootVmVerifierPvs,
25+
utils::compress_babybear_var_to_bn254,
26+
},
27+
RootSC,
28+
};
29+
/// Custom public values handler for static verifier.
30+
/// This trait implementation defines what the public values of the
31+
/// final EVM proof will be.
32+
pub trait StaticVerifierPvHandler {
33+
/// Returns the number of public values, as [Bn254Fr] field elements.
34+
fn handle_public_values(
35+
&self,
36+
builder: &mut Builder<OuterConfig>,
37+
input: &StarkProofVariable<OuterConfig>,
38+
special_air_ids: &SpecialAirIds,
39+
) -> usize;
40+
}
41+
42+
pub struct DefaultStaticVerifierPvHandler;
43+
44+
impl StaticVerifierPvHandler for DefaultStaticVerifierPvHandler {
45+
fn handle_public_values(
46+
&self,
47+
builder: &mut Builder<OuterConfig>,
48+
input: &StarkProofVariable<OuterConfig>,
49+
special_air_ids: &SpecialAirIds,
50+
) -> usize {
51+
let pv_air = builder.get(&input.per_air, special_air_ids.public_values_air_id);
52+
let public_values: Vec<_> = pv_air
53+
.public_values
54+
.vec()
55+
.into_iter()
56+
.map(|x| builder.cast_felt_to_var(x))
57+
.collect();
58+
let pvs = RootVmVerifierPvs::from_flatten(public_values);
59+
let exe_commit = compress_babybear_var_to_bn254(builder, pvs.exe_commit);
60+
let leaf_commit = compress_babybear_var_to_bn254(builder, pvs.leaf_verifier_commit);
61+
let num_public_values = 2 + pvs.public_values.len();
62+
builder.static_commit_public_value(0, exe_commit);
63+
builder.static_commit_public_value(1, leaf_commit);
64+
for (i, x) in pvs.public_values.into_iter().enumerate() {
65+
builder.static_commit_public_value(i + 2, x);
66+
}
67+
num_public_values
68+
}
69+
}
70+
71+
/// Config to generate static verifier DSL operations.
72+
pub struct StaticVerifierConfig {
73+
pub root_verifier_fri_params: FriParameters,
74+
pub special_air_ids: SpecialAirIds,
75+
pub root_verifier_program_commit: [Bn254Fr; 1],
76+
}
77+
78+
impl StaticVerifierConfig {
79+
pub fn build_static_verifier_operations(
80+
&self,
81+
root_verifier_vk: &MultiStarkVerifyingKey<RootSC>,
82+
proof: &Proof<RootSC>,
83+
pv_handler: &impl StaticVerifierPvHandler,
84+
) -> DslOperations<OuterConfig> {
85+
let mut builder = Builder::<OuterConfig>::default();
86+
builder.flags.static_only = true;
87+
let num_public_values = {
88+
builder.cycle_tracker_start("VerifierProgram");
89+
let input = proof.read(&mut builder);
90+
self.verify_root_proof(&mut builder, root_verifier_vk, &input);
91+
92+
let num_public_values =
93+
pv_handler.handle_public_values(&mut builder, &input, &self.special_air_ids);
94+
builder.cycle_tracker_end("VerifierProgram");
95+
num_public_values
96+
};
97+
DslOperations {
98+
operations: builder.operations,
99+
num_public_values,
100+
}
101+
}
102+
103+
/// `root_verifier_vk` is the verifying key of the root verifier STARK circuit.
104+
/// `root_verifier_fri_params` are the FRI parameters used to prove the root
105+
/// verifier STARK circuit.
106+
fn verify_root_proof(
107+
&self,
108+
builder: &mut Builder<OuterConfig>,
109+
root_verifier_vk: &MultiStarkVerifyingKey<RootSC>,
110+
input: &StarkProofVariable<OuterConfig>,
111+
) {
112+
let advice = new_from_outer_multi_vk(root_verifier_vk);
113+
let pcs = TwoAdicFriPcsVariable {
114+
config: const_fri_config(builder, &self.root_verifier_fri_params),
115+
};
116+
StarkVerifier::verify::<MultiField32ChallengerVariable<_>>(builder, &pcs, &advice, input);
117+
{
118+
// Program AIR is the only AIR with a cached trace. The cached trace index doesn't
119+
// change after reordering.
120+
let t_id = RVar::from(PROGRAM_CACHED_TRACE_INDEX);
121+
let commit = builder.get(&input.commitments.main_trace, t_id);
122+
let commit = if let DigestVariable::Var(commit_arr) = commit {
123+
builder.get(&commit_arr, 0)
124+
} else {
125+
unreachable!()
126+
};
127+
builder.assert_var_eq(commit, self.root_verifier_program_commit[0]);
128+
}
129+
assert_single_segment_vm_exit_successfully_with_connector_air_id(
130+
builder,
131+
input,
132+
self.special_air_ids.connector_air_id,
133+
);
134+
}
135+
}

0 commit comments

Comments
 (0)