Check a single POD against a POD Request (#359)
This commit is contained in:
parent
c7b39f21f0
commit
f10a5adb41
11 changed files with 419 additions and 102 deletions
|
|
@ -768,21 +768,12 @@ pub mod tests {
|
||||||
vds.push(rec_main_pod_circuit_data(¶ms).1.verifier_only.clone());
|
vds.push(rec_main_pod_circuit_data(¶ms).1.verifier_only.clone());
|
||||||
let vd_set = VDSet::new(params.max_depth_mt_vds, &vds).unwrap();
|
let vd_set = VDSet::new(params.max_depth_mt_vds, &vds).unwrap();
|
||||||
|
|
||||||
let (gov_id_builder, pay_stub_builder, sanction_list_builder) =
|
let (gov_id_builder, pay_stub_builder) = zu_kyc_sign_pod_builders(¶ms);
|
||||||
zu_kyc_sign_pod_builders(¶ms);
|
|
||||||
let signer = Signer(SecretKey(BigUint::one()));
|
let signer = Signer(SecretKey(BigUint::one()));
|
||||||
let gov_id_pod = gov_id_builder.sign(&signer)?;
|
let gov_id_pod = gov_id_builder.sign(&signer)?;
|
||||||
let signer = Signer(SecretKey(2u64.into()));
|
let signer = Signer(SecretKey(2u64.into()));
|
||||||
let pay_stub_pod = pay_stub_builder.sign(&signer)?;
|
let pay_stub_pod = pay_stub_builder.sign(&signer)?;
|
||||||
let signer = Signer(SecretKey(3u64.into()));
|
let kyc_builder = zu_kyc_pod_builder(¶ms, &vd_set, &gov_id_pod, &pay_stub_pod)?;
|
||||||
let sanction_list_pod = sanction_list_builder.sign(&signer)?;
|
|
||||||
let kyc_builder = zu_kyc_pod_builder(
|
|
||||||
¶ms,
|
|
||||||
&vd_set,
|
|
||||||
&gov_id_pod,
|
|
||||||
&pay_stub_pod,
|
|
||||||
&sanction_list_pod,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let prover = Prover {};
|
let prover = Prover {};
|
||||||
let kyc_pod = kyc_builder.prove(&prover, ¶ms)?;
|
let kyc_pod = kyc_builder.prove(&prover, ¶ms)?;
|
||||||
|
|
|
||||||
|
|
@ -427,7 +427,7 @@ pub mod tests {
|
||||||
use crate::{
|
use crate::{
|
||||||
backends::plonky2::{primitives::ec::schnorr::SecretKey, signedpod::Signer},
|
backends::plonky2::{primitives::ec::schnorr::SecretKey, signedpod::Signer},
|
||||||
examples::{
|
examples::{
|
||||||
great_boy_pod_full_flow, tickets_pod_full_flow, zu_kyc_pod_builder,
|
great_boy_pod_full_flow, tickets_pod_full_flow, zu_kyc_pod_builder, zu_kyc_pod_request,
|
||||||
zu_kyc_sign_pod_builders, MOCK_VD_SET,
|
zu_kyc_sign_pod_builders, MOCK_VD_SET,
|
||||||
},
|
},
|
||||||
frontend, middleware,
|
frontend, middleware,
|
||||||
|
|
@ -437,21 +437,12 @@ pub mod tests {
|
||||||
fn test_mock_main_zu_kyc() -> frontend::Result<()> {
|
fn test_mock_main_zu_kyc() -> frontend::Result<()> {
|
||||||
let params = middleware::Params::default();
|
let params = middleware::Params::default();
|
||||||
let vd_set = &*MOCK_VD_SET;
|
let vd_set = &*MOCK_VD_SET;
|
||||||
let (gov_id_builder, pay_stub_builder, sanction_list_builder) =
|
let (gov_id_builder, pay_stub_builder) = zu_kyc_sign_pod_builders(¶ms);
|
||||||
zu_kyc_sign_pod_builders(¶ms);
|
|
||||||
let signer = Signer(SecretKey(1u32.into()));
|
let signer = Signer(SecretKey(1u32.into()));
|
||||||
let gov_id_pod = gov_id_builder.sign(&signer)?;
|
let gov_id_pod = gov_id_builder.sign(&signer)?;
|
||||||
let signer = Signer(SecretKey(2u32.into()));
|
let signer = Signer(SecretKey(2u32.into()));
|
||||||
let pay_stub_pod = pay_stub_builder.sign(&signer)?;
|
let pay_stub_pod = pay_stub_builder.sign(&signer)?;
|
||||||
let signer = Signer(SecretKey(3u32.into()));
|
let kyc_builder = zu_kyc_pod_builder(¶ms, vd_set, &gov_id_pod, &pay_stub_pod)?;
|
||||||
let sanction_list_pod = sanction_list_builder.sign(&signer)?;
|
|
||||||
let kyc_builder = zu_kyc_pod_builder(
|
|
||||||
¶ms,
|
|
||||||
vd_set,
|
|
||||||
&gov_id_pod,
|
|
||||||
&pay_stub_pod,
|
|
||||||
&sanction_list_pod,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let prover = MockProver {};
|
let prover = MockProver {};
|
||||||
let kyc_pod = kyc_builder.prove(&prover, ¶ms)?;
|
let kyc_pod = kyc_builder.prove(&prover, ¶ms)?;
|
||||||
|
|
@ -462,6 +453,13 @@ pub mod tests {
|
||||||
println!("{:#}", pod);
|
println!("{:#}", pod);
|
||||||
|
|
||||||
pod.verify()?;
|
pod.verify()?;
|
||||||
|
|
||||||
|
let request = zu_kyc_pod_request(
|
||||||
|
gov_id_pod.get("_signer").unwrap(),
|
||||||
|
pay_stub_pod.get("_signer").unwrap(),
|
||||||
|
)?;
|
||||||
|
assert!(request.exact_match_pod(&*pod).is_ok());
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use hex::ToHex;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
frontend::Result,
|
frontend::{PodRequest, Result},
|
||||||
lang::parse,
|
lang::parse,
|
||||||
middleware::{CustomPredicateBatch, Params, PodType, Value, KEY_SIGNER, KEY_TYPE},
|
middleware::{CustomPredicateBatch, Params, PodType, Value, KEY_SIGNER, KEY_TYPE},
|
||||||
};
|
};
|
||||||
|
|
@ -53,6 +55,21 @@ pub fn eth_dos_batch(params: &Params) -> Result<Arc<CustomPredicateBatch>> {
|
||||||
Ok(batch)
|
Ok(batch)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn eth_dos_request() -> Result<PodRequest> {
|
||||||
|
let batch = eth_dos_batch(&Params::default())?;
|
||||||
|
let batch_id = batch.id().encode_hex::<String>();
|
||||||
|
let input = format!(
|
||||||
|
r#"
|
||||||
|
use _, _, _, eth_dos from 0x{batch_id}
|
||||||
|
REQUEST(
|
||||||
|
eth_dos(?src, ?dst, ?distance)
|
||||||
|
)
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
let parsed = parse(&input, &Params::default(), &[batch])?;
|
||||||
|
Ok(parsed.request)
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,8 @@ pub static MOCK_VD_SET: LazyLock<VDSet> = LazyLock::new(|| VDSet::new(6, &[]).un
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
backends::plonky2::{primitives::ec::schnorr::SecretKey, signedpod::Signer},
|
backends::plonky2::{primitives::ec::schnorr::SecretKey, signedpod::Signer},
|
||||||
frontend::{MainPod, MainPodBuilder, Result, SignedPod, SignedPodBuilder},
|
frontend::{MainPod, MainPodBuilder, PodRequest, Result, SignedPod, SignedPodBuilder},
|
||||||
|
lang::parse,
|
||||||
middleware::{
|
middleware::{
|
||||||
containers::Set, hash_values, CustomPredicateRef, Params, PodSigner, PodType, Predicate,
|
containers::Set, hash_values, CustomPredicateRef, Params, PodSigner, PodType, Predicate,
|
||||||
Statement, StatementArg, TypedValue, VDSet, Value, KEY_SIGNER, KEY_TYPE,
|
Statement, StatementArg, TypedValue, VDSet, Value, KEY_SIGNER, KEY_TYPE,
|
||||||
|
|
@ -19,13 +20,7 @@ use crate::{
|
||||||
|
|
||||||
// ZuKYC
|
// ZuKYC
|
||||||
|
|
||||||
pub fn zu_kyc_sign_pod_builders(
|
pub fn zu_kyc_sign_pod_builders(params: &Params) -> (SignedPodBuilder, SignedPodBuilder) {
|
||||||
params: &Params,
|
|
||||||
) -> (SignedPodBuilder, SignedPodBuilder, SignedPodBuilder) {
|
|
||||||
let sanctions_values: HashSet<Value> = ["A343434340"].iter().map(|s| Value::from(*s)).collect();
|
|
||||||
let sanction_set =
|
|
||||||
Value::from(Set::new(params.max_depth_mt_containers, sanctions_values).unwrap());
|
|
||||||
|
|
||||||
let mut gov_id = SignedPodBuilder::new(params);
|
let mut gov_id = SignedPodBuilder::new(params);
|
||||||
gov_id.insert("idNumber", "4242424242");
|
gov_id.insert("idNumber", "4242424242");
|
||||||
gov_id.insert("dateOfBirth", 1169909384);
|
gov_id.insert("dateOfBirth", 1169909384);
|
||||||
|
|
@ -35,32 +30,32 @@ pub fn zu_kyc_sign_pod_builders(
|
||||||
pay_stub.insert("socialSecurityNumber", "G2121210");
|
pay_stub.insert("socialSecurityNumber", "G2121210");
|
||||||
pay_stub.insert("startDate", 1706367566);
|
pay_stub.insert("startDate", 1706367566);
|
||||||
|
|
||||||
let mut sanction_list = SignedPodBuilder::new(params);
|
(gov_id, pay_stub)
|
||||||
|
|
||||||
sanction_list.insert("sanctionList", sanction_set);
|
|
||||||
|
|
||||||
(gov_id, pay_stub, sanction_list)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const ZU_KYC_NOW_MINUS_18Y: i64 = 1169909388;
|
||||||
|
pub const ZU_KYC_NOW_MINUS_1Y: i64 = 1706367566;
|
||||||
|
pub const ZU_KYC_SANCTION_LIST: &[&str] = &["A343434340"];
|
||||||
|
|
||||||
pub fn zu_kyc_pod_builder(
|
pub fn zu_kyc_pod_builder(
|
||||||
params: &Params,
|
params: &Params,
|
||||||
vd_set: &VDSet,
|
vd_set: &VDSet,
|
||||||
gov_id: &SignedPod,
|
gov_id: &SignedPod,
|
||||||
pay_stub: &SignedPod,
|
pay_stub: &SignedPod,
|
||||||
sanction_list: &SignedPod,
|
|
||||||
) -> Result<MainPodBuilder> {
|
) -> Result<MainPodBuilder> {
|
||||||
let now_minus_18y: i64 = 1169909388;
|
let now_minus_18y = ZU_KYC_NOW_MINUS_18Y;
|
||||||
let now_minus_1y: i64 = 1706367566;
|
let now_minus_1y = ZU_KYC_NOW_MINUS_1Y;
|
||||||
|
let sanctions_values: HashSet<Value> = ZU_KYC_SANCTION_LIST
|
||||||
|
.iter()
|
||||||
|
.map(|s| Value::from(*s))
|
||||||
|
.collect();
|
||||||
|
let sanction_set =
|
||||||
|
Value::from(Set::new(params.max_depth_mt_containers, sanctions_values).unwrap());
|
||||||
|
|
||||||
let mut kyc = MainPodBuilder::new(params, vd_set);
|
let mut kyc = MainPodBuilder::new(params, vd_set);
|
||||||
kyc.add_signed_pod(gov_id);
|
kyc.add_signed_pod(gov_id);
|
||||||
kyc.add_signed_pod(pay_stub);
|
kyc.add_signed_pod(pay_stub);
|
||||||
kyc.add_signed_pod(sanction_list);
|
kyc.pub_op(op!(set_not_contains, sanction_set, (gov_id, "idNumber")))?;
|
||||||
kyc.pub_op(op!(
|
|
||||||
set_not_contains,
|
|
||||||
(sanction_list, "sanctionList"),
|
|
||||||
(gov_id, "idNumber")
|
|
||||||
))?;
|
|
||||||
kyc.pub_op(op!(lt, (gov_id, "dateOfBirth"), now_minus_18y))?;
|
kyc.pub_op(op!(lt, (gov_id, "dateOfBirth"), now_minus_18y))?;
|
||||||
kyc.pub_op(op!(
|
kyc.pub_op(op!(
|
||||||
eq,
|
eq,
|
||||||
|
|
@ -68,10 +63,42 @@ pub fn zu_kyc_pod_builder(
|
||||||
(pay_stub, "socialSecurityNumber")
|
(pay_stub, "socialSecurityNumber")
|
||||||
))?;
|
))?;
|
||||||
kyc.pub_op(op!(eq, (pay_stub, "startDate"), now_minus_1y))?;
|
kyc.pub_op(op!(eq, (pay_stub, "startDate"), now_minus_1y))?;
|
||||||
|
kyc.pub_op(op!(eq, (gov_id, "_signer"), gov_id.get("_signer").unwrap()))?;
|
||||||
|
kyc.pub_op(op!(
|
||||||
|
eq,
|
||||||
|
(pay_stub, "_signer"),
|
||||||
|
pay_stub.get("_signer").unwrap()
|
||||||
|
))?;
|
||||||
|
|
||||||
Ok(kyc)
|
Ok(kyc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn zu_kyc_pod_request(gov_signer: &Value, pay_signer: &Value) -> Result<PodRequest> {
|
||||||
|
let params = Params::default();
|
||||||
|
let sanctions_values: HashSet<Value> = ZU_KYC_SANCTION_LIST
|
||||||
|
.iter()
|
||||||
|
.map(|s| Value::from(*s))
|
||||||
|
.collect();
|
||||||
|
let sanction_set =
|
||||||
|
Value::from(Set::new(params.max_depth_mt_containers, sanctions_values).unwrap());
|
||||||
|
let input = format!(
|
||||||
|
r#"
|
||||||
|
REQUEST(
|
||||||
|
SetNotContains({sanction_set}, ?gov["idNumber"])
|
||||||
|
Lt(?gov["dateOfBirth"], {ZU_KYC_NOW_MINUS_18Y})
|
||||||
|
Equal(?pay["startDate"], {ZU_KYC_NOW_MINUS_1Y})
|
||||||
|
Equal(?gov["socialSecurityNumber"], ?pay["socialSecurityNumber"])
|
||||||
|
Equal(?gov["_signer"], {gov_signer})
|
||||||
|
Equal(?pay["_signer"], {pay_signer})
|
||||||
|
// TODO: Ownership check and watermarking
|
||||||
|
// Depends partly on https://github.com/0xPARC/pod2/issues/351
|
||||||
|
)
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
let parsed = parse(&input, &Params::default(), &[])?;
|
||||||
|
Ok(parsed.request)
|
||||||
|
}
|
||||||
|
|
||||||
// ETHDoS
|
// ETHDoS
|
||||||
|
|
||||||
pub fn attest_eth_friend(params: &Params, src: &impl PodSigner, dst: Value) -> SignedPod {
|
pub fn attest_eth_friend(params: &Params, src: &impl PodSigner, dst: Value) -> SignedPod {
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,10 @@ pub enum InnerError {
|
||||||
),
|
),
|
||||||
#[error("invalid arguments to {0} operation")]
|
#[error("invalid arguments to {0} operation")]
|
||||||
OpInvalidArgs(String),
|
OpInvalidArgs(String),
|
||||||
|
#[error("Podlang parse error: {0}")]
|
||||||
|
PodlangParse(String),
|
||||||
|
#[error("POD Request validation error: {0}")]
|
||||||
|
PodRequestValidation(String),
|
||||||
// Other
|
// Other
|
||||||
#[error("{0}")]
|
#[error("{0}")]
|
||||||
Custom(String),
|
Custom(String),
|
||||||
|
|
@ -55,6 +59,12 @@ impl From<std::convert::Infallible> for Error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<crate::lang::LangError> for Error {
|
||||||
|
fn from(value: crate::lang::LangError) -> Self {
|
||||||
|
Error::podlang_parse(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Debug for Error {
|
impl Debug for Error {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
std::fmt::Display::fmt(self, f)
|
std::fmt::Display::fmt(self, f)
|
||||||
|
|
@ -88,4 +98,10 @@ impl Error {
|
||||||
pub(crate) fn max_length(obj: String, found: usize, expect: usize) -> Self {
|
pub(crate) fn max_length(obj: String, found: usize, expect: usize) -> Self {
|
||||||
new!(MaxLength(obj, found, expect))
|
new!(MaxLength(obj, found, expect))
|
||||||
}
|
}
|
||||||
|
pub(crate) fn podlang_parse(e: crate::lang::LangError) -> Self {
|
||||||
|
new!(PodlangParse(e.to_string()))
|
||||||
|
}
|
||||||
|
pub(crate) fn pod_request_validation(e: String) -> Self {
|
||||||
|
new!(PodRequestValidation(e))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,10 +16,12 @@ use crate::middleware::{
|
||||||
mod custom;
|
mod custom;
|
||||||
mod error;
|
mod error;
|
||||||
mod operation;
|
mod operation;
|
||||||
|
mod pod_request;
|
||||||
mod serialization;
|
mod serialization;
|
||||||
pub use custom::*;
|
pub use custom::*;
|
||||||
pub use error::*;
|
pub use error::*;
|
||||||
pub use operation::*;
|
pub use operation::*;
|
||||||
|
pub use pod_request::*;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct SignedPodBuilder {
|
pub struct SignedPodBuilder {
|
||||||
|
|
@ -857,7 +859,8 @@ pub mod tests {
|
||||||
mock::mainpod::MockProver, primitives::ec::schnorr::SecretKey, signedpod::Signer,
|
mock::mainpod::MockProver, primitives::ec::schnorr::SecretKey, signedpod::Signer,
|
||||||
},
|
},
|
||||||
examples::{
|
examples::{
|
||||||
attest_eth_friend, great_boy_pod_full_flow, tickets_pod_full_flow, zu_kyc_pod_builder,
|
attest_eth_friend, custom::eth_dos_request, great_boy_pod_full_flow,
|
||||||
|
tickets_pod_full_flow, zu_kyc_pod_builder, zu_kyc_pod_request,
|
||||||
zu_kyc_sign_pod_builders, EthDosHelper, MOCK_VD_SET,
|
zu_kyc_sign_pod_builders, EthDosHelper, MOCK_VD_SET,
|
||||||
},
|
},
|
||||||
middleware::{containers::Dictionary, Value},
|
middleware::{containers::Dictionary, Value},
|
||||||
|
|
@ -896,7 +899,7 @@ pub mod tests {
|
||||||
fn test_front_zu_kyc() -> Result<()> {
|
fn test_front_zu_kyc() -> Result<()> {
|
||||||
let params = Params::default();
|
let params = Params::default();
|
||||||
let vd_set = &*MOCK_VD_SET;
|
let vd_set = &*MOCK_VD_SET;
|
||||||
let (gov_id, pay_stub, sanction_list) = zu_kyc_sign_pod_builders(¶ms);
|
let (gov_id, pay_stub) = zu_kyc_sign_pod_builders(¶ms);
|
||||||
|
|
||||||
println!("{}", gov_id);
|
println!("{}", gov_id);
|
||||||
println!("{}", pay_stub);
|
println!("{}", pay_stub);
|
||||||
|
|
@ -911,12 +914,7 @@ pub mod tests {
|
||||||
check_kvs(&pay_stub)?;
|
check_kvs(&pay_stub)?;
|
||||||
println!("{}", pay_stub);
|
println!("{}", pay_stub);
|
||||||
|
|
||||||
let signer = Signer(SecretKey(3u32.into()));
|
let kyc_builder = zu_kyc_pod_builder(¶ms, vd_set, &gov_id, &pay_stub)?;
|
||||||
let sanction_list = sanction_list.sign(&signer)?;
|
|
||||||
check_kvs(&sanction_list)?;
|
|
||||||
println!("{}", sanction_list);
|
|
||||||
|
|
||||||
let kyc_builder = zu_kyc_pod_builder(¶ms, vd_set, &gov_id, &pay_stub, &sanction_list)?;
|
|
||||||
println!("{}", kyc_builder);
|
println!("{}", kyc_builder);
|
||||||
|
|
||||||
// prove kyc with MockProver and print it
|
// prove kyc with MockProver and print it
|
||||||
|
|
@ -925,6 +923,15 @@ pub mod tests {
|
||||||
|
|
||||||
println!("{}", kyc);
|
println!("{}", kyc);
|
||||||
|
|
||||||
|
let request = zu_kyc_pod_request(
|
||||||
|
gov_id.get("_signer").unwrap(),
|
||||||
|
pay_stub.get("_signer").unwrap(),
|
||||||
|
)?;
|
||||||
|
// Check the bindings of the "gov" and "pay" wildcards from the PodRequest
|
||||||
|
let bindings = request.exact_match_pod(&*kyc.pod).unwrap();
|
||||||
|
assert_eq!(*bindings.get("gov").unwrap(), gov_id.id().into());
|
||||||
|
assert_eq!(*bindings.get("pay").unwrap(), pay_stub.id().into());
|
||||||
|
|
||||||
check_public_statements(&kyc)
|
check_public_statements(&kyc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -950,18 +957,34 @@ pub mod tests {
|
||||||
let alice_attestation = attest_eth_friend(¶ms, &alice, bob.public_key());
|
let alice_attestation = attest_eth_friend(¶ms, &alice, bob.public_key());
|
||||||
let dist_1 = helper.dist_1(&alice_attestation)?.prove(&prover, ¶ms)?;
|
let dist_1 = helper.dist_1(&alice_attestation)?.prove(&prover, ¶ms)?;
|
||||||
dist_1.pod.verify()?;
|
dist_1.pod.verify()?;
|
||||||
|
let request = eth_dos_request()?;
|
||||||
|
assert!(request.exact_match_pod(&*dist_1.pod).is_ok());
|
||||||
|
let bindings = request.exact_match_pod(&*dist_1.pod).unwrap();
|
||||||
|
assert_eq!(*bindings.get("src").unwrap(), alice.public_key());
|
||||||
|
assert_eq!(*bindings.get("dst").unwrap(), bob.public_key());
|
||||||
|
assert_eq!(*bindings.get("distance").unwrap(), 1.into());
|
||||||
|
|
||||||
let bob_attestation = attest_eth_friend(¶ms, &bob, charlie.public_key());
|
let bob_attestation = attest_eth_friend(¶ms, &bob, charlie.public_key());
|
||||||
let dist_2 = helper
|
let dist_2 = helper
|
||||||
.dist_n_plus_1(&dist_1, &bob_attestation)?
|
.dist_n_plus_1(&dist_1, &bob_attestation)?
|
||||||
.prove(&prover, ¶ms)?;
|
.prove(&prover, ¶ms)?;
|
||||||
dist_2.pod.verify()?;
|
dist_2.pod.verify()?;
|
||||||
|
assert!(request.exact_match_pod(&*dist_2.pod).is_ok());
|
||||||
|
let bindings = request.exact_match_pod(&*dist_2.pod).unwrap();
|
||||||
|
assert_eq!(*bindings.get("src").unwrap(), alice.public_key());
|
||||||
|
assert_eq!(*bindings.get("dst").unwrap(), charlie.public_key());
|
||||||
|
assert_eq!(*bindings.get("distance").unwrap(), 2.into());
|
||||||
|
|
||||||
let charlie_attestation = attest_eth_friend(¶ms, &charlie, david.public_key());
|
let charlie_attestation = attest_eth_friend(¶ms, &charlie, david.public_key());
|
||||||
let dist_3 = helper
|
let dist_3 = helper
|
||||||
.dist_n_plus_1(&dist_2, &charlie_attestation)?
|
.dist_n_plus_1(&dist_2, &charlie_attestation)?
|
||||||
.prove(&prover, ¶ms)?;
|
.prove(&prover, ¶ms)?;
|
||||||
dist_3.pod.verify()?;
|
dist_3.pod.verify()?;
|
||||||
|
assert!(request.exact_match_pod(&*dist_3.pod).is_ok());
|
||||||
|
let bindings = request.exact_match_pod(&*dist_3.pod).unwrap();
|
||||||
|
assert_eq!(*bindings.get("src").unwrap(), alice.public_key());
|
||||||
|
assert_eq!(*bindings.get("dst").unwrap(), david.public_key());
|
||||||
|
assert_eq!(*bindings.get("distance").unwrap(), 3.into());
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
255
src/frontend/pod_request.rs
Normal file
255
src/frontend/pod_request.rs
Normal file
|
|
@ -0,0 +1,255 @@
|
||||||
|
use std::{collections::HashMap, fmt::Display};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
frontend::{Error, Result},
|
||||||
|
lang::PrettyPrint,
|
||||||
|
middleware::{Pod, Statement, StatementArg, StatementTmpl, StatementTmplArg, Value},
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Represents a request for a POD, in terms of a set of statement templates.
|
||||||
|
/// The response should be a POD (or PODs) containing a set of statements which
|
||||||
|
/// satisfy the templates, with consistent wildcard bindings across all templates.
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub struct PodRequest {
|
||||||
|
pub request_templates: Vec<StatementTmpl>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PodRequest {
|
||||||
|
pub fn new(request_templates: Vec<StatementTmpl>) -> Self {
|
||||||
|
Self { request_templates }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Checks if the request is fully satisfied by a single supplied POD.
|
||||||
|
/// This checks for exact matches to the statement templates; that is to say
|
||||||
|
/// that it performs a "syntactic" match, not a "semantic" match; no
|
||||||
|
/// processing of the semantics of the statements is performed.
|
||||||
|
pub fn exact_match_pod(&self, pod: &dyn Pod) -> Result<HashMap<String, Value>> {
|
||||||
|
let pod_statements = pod.pub_statements();
|
||||||
|
let mut bindings: HashMap<String, Value> = HashMap::new();
|
||||||
|
|
||||||
|
if self.dfs_match_all(&pod_statements, &mut bindings, 0) {
|
||||||
|
Ok(bindings)
|
||||||
|
} else {
|
||||||
|
Err(Error::pod_request_validation("No match found".to_string()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Performs a depth-first search through the statement templates, trying to
|
||||||
|
/// match each template to a statement in the POD.
|
||||||
|
/// Returns true if all templates are matched, false otherwise.
|
||||||
|
/// The bindings map is used to store the bindings of the wildcards to the
|
||||||
|
/// values in the POD.
|
||||||
|
/// The template_idx is used to track the current template being matched.
|
||||||
|
fn dfs_match_all(
|
||||||
|
&self,
|
||||||
|
pod_statements: &[Statement],
|
||||||
|
bindings: &mut HashMap<String, Value>,
|
||||||
|
template_idx: usize,
|
||||||
|
) -> bool {
|
||||||
|
// Base case: all templates matched
|
||||||
|
if template_idx >= self.request_templates.len() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
let template = &self.request_templates[template_idx];
|
||||||
|
|
||||||
|
// Try to match this template with each statement in the POD
|
||||||
|
for stmt in pod_statements {
|
||||||
|
if let Some(new_bindings) = self.try_match_template(template, stmt, bindings) {
|
||||||
|
let original_bindings = bindings.clone();
|
||||||
|
bindings.extend(new_bindings);
|
||||||
|
|
||||||
|
if self.dfs_match_all(pod_statements, bindings, template_idx + 1) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
*bindings = original_bindings;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn try_match_template(
|
||||||
|
&self,
|
||||||
|
template: &StatementTmpl,
|
||||||
|
statement: &Statement,
|
||||||
|
current_bindings: &HashMap<String, Value>,
|
||||||
|
) -> Option<HashMap<String, Value>> {
|
||||||
|
if template.pred != statement.predicate() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let template_args = template.args();
|
||||||
|
let statement_args = statement.args();
|
||||||
|
|
||||||
|
if template_args.len() != statement_args.len() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut new_bindings = HashMap::new();
|
||||||
|
|
||||||
|
for (tmpl_arg, stmt_arg) in template_args.iter().zip(statement_args.iter()) {
|
||||||
|
if !self.try_match_arg(tmpl_arg, stmt_arg, current_bindings, &mut new_bindings) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(new_bindings)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn try_match_arg(
|
||||||
|
&self,
|
||||||
|
template_arg: &StatementTmplArg,
|
||||||
|
statement_arg: &StatementArg,
|
||||||
|
current_bindings: &HashMap<String, Value>,
|
||||||
|
new_bindings: &mut HashMap<String, Value>,
|
||||||
|
) -> bool {
|
||||||
|
match (template_arg, statement_arg) {
|
||||||
|
// Literal must match exactly
|
||||||
|
(StatementTmplArg::Literal(tmpl_val), StatementArg::Literal(stmt_val)) => {
|
||||||
|
tmpl_val == stmt_val
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wildcard can bind to any literal value
|
||||||
|
(StatementTmplArg::Wildcard(wildcard), StatementArg::Literal(stmt_val)) => self
|
||||||
|
.try_bind_wildcard(
|
||||||
|
&wildcard.name,
|
||||||
|
stmt_val.clone(),
|
||||||
|
current_bindings,
|
||||||
|
new_bindings,
|
||||||
|
),
|
||||||
|
|
||||||
|
// AnchoredKey wildcard must match statement's anchored key
|
||||||
|
(StatementTmplArg::AnchoredKey(wildcard, tmpl_key), StatementArg::Key(stmt_key)) => {
|
||||||
|
// Check if keys match
|
||||||
|
if tmpl_key != &stmt_key.key {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to bind wildcard to the POD ID
|
||||||
|
let pod_id_value = Value::from(stmt_key.pod_id);
|
||||||
|
self.try_bind_wildcard(&wildcard.name, pod_id_value, current_bindings, new_bindings)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Other combinations don't match
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn try_bind_wildcard(
|
||||||
|
&self,
|
||||||
|
wildcard_name: &str,
|
||||||
|
value: Value,
|
||||||
|
current_bindings: &HashMap<String, Value>,
|
||||||
|
new_bindings: &mut HashMap<String, Value>,
|
||||||
|
) -> bool {
|
||||||
|
// Check if wildcard is already bound
|
||||||
|
if let Some(existing_value) = current_bindings.get(wildcard_name) {
|
||||||
|
// Must match existing binding
|
||||||
|
return existing_value == &value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if we're trying to bind it in new_bindings
|
||||||
|
if let Some(existing_value) = new_bindings.get(wildcard_name) {
|
||||||
|
// Must match existing binding in this attempt
|
||||||
|
return existing_value == &value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bind the wildcard
|
||||||
|
new_bindings.insert(wildcard_name.to_string(), value);
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn templates(&self) -> &[StatementTmpl] {
|
||||||
|
&self.request_templates
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for PodRequest {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
self.fmt_podlang(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use crate::{
|
||||||
|
backends::plonky2::{
|
||||||
|
mock::mainpod::MockProver, primitives::ec::schnorr::SecretKey, signedpod::Signer,
|
||||||
|
},
|
||||||
|
examples::{zu_kyc_pod_builder, zu_kyc_pod_request, zu_kyc_sign_pod_builders, MOCK_VD_SET},
|
||||||
|
frontend::{MainPodBuilder, Operation},
|
||||||
|
lang::parse,
|
||||||
|
middleware::Params,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_pod_request_exact_match_pod() {
|
||||||
|
let params = Params::default();
|
||||||
|
let vd_set = &*MOCK_VD_SET;
|
||||||
|
|
||||||
|
let (gov_id, pay_stub) = zu_kyc_sign_pod_builders(¶ms);
|
||||||
|
let gov_id = gov_id.sign(&Signer(SecretKey(1u32.into()))).unwrap();
|
||||||
|
let pay_stub = pay_stub.sign(&Signer(SecretKey(2u32.into()))).unwrap();
|
||||||
|
let builder = zu_kyc_pod_builder(&Params::default(), vd_set, &gov_id, &pay_stub).unwrap();
|
||||||
|
let prover = MockProver {};
|
||||||
|
let kyc = builder.prove(&prover, ¶ms).unwrap();
|
||||||
|
|
||||||
|
// This request matches the POD
|
||||||
|
let request = zu_kyc_pod_request(
|
||||||
|
gov_id.get("_signer").unwrap(),
|
||||||
|
pay_stub.get("_signer").unwrap(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
assert!(request.exact_match_pod(&*kyc.pod).is_ok());
|
||||||
|
|
||||||
|
// This request does not match the POD, because the POD does not contain a NotEqual statement.
|
||||||
|
let non_matching_request = parse(
|
||||||
|
r#"
|
||||||
|
REQUEST(
|
||||||
|
NotEqual(4, 5)
|
||||||
|
)
|
||||||
|
"#,
|
||||||
|
¶ms,
|
||||||
|
&[],
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
.request;
|
||||||
|
assert!(non_matching_request.exact_match_pod(&*kyc.pod).is_err());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_ambiguous_pod() {
|
||||||
|
let params = Params::default();
|
||||||
|
let vd_set = &*MOCK_VD_SET;
|
||||||
|
|
||||||
|
let mut builder = MainPodBuilder::new(¶ms, vd_set);
|
||||||
|
let _sum_of_stmt_1 = builder.pub_op(Operation::sum_of(11, 1, 10));
|
||||||
|
let _sum_of_stmt_2 = builder.pub_op(Operation::sum_of(10, 9, 1));
|
||||||
|
let _eq_stmt = builder.pub_op(Operation::eq(10, 10));
|
||||||
|
|
||||||
|
let prover = MockProver {};
|
||||||
|
|
||||||
|
let pod = builder.prove(&prover, ¶ms).unwrap();
|
||||||
|
|
||||||
|
println!("{pod}");
|
||||||
|
|
||||||
|
let request = parse(
|
||||||
|
r#"
|
||||||
|
REQUEST(
|
||||||
|
SumOf(?a, ?b, ?c)
|
||||||
|
Equal(?a, 10)
|
||||||
|
)
|
||||||
|
"#,
|
||||||
|
¶ms,
|
||||||
|
&[],
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let bindings = request.request.exact_match_pod(&*pod.pod).unwrap();
|
||||||
|
assert_eq!(*bindings.get("a").unwrap(), 10.into());
|
||||||
|
assert_eq!(*bindings.get("b").unwrap(), 9.into());
|
||||||
|
assert_eq!(*bindings.get("c").unwrap(), 1.into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -267,22 +267,12 @@ mod tests {
|
||||||
let params = middleware::Params::default();
|
let params = middleware::Params::default();
|
||||||
let vd_set = &*MOCK_VD_SET;
|
let vd_set = &*MOCK_VD_SET;
|
||||||
|
|
||||||
let (gov_id_builder, pay_stub_builder, sanction_list_builder) =
|
let (gov_id_builder, pay_stub_builder) = zu_kyc_sign_pod_builders(¶ms);
|
||||||
zu_kyc_sign_pod_builders(¶ms);
|
|
||||||
let signer = Signer(SecretKey(1u32.into()));
|
let signer = Signer(SecretKey(1u32.into()));
|
||||||
let gov_id_pod = gov_id_builder.sign(&signer).unwrap();
|
let gov_id_pod = gov_id_builder.sign(&signer).unwrap();
|
||||||
let signer = Signer(SecretKey(2u32.into()));
|
let signer = Signer(SecretKey(2u32.into()));
|
||||||
let pay_stub_pod = pay_stub_builder.sign(&signer).unwrap();
|
let pay_stub_pod = pay_stub_builder.sign(&signer).unwrap();
|
||||||
let signer = Signer(SecretKey(3u32.into()));
|
let kyc_builder = zu_kyc_pod_builder(¶ms, vd_set, &gov_id_pod, &pay_stub_pod).unwrap();
|
||||||
let sanction_list_pod = sanction_list_builder.sign(&signer).unwrap();
|
|
||||||
let kyc_builder = zu_kyc_pod_builder(
|
|
||||||
¶ms,
|
|
||||||
vd_set,
|
|
||||||
&gov_id_pod,
|
|
||||||
&pay_stub_pod,
|
|
||||||
&sanction_list_pod,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let prover = MockProver {};
|
let prover = MockProver {};
|
||||||
let kyc_pod = kyc_builder.prove(&prover, ¶ms).unwrap();
|
let kyc_pod = kyc_builder.prove(&prover, ¶ms).unwrap();
|
||||||
|
|
@ -300,21 +290,12 @@ mod tests {
|
||||||
vds.push(rec_main_pod_circuit_data(¶ms).1.verifier_only.clone());
|
vds.push(rec_main_pod_circuit_data(¶ms).1.verifier_only.clone());
|
||||||
let vd_set = VDSet::new(params.max_depth_mt_vds, &vds).unwrap();
|
let vd_set = VDSet::new(params.max_depth_mt_vds, &vds).unwrap();
|
||||||
|
|
||||||
let (gov_id_builder, pay_stub_builder, sanction_list_builder) =
|
let (gov_id_builder, pay_stub_builder) = zu_kyc_sign_pod_builders(¶ms);
|
||||||
zu_kyc_sign_pod_builders(¶ms);
|
|
||||||
let signer = Signer(SecretKey(1u32.into()));
|
let signer = Signer(SecretKey(1u32.into()));
|
||||||
let gov_id_pod = gov_id_builder.sign(&signer)?;
|
let gov_id_pod = gov_id_builder.sign(&signer)?;
|
||||||
let signer = Signer(SecretKey(2u32.into()));
|
let signer = Signer(SecretKey(2u32.into()));
|
||||||
let pay_stub_pod = pay_stub_builder.sign(&signer)?;
|
let pay_stub_pod = pay_stub_builder.sign(&signer)?;
|
||||||
let signer = Signer(SecretKey(3u32.into()));
|
let kyc_builder = zu_kyc_pod_builder(¶ms, &vd_set, &gov_id_pod, &pay_stub_pod)?;
|
||||||
let sanction_list_pod = sanction_list_builder.sign(&signer)?;
|
|
||||||
let kyc_builder = zu_kyc_pod_builder(
|
|
||||||
¶ms,
|
|
||||||
&vd_set,
|
|
||||||
&gov_id_pod,
|
|
||||||
&pay_stub_pod,
|
|
||||||
&sanction_list_pod,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let prover = Prover {};
|
let prover = Prover {};
|
||||||
let kyc_pod = kyc_builder.prove(&prover, ¶ms)?;
|
let kyc_pod = kyc_builder.prove(&prover, ¶ms)?;
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@ mod tests {
|
||||||
let params = Params::default();
|
let params = Params::default();
|
||||||
let processed = parse(input, ¶ms, &[])?;
|
let processed = parse(input, ¶ms, &[])?;
|
||||||
let batch_result = processed.custom_batch;
|
let batch_result = processed.custom_batch;
|
||||||
let request_result = processed.request_templates;
|
let request_result = processed.request.templates();
|
||||||
|
|
||||||
assert_eq!(request_result.len(), 0);
|
assert_eq!(request_result.len(), 0);
|
||||||
assert_eq!(batch_result.predicates.len(), 1);
|
assert_eq!(batch_result.predicates.len(), 1);
|
||||||
|
|
@ -115,13 +115,11 @@ mod tests {
|
||||||
let params = Params::default();
|
let params = Params::default();
|
||||||
let processed = parse(input, ¶ms, &[])?;
|
let processed = parse(input, ¶ms, &[])?;
|
||||||
let batch_result = processed.custom_batch;
|
let batch_result = processed.custom_batch;
|
||||||
let request_templates = processed.request_templates;
|
let request_templates = processed.request.templates();
|
||||||
|
|
||||||
assert_eq!(batch_result.predicates.len(), 0);
|
assert_eq!(batch_result.predicates.len(), 0);
|
||||||
assert!(!request_templates.is_empty());
|
assert!(!request_templates.is_empty());
|
||||||
|
|
||||||
let request_templates = request_templates;
|
|
||||||
|
|
||||||
// Expected structure
|
// Expected structure
|
||||||
let expected_templates = vec![
|
let expected_templates = vec![
|
||||||
StatementTmpl {
|
StatementTmpl {
|
||||||
|
|
@ -157,7 +155,7 @@ mod tests {
|
||||||
let params = Params::default();
|
let params = Params::default();
|
||||||
let processed = parse(input, ¶ms, &[])?;
|
let processed = parse(input, ¶ms, &[])?;
|
||||||
let batch_result = processed.custom_batch;
|
let batch_result = processed.custom_batch;
|
||||||
let request_result = processed.request_templates;
|
let request_result = processed.request.templates();
|
||||||
|
|
||||||
assert_eq!(request_result.len(), 0);
|
assert_eq!(request_result.len(), 0);
|
||||||
assert_eq!(batch_result.predicates.len(), 1);
|
assert_eq!(batch_result.predicates.len(), 1);
|
||||||
|
|
@ -214,13 +212,12 @@ mod tests {
|
||||||
let params = Params::default();
|
let params = Params::default();
|
||||||
let processed = parse(input, ¶ms, &[])?;
|
let processed = parse(input, ¶ms, &[])?;
|
||||||
let batch_result = processed.custom_batch;
|
let batch_result = processed.custom_batch;
|
||||||
let request_templates = processed.request_templates;
|
let request_templates = processed.request.templates();
|
||||||
|
|
||||||
assert_eq!(batch_result.predicates.len(), 1);
|
assert_eq!(batch_result.predicates.len(), 1);
|
||||||
assert!(!request_templates.is_empty());
|
assert!(!request_templates.is_empty());
|
||||||
|
|
||||||
let batch = batch_result;
|
let batch = batch_result;
|
||||||
let request_templates = request_templates;
|
|
||||||
|
|
||||||
// Expected Batch structure
|
// Expected Batch structure
|
||||||
let expected_pred_statements = vec![StatementTmpl {
|
let expected_pred_statements = vec![StatementTmpl {
|
||||||
|
|
@ -278,13 +275,11 @@ mod tests {
|
||||||
let params = Params::default();
|
let params = Params::default();
|
||||||
let processed = parse(input, ¶ms, &[])?;
|
let processed = parse(input, ¶ms, &[])?;
|
||||||
let batch_result = processed.custom_batch;
|
let batch_result = processed.custom_batch;
|
||||||
let request_templates = processed.request_templates;
|
let request_templates = processed.request.templates();
|
||||||
|
|
||||||
assert_eq!(batch_result.predicates.len(), 1); // some_pred is defined
|
assert_eq!(batch_result.predicates.len(), 1); // some_pred is defined
|
||||||
assert!(!request_templates.is_empty());
|
assert!(!request_templates.is_empty());
|
||||||
|
|
||||||
let request_templates = request_templates;
|
|
||||||
|
|
||||||
// Expected Wildcard Indices in Request Scope:
|
// Expected Wildcard Indices in Request Scope:
|
||||||
// ?Var1 -> 0
|
// ?Var1 -> 0
|
||||||
// ?AnotherPod -> 1
|
// ?AnotherPod -> 1
|
||||||
|
|
@ -330,13 +325,11 @@ mod tests {
|
||||||
let params = Params::default();
|
let params = Params::default();
|
||||||
let processed = parse(input, ¶ms, &[])?;
|
let processed = parse(input, ¶ms, &[])?;
|
||||||
let batch_result = processed.custom_batch;
|
let batch_result = processed.custom_batch;
|
||||||
let request_templates = processed.request_templates;
|
let request_templates = processed.request.templates();
|
||||||
|
|
||||||
assert_eq!(batch_result.predicates.len(), 0);
|
assert_eq!(batch_result.predicates.len(), 0);
|
||||||
assert!(!request_templates.is_empty());
|
assert!(!request_templates.is_empty());
|
||||||
|
|
||||||
let request_templates = request_templates;
|
|
||||||
|
|
||||||
let expected_templates = vec![
|
let expected_templates = vec![
|
||||||
StatementTmpl {
|
StatementTmpl {
|
||||||
pred: Predicate::Native(NativePredicate::LtEq),
|
pred: Predicate::Native(NativePredicate::LtEq),
|
||||||
|
|
@ -389,7 +382,7 @@ mod tests {
|
||||||
|
|
||||||
// Parse the input string
|
// Parse the input string
|
||||||
let processed = super::parse(input, &Params::default(), &[])?;
|
let processed = super::parse(input, &Params::default(), &[])?;
|
||||||
let parsed_templates = processed.request_templates;
|
let parsed_templates = processed.request.templates();
|
||||||
|
|
||||||
// Define Expected Templates (Copied from prover/mod.rs)
|
// Define Expected Templates (Copied from prover/mod.rs)
|
||||||
let now_minus_18y_val = Value::from(1169909388_i64);
|
let now_minus_18y_val = Value::from(1169909388_i64);
|
||||||
|
|
@ -529,7 +522,7 @@ mod tests {
|
||||||
let processed = super::parse(input, ¶ms, &[])?;
|
let processed = super::parse(input, ¶ms, &[])?;
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
processed.request_templates.is_empty(),
|
processed.request.templates().is_empty(),
|
||||||
"Expected no request templates"
|
"Expected no request templates"
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|
@ -719,7 +712,7 @@ mod tests {
|
||||||
|
|
||||||
// 3. Parse the input
|
// 3. Parse the input
|
||||||
let processed = parse(&input, ¶ms, &available_batches)?;
|
let processed = parse(&input, ¶ms, &available_batches)?;
|
||||||
let request_templates = processed.request_templates;
|
let request_templates = processed.request.templates();
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
processed.custom_batch.predicates.is_empty(),
|
processed.custom_batch.predicates.is_empty(),
|
||||||
|
|
@ -771,7 +764,7 @@ mod tests {
|
||||||
|
|
||||||
// 3. Parse the input
|
// 3. Parse the input
|
||||||
let processed = parse(&input, ¶ms, &available_batches)?;
|
let processed = parse(&input, ¶ms, &available_batches)?;
|
||||||
let request_templates = processed.request_templates;
|
let request_templates = processed.request.templates();
|
||||||
|
|
||||||
assert_eq!(request_templates.len(), 2, "Expected two request templates");
|
assert_eq!(request_templates.len(), 2, "Expected two request templates");
|
||||||
|
|
||||||
|
|
@ -830,7 +823,7 @@ mod tests {
|
||||||
let processed = parse(&input, ¶ms, &available_batches)?;
|
let processed = parse(&input, ¶ms, &available_batches)?;
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
processed.request_templates.is_empty(),
|
processed.request.templates().is_empty(),
|
||||||
"No request should be defined"
|
"No request should be defined"
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|
@ -903,7 +896,7 @@ mod tests {
|
||||||
|
|
||||||
let params = Params::default();
|
let params = Params::default();
|
||||||
let processed = parse(&input, ¶ms, &[])?;
|
let processed = parse(&input, ¶ms, &[])?;
|
||||||
let request_templates = processed.request_templates;
|
let request_templates = processed.request.templates();
|
||||||
|
|
||||||
let expected_templates = vec![
|
let expected_templates = vec![
|
||||||
StatementTmpl {
|
StatementTmpl {
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,11 @@
|
||||||
|
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
|
|
||||||
use crate::middleware::{
|
use crate::{
|
||||||
|
frontend::PodRequest,
|
||||||
|
middleware::{
|
||||||
CustomPredicate, CustomPredicateBatch, Predicate, StatementTmpl, StatementTmplArg, Value,
|
CustomPredicate, CustomPredicateBatch, Predicate, StatementTmpl, StatementTmplArg, Value,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Trait for converting AST nodes to Podlang source code
|
/// Trait for converting AST nodes to Podlang source code
|
||||||
|
|
@ -122,6 +125,19 @@ impl PrettyPrint for Value {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl PrettyPrint for PodRequest {
|
||||||
|
fn fmt_podlang_with_indent(&self, w: &mut dyn Write, _indent: usize) -> std::fmt::Result {
|
||||||
|
write!(w, "REQUEST(")?;
|
||||||
|
for (i, template) in self.request_templates.iter().enumerate() {
|
||||||
|
if i > 0 {
|
||||||
|
write!(w, ", ")?;
|
||||||
|
}
|
||||||
|
template.fmt_podlang_with_indent(w, 4)?;
|
||||||
|
}
|
||||||
|
write!(w, ")")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn fmt_predicate_definition(
|
fn fmt_predicate_definition(
|
||||||
w: &mut dyn Write,
|
w: &mut dyn Write,
|
||||||
predicate: &CustomPredicate,
|
predicate: &CustomPredicate,
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,8 @@ use crate::{
|
||||||
deserialize_bytes,
|
deserialize_bytes,
|
||||||
primitives::ec::{curve::Point, schnorr::SecretKey},
|
primitives::ec::{curve::Point, schnorr::SecretKey},
|
||||||
},
|
},
|
||||||
frontend::{BuilderArg, CustomPredicateBatchBuilder, StatementTmplBuilder},
|
frontend::{BuilderArg, CustomPredicateBatchBuilder, PodRequest, StatementTmplBuilder},
|
||||||
lang::Rule,
|
lang::parser::Rule,
|
||||||
middleware::{
|
middleware::{
|
||||||
self, CustomPredicateBatch, CustomPredicateRef, Key, NativePredicate, Params, Predicate,
|
self, CustomPredicateBatch, CustomPredicateRef, Key, NativePredicate, Params, Predicate,
|
||||||
StatementTmpl, StatementTmplArg, Value, Wildcard, F, VALUE_SIZE,
|
StatementTmpl, StatementTmplArg, Value, Wildcard, F, VALUE_SIZE,
|
||||||
|
|
@ -57,7 +57,7 @@ pub fn native_predicate_from_string(s: &str) -> Option<NativePredicate> {
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct PodlangOutput {
|
pub struct PodlangOutput {
|
||||||
pub custom_batch: Arc<CustomPredicateBatch>,
|
pub custom_batch: Arc<CustomPredicateBatch>,
|
||||||
pub request_templates: Vec<StatementTmpl>,
|
pub request: PodRequest,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ProcessingContext<'a> {
|
struct ProcessingContext<'a> {
|
||||||
|
|
@ -295,7 +295,7 @@ fn second_pass(
|
||||||
|
|
||||||
Ok(PodlangOutput {
|
Ok(PodlangOutput {
|
||||||
custom_batch,
|
custom_batch,
|
||||||
request_templates,
|
request: PodRequest::new(request_templates),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue