Integrate recursion into MainPod (#243)

* calculate MainPod id in a dynamic-friendly way

The MainPod id is now calculated with front padding and a fixed size
independent of max_public_statements so that introduction gadgets can be
verified by a MainPod while paying only for the number of statements
they use.  This is because with front padding of none-statements we can
precompute the poseidon state corresponding to absorbing all the padding
statements and only pay constraints for the non-padding statements.

The id is calculated as follows:
`id = hash(serialize(reverse(statements || none-statements)))`

* add time feature and disable timing by default

* apply suggestions from @arnaucube

* link issues in todos
This commit is contained in:
Eduard S. 2025-05-29 17:10:19 +02:00 committed by GitHub
parent d3fef8392e
commit 88a75986b8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
23 changed files with 1405 additions and 729 deletions

View file

@ -0,0 +1,93 @@
use itertools::Itertools;
use crate::{
backends::plonky2::{
basetypes::{Proof, VerifierOnlyCircuitData},
error::{Error, Result},
mainpod::{self, calculate_id},
},
middleware::{
AnchoredKey, DynError, Hash, Params, Pod, PodId, PodType, RecursivePod, Statement, Value,
KEY_TYPE, SELF,
},
};
#[derive(Clone, Debug)]
pub struct MockEmptyPod {
params: Params,
id: PodId,
}
fn type_statement() -> Statement {
Statement::ValueOf(
AnchoredKey::from((SELF, KEY_TYPE)),
Value::from(PodType::Empty),
)
}
impl MockEmptyPod {
pub fn new_boxed(params: &Params) -> Box<dyn RecursivePod> {
let statements = [mainpod::Statement::from(type_statement())];
let id = PodId(calculate_id(&statements, params));
Box::new(Self {
params: params.clone(),
id,
})
}
fn _verify(&self) -> Result<()> {
let statements = self
.pub_self_statements()
.into_iter()
.map(mainpod::Statement::from)
.collect_vec();
let id = PodId(calculate_id(&statements, &self.params));
if id != self.id {
return Err(Error::id_not_equal(self.id, id));
}
Ok(())
}
}
impl Pod for MockEmptyPod {
fn params(&self) -> &Params {
&self.params
}
fn verify(&self) -> Result<(), Box<DynError>> {
Ok(self._verify()?)
}
fn id(&self) -> PodId {
self.id
}
fn pub_self_statements(&self) -> Vec<Statement> {
vec![type_statement()]
}
fn serialized_proof(&self) -> String {
todo!()
}
}
impl RecursivePod for MockEmptyPod {
fn verifier_data(&self) -> VerifierOnlyCircuitData {
panic!("MockEmptyPod can't be verified in a recursive MainPod circuit");
}
fn proof(&self) -> Proof {
panic!("MockEmptyPod can't be verified in a recursive MainPod circuit");
}
fn vds_root(&self) -> Hash {
panic!("MockEmptyPod can't be verified in a recursive MainPod circuit");
}
}
#[cfg(test)]
pub mod tests {
use super::*;
#[test]
fn test_mock_empty_pod() {
let params = Params::default();
let empty_pod = MockEmptyPod::new_boxed(&params);
empty_pod.verify().unwrap();
}
}