From 3b4edab1f5f4a61952dbdd9b7a14ad88467e5c19 Mon Sep 17 00:00:00 2001 From: "Eduard S." Date: Fri, 13 Jun 2025 10:14:15 +0200 Subject: [PATCH] remove NonePod and use dummy signed pods (#272) * remove NonePod and use dummy signed pods * apply suggestion by @arnaucube --- src/backends/plonky2/circuits/mainpod.rs | 7 ++---- src/backends/plonky2/emptypod.rs | 7 ++++-- src/backends/plonky2/mainpod/mod.rs | 19 +++++++++------ src/backends/plonky2/mock/signedpod.rs | 9 +++++++ src/backends/plonky2/signedpod.rs | 31 +++++++++++++++++++++--- src/middleware/mod.rs | 30 ----------------------- 6 files changed, 54 insertions(+), 49 deletions(-) diff --git a/src/backends/plonky2/circuits/mainpod.rs b/src/backends/plonky2/circuits/mainpod.rs index 685f065..1f8939c 100644 --- a/src/backends/plonky2/circuits/mainpod.rs +++ b/src/backends/plonky2/circuits/mainpod.rs @@ -1464,12 +1464,9 @@ impl InnerCircuit for MainPodVerifyTarget { } // Padding if input.signed_pods.len() != self.params.max_input_signed_pods { - // TODO: Instead of using an input for padding, use a canonical minimal SignedPod, - // without it a MainPod configured to support input signed pods must have at least one - // input signed pod :( - let pad_pod = &input.signed_pods[0]; + let dummy = SignedPod::dummy(); for i in input.signed_pods.len()..self.params.max_input_signed_pods { - self.signed_pods[i].set_targets(pw, pad_pod)?; + self.signed_pods[i].set_targets(pw, &dummy)?; } } diff --git a/src/backends/plonky2/emptypod.rs b/src/backends/plonky2/emptypod.rs index 20ff0ef..21ba8c9 100644 --- a/src/backends/plonky2/emptypod.rs +++ b/src/backends/plonky2/emptypod.rs @@ -1,4 +1,7 @@ -use std::{collections::HashMap, sync::Mutex}; +use std::{ + collections::HashMap, + sync::{LazyLock, Mutex}, +}; use itertools::Itertools; use plonky2::{ @@ -23,7 +26,7 @@ use crate::{ error::{Error, Result}, mainpod::{self, calculate_id}, recursion::pad_circuit, - serialize_proof, LazyLock, DEFAULT_PARAMS, STANDARD_REC_MAIN_POD_CIRCUIT_DATA, + serialize_proof, DEFAULT_PARAMS, STANDARD_REC_MAIN_POD_CIRCUIT_DATA, }, middleware::{ self, AnchoredKey, DynError, Hash, Params, Pod, PodId, PodType, RecursivePod, Statement, diff --git a/src/backends/plonky2/mainpod/mod.rs b/src/backends/plonky2/mainpod/mod.rs index 74126a1..db3e801 100644 --- a/src/backends/plonky2/mainpod/mod.rs +++ b/src/backends/plonky2/mainpod/mod.rs @@ -18,7 +18,7 @@ use crate::{ deserialize_proof, emptypod::EmptyPod, error::{Error, Result}, - mock::emptypod::MockEmptyPod, + mock::{emptypod::MockEmptyPod, signedpod::MockSignedPod}, primitives::merkletree::MerkleClaimAndProof, recursion::{RecursiveCircuit, RecursiveParams}, serialize_proof, @@ -27,8 +27,8 @@ use crate::{ }, middleware::{ self, resolve_wildcard_values, AnchoredKey, CustomPredicateBatch, DynError, Hash, - MainPodInputs, NativeOperation, NonePod, OperationType, Params, Pod, PodId, PodProver, - PodType, RecursivePod, StatementArg, ToFields, VDSet, F, KEY_TYPE, SELF, + MainPodInputs, NativeOperation, OperationType, Params, Pod, PodId, PodProver, PodType, + RecursivePod, StatementArg, ToFields, VDSet, F, KEY_TYPE, SELF, }, }; @@ -257,13 +257,16 @@ pub(crate) fn layout_statements( statements.push(middleware::Statement::None.into()); // Input signed pods region - // TODO: Replace this with a dumb signed pod - // https://github.com/0xPARC/pod2/issues/246 - let none_sig_pod_box: Box = Box::new(NonePod {}); - let none_sig_pod = none_sig_pod_box.as_ref(); + let dummy_signed_pod_box: Box = + if mock || inputs.signed_pods.len() == params.max_input_signed_pods { + Box::new(MockSignedPod::dummy()) + } else { + Box::new(SignedPod::dummy()) + }; + let dummy_signed_pod = dummy_signed_pod_box.as_ref(); assert!(inputs.signed_pods.len() <= params.max_input_signed_pods); for i in 0..params.max_input_signed_pods { - let pod = inputs.signed_pods.get(i).unwrap_or(&none_sig_pod); + let pod = inputs.signed_pods.get(i).unwrap_or(&dummy_signed_pod); let sts = pod.pub_statements(); assert!(sts.len() <= params.max_signed_pod_values); for j in 0..params.max_signed_pod_values { diff --git a/src/backends/plonky2/mock/signedpod.rs b/src/backends/plonky2/mock/signedpod.rs index 2a1735d..3ac05d0 100644 --- a/src/backends/plonky2/mock/signedpod.rs +++ b/src/backends/plonky2/mock/signedpod.rs @@ -120,6 +120,15 @@ impl MockSignedPod { kvs: data.kvs, })) } + /// Generate a valid MockSignedPod with a public deterministic public key and no other + /// key-values than the default ones. This is used for padding. + pub fn dummy() -> MockSignedPod { + MockSigner { + pk: "dummy".to_string(), + } + ._sign(&Params::default(), &HashMap::new()) + .expect("valid") + } } impl Pod for MockSignedPod { diff --git a/src/backends/plonky2/signedpod.rs b/src/backends/plonky2/signedpod.rs index f5d8db1..975e836 100644 --- a/src/backends/plonky2/signedpod.rs +++ b/src/backends/plonky2/signedpod.rs @@ -1,7 +1,7 @@ -use std::collections::HashMap; +use std::{collections::HashMap, sync::LazyLock}; use itertools::Itertools; -use num_bigint::RandBigInt; +use num_bigint::{BigUint, RandBigInt}; use rand::rngs::OsRng; use serde::{Deserialize, Serialize}; @@ -28,7 +28,12 @@ use crate::{ pub struct Signer(pub SecretKey); impl Signer { - fn _sign(&mut self, params: &Params, kvs: &HashMap) -> Result { + fn sign_with_nonce( + &mut self, + params: &Params, + nonce: BigUint, + kvs: &HashMap, + ) -> Result { let mut kvs = kvs.clone(); let pubkey = self.0.public_key(); kvs.insert(Key::from(KEY_SIGNER), Value::from(pubkey)); @@ -37,7 +42,6 @@ impl Signer { let dict = Dictionary::new(params.max_depth_mt_containers, kvs)?; let id = RawValue::from(dict.commitment()); // PodId as Value - let nonce = OsRng.gen_biguint_below(&GROUP_ORDER); let signature: Signature = self.0.sign(id, &nonce); Ok(SignedPod { id: PodId(Hash::from(id)), @@ -46,6 +50,10 @@ impl Signer { dict, }) } + fn _sign(&mut self, params: &Params, kvs: &HashMap) -> Result { + let nonce = OsRng.gen_biguint_below(&GROUP_ORDER); + self.sign_with_nonce(params, nonce, kvs) + } pub fn public_key(&self) -> Point { self.0.public_key() @@ -77,6 +85,15 @@ struct Data { kvs: Dictionary, } +static DUMMY_POD: LazyLock = LazyLock::new(dummy); + +fn dummy() -> SignedPod { + let nonce = BigUint::from(2u32); + Signer(SecretKey(BigUint::from(1u32))) + .sign_with_nonce(&Params::default(), nonce, &HashMap::new()) + .expect("valid") +} + impl SignedPod { fn _verify(&self) -> Result<()> { // 1. Verify type @@ -142,6 +159,12 @@ impl SignedPod { dict: data.kvs, })) } + + /// Generate a valid SignedPod with a public deterministic secret key and nonce and no other + /// key-values than the default ones. This is used for padding. + pub fn dummy() -> SignedPod { + DUMMY_POD.clone() + } } impl Pod for SignedPod { diff --git a/src/middleware/mod.rs b/src/middleware/mod.rs index 6b1cc3f..dc3247a 100644 --- a/src/middleware/mod.rs +++ b/src/middleware/mod.rs @@ -599,7 +599,6 @@ impl ToFields for PodId { #[derive(Clone, Copy, Debug, PartialEq, Eq, FromRepr, Serialize, Deserialize, JsonSchema)] pub enum PodType { - None = 0, MockSigned = 1, MockMain = 2, MockEmpty = 3, @@ -611,7 +610,6 @@ pub enum PodType { impl fmt::Display for PodType { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - PodType::None => write!(f, "None"), PodType::MockSigned => write!(f, "MockSigned"), PodType::MockMain => write!(f, "MockMain"), PodType::MockEmpty => write!(f, "MockEmpty"), @@ -837,34 +835,6 @@ pub trait PodSigner { ) -> Result, Box>; } -// TODO: Delete once we have a fully working EmptyPod and a dumb SignedPod -// https://github.com/0xPARC/pod2/issues/246 -/// This is a filler type that fulfills the Pod trait and always verifies. It's empty. This -/// can be used to simulate padding in a circuit. -#[derive(Debug, Clone)] -pub struct NonePod {} - -impl Pod for NonePod { - fn params(&self) -> &Params { - panic!("NonePod doesn't have params"); - } - fn verify(&self) -> Result<(), Box> { - Ok(()) - } - fn id(&self) -> PodId { - PodId(EMPTY_HASH) - } - fn pod_type(&self) -> (usize, &'static str) { - (PodType::None as usize, "None") - } - fn pub_self_statements(&self) -> Vec { - Vec::new() - } - fn serialize_data(&self) -> serde_json::Value { - serde_json::Value::Null - } -} - #[derive(Debug)] pub struct MainPodInputs<'a> { pub signed_pods: &'a [&'a dyn Pod],