Skip to content

Commit 906e765

Browse files
committed
Move E2eStarkProof to openvm-continuations crate
1 parent 00a2a74 commit 906e765

File tree

11 files changed

+336
-71
lines changed

11 files changed

+336
-71
lines changed

crates/cli/src/commands/setup.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@ use openvm_sdk::{
1717
DefaultStaticVerifierPvHandler, Sdk,
1818
};
1919

20-
use crate::default::{DEFAULT_AGG_PK_PATH, DEFAULT_EVM_HALO2_VERIFIER_PATH, DEFAULT_PARAMS_DIR};
20+
use crate::default::{
21+
DEFAULT_AGG_PK_PATH, DEFAULT_ASM_PATH, DEFAULT_EVM_HALO2_VERIFIER_PATH, DEFAULT_PARAMS_DIR,
22+
};
2123

2224
#[derive(Parser)]
2325
#[command(
@@ -56,12 +58,18 @@ impl EvmProvingSetupCmd {
5658
println!("Generating proving key...");
5759
let agg_pk = sdk.agg_keygen(agg_config, &params_reader, &DefaultStaticVerifierPvHandler)?;
5860

61+
println!("Generating root verifier ASM...");
62+
let root_verifier_asm = sdk.generate_root_verifier_asm(&agg_pk.agg_stark_pk);
63+
5964
println!("Generating verifier contract...");
6065
let verifier = sdk.generate_halo2_verifier_solidity(&params_reader, &agg_pk)?;
6166

6267
println!("Writing proving key to file...");
6368
write_agg_pk_to_file(agg_pk, DEFAULT_AGG_PK_PATH)?;
6469

70+
println!("Writing root verifier ASM to file...");
71+
write(DEFAULT_ASM_PATH, root_verifier_asm)?;
72+
6573
println!("Writing verifier contract to file...");
6674
write_evm_halo2_verifier_to_folder(verifier, DEFAULT_EVM_HALO2_VERIFIER_PATH)?;
6775

crates/cli/src/default.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use openvm_stark_sdk::config::FriParameters;
44
pub const DEFAULT_MANIFEST_DIR: &str = ".";
55

66
pub const DEFAULT_AGG_PK_PATH: &str = concat!(env!("HOME"), "/.openvm/agg.pk");
7+
pub const DEFAULT_ASM_PATH: &str = concat!(env!("HOME"), "/.openvm/root.asm");
78
pub const DEFAULT_PARAMS_DIR: &str = concat!(env!("HOME"), "/.openvm/params/");
89

910
pub const DEFAULT_EVM_HALO2_VERIFIER_PATH: &str = concat!(env!("HOME"), "/.openvm/halo2/");

crates/continuations/src/verifier/internal/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use crate::{
2121
};
2222

2323
pub mod types;
24-
mod vars;
24+
pub mod vars;
2525

2626
/// Config to generate internal VM verifier program.
2727
pub struct InternalVmVerifierConfig {

crates/continuations/src/verifier/internal/vars.rs

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,11 @@ use openvm_native_recursion::{hints::Hintable, vars::StarkProofVariable};
55
use openvm_stark_sdk::openvm_stark_backend::proof::Proof;
66

77
use crate::{
8-
verifier::{internal::types::InternalVmVerifierInput, utils::write_field_slice},
9-
C, SC,
8+
verifier::{
9+
internal::types::{E2eStarkProof, InternalVmVerifierInput},
10+
utils::write_field_slice,
11+
},
12+
C, F, SC,
1013
};
1114

1215
#[derive(DslVariable, Clone)]
@@ -16,6 +19,12 @@ pub struct InternalVmVerifierInputVariable<C: Config> {
1619
pub proofs: Array<C, StarkProofVariable<C>>,
1720
}
1821

22+
#[derive(DslVariable, Clone)]
23+
pub struct E2eStarkProofVariable<C: Config> {
24+
pub proof: StarkProofVariable<C>,
25+
pub user_public_values: Array<C, Felt<C::F>>,
26+
}
27+
1928
impl Hintable<C> for InternalVmVerifierInput<SC> {
2029
type HintVariable = InternalVmVerifierInputVariable<C>;
2130

@@ -34,3 +43,22 @@ impl Hintable<C> for InternalVmVerifierInput<SC> {
3443
stream
3544
}
3645
}
46+
47+
impl Hintable<C> for E2eStarkProof<SC> {
48+
type HintVariable = E2eStarkProofVariable<C>;
49+
50+
fn read(builder: &mut Builder<C>) -> Self::HintVariable {
51+
let proof = Proof::<SC>::read(builder);
52+
let user_public_values = Vec::<F>::read(builder);
53+
Self::HintVariable {
54+
proof,
55+
user_public_values,
56+
}
57+
}
58+
59+
fn write(&self) -> Vec<Vec<<C as Config>::N>> {
60+
let mut stream = self.proof.write();
61+
stream.extend(self.user_public_values.write());
62+
stream
63+
}
64+
}

crates/continuations/src/verifier/root/mod.rs

Lines changed: 152 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
use std::array;
22

33
use openvm_circuit::arch::instructions::program::Program;
4-
use openvm_native_compiler::{conversion::CompilerOptions, prelude::*};
4+
use openvm_native_compiler::{asm::HEAP_START_ADDRESS, conversion::CompilerOptions, prelude::*};
55
use openvm_native_recursion::{
66
fri::TwoAdicFriPcsVariable, hints::Hintable, types::new_from_inner_multi_vk,
77
utils::const_fri_config,
88
};
9+
use openvm_stark_backend::proof::Proof;
910
use openvm_stark_sdk::{
1011
config::FriParameters,
1112
openvm_stark_backend::{keygen::types::MultiStarkVerifyingKey, p3_field::FieldAlgebra},
@@ -30,7 +31,7 @@ mod vars;
3031
pub struct RootVmVerifierConfig {
3132
pub leaf_fri_params: FriParameters,
3233
pub internal_fri_params: FriParameters,
33-
pub num_public_values: usize,
34+
pub num_user_public_values: usize,
3435
pub internal_vm_verifier_commit: [F; DIGEST_SIZE],
3536
pub compiler_options: CompilerOptions,
3637
}
@@ -40,73 +41,163 @@ impl RootVmVerifierConfig {
4041
leaf_vm_vk: &MultiStarkVerifyingKey<SC>,
4142
internal_vm_vk: &MultiStarkVerifyingKey<SC>,
4243
) -> Program<F> {
43-
let leaf_advice = new_from_inner_multi_vk(leaf_vm_vk);
44-
let internal_advice = new_from_inner_multi_vk(internal_vm_vk);
4544
let mut builder = Builder::<C>::default();
4645

47-
{
48-
builder.cycle_tracker_start("ReadProofsFromInput");
49-
let RootVmVerifierInputVariable {
46+
builder.cycle_tracker_start("ReadProofsFromInput");
47+
let root_verifier_input = RootVmVerifierInput::<SC>::read(&mut builder);
48+
builder.cycle_tracker_end("ReadProofsFromInput");
49+
let pvs = self.verifier_impl(
50+
&mut builder,
51+
leaf_vm_vk,
52+
internal_vm_vk,
53+
root_verifier_input,
54+
);
55+
pvs.flatten()
56+
.into_iter()
57+
.for_each(|v| builder.commit_public_value(v));
58+
builder.halt();
59+
builder.compile_isa_with_options(self.compiler_options)
60+
}
61+
62+
/// Build instructions which can be called as a kernel function in RISC-V guest programs.
63+
/// Inputs for generated instructions:
64+
/// - expected `app_exe_commit`, `app_vm_commit` and user public values should be stored from
65+
/// `HEAP_START_ADDRESS` in the native address space .
66+
///
67+
/// These instructions take a proof from the input stream and verify the proof. Then these
68+
/// instructions check if the public values are consistent with the expected public values
69+
/// from RISC-V guest programs.
70+
pub fn build_kernel_asm(
71+
&self,
72+
leaf_vm_vk: &MultiStarkVerifyingKey<SC>,
73+
internal_vm_vk: &MultiStarkVerifyingKey<SC>,
74+
) -> Program<F> {
75+
let mut builder = Builder::<C>::default();
76+
77+
const BYTE_PER_WORD: usize = 4;
78+
let num_public_values = self.num_user_public_values + DIGEST_SIZE * 2;
79+
let num_bytes = num_public_values * BYTE_PER_WORD;
80+
// Move heap pointer in order to keep input arguments from address space 2.
81+
let heap_addr: Var<F> = builder.eval(F::from_canonical_u32(
82+
HEAP_START_ADDRESS as u32 + num_bytes as u32,
83+
));
84+
builder.store_heap_ptr(Ptr { address: heap_addr });
85+
let expected_pvs: Vec<Felt<_>> = (0..num_public_values)
86+
.map(|i| {
87+
let fs: [Felt<_>; BYTE_PER_WORD] = array::from_fn(|j| {
88+
let ptr = Ptr {
89+
address: builder.eval(F::from_canonical_u32(
90+
HEAP_START_ADDRESS as u32 + (i * 4) as u32,
91+
)),
92+
};
93+
let idx = MemIndex {
94+
index: RVar::from(j),
95+
offset: 0,
96+
size: 1,
97+
};
98+
let f = Felt::uninit(&mut builder);
99+
f.load(ptr, idx, &mut builder);
100+
f
101+
});
102+
builder.eval(
103+
fs[0]
104+
+ fs[1] * F::from_canonical_u32(1 << 8)
105+
+ fs[2] * F::from_canonical_u32(1 << 16)
106+
+ fs[3] * F::from_canonical_u32(1 << 24),
107+
)
108+
})
109+
.collect();
110+
let expected_pvs = RootVmVerifierPvs::<Felt<F>>::from_flatten(expected_pvs);
111+
let user_pvs = builder.array(self.num_user_public_values);
112+
for (i, &pv) in expected_pvs.public_values.iter().enumerate() {
113+
builder.set(&user_pvs, i, pv);
114+
}
115+
116+
builder.cycle_tracker_start("ReadFromStdin");
117+
let proof = Proof::<SC>::read(&mut builder);
118+
builder.cycle_tracker_end("ReadFromStdin");
119+
let proofs = builder.array(1);
120+
builder.set(&proofs, 0, proof);
121+
let pvs = self.verifier_impl(
122+
&mut builder,
123+
leaf_vm_vk,
124+
internal_vm_vk,
125+
RootVmVerifierInputVariable {
50126
proofs,
51-
public_values,
52-
} = RootVmVerifierInput::<SC>::read(&mut builder);
53-
builder.cycle_tracker_end("ReadProofsFromInput");
54-
builder.cycle_tracker_start("InitializePcsConst");
55-
let leaf_pcs = TwoAdicFriPcsVariable {
56-
config: const_fri_config(&mut builder, &self.leaf_fri_params),
57-
};
58-
let internal_pcs = TwoAdicFriPcsVariable {
59-
config: const_fri_config(&mut builder, &self.internal_fri_params),
60-
};
61-
builder.cycle_tracker_end("InitializePcsConst");
62-
builder.cycle_tracker_start("VerifyProofs");
63-
let internal_program_commit =
64-
array::from_fn(|i| builder.eval(self.internal_vm_verifier_commit[i]));
65-
let non_leaf_verifier = NonLeafVerifierVariables {
66-
internal_program_commit,
67-
leaf_pcs,
68-
leaf_advice,
69-
internal_pcs,
70-
internal_advice,
71-
};
72-
let (merged_pvs, expected_leaf_commit) =
73-
non_leaf_verifier.verify_internal_or_leaf_verifier_proofs(&mut builder, &proofs);
74-
builder.cycle_tracker_end("VerifyProofs");
127+
public_values: user_pvs,
128+
},
129+
);
130+
builder.assert_eq::<[Felt<_>; DIGEST_SIZE]>(pvs.exe_commit, expected_pvs.exe_commit);
131+
builder.assert_eq::<[Felt<_>; DIGEST_SIZE]>(
132+
pvs.leaf_verifier_commit,
133+
expected_pvs.leaf_verifier_commit,
134+
);
135+
136+
builder.compile_isa_with_options(self.compiler_options)
137+
}
138+
139+
fn verifier_impl(
140+
&self,
141+
builder: &mut Builder<C>,
142+
leaf_vm_vk: &MultiStarkVerifyingKey<SC>,
143+
internal_vm_vk: &MultiStarkVerifyingKey<SC>,
144+
root_verifier_input: RootVmVerifierInputVariable<C>,
145+
) -> RootVmVerifierPvs<Felt<F>> {
146+
let leaf_advice = new_from_inner_multi_vk(leaf_vm_vk);
147+
let internal_advice = new_from_inner_multi_vk(internal_vm_vk);
148+
let RootVmVerifierInputVariable {
149+
proofs,
150+
public_values,
151+
} = root_verifier_input;
75152

76-
// App Program should terminate
77-
builder.assert_felt_eq(merged_pvs.connector.is_terminate, F::ONE);
78-
// App Program should exit successfully
79-
builder.assert_felt_eq(merged_pvs.connector.exit_code, F::ZERO);
153+
builder.cycle_tracker_start("InitializePcsConst");
154+
let leaf_pcs = TwoAdicFriPcsVariable {
155+
config: const_fri_config(builder, &self.leaf_fri_params),
156+
};
157+
let internal_pcs = TwoAdicFriPcsVariable {
158+
config: const_fri_config(builder, &self.internal_fri_params),
159+
};
160+
builder.cycle_tracker_end("InitializePcsConst");
161+
builder.cycle_tracker_start("VerifyProofs");
162+
let internal_program_commit =
163+
array::from_fn(|i| builder.eval(self.internal_vm_verifier_commit[i]));
164+
let non_leaf_verifier = NonLeafVerifierVariables {
165+
internal_program_commit,
166+
leaf_pcs,
167+
leaf_advice,
168+
internal_pcs,
169+
internal_advice,
170+
};
171+
let (merged_pvs, expected_leaf_commit) =
172+
non_leaf_verifier.verify_internal_or_leaf_verifier_proofs(builder, &proofs);
173+
builder.cycle_tracker_end("VerifyProofs");
80174

81-
builder.cycle_tracker_start("ExtractPublicValues");
82-
builder.assert_usize_eq(public_values.len(), RVar::from(self.num_public_values));
83-
let public_values_vec: Vec<Felt<F>> = (0..self.num_public_values)
84-
.map(|i| builder.get(&public_values, i))
85-
.collect();
86-
let hasher = VariableP2Hasher::new(&mut builder);
87-
let pv_commit = hasher.merkle_root(&mut builder, &public_values_vec);
88-
builder.assert_eq::<[_; DIGEST_SIZE]>(merged_pvs.public_values_commit, pv_commit);
89-
builder.cycle_tracker_end("ExtractPublicValues");
175+
// App Program should terminate
176+
builder.assert_felt_eq(merged_pvs.connector.is_terminate, F::ONE);
177+
// App Program should exit successfully
178+
builder.assert_felt_eq(merged_pvs.connector.exit_code, F::ZERO);
90179

91-
let pvs = RootVmVerifierPvs {
92-
exe_commit: compute_exe_commit(
93-
&mut builder,
94-
&hasher,
95-
merged_pvs.app_commit,
96-
merged_pvs.memory.initial_root,
97-
merged_pvs.connector.initial_pc,
98-
),
99-
leaf_verifier_commit: expected_leaf_commit,
100-
public_values: public_values_vec,
101-
};
102-
pvs.flatten()
103-
.into_iter()
104-
.for_each(|v| builder.commit_public_value(v));
180+
builder.cycle_tracker_start("ExtractPublicValues");
181+
builder.assert_usize_eq(public_values.len(), RVar::from(self.num_user_public_values));
182+
let public_values_vec: Vec<Felt<F>> = (0..self.num_user_public_values)
183+
.map(|i| builder.get(&public_values, i))
184+
.collect();
185+
let hasher = VariableP2Hasher::new(builder);
186+
let pv_commit = hasher.merkle_root(builder, &public_values_vec);
187+
builder.assert_eq::<[_; DIGEST_SIZE]>(merged_pvs.public_values_commit, pv_commit);
188+
builder.cycle_tracker_end("ExtractPublicValues");
105189

106-
builder.halt();
190+
RootVmVerifierPvs {
191+
exe_commit: compute_exe_commit(
192+
builder,
193+
&hasher,
194+
merged_pvs.app_commit,
195+
merged_pvs.memory.initial_root,
196+
merged_pvs.connector.initial_pc,
197+
),
198+
leaf_verifier_commit: expected_leaf_commit,
199+
public_values: public_values_vec,
107200
}
108-
109-
builder.compile_isa_with_options(self.compiler_options)
110201
}
111202
}
112203

0 commit comments

Comments
 (0)