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

@ -1,45 +1,30 @@
// TODO: Update this doc
//! This file exposes the backend dependent basetypes as middleware types,
//! taking them from the feature-enabled backend.
//! This file exposes the imported backend dependent basetypes as middleware types, taking them
//! from the feature-enabled backend.
//!
//! This is done in order to avoid inconsistencies where a type or parameter is
//! defined in the middleware to have certain carachteristic and later in the
//! backend it gets used differently. The idea is that those types and
//! parameters (eg. lengths) have a single source of truth in the code; and in
//! the case of the "base types" this is determined by the backend being used
//! under the hood, not by a choice of the middleware parameters.
//! This is done in order to avoid inconsistencies where a type or parameter is defined in the
//! middleware to have certain carachteristic and later in the backend it gets used differently.
//! The idea is that those types and parameters (eg. lengths) have a single source of truth in the
//! code; and in the case of the "base types" this is determined by the backend being used under
//! the hood, not by a choice of the middleware parameters.
//!
//! The idea with this approach, is that the frontend & middleware should not
//! need to import the proving library used by the backend (eg. plonky2,
//! plonky3, etc).
//! The idea with this approach, is that the frontend & middleware should not need to import the
//! proving library used by the backend (eg. plonky2, plonky3, etc).
//!
//! For example, the `Hash` and `Value` types are types belonging at the
//! middleware, and is the middleware who reasons about them, but depending on
//! the backend being used, the `Hash` and `Value` types will have different
//! sizes. So it's the backend being used who actually defines their nature
//! under the hood. For example with a plonky2 backend, these types will have a
//! length of 4 field elements, whereas with a plonky3 backend they will have a
//! length of 8 field eleements.
//! For example, the `Hash` and `Value` types are types belonging at the middleware, and is the
//! middleware who reasons about them, but depending on the backend being used, the `Hash` and
//! `Value` types will have different sizes. So it's the backend being used who actually defines
//! their nature under the hood. For example with a plonky2 backend, these types will have a length
//! of 4 field elements, whereas with a plonky3 backend they will have a length of 8 field
//! eleements.
//!
//! Note that his approach does not introduce new traits or abstract code,
//! just makes use of rust features to define 'base types' that are being used
//! in the middleware.
//! Note that his approach does not introduce new traits or abstract code, just makes use of rust
//! features to define 'base types' that are being used in the middleware.
//!
//!
//! NOTE (TMP): current implementation still uses plonky2 in the middleware for
//! u64/i64 to F conversion. Eventually we will do those conversions through the
//! approach described in this file, removing the imports of plonky2 in the
//! middleware.
//! TODO: Update this doc
//! NOTE (TMP): current implementation still uses plonky2 in the middleware for u64/i64 to F
//! conversion. Eventually we will do those conversions through the approach described in this
//! file, removing the imports of plonky2 in the middleware.
/// Value, Hash and F are imported based on 'features'. For example by default
/// we use the 'plonky2' feature, but it could be used a 'plonky3' feature, so
/// then the Value, Hash and F types would come from the plonky3 backend.
// #[cfg(feature = "backend_plonky2")]
// pub use crate::backends::plonky2::basetypes::{
// hash_fields, hash_str, hash_value, Hash, RawValue, EMPTY_HASH, EMPTY_VALUE, F, HASH_SIZE,
// SELF_ID_HASH, VALUE_SIZE,
// };
use std::{
cmp::{Ord, Ordering},
fmt,
@ -47,10 +32,7 @@ use std::{
use hex::{FromHex, FromHexError};
use plonky2::{
field::{
goldilocks_field::GoldilocksField,
types::{Field, PrimeField64},
},
field::types::{Field, PrimeField64},
hash::poseidon::PoseidonHash,
plonk::config::Hasher,
};
@ -58,11 +40,14 @@ use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use super::serialization::*;
// Plonky2 specific types.
// Value, Hash, F and other types are imported based on 'features'. For example by default we use
// theg'plonky2' feature, but it could be used a 'plonky3' feature, so then the Value, Hash and F
// types would come from the plonky3 backend.
#[cfg(feature = "backend_plonky2")]
pub use crate::backends::plonky2::basetypes::*;
use crate::middleware::{Params, ToFields, Value};
/// F is the native field we use everywhere. Currently it's Goldilocks from plonky2
pub type F = GoldilocksField;
pub const HASH_SIZE: usize = 4;
pub const VALUE_SIZE: usize = 4;