Add versioning features (#387)
- Add a function to calculate the hash of the `CommonCircuitData`. The hash uniquely identify the `CommonCircuitData` used for a circuit/proof. Serializing the struct is not enough because the polynomial identities of the custom gates are not serialized (only their parameters are); so I made a function to extract "fingerprints" of the custom gates by evaluating them over a predefined list of uniform values, and then doing a random linear combination over the results.
- Store the full verifier only circuit data of a proof in the MainPod so that we can verify pods from old circuits in new circuits and code
- Store the hash of the `CommonCircuitData` in the MainPod so that we can reject verifying old pods that use a different `CommonCircuitData` than the current one. This has two goals
- If the `CommonCircuitData` changes it's very likely that the verification will fail, but it will be hard to debug. Doing this early check helps identify the origin of the verification failure as early as possible
- There's a chance that the verification could succeed when the `CommonCircuitData` changes, and that could be dangerous because the verification will be doing different checks than the ones intended for the original proof, so we may be skipping some constraints that could lead to exploiting the system. For this reason, whenever the common circuit data hash changes, all previous verifying keys should be discarded (that is, not included in the VDSet)
- The fingerprint only has ~64 bits and the "random evaluation point" is fixed. The assumption is that the pod developers are not malicious and are not changing the gates such that different gates give the same fingerprint. With this assumption, I find it reasonable to assume that with high probability if a gate changes, its fingerprint changes as well.
- Add a github action that updates a wiki page with a table that contains: date, commit, params hash (with a link to the actual params), verifier data only circuit data hash and common circuit data hash. This will make it easy to track when the common circuit data changes as well as track the verifier data corresponding to various versions (identified by commit)
- The edited page is this one https://github.com/0xPARC/pod2/wiki/MainPod-circuit-info
Resolve https://github.com/0xPARC/pod2/issues/386
Summary of breaking changes:
- The `RecursivePod` trait has a new method `common_hash` that needs to return the result of `hash_common_data` on the `CommonCircuitData` that the circuit uses.
This commit is contained in:
parent
594c4d2e63
commit
656cae77e0
12 changed files with 357 additions and 27 deletions
|
|
@ -18,12 +18,15 @@ use crate::{
|
|||
common::{Flattenable, StatementTarget},
|
||||
mainpod::{calculate_id_circuit, PI_OFFSET_ID},
|
||||
},
|
||||
deserialize_proof,
|
||||
deserialize_proof, deserialize_verifier_only,
|
||||
error::{Error, Result},
|
||||
hash_common_data,
|
||||
mainpod::{self, calculate_id},
|
||||
recursion::pad_circuit,
|
||||
serialization::{CircuitDataSerializer, VerifierCircuitDataSerializer},
|
||||
serialize_proof,
|
||||
serialization::{
|
||||
CircuitDataSerializer, VerifierCircuitDataSerializer, VerifierOnlyCircuitDataSerializer,
|
||||
},
|
||||
serialize_proof, serialize_verifier_only,
|
||||
},
|
||||
cache::{self, CacheEntry},
|
||||
middleware::{
|
||||
|
|
@ -73,6 +76,8 @@ impl EmptyPodVerifyTarget {
|
|||
pub struct EmptyPod {
|
||||
params: Params,
|
||||
id: PodId,
|
||||
verifier_only: VerifierOnlyCircuitDataSerializer,
|
||||
common_hash: String,
|
||||
vd_set: VDSet,
|
||||
proof: Proof,
|
||||
}
|
||||
|
|
@ -119,17 +124,19 @@ fn build() -> Result<(EmptyPodVerifyTarget, CircuitData)> {
|
|||
}
|
||||
|
||||
impl EmptyPod {
|
||||
pub fn new(params: &Params, vd_set: VDSet) -> Result<EmptyPod> {
|
||||
let standard_empty_pod_data = cache_get_standard_empty_pod_circuit_data();
|
||||
let (empty_pod_verify_target, data) = &*standard_empty_pod_data;
|
||||
fn new(params: &Params, vd_set: VDSet) -> Result<EmptyPod> {
|
||||
let (empty_pod_verify_target, data) = &*cache_get_standard_empty_pod_circuit_data();
|
||||
|
||||
let mut pw = PartialWitness::<F>::new();
|
||||
empty_pod_verify_target.set_targets(&mut pw, vd_set.root())?;
|
||||
let proof = timed!("EmptyPod prove", data.prove(pw)?);
|
||||
let id = &proof.public_inputs[PI_OFFSET_ID..PI_OFFSET_ID + HASH_SIZE];
|
||||
let id = PodId(Hash([id[0], id[1], id[2], id[3]]));
|
||||
let common_hash = hash_common_data(&data.common).expect("hash ok");
|
||||
Ok(EmptyPod {
|
||||
params: params.clone(),
|
||||
verifier_only: VerifierOnlyCircuitDataSerializer(data.verifier_only.clone()),
|
||||
common_hash,
|
||||
id,
|
||||
vd_set,
|
||||
proof: proof.proof,
|
||||
|
|
@ -152,6 +159,8 @@ impl EmptyPod {
|
|||
#[derive(Serialize, Deserialize)]
|
||||
struct Data {
|
||||
proof: String,
|
||||
verifier_only: String,
|
||||
common_hash: String,
|
||||
}
|
||||
|
||||
impl Pod for EmptyPod {
|
||||
|
|
@ -199,6 +208,8 @@ impl Pod for EmptyPod {
|
|||
fn serialize_data(&self) -> serde_json::Value {
|
||||
serde_json::to_value(Data {
|
||||
proof: serialize_proof(&self.proof),
|
||||
verifier_only: serialize_verifier_only(&self.verifier_only),
|
||||
common_hash: self.common_hash.clone(),
|
||||
})
|
||||
.expect("serialization to json")
|
||||
}
|
||||
|
|
@ -206,11 +217,10 @@ impl Pod for EmptyPod {
|
|||
|
||||
impl RecursivePod for EmptyPod {
|
||||
fn verifier_data(&self) -> VerifierOnlyCircuitData {
|
||||
let standard_empty_pod_verifier_circuit_data =
|
||||
cache_get_standard_empty_pod_verifier_circuit_data();
|
||||
standard_empty_pod_verifier_circuit_data
|
||||
.verifier_only
|
||||
.clone()
|
||||
self.verifier_only.0.clone()
|
||||
}
|
||||
fn common_hash(&self) -> String {
|
||||
self.common_hash.clone()
|
||||
}
|
||||
fn proof(&self) -> Proof {
|
||||
self.proof.clone()
|
||||
|
|
@ -227,9 +237,12 @@ impl RecursivePod for EmptyPod {
|
|||
let data: Data = serde_json::from_value(data)?;
|
||||
let common_circuit_data = cache_get_standard_rec_main_pod_common_circuit_data();
|
||||
let proof = deserialize_proof(&common_circuit_data, &data.proof)?;
|
||||
let verifier_only = deserialize_verifier_only(&data.verifier_only)?;
|
||||
Ok(Box::new(Self {
|
||||
params,
|
||||
id,
|
||||
verifier_only: VerifierOnlyCircuitDataSerializer(verifier_only),
|
||||
common_hash: data.common_hash,
|
||||
vd_set,
|
||||
proof,
|
||||
}))
|
||||
|
|
|
|||
|
|
@ -14,9 +14,10 @@ use crate::{
|
|||
cache::{self, CacheEntry},
|
||||
cache_get_standard_rec_main_pod_common_circuit_data,
|
||||
circuits::mainpod::{CustomPredicateVerification, MainPodVerifyInput, MainPodVerifyTarget},
|
||||
deserialize_proof,
|
||||
deserialize_proof, deserialize_verifier_only,
|
||||
emptypod::EmptyPod,
|
||||
error::{Error, Result},
|
||||
hash_common_data,
|
||||
mock::emptypod::MockEmptyPod,
|
||||
primitives::{ec::schnorr::SecretKey, merkletree::MerkleClaimAndProof},
|
||||
recursion::{
|
||||
|
|
@ -25,7 +26,7 @@ use crate::{
|
|||
serialization::{
|
||||
CircuitDataSerializer, CommonCircuitDataSerializer, VerifierCircuitDataSerializer,
|
||||
},
|
||||
serialize_proof,
|
||||
serialize_proof, serialize_verifier_only,
|
||||
signedpod::SignedPod,
|
||||
},
|
||||
middleware::{
|
||||
|
|
@ -482,10 +483,12 @@ impl PodProver for Prover {
|
|||
// get the id out of the public statements
|
||||
let id: PodId = PodId(calculate_id(&public_statements, params));
|
||||
|
||||
let common_hash: String = cache_get_rec_main_pod_common_hash(params).clone();
|
||||
let proofs = inputs
|
||||
.recursive_pods
|
||||
.iter()
|
||||
.map(|pod| {
|
||||
assert_eq!(pod.common_hash(), common_hash);
|
||||
assert_eq!(inputs.vd_set.root(), pod.vd_set().root());
|
||||
ProofWithPublicInputs {
|
||||
proof: pod.proof(),
|
||||
|
|
@ -528,6 +531,8 @@ impl PodProver for Prover {
|
|||
|
||||
Ok(Box::new(MainPod {
|
||||
params: params.clone(),
|
||||
verifier_only: circuit_data.verifier_only.clone(),
|
||||
common_hash,
|
||||
id,
|
||||
vd_set: inputs.vd_set,
|
||||
public_statements,
|
||||
|
|
@ -540,6 +545,8 @@ impl PodProver for Prover {
|
|||
pub struct MainPod {
|
||||
params: Params,
|
||||
id: PodId,
|
||||
verifier_only: VerifierOnlyCircuitData,
|
||||
common_hash: String,
|
||||
/// vds_root is the merkle-root of the `VDSet`, which contains the
|
||||
/// verifier_data hashes of the allowed set of VerifierOnlyCircuitData, for
|
||||
/// the succession of recursive MainPods, which when proving the POD, it is
|
||||
|
|
@ -605,10 +612,20 @@ pub fn cache_get_rec_main_pod_common_circuit_data(
|
|||
.expect("cache ok")
|
||||
}
|
||||
|
||||
pub fn cache_get_rec_main_pod_common_hash(params: &Params) -> CacheEntry<String> {
|
||||
cache::get("rec_main_pod_common_hash", params, |params| {
|
||||
let common = &*cache_get_rec_main_pod_common_circuit_data(params);
|
||||
hash_common_data(common).expect("hash ok")
|
||||
})
|
||||
.expect("cache ok")
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct Data {
|
||||
public_statements: Vec<Statement>,
|
||||
proof: String,
|
||||
verifier_only: String,
|
||||
common_hash: String,
|
||||
}
|
||||
|
||||
impl MainPod {
|
||||
|
|
@ -626,6 +643,14 @@ impl Pod for MainPod {
|
|||
&self.params
|
||||
}
|
||||
fn verify(&self) -> Result<()> {
|
||||
// 0. Assert that the CommonCircuitData of the pod is the current one
|
||||
let expect_common_hash = &*cache_get_rec_main_pod_common_hash(&self.params);
|
||||
if &self.common_hash != expect_common_hash {
|
||||
return Err(Error::custom(format!(
|
||||
"The pod common_hash: {} is different than the current one: {}",
|
||||
self.common_hash, expect_common_hash,
|
||||
)));
|
||||
}
|
||||
// 2. get the id out of the public statements
|
||||
let id = PodId(calculate_id(&self.public_statements, &self.params));
|
||||
if id != self.id {
|
||||
|
|
@ -679,6 +704,8 @@ impl Pod for MainPod {
|
|||
serde_json::to_value(Data {
|
||||
proof: serialize_proof(&self.proof),
|
||||
public_statements: self.public_statements.clone(),
|
||||
verifier_only: serialize_verifier_only(&self.verifier_only),
|
||||
common_hash: self.common_hash.clone(),
|
||||
})
|
||||
.expect("serialization to json")
|
||||
}
|
||||
|
|
@ -686,9 +713,10 @@ impl Pod for MainPod {
|
|||
|
||||
impl RecursivePod for MainPod {
|
||||
fn verifier_data(&self) -> VerifierOnlyCircuitData {
|
||||
let rec_main_pod_verifier_circuit_data =
|
||||
cache_get_rec_main_pod_verifier_circuit_data(&self.params);
|
||||
rec_main_pod_verifier_circuit_data.verifier_only.clone()
|
||||
self.verifier_only.clone()
|
||||
}
|
||||
fn common_hash(&self) -> String {
|
||||
self.common_hash.clone()
|
||||
}
|
||||
fn proof(&self) -> Proof {
|
||||
self.proof.clone()
|
||||
|
|
@ -705,9 +733,12 @@ impl RecursivePod for MainPod {
|
|||
let data: Data = serde_json::from_value(data)?;
|
||||
let common = cache_get_rec_main_pod_common_circuit_data(¶ms);
|
||||
let proof = deserialize_proof(&common, &data.proof)?;
|
||||
let verifier_only = deserialize_verifier_only(&data.verifier_only)?;
|
||||
Ok(Box::new(Self {
|
||||
params,
|
||||
id,
|
||||
verifier_only,
|
||||
common_hash: data.common_hash,
|
||||
vd_set,
|
||||
proof,
|
||||
public_statements: data.public_statements,
|
||||
|
|
@ -1019,4 +1050,13 @@ pub mod tests {
|
|||
let pod = (proof.pod as Box<dyn Any>).downcast::<MainPod>().unwrap();
|
||||
Ok(pod.verify()?)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_common() {
|
||||
use pretty_assertions::assert_eq;
|
||||
let params = Params::default();
|
||||
let main_common = &*cache_get_rec_main_pod_common_circuit_data(¶ms);
|
||||
let std_common = &*cache_get_standard_rec_main_pod_common_circuit_data();
|
||||
assert_eq!(std_common.0, main_common.0);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,6 +73,9 @@ impl RecursivePod for MockEmptyPod {
|
|||
fn verifier_data(&self) -> VerifierOnlyCircuitData {
|
||||
panic!("MockEmptyPod can't be verified in a recursive MainPod circuit");
|
||||
}
|
||||
fn common_hash(&self) -> String {
|
||||
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");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -373,6 +373,9 @@ impl RecursivePod for MockMainPod {
|
|||
fn verifier_data(&self) -> VerifierOnlyCircuitData {
|
||||
panic!("MockMainPod can't be verified in a recursive MainPod circuit");
|
||||
}
|
||||
fn common_hash(&self) -> String {
|
||||
panic!("MockMainPod can't be verified in a recursive MainPod circuit");
|
||||
}
|
||||
fn proof(&self) -> Proof {
|
||||
panic!("MockMainPod can't be verified in a recursive MainPod circuit");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,19 +6,33 @@ pub mod mainpod;
|
|||
pub mod mock;
|
||||
pub mod primitives;
|
||||
pub mod recursion;
|
||||
mod serialization;
|
||||
pub mod serialization;
|
||||
pub mod signedpod;
|
||||
|
||||
use std::iter;
|
||||
|
||||
use base64::{prelude::BASE64_STANDARD, Engine};
|
||||
pub use error::*;
|
||||
use plonky2::util::serialization::{Buffer, Read};
|
||||
use plonky2::{
|
||||
field::{
|
||||
extension::quadratic::QuadraticExtension,
|
||||
types::{Field, Field64},
|
||||
},
|
||||
hash::hash_types::HashOut,
|
||||
plonk::vars::EvaluationVars,
|
||||
util::serialization::{Buffer, Read},
|
||||
};
|
||||
use rand::prelude::*;
|
||||
use rand_chacha::ChaCha20Rng;
|
||||
use serde::{ser, Deserialize, Serialize};
|
||||
use sha2::{Digest, Sha256};
|
||||
|
||||
use crate::{
|
||||
backends::plonky2::{
|
||||
basetypes::{CommonCircuitData, Proof},
|
||||
basetypes::{CommonCircuitData, Proof, VerifierOnlyCircuitData, F},
|
||||
circuits::mainpod::{MainPodVerifyTarget, NUM_PUBLIC_INPUTS},
|
||||
recursion::RecursiveCircuit,
|
||||
serialization::CommonCircuitDataSerializer,
|
||||
serialization::{CommonCircuitDataSerializer, Pod2GateSerializer},
|
||||
},
|
||||
cache::{self, CacheEntry},
|
||||
middleware::Params,
|
||||
|
|
@ -73,9 +87,99 @@ pub fn deserialize_proof(common: &CommonCircuitData, proof: &str) -> Result<Proo
|
|||
Ok(proof)
|
||||
}
|
||||
|
||||
pub fn serialize_verifier_only(verifier_only: &VerifierOnlyCircuitData) -> String {
|
||||
let bytes = verifier_only.to_bytes().expect("write to Vec");
|
||||
serialize_bytes(&bytes)
|
||||
}
|
||||
|
||||
pub fn deserialize_verifier_only(verifier_only: &str) -> Result<VerifierOnlyCircuitData> {
|
||||
let decoded = deserialize_bytes(verifier_only)?;
|
||||
let verifier_only = VerifierOnlyCircuitData::from_bytes(&decoded).map_err(|e| {
|
||||
Error::custom(format!(
|
||||
"Failed to read VerifierOnlyCircuitData from buffer: {}. Value: {}",
|
||||
e, verifier_only
|
||||
))
|
||||
})?;
|
||||
|
||||
Ok(verifier_only)
|
||||
}
|
||||
|
||||
pub fn serialize_proof(proof: &Proof) -> String {
|
||||
let mut buffer = Vec::new();
|
||||
use plonky2::util::serialization::Write;
|
||||
buffer.write_proof(proof).unwrap();
|
||||
serialize_bytes(&buffer)
|
||||
}
|
||||
|
||||
fn rand_vec(rng: &mut impl RngCore, len: usize) -> Vec<F> {
|
||||
iter::repeat_with(|| rng.next_u64())
|
||||
.filter(|v| *v < F::ORDER)
|
||||
.map(F::from_canonical_u64)
|
||||
.take(len)
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn base(r: F, xs: &[F]) -> F {
|
||||
let mut res = F::ZERO;
|
||||
for x in xs.iter().rev() {
|
||||
res *= r;
|
||||
res += *x;
|
||||
}
|
||||
res
|
||||
}
|
||||
|
||||
fn gate_fingerprints(common: &CommonCircuitData) -> Vec<(String, F)> {
|
||||
type Ext = QuadraticExtension<F>;
|
||||
let config = &common.config;
|
||||
let mut rng = ChaCha20Rng::seed_from_u64(42);
|
||||
let r = rand_vec(&mut rng, 1)[0];
|
||||
let local_constants: Vec<Ext> = rand_vec(&mut rng, config.num_constants)
|
||||
.into_iter()
|
||||
.map(Ext::from)
|
||||
.collect();
|
||||
let local_wires: Vec<Ext> = rand_vec(&mut rng, config.num_wires)
|
||||
.into_iter()
|
||||
.map(Ext::from)
|
||||
.collect();
|
||||
let public_inputs_hash = HashOut::from_vec(rand_vec(&mut rng, 4));
|
||||
let vars = EvaluationVars {
|
||||
local_constants: &local_constants,
|
||||
local_wires: &local_wires,
|
||||
public_inputs_hash: &public_inputs_hash,
|
||||
};
|
||||
let mut fingerprints = Vec::new();
|
||||
for gate in &common.gates {
|
||||
let eval: Vec<F> = gate
|
||||
.0
|
||||
.eval_unfiltered(vars)
|
||||
.into_iter()
|
||||
.map(|e| e.0[0])
|
||||
.collect();
|
||||
fingerprints.push((gate.0.id(), base(r, &eval)));
|
||||
}
|
||||
fingerprints
|
||||
}
|
||||
|
||||
pub fn hash_common_data(common: &CommonCircuitData) -> serde_json::Result<String> {
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct CommonFingerprintData {
|
||||
common: String,
|
||||
gate_fingerprints: Vec<(String, F)>,
|
||||
}
|
||||
|
||||
let gate_serializer = Pod2GateSerializer {};
|
||||
let bytes = common
|
||||
.to_bytes(&gate_serializer)
|
||||
.map_err(ser::Error::custom)?;
|
||||
let gate_fingerprints = gate_fingerprints(common);
|
||||
let data = CommonFingerprintData {
|
||||
common: serialize_bytes(&bytes),
|
||||
gate_fingerprints,
|
||||
};
|
||||
|
||||
let json = serde_json::to_string(&data)?;
|
||||
let json_hash = Sha256::digest(&json);
|
||||
let json_hash_str_long = format!("{:x}", json_hash);
|
||||
let json_hash_str = json_hash_str_long[..32].to_string();
|
||||
Ok(json_hash_str)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,9 @@ use plonky2_u32::gates::comparison::{ComparisonGate, ComparisonGenerator};
|
|||
use serde::{de, ser, Deserialize, Serialize};
|
||||
|
||||
use crate::backends::plonky2::{
|
||||
basetypes::{CircuitData, CommonCircuitData, VerifierCircuitData, C, D, F},
|
||||
basetypes::{
|
||||
CircuitData, CommonCircuitData, VerifierCircuitData, VerifierOnlyCircuitData, C, D, F,
|
||||
},
|
||||
circuits::{common::LtMaskGenerator, mux_table::TableGetGenerator, utils::DebugGenerator},
|
||||
primitives::ec::{
|
||||
bits::ConditionalZeroGenerator,
|
||||
|
|
@ -33,7 +35,7 @@ use crate::backends::plonky2::{
|
|||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct Pod2GateSerializer;
|
||||
pub struct Pod2GateSerializer;
|
||||
impl GateSerializer<F, D> for Pod2GateSerializer {
|
||||
impl_gate_serializer! {
|
||||
Pod2GateSerializer,
|
||||
|
|
@ -171,13 +173,13 @@ impl<'de> Deserialize<'de> for CircuitDataSerializer {
|
|||
let generator_serializer = Pod2GeneratorSerializer {};
|
||||
let circuit_data = CircuitData::from_bytes(bytes, &gate_serializer, &generator_serializer)
|
||||
.map_err(de::Error::custom)?;
|
||||
Ok(CircuitDataSerializer(circuit_data))
|
||||
Ok(Self(circuit_data))
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper type to serialize and deserialize the pod2 `CommonCircuitData` using serde traits.
|
||||
#[derive(Clone)]
|
||||
pub struct CommonCircuitDataSerializer(pub(crate) CommonCircuitData);
|
||||
pub struct CommonCircuitDataSerializer(pub CommonCircuitData);
|
||||
|
||||
impl Deref for CommonCircuitDataSerializer {
|
||||
type Target = CommonCircuitData;
|
||||
|
|
@ -210,7 +212,7 @@ impl<'de> Deserialize<'de> for CommonCircuitDataSerializer {
|
|||
let gate_serializer = Pod2GateSerializer {};
|
||||
let circuit_data =
|
||||
CommonCircuitData::from_bytes(bytes, &gate_serializer).map_err(de::Error::custom)?;
|
||||
Ok(CommonCircuitDataSerializer(circuit_data))
|
||||
Ok(Self(circuit_data))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -248,9 +250,43 @@ impl<'de> Deserialize<'de> for VerifierCircuitDataSerializer {
|
|||
let bytes = <&'de serde_bytes::Bytes>::deserialize(deserializer)?;
|
||||
|
||||
let gate_serializer = Pod2GateSerializer {};
|
||||
let circuit_data =
|
||||
let verifier_data =
|
||||
VerifierCircuitData::from_bytes(bytes, &gate_serializer).map_err(de::Error::custom)?;
|
||||
Ok(VerifierCircuitDataSerializer(circuit_data))
|
||||
Ok(Self(verifier_data))
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper type to serialize and deserialize the pod2 `VerifierOnlyCircuitData` using serde traits.
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct VerifierOnlyCircuitDataSerializer(pub(crate) VerifierOnlyCircuitData);
|
||||
|
||||
impl Deref for VerifierOnlyCircuitDataSerializer {
|
||||
type Target = VerifierOnlyCircuitData;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for VerifierOnlyCircuitDataSerializer {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
let bytes = self.0.to_bytes().map_err(ser::Error::custom)?;
|
||||
serde_bytes::ByteBuf::from(bytes).serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for VerifierOnlyCircuitDataSerializer {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
let bytes = <&'de serde_bytes::Bytes>::deserialize(deserializer)?;
|
||||
let verifier_only =
|
||||
VerifierOnlyCircuitData::from_bytes(bytes).map_err(de::Error::custom)?;
|
||||
Ok(Self(verifier_only))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
53
src/bin/mainpod_circuit_info.rs
Normal file
53
src/bin/mainpod_circuit_info.rs
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
use std::env;
|
||||
|
||||
use anyhow::anyhow;
|
||||
use pod2::{
|
||||
backends::plonky2::{
|
||||
hash_common_data, mainpod::cache_get_rec_main_pod_verifier_circuit_data,
|
||||
recursion::circuit::hash_verifier_data,
|
||||
},
|
||||
middleware::{Hash, Params},
|
||||
};
|
||||
use serde::Serialize;
|
||||
use sha2::{Digest, Sha256};
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct Info {
|
||||
params_hash: String,
|
||||
verifier_hash: Hash,
|
||||
common_hash: String,
|
||||
}
|
||||
|
||||
fn main() -> anyhow::Result<()> {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
|
||||
let params = Params::default();
|
||||
match args.get(1).map(|s| s.as_str()) {
|
||||
Some("params") => {
|
||||
let params_json = serde_json::to_string_pretty(¶ms)?;
|
||||
println!("{params_json}");
|
||||
}
|
||||
Some("circuit-info") => {
|
||||
let params_json = serde_json::to_string(¶ms)?;
|
||||
let params_json_hash = Sha256::digest(¶ms_json);
|
||||
let params_json_hash_str_long = format!("{params_json_hash:x}");
|
||||
let params_json_hash_str = params_json_hash_str_long[..32].to_string();
|
||||
|
||||
let vd = &*cache_get_rec_main_pod_verifier_circuit_data(¶ms);
|
||||
let info = Info {
|
||||
params_hash: params_json_hash_str,
|
||||
verifier_hash: Hash(hash_verifier_data(&vd.verifier_only).elements),
|
||||
common_hash: hash_common_data(&vd.common)?,
|
||||
};
|
||||
let json = serde_json::to_string_pretty(&info)?;
|
||||
println!("{json}");
|
||||
}
|
||||
_ => {
|
||||
return Err(anyhow!(
|
||||
"Invalid arguments. Usage: {} params/circuit-info",
|
||||
args[0]
|
||||
));
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -964,6 +964,9 @@ dyn_clone::clone_trait_object!(Pod);
|
|||
/// recursion: for example an introduction Pod in general is not recursive.
|
||||
pub trait RecursivePod: Pod {
|
||||
fn verifier_data(&self) -> VerifierOnlyCircuitData;
|
||||
/// Return a hash of the CommonCircuitData that uniquely identifies the circuit
|
||||
/// configuration and list of custom gates.
|
||||
fn common_hash(&self) -> String;
|
||||
fn proof(&self) -> Proof;
|
||||
fn vd_set(&self) -> &VDSet;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue