From fb2bc47a4c5c87a04af0c2fa6ef56d3727af79de Mon Sep 17 00:00:00 2001 From: gubsheep Date: Sun, 13 Oct 2024 03:17:35 -0700 Subject: [PATCH 1/8] wip --- src/pod.rs | 748 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 478 insertions(+), 270 deletions(-) diff --git a/src/pod.rs b/src/pod.rs index 53a1898..44f7896 100644 --- a/src/pod.rs +++ b/src/pod.rs @@ -1,10 +1,8 @@ -use std::cmp::Ordering; use std::collections::HashMap; //use circuit::pod2_circuit; use plonky2::field::goldilocks_field::GoldilocksField; use plonky2::field::types::Field; -use plonky2::field::types::PrimeField64; use plonky2::hash::poseidon::PoseidonHash; use plonky2::plonk::config::GenericHashOut; use plonky2::plonk::config::Hasher; @@ -22,117 +20,19 @@ mod util; pub(crate) type Error = Box; -pub trait HashablePayload: Clone + PartialEq { - fn to_field_vec(&self) -> Vec; - - fn hash_payload(&self) -> GoldilocksField { - let ins = self.to_field_vec(); - PoseidonHash::hash_no_pad(&ins).to_vec()[0] - } -} - -impl HashablePayload for Vec> { - fn to_field_vec(&self) -> Vec { - // let mut sorted_by_key_name = self.clone(); - // sorted_by_key_name.sort_by(|a, b| a.key_name.cmp(&b.key_name)); - let mut ins = Vec::new(); - // sorted_by_key_name.iter().for_each(|entry| { - // ins.push(entry.key_hash); - // ins.push(entry.value_hash); - // }); - self.iter().for_each(|entry| { - ins.push(entry.key_hash); - ins.push(entry.value_hash); - }); - ins - } -} - -// TODO -impl HashablePayload for Vec { - fn to_field_vec(&self) -> Vec { - self.iter() - .map(|statement| { - [ - vec![ - GoldilocksField(statement.predicate as u64), - statement.origin1.origin_id, - GoldilocksField(statement.origin1.gadget_id as u64), - hash_string_to_field(&statement.key1), - ], - match statement.origin2 { - Some(ro) => vec![ro.origin_id, GoldilocksField(ro.gadget_id as u64)], - _ => vec![GoldilocksField(0), GoldilocksField(0)], - }, - vec![ - match &statement.key2 { - Some(rkn) => hash_string_to_field(&rkn), - _ => GoldilocksField::ZERO, - }, - match statement.optional_value { - Some(x) => x, - _ => GoldilocksField::ZERO, - }, - ], - ] - .concat() - }) - .collect::>>() - .concat() - } -} - -pub trait ProofOf: Clone { - fn verify(&self, payload: &Payload) -> Result; -} - -// verify schnorr POD -impl ProofOf>> for SchnorrSignature { - fn verify(&self, payload: &Vec>) -> Result { - let payload_hash = payload.hash_payload(); - let payload_hash_vec = vec![payload_hash]; - let protocol = SchnorrSigner::new(); - let wrapped_pk = payload - .iter() - .filter(|entry| entry.key_name == "_signer") - .collect::>>(); - if wrapped_pk.len() == 0 { - return Err("No signer found in payload".into()); - } - - let pk = match wrapped_pk[0].value { - ScalarOrVec::Vector(_) => Err(Error::from("Signer is a vector")), - ScalarOrVec::Scalar(s) => Ok(s), - }?; - Ok(protocol.verify(&self, &payload_hash_vec, &SchnorrPublicKey { pk })) - } -} - -// verify GODPOD -impl ProofOf> for SchnorrSignature { - fn verify(&self, payload: &Vec) -> Result { - let payload_hash = payload.hash_payload(); - let payload_hash_vec = vec![payload_hash]; - let protocol = SchnorrSigner::new(); - Ok(protocol.verify( - &self, - &payload_hash_vec, - &protocol.keygen(&SchnorrSecretKey { sk: 0 }), // hardcoded secret key - )) - } -} - -pub trait EntryValue: Clone + PartialEq { +// EntryValue trait, and ScalarOrVec type which implements it. +// This is a field element or array of field elements. +pub trait HashableEntryValue: Clone + PartialEq { fn hash_or_value(&self) -> GoldilocksField; } -impl EntryValue for GoldilocksField { +impl HashableEntryValue for GoldilocksField { fn hash_or_value(&self) -> GoldilocksField { *self } } -impl EntryValue for Vec { +impl HashableEntryValue for Vec { fn hash_or_value(&self) -> GoldilocksField { PoseidonHash::hash_no_pad(self).to_vec()[0] } @@ -144,7 +44,7 @@ pub enum ScalarOrVec { Vector(Vec), } -impl EntryValue for ScalarOrVec { +impl HashableEntryValue for ScalarOrVec { fn hash_or_value(&self) -> GoldilocksField { match self { Self::Scalar(s) => s.hash_or_value(), @@ -153,45 +53,33 @@ impl EntryValue for ScalarOrVec { } } -#[derive(Copy, Clone, Debug, PartialEq)] -#[repr(usize)] -pub enum GadgetID { - NONE = 0, - SCHNORR16 = 1, - GOD = 2, +// An Entry, which is just a key-value pair. + +#[derive(Clone, Debug, PartialEq)] +pub struct Entry { + pub key: String, + pub value: ScalarOrVec, } -#[derive(Copy, Clone, Debug, PartialEq)] +// An Origin, which represents a reference to an ancestor POD. + +#[derive(Clone, Debug, PartialEq)] pub struct Origin { pub origin_id: GoldilocksField, // reserve 0 for NONE, 1 for SELF + pub origin_name: String, pub gadget_id: GadgetID, // if origin_id is SELF, this is none; otherwise, it's the gadget_id } impl Origin { pub const NONE: Self = Origin { origin_id: GoldilocksField::ZERO, + origin_name: String::new(), gadget_id: GadgetID::NONE, }; } -#[derive(Clone, Debug, PartialEq)] -pub struct Entry { - pub key_name: String, - pub key_hash: GoldilocksField, - pub value_hash: GoldilocksField, - pub value: V, -} - -impl Entry { - fn new(key_name: &str, value: V) -> Self { - Entry { - key_name: key_name.to_string(), - key_hash: hash_string_to_field(key_name), - value_hash: value.hash_or_value(), - value, - } - } -} +// A Statement, which is a claim about one or more entries. +// Entries are ValueOf statements. #[derive(Copy, Clone, Debug, PartialEq)] #[repr(u64)] @@ -207,6 +95,7 @@ pub enum StatementPredicate { #[derive(Clone, Debug, PartialEq)] pub struct Statement { + pub name: String, // human-readable name that can be referenced in operations pub predicate: StatementPredicate, pub origin1: Origin, pub key1: String, @@ -214,151 +103,405 @@ pub struct Statement { pub key2: Option, pub origin3: Option, pub key3: Option, - pub optional_value: Option, // todo: figure out how to allow this to be any EntryValue + pub optional_value: Option, // todo: figure out how to allow this to be any EntryValue } -pub fn entry_to_statement(entry: &Entry, gadget_id: GadgetID) -> Statement { - Statement { - predicate: StatementPredicate::ValueOf, - origin1: Origin { - origin_id: GoldilocksField(1), - gadget_id, - }, - key1: entry.key_name.clone(), - origin2: None, - key2: None, - origin3: None, - key3: None, - optional_value: Some(entry.value.hash_or_value()), +impl Statement { + pub fn from_entry(entry: &Entry, this_gadget_id: GadgetID) -> Self { + Statement { + name: entry.key.to_string(), + predicate: StatementPredicate::ValueOf, + origin1: Origin { + origin_id: GoldilocksField(1), + origin_name: "_SELF".to_string(), + gadget_id: this_gadget_id, + }, + key1: entry.key.to_string(), + origin2: None, + key2: None, + origin3: None, + key3: None, + optional_value: Some(entry.value.clone()), + } } } -impl Into for Entry { - fn into(self) -> Statement { - entry_to_statement(&self, GadgetID::NONE) +// HashablePayload trait, and PODPayload which implements it. + +pub trait HashablePayload: Clone + PartialEq { + fn to_field_vec(&self) -> Vec; + + fn hash_payload(&self) -> GoldilocksField { + let ins = self.to_field_vec(); + PoseidonHash::hash_no_pad(&ins).to_vec()[0] } } #[derive(Clone, Debug, PartialEq)] -pub struct POD, const FromGadgetID: usize> { - pub payload: Payload, - proof: Proof, +pub struct PODPayload { + pub statements_list: Vec, // ORDERED list of statements, ordered by names + pub statements_map: HashMap, +} + +impl PODPayload { + pub fn new(statements: HashMap) -> Self { + let mut statements_list = Vec::new(); + for (_, statement) in statements.iter() { + statements_list.push(statement.clone()); + } + statements_list.sort_by(|a, b| a.name.cmp(&b.name)); + Self { + statements_list, + statements_map: statements.clone(), + } + } +} + +impl HashablePayload for Vec { + fn to_field_vec(&self) -> Vec { + self.iter() + .map(|statement| { + [ + vec![ + GoldilocksField(statement.predicate as u64), + statement.origin1.origin_id, + GoldilocksField(statement.origin1.gadget_id as u64), + hash_string_to_field(&statement.key1), + ], + match &statement.origin2 { + Some(o) => vec![o.origin_id, GoldilocksField(o.gadget_id as u64)], + _ => vec![GoldilocksField(0), GoldilocksField(0)], + }, + match &statement.key2 { + Some(kn) => vec![hash_string_to_field(&kn)], + _ => vec![GoldilocksField::ZERO], + }, + match &statement.origin3 { + Some(o) => vec![o.origin_id, GoldilocksField(o.gadget_id as u64)], + _ => vec![GoldilocksField(0), GoldilocksField(0)], + }, + match &statement.key3 { + Some(kn) => vec![hash_string_to_field(&kn)], + _ => vec![GoldilocksField::ZERO], + }, + match &statement.optional_value { + Some(x) => vec![x.hash_or_value()], + _ => vec![GoldilocksField::ZERO], + }, + ] + .concat() + }) + .collect::>>() + .concat() + } } -type SchnorrPOD = POD>, SchnorrSignature, { GadgetID::SCHNORR16 as usize }>; +impl HashablePayload for PODPayload { + fn to_field_vec(&self) -> Vec { + self.statements_list.to_field_vec() + } +} -type GODPOD = POD, SchnorrSignature, { GadgetID::GOD as usize }>; +#[derive(Copy, Clone, Debug, PartialEq)] +pub enum GadgetID { + NONE = 0, + SCHNORR16 = 1, + ORACLE = 2, +} + +#[derive(Copy, Clone, Debug, PartialEq)] +pub enum PODProof { + Schnorr(SchnorrSignature), + Oracle(SchnorrSignature), +} #[derive(Clone, Debug, PartialEq)] -pub enum SchnorrOrGODPOD { - SchnorrPOD(SchnorrPOD), - GODPOD(GODPOD), +pub struct POD { + pub payload: PODPayload, + proof: PODProof, + pub proof_type: GadgetID, } -impl, const FromGadgetID: usize> - POD -{ +impl POD { pub fn verify(&self) -> Result { - self.proof.verify(&self.payload) + match self.proof { + PODProof::Schnorr(p) => { + if self.proof_type != GadgetID::SCHNORR16 { + return Err("Proof and POD proofType mismatch".into()); + } + + let payload_hash = self.payload.hash_payload(); + let payload_hash_vec = vec![payload_hash]; + let protocol = SchnorrSigner::new(); + + let wrapped_pk = self + .payload + .statements_list + .iter() + .filter(|&statement| { + statement.predicate == StatementPredicate::ValueOf + && statement.key1 == "_signer" + }) + .collect::>(); + + if wrapped_pk.len() == 0 { + return Err("No signer found in payload".into()); + } + + let pk = match wrapped_pk[0].optional_value { + Some(ScalarOrVec::Vector(_)) => Err(Error::from("Signer is a vector")), + Some(ScalarOrVec::Scalar(s)) => Ok(s), + _ => Err("_signer key found but no corresponding value".into()), + }?; + Ok(protocol.verify(&p, &payload_hash_vec, &SchnorrPublicKey { pk })) + } + PODProof::Oracle(p) => { + if self.proof_type != GadgetID::ORACLE { + return Err("Proof and POD proofType mismatch".into()); + } + + let payload_hash = self.payload.hash_payload(); + let payload_hash_vec = vec![payload_hash]; + let protocol = SchnorrSigner::new(); + + Ok(protocol.verify( + &p, + &payload_hash_vec, + &protocol.keygen(&SchnorrSecretKey { sk: 0 }), // hardcoded secret key + )) + } + _ => Err("Invalid proof type".into()), + } } -} -impl SchnorrPOD { - pub fn gadget(entries: &Vec>, sk: &SchnorrSecretKey) -> Self { + pub fn execute_schnorr_gadget(entries: &Vec, sk: &SchnorrSecretKey) -> Self { let mut rng: rand::rngs::ThreadRng = rand::thread_rng(); let protocol = SchnorrSigner::new(); - let mut payload = entries.clone(); - payload.push(Entry::new( - "_signer", - ScalarOrVec::Scalar(protocol.keygen(sk).pk), - )); + let mut kv_pairs = entries.clone(); + kv_pairs.push(Entry { + key: "_signer".to_string(), + value: ScalarOrVec::Scalar(protocol.keygen(sk).pk), + }); + let mut statement_map: HashMap = HashMap::new(); + + for entry in kv_pairs { + statement_map.insert( + entry.key.clone(), + Statement::from_entry(&entry, GadgetID::SCHNORR16), + ); + } + + let payload = PODPayload::new(statement_map); let payload_hash = payload.hash_payload(); let payload_hash_vec = vec![payload_hash]; let proof = protocol.sign(&payload_hash_vec, sk, &mut rng); - Self { payload, proof } + Self { + payload, + proof: PODProof::Schnorr(proof), + proof_type: GadgetID::SCHNORR16, + } } -} -pub fn remap_origin_ids(inputs: &Vec>) -> Vec> { - let mut all_in_origin_ids = Vec::new(); - for i in 0..inputs.len() { - for statement in inputs[i].iter() { - let left_origin_tuple = (i, statement.origin1.origin_id); - if !all_in_origin_ids.contains(&left_origin_tuple) { - all_in_origin_ids.push(left_origin_tuple); - } + fn remap_origin_ids_by_name( + inputs: GPGInput, + ) -> Result>, Error> { + let mut new_origin_name_list = Vec::new(); + for (_, new_name) in inputs.origin_renaming_map.iter() { + new_origin_name_list.push(new_name.clone()); + } + new_origin_name_list.sort(); + + let mut new_origin_name_to_id_map = HashMap::new(); + for (idx, new_name) in new_origin_name_list.iter().enumerate() { + new_origin_name_to_id_map.insert(new_name.clone(), idx + 2); // 0 reserved for none, 1 reserved for _SELF + } - if let Some(right_origin) = statement.origin2 { - let right_origin_tuple = (i, right_origin.origin_id); - if !all_in_origin_ids.contains(&right_origin_tuple) { - all_in_origin_ids.push(right_origin_tuple); + let mut statements_with_renamed_origins = HashMap::new(); + + for (pod_idx, (pod_name, pod)) in inputs.pods_list.iter().enumerate() { + let mut inner_map = HashMap::new(); + + for statement in pod.payload.statements_list.iter() { + let mut statement_with_remapped_origins = statement.clone(); + let pod_name_clone = pod_name.clone(); + // origin 1 + let new_origin1_name = inputs + .origin_renaming_map + .get(&(pod_name.clone(), statement.origin1.origin_name.clone())); + match new_origin1_name { + Some(new_origin1_name) => { + let new_origin1_id = new_origin_name_to_id_map.get(new_origin1_name); + match new_origin1_id { + Some(&new_origin1_id) => { + statement_with_remapped_origins.origin1 = Origin { + origin_id: GoldilocksField(new_origin1_id as u64), + origin_name: new_origin1_name.clone(), + gadget_id: statement.origin1.gadget_id, + } + } + None => { + return Err(("couldn't find id for new origin: ".to_string() + + new_origin1_name) + .into()); + } + } + } + None => { + return Err(("couldn't find new origin name for origin: ".to_string() + + &pod_name.clone() + + "." + + &statement.origin1.origin_name.clone()) + .into()) + } + } + // origin 2 + if let Some(old_origin2) = &statement.origin2 { + let new_origin2_name = inputs + .origin_renaming_map + .get(&(pod_name.clone(), old_origin2.origin_name.clone())); + match new_origin2_name { + Some(new_origin2_name) => { + let new_origin2_id = new_origin_name_to_id_map.get(new_origin2_name); + match new_origin2_id { + Some(&new_origin2_id) => { + statement_with_remapped_origins.origin2 = Some(Origin { + origin_id: GoldilocksField(new_origin2_id as u64), + origin_name: new_origin2_name.clone(), + gadget_id: old_origin2.gadget_id, + }) + } + None => { + return Err(("couldn't find id for new origin: ".to_string() + + new_origin2_name) + .into()); + } + } + } + None => { + return Err(("couldn't find new origin name for origin: ".to_string() + + &pod_name.clone() + + "." + + &old_origin2.origin_name.clone()) + .into()) + } + } + } + // origin 3 + if let Some(old_origin3) = &statement.origin3 { + let new_origin3_name = inputs + .origin_renaming_map + .get(&(pod_name.clone(), old_origin3.origin_name.clone())); + match new_origin3_name { + Some(new_origin3_name) => { + let new_origin3_id = new_origin_name_to_id_map.get(new_origin3_name); + match new_origin3_id { + Some(&new_origin3_id) => { + statement_with_remapped_origins.origin3 = Some(Origin { + origin_id: GoldilocksField(new_origin3_id as u64), + origin_name: new_origin3_name.clone(), + gadget_id: old_origin3.gadget_id, + }) + } + None => { + return Err(("couldn't find id for new origin: ".to_string() + + new_origin3_name) + .into()); + } + } + } + None => { + return Err(("couldn't find new origin name for origin: ".to_string() + + &pod_name.clone() + + "." + + &old_origin3.origin_name.clone()) + .into()) + } + } } + + inner_map.insert(statement.name.clone(), statement_with_remapped_origins); } + statements_with_renamed_origins.insert(pod_name.clone(), inner_map); } + + Ok(statements_with_renamed_origins) } - // sort all_in_origin_ids in place - all_in_origin_ids.sort_by(|a, b| { - let first_cmp = a.0.cmp(&b.0); - if first_cmp == Ordering::Equal { - (a.1).to_canonical_u64().cmp(&(b.1).to_canonical_u64()) - } else { - first_cmp + fn get_statement_with_origin_and_name( + statements: &HashMap>, + self_statements: &HashMap, + origin: Option, + name: Option, + ) -> Option { + if let Some(origin) = origin { + if let Some(name) = name { + if origin == "_SELF" { + return self_statements.get(&name).cloned(); + } + if let Some(map) = statements.get(&origin) { + if let Some(statement) = map.get(&name) { + return Some(statement.clone()); + } + } + } } - }); - - let mut origin_id_map = HashMap::new(); - for idx_and_origin_id in all_in_origin_ids.iter().enumerate() { - origin_id_map.insert(idx_and_origin_id.1, (idx_and_origin_id.0 + 2) as u64); + None } - let mut remapped_inputs = Vec::new(); - - println!("origin id map: {:?}", origin_id_map); - - for (idx, input) in inputs.iter().enumerate() { - let mut remapped_input = Vec::new(); - for statement in input { - let mut remapped_statement = statement.clone(); - println!("index: {:?}", idx); - println!("OLD statement: {:?}", remapped_statement); - remapped_statement.origin1.origin_id = GoldilocksField( - *origin_id_map - .get(&(idx, remapped_statement.origin1.origin_id)) - .unwrap(), - ); - if let Some(right_origin) = remapped_statement.origin2 { - remapped_statement.origin2 = Some(Origin { - origin_id: GoldilocksField( - *origin_id_map.get(&(idx, right_origin.origin_id)).unwrap(), - ), - gadget_id: right_origin.gadget_id, - }); + pub fn execute_oracle_gadget(input: GPGInput, cmds: &Vec) -> Result { + let statements = POD::remap_origin_ids_by_name(input); + match &statements { + Ok(statements) => { + let mut out_statements = HashMap::new(); + for cmd in cmds { + let statement1 = POD::get_statement_with_origin_and_name( + statements, + &out_statements, + cmd.statement_1_name.clone(), + cmd.statement_1_origin.clone(), + ); + let statement2 = POD::get_statement_with_origin_and_name( + &statements, + &out_statements, + cmd.statement_2_name.clone(), + cmd.statement_2_origin.clone(), + ); + let statement3 = POD::get_statement_with_origin_and_name( + &statements, + &out_statements, + cmd.statement_3_name.clone(), + cmd.statement_3_origin.clone(), + ); + let new_statement = cmd.execute(GadgetID::ORACLE, statements, &out_statements); + match new_statement { + Ok(new_statement) => { + out_statements.insert(cmd.output_statement_name.clone(), new_statement); + } + Err(e) => return Err(e), + } + } + let out_payload = PODPayload::new(out_statements); + let mut rng: rand::rngs::ThreadRng = rand::thread_rng(); + let protocol = SchnorrSigner::new(); + let payload_hash = out_payload.hash_payload(); + let payload_hash_vec = vec![payload_hash]; + + // signature is a hardcoded skey (currently 0) + // todo is to build a limited version of this with a ZKP + // would start by making it so that the ZKP only allows + // a max number of input PODs, max number of entries/statements per input POD, + // max number of statements for output POD, and some max number of each type of operation + let proof = protocol.sign(&payload_hash_vec, &SchnorrSecretKey { sk: 0 }, &mut rng); + Ok(Self { + payload: out_payload, + proof: PODProof::Oracle(proof), + proof_type: GadgetID::ORACLE, + }) } - println!("NEW statement: {:?}", remapped_statement); - remapped_input.push(remapped_statement); + Err(e) => Err(*e), } - remapped_inputs.push(remapped_input); } - remapped_inputs -} - -pub fn to_statements_with_remapping(inputs: &Vec<&SchnorrOrGODPOD>) -> Vec { - let statements = inputs - .iter() - .map(|pod| match pod { - SchnorrOrGODPOD::GODPOD(p) => p.clone().payload, - SchnorrOrGODPOD::SchnorrPOD(p) => p - .payload - .iter() - .map(|entry| entry_to_statement(entry, GadgetID::SCHNORR16)) - .collect::>(), - }) - .collect::>>(); - - // Now remap - remap_origin_ids(&statements).concat() } impl GODPOD { @@ -381,7 +524,7 @@ impl GODPOD { pub fn gadget( inputs: &Vec<&SchnorrOrGODPOD>, // will be converted to a vector of statements operations: &Vec<( - Operation, + OperationType, Option, Option, Option, @@ -440,8 +583,37 @@ impl GODPOD { } } +// Operations + +pub struct GPGInput { + pub pods_list: Vec<(String, POD)>, // ORDERED list of pods, ordered by names + pub pods_map: HashMap, // map from pod name to pod + + // map from (pod name, old origin name) to new origin name + pub origin_renaming_map: HashMap<(String, String), String>, +} + +impl GPGInput { + pub fn new( + named_pods: HashMap, + origin_renaming_map: HashMap<(String, String), String>, + ) -> Self { + let mut pods_and_names_list = Vec::new(); + for (name, pod) in named_pods.iter() { + pods_and_names_list.push((name.clone(), pod.clone())); + } + pods_and_names_list.sort_by(|a, b| a.0.cmp(&b.0)); + + return Self { + pods_list: pods_and_names_list.clone(), + pods_map: named_pods.clone(), + origin_renaming_map: origin_renaming_map.clone(), + }; + } +} + #[derive(Copy, Clone, Debug)] -pub enum Operation { +pub enum OperationType { None = 0, NewEntry = 1, CopyStatement = 2, @@ -454,8 +626,32 @@ pub enum Operation { SumOf = 9, } -impl Operation { - pub fn apply_operation( +#[derive(Clone, Debug)] +pub struct OperationCmd { + pub operation_type: OperationType, + pub statement_1_origin: Option, + pub statement_1_name: Option, + pub statement_2_origin: Option, + pub statement_2_name: Option, + pub statement_3_origin: Option, + pub statement_3_name: Option, + pub optional_entry: Option<(String, ScalarOrVec)>, + pub output_statement_name: String, +} + +impl OperationCmd { + pub fn execute( + &self, + gadget_id: GadgetID, + in_statements: &HashMap>, + self_statements: &HashMap, + ) -> Result { + Err("unimplemented".into()) + } +} + +impl OperationType { + pub fn apply_operation( &self, gadget_id: GadgetID, statement1: Option<&Statement>, @@ -668,7 +864,7 @@ fn op_test() -> Result<(), Error> { let entry_statement6 = entry6.into(); // Entry 2's value = entry 1's value + entry 6's value - let sum_of_statement = Operation::SumOf + let sum_of_statement = OperationType::SumOf .apply_operation( GadgetID::GOD, Some(&entry_statement2), @@ -695,7 +891,7 @@ fn op_test() -> Result<(), Error> { // Copy statements and check for equality of entries. entries.into_iter().for_each(|statement| { - let copy = Operation::CopyStatement + let copy = OperationType::CopyStatement .apply_operation::(GadgetID::GOD, Some(statement), None, None, None) .expect("This value should exist."); assert!(© == statement); @@ -704,7 +900,7 @@ fn op_test() -> Result<(), Error> { // Equality checks println!( "{:?}", - Operation::EqualityFromEntries.apply_operation::( + OperationType::EqualityFromEntries.apply_operation::( GadgetID::GOD, Some(&entry_statement1), Some(&entry_statement2), @@ -714,7 +910,7 @@ fn op_test() -> Result<(), Error> { ); entries.into_iter().for_each(|statement| { assert!( - Operation::EqualityFromEntries.apply_operation::( + OperationType::EqualityFromEntries.apply_operation::( GadgetID::GOD, Some(statement), Some(statement), @@ -748,7 +944,7 @@ fn op_test() -> Result<(), Error> { // }) // ); assert!( - Operation::EqualityFromEntries.apply_operation::( + OperationType::EqualityFromEntries.apply_operation::( GadgetID::GOD, Some(&entry_statement1), Some(&entry_statement2), @@ -758,7 +954,7 @@ fn op_test() -> Result<(), Error> { ); // Gt check - let gt_statement = Operation::GtFromEntries.apply_operation::( + let gt_statement = OperationType::GtFromEntries.apply_operation::( GadgetID::GOD, Some(&entry_statement2), Some(&entry_statement1), @@ -780,7 +976,7 @@ fn op_test() -> Result<(), Error> { ); // Eq transitivity check - let eq_statement1 = Operation::EqualityFromEntries + let eq_statement1 = OperationType::EqualityFromEntries .apply_operation::( GadgetID::GOD, Some(&entry_statement4), @@ -789,7 +985,7 @@ fn op_test() -> Result<(), Error> { None, ) .unwrap(); - let eq_statement2 = Operation::EqualityFromEntries + let eq_statement2 = OperationType::EqualityFromEntries .apply_operation::( GadgetID::GOD, Some(&entry_statement1), @@ -798,7 +994,7 @@ fn op_test() -> Result<(), Error> { None, ) .unwrap(); - let eq_statement3 = Operation::EqualityFromEntries + let eq_statement3 = OperationType::EqualityFromEntries .apply_operation::( GadgetID::GOD, Some(&entry_statement4), @@ -809,7 +1005,7 @@ fn op_test() -> Result<(), Error> { .unwrap(); assert!( - Operation::TransitiveEqualityFromStatements.apply_operation::( + OperationType::TransitiveEqualityFromStatements.apply_operation::( GadgetID::GOD, Some(&eq_statement1), Some(&eq_statement2), @@ -823,7 +1019,7 @@ fn op_test() -> Result<(), Error> { let mut expected_statement = unwrapped_gt_statement.clone(); expected_statement.predicate = StatementPredicate::NotEqual; assert!( - Operation::GtToNonequality.apply_operation::( + OperationType::GtToNonequality.apply_operation::( GadgetID::GOD, Some(&unwrapped_gt_statement), None, @@ -932,23 +1128,35 @@ fn god_pod_from_schnorr_test() -> Result<(), Error> { &SchnorrOrGODPOD::SchnorrPOD(schnorrPOD3.clone()), ], &vec![ - (Operation::CopyStatement, Some(0), None, None, None), - (Operation::CopyStatement, Some(1), None, None, None), - (Operation::CopyStatement, Some(2), None, None, None), - (Operation::CopyStatement, Some(3), None, None, None), - (Operation::CopyStatement, Some(4), None, None, None), - (Operation::CopyStatement, Some(5), None, None, None), - (Operation::NewEntry, None, None, None, Some(&entry9)), - (Operation::EqualityFromEntries, Some(1), Some(4), None, None), - (Operation::EqualityFromEntries, Some(4), Some(8), None, None), + (OperationType::CopyStatement, Some(0), None, None, None), + (OperationType::CopyStatement, Some(1), None, None, None), + (OperationType::CopyStatement, Some(2), None, None, None), + (OperationType::CopyStatement, Some(3), None, None, None), + (OperationType::CopyStatement, Some(4), None, None, None), + (OperationType::CopyStatement, Some(5), None, None, None), + (OperationType::NewEntry, None, None, None, Some(&entry9)), + ( + OperationType::EqualityFromEntries, + Some(1), + Some(4), + None, + None, + ), + ( + OperationType::EqualityFromEntries, + Some(4), + Some(8), + None, + None, + ), ( - Operation::NonequalityFromEntries, + OperationType::NonequalityFromEntries, Some(0), Some(1), None, None, ), - (Operation::GtFromEntries, Some(1), Some(0), None, None), + (OperationType::GtFromEntries, Some(1), Some(0), None, None), ], ); println!("GODPOD1: {:?}", god_pod_1); @@ -962,18 +1170,18 @@ fn god_pod_from_schnorr_test() -> Result<(), Error> { &SchnorrOrGODPOD::SchnorrPOD(schnorrPOD3.clone()), ], &vec![ - (Operation::CopyStatement, Some(8), None, None, None), - (Operation::CopyStatement, Some(9), None, None, None), - (Operation::CopyStatement, Some(3), None, None, None), - (Operation::GtFromEntries, Some(6), Some(0), None, None), + (OperationType::CopyStatement, Some(8), None, None, None), + (OperationType::CopyStatement, Some(9), None, None, None), + (OperationType::CopyStatement, Some(3), None, None, None), + (OperationType::GtFromEntries, Some(6), Some(0), None, None), ( - Operation::TransitiveEqualityFromStatements, + OperationType::TransitiveEqualityFromStatements, Some(7), Some(8), None, None, ), - (Operation::GtToNonequality, Some(10), None, None, None), + (OperationType::GtToNonequality, Some(10), None, None, None), ], ); println!("GODPOD2: {:?}", god_pod_2); @@ -1030,6 +1238,6 @@ fn god_pod_should_panic() { &SchnorrOrGODPOD::SchnorrPOD(schnorrPOD2.clone()), ], // this Gt operation should fail because 36 is not gt 52 - &vec![(Operation::GtFromEntries, Some(0), Some(1), None, None)], + &vec![(OperationType::GtFromEntries, Some(0), Some(1), None, None)], ); } From 6771fca4b3730f14d1660be7c5d3f38f7ac1232c Mon Sep 17 00:00:00 2001 From: gubsheep Date: Sun, 13 Oct 2024 03:57:52 -0700 Subject: [PATCH 2/8] code added but no tests yet --- src/pod.rs | 360 +++++++++++++++++++++++++---------------------------- 1 file changed, 167 insertions(+), 193 deletions(-) diff --git a/src/pod.rs b/src/pod.rs index 44f7896..03c1248 100644 --- a/src/pod.rs +++ b/src/pod.rs @@ -3,6 +3,7 @@ use std::collections::HashMap; //use circuit::pod2_circuit; use plonky2::field::goldilocks_field::GoldilocksField; use plonky2::field::types::Field; +use plonky2::field::types::PrimeField64; use plonky2::hash::poseidon::PoseidonHash; use plonky2::plonk::config::GenericHashOut; use plonky2::plonk::config::Hasher; @@ -144,7 +145,7 @@ pub struct PODPayload { } impl PODPayload { - pub fn new(statements: HashMap) -> Self { + pub fn new(statements: &HashMap) -> Self { let mut statements_list = Vec::new(); for (_, statement) in statements.iter() { statements_list.push(statement.clone()); @@ -292,7 +293,7 @@ impl POD { ); } - let payload = PODPayload::new(statement_map); + let payload = PODPayload::new(&statement_map); let payload_hash = payload.hash_payload(); let payload_hash_vec = vec![payload_hash]; let proof = protocol.sign(&payload_hash_vec, sk, &mut rng); @@ -428,59 +429,26 @@ impl POD { Ok(statements_with_renamed_origins) } - fn get_statement_with_origin_and_name( - statements: &HashMap>, - self_statements: &HashMap, - origin: Option, - name: Option, - ) -> Option { - if let Some(origin) = origin { - if let Some(name) = name { - if origin == "_SELF" { - return self_statements.get(&name).cloned(); - } - if let Some(map) = statements.get(&origin) { - if let Some(statement) = map.get(&name) { - return Some(statement.clone()); - } - } - } - } - None - } - pub fn execute_oracle_gadget(input: GPGInput, cmds: &Vec) -> Result { - let statements = POD::remap_origin_ids_by_name(input); - match &statements { + let mut statements = POD::remap_origin_ids_by_name(input); + match &mut statements { Ok(statements) => { - let mut out_statements = HashMap::new(); + statements.insert("_SELF".to_string(), HashMap::new()); for cmd in cmds { - let statement1 = POD::get_statement_with_origin_and_name( - statements, - &out_statements, - cmd.statement_1_name.clone(), - cmd.statement_1_origin.clone(), - ); - let statement2 = POD::get_statement_with_origin_and_name( - &statements, - &out_statements, - cmd.statement_2_name.clone(), - cmd.statement_2_origin.clone(), - ); - let statement3 = POD::get_statement_with_origin_and_name( - &statements, - &out_statements, - cmd.statement_3_name.clone(), - cmd.statement_3_origin.clone(), - ); - let new_statement = cmd.execute(GadgetID::ORACLE, statements, &out_statements); + let new_statement = cmd.execute(GadgetID::ORACLE, statements); match new_statement { - Ok(new_statement) => { - out_statements.insert(cmd.output_statement_name.clone(), new_statement); + Some(new_statement) => { + statements + .get_mut("_SELF") + .unwrap() + .insert(cmd.output_statement_name.clone(), new_statement); + } + None => { + return Err("operation failed to execute".into()); } - Err(e) => return Err(e), } } + let out_statements = statements.get("_SELF").unwrap(); let out_payload = PODPayload::new(out_statements); let mut rng: rand::rngs::ThreadRng = rand::thread_rng(); let protocol = SchnorrSigner::new(); @@ -499,87 +467,8 @@ impl POD { proof_type: GadgetID::ORACLE, }) } - Err(e) => Err(*e), - } - } -} - -impl GODPOD { - pub fn new(statements: &Vec) -> Self { - let mut rng: rand::rngs::ThreadRng = rand::thread_rng(); - let protocol = SchnorrSigner::new(); - let payload = statements.clone(); - let payload_hash = statements.hash_payload(); - let payload_hash_vec = vec![payload_hash]; - - // signature is a hardcoded skey (currently 0) - // todo is to build a limited version of this with a ZKP - // would start by making it so that the ZKP only allows - // a max number of input PODs, max number of entries/statements per input POD, - // max number of statements for output POD, and some max number of each type of operation - let proof = protocol.sign(&payload_hash_vec, &SchnorrSecretKey { sk: 0 }, &mut rng); - Self { payload, proof } - } - - pub fn gadget( - inputs: &Vec<&SchnorrOrGODPOD>, // will be converted to a vector of statements - operations: &Vec<( - OperationType, - Option, - Option, - Option, - Option<&Entry>, - )>, - ) -> Self { - // Check all input pods are valid. - for pod in inputs { - match pod { - SchnorrOrGODPOD::GODPOD(p) => { - assert!(p.verify().expect("input GODPOD verification failed")); - } - SchnorrOrGODPOD::SchnorrPOD(p) => { - assert!(p.verify().expect("input SchnorrPOD verification failed")); - } - } - } - // Compile/arrange list of statements as Vec (after converting each `Entry` into a `ValueOf` statement). - // and then remap - let remapped_statements = to_statements_with_remapping(inputs); - - // apply operations one by one on remapped_statements - let mut final_statements = Vec::new(); - for (operation, idx1, idx2, idx3, entry) in operations { - let statement1 = match idx1 { - Some(idx) => Some(&remapped_statements[*idx]), - None => None, - }; - let statement2 = match idx2 { - Some(idx) => Some(&remapped_statements[*idx]), - None => None, - }; - let statement3 = match idx3 { - Some(idx) => Some(&remapped_statements[*idx]), - None => None, - }; - let optional_entry = match entry { - Some(entry) => Some(*entry), - None => None, - }; - final_statements.push(operation.apply_operation( - GadgetID::GOD, - statement1, - statement2, - statement3, - optional_entry, - )) + Err(e) => panic!("Error: {:?}", e), } - - GODPOD::new( - &final_statements - .iter() - .map(|maybe_statement| maybe_statement.clone().unwrap()) - .collect::>(), - ) } } @@ -635,68 +524,71 @@ pub struct OperationCmd { pub statement_2_name: Option, pub statement_3_origin: Option, pub statement_3_name: Option, - pub optional_entry: Option<(String, ScalarOrVec)>, + pub optional_entry: Option, pub output_statement_name: String, } impl OperationCmd { - pub fn execute( - &self, - gadget_id: GadgetID, - in_statements: &HashMap>, - self_statements: &HashMap, - ) -> Result { - Err("unimplemented".into()) + fn get_statement_with_origin_and_name( + statements: &HashMap>, + origin: Option, + name: Option, + ) -> Option { + if let Some(origin) = origin { + if let Some(name) = name { + if let Some(map) = statements.get(&origin) { + if let Some(statement) = map.get(&name) { + return Some(statement.clone()); + } + } + } + } + None } -} -impl OperationType { - pub fn apply_operation( + pub fn execute( &self, gadget_id: GadgetID, - statement1: Option<&Statement>, - statement2: Option<&Statement>, - statement3: Option<&Statement>, - optional_entry: Option<&Entry>, + statements: &HashMap>, ) -> Option { - match (self, statement1, statement2, statement3, optional_entry) { + let statement1 = OperationCmd::get_statement_with_origin_and_name( + statements, + self.statement_1_name.clone(), + self.statement_1_origin.clone(), + ); + let statement2 = OperationCmd::get_statement_with_origin_and_name( + statements, + self.statement_2_name.clone(), + self.statement_2_origin.clone(), + ); + let statement3 = OperationCmd::get_statement_with_origin_and_name( + statements, + self.statement_3_name.clone(), + self.statement_3_origin.clone(), + ); + let optional_entry = self.optional_entry.clone(); + + match ( + self.operation_type, + statement1, + statement2, + statement3, + optional_entry, + ) { // A new statement is created from a single `Entry`. - (Self::NewEntry, _, _, _, Some(entry)) => Some(entry_to_statement(&entry, gadget_id)), - // SumOf <=> statement 1's value = statement 2's value + statement 3's value - (Self::SumOf, Some(statement1), Some(statement2), Some(statement3), _) => { - if [ - statement1.predicate, - statement2.predicate, - statement3.predicate, - ] - .into_iter() - .all(|p| p == StatementPredicate::ValueOf) - && (statement1.optional_value? - == statement2.optional_value? + statement3.optional_value?) - { - Some(Statement { - predicate: StatementPredicate::SumOf, - origin1: statement1.origin1, - key1: statement1.key1.clone(), - origin2: Some(statement2.origin1), - key2: Some(statement2.key1.clone()), - origin3: Some(statement3.origin1), - key3: Some(statement3.key1.clone()), - optional_value: None, - }) - } else { - None - } + (OperationType::NewEntry, _, _, _, Some(entry)) => { + return Some(Statement::from_entry(&entry, gadget_id)); } // A statement is copied from a single (left) statement. - (Self::CopyStatement, Some(statement), _, _, _) => Some(statement.clone()), + (OperationType::CopyStatement, Some(statement), _, _, _) => Some(statement.clone()), // Eq <=> Left entry = right entry - (Self::EqualityFromEntries, Some(left_entry), Some(right_entry), _, _) => { + (OperationType::EqualityFromEntries, Some(left_entry), Some(right_entry), _, _) => { match (left_entry.predicate, right_entry.predicate) { (StatementPredicate::ValueOf, StatementPredicate::ValueOf) if left_entry.optional_value == right_entry.optional_value => { - Some(Statement { + return Some(Statement { + name: self.output_statement_name.clone(), predicate: StatementPredicate::Equal, origin1: left_entry.origin1, key1: left_entry.key1.clone(), @@ -705,18 +597,21 @@ impl OperationType { origin3: None, key3: None, optional_value: None, - }) + }); + } + _ => { + return None; } - _ => None, } } // Neq <=> Left entry != right entry - (Self::NonequalityFromEntries, Some(left_entry), Some(right_entry), _, _) => { + (OperationType::NonequalityFromEntries, Some(left_entry), Some(right_entry), _, _) => { match (left_entry.predicate, right_entry.predicate) { (StatementPredicate::ValueOf, StatementPredicate::ValueOf) if left_entry.optional_value != right_entry.optional_value => { - Some(Statement { + return Some(Statement { + name: self.output_statement_name.clone(), predicate: StatementPredicate::NotEqual, origin1: left_entry.origin1, key1: left_entry.key1.clone(), @@ -725,13 +620,15 @@ impl OperationType { origin3: None, key3: None, optional_value: None, - }) + }); + } + _ => { + return None; } - _ => None, } } // Gt <=> Left entry > right entry - (Self::GtFromEntries, Some(left_entry), Some(right_entry), _, _) => { + (OperationType::GtFromEntries, Some(left_entry), Some(right_entry), _, _) => { match ( left_entry.predicate, left_entry.optional_value, @@ -740,11 +637,12 @@ impl OperationType { ) { ( StatementPredicate::ValueOf, - Some(left_value), + Some(ScalarOrVec::Scalar(left_value)), StatementPredicate::ValueOf, - Some(right_value), + Some(ScalarOrVec::Scalar(right_value)), ) if left_value.to_canonical_u64() > right_value.to_canonical_u64() => { - Some(Statement { + return Some(Statement { + name: self.output_statement_name.clone(), predicate: StatementPredicate::Gt, origin1: left_entry.origin1, key1: left_entry.key1.clone(), @@ -753,15 +651,17 @@ impl OperationType { origin3: None, key3: None, optional_value: None, - }) + }); + } + _ => { + return None; } - _ => None, } } // Equality deduction: a = b ∧ b = c => a = c. // TODO: Allow for permutations of left/right values. ( - Self::TransitiveEqualityFromStatements, + OperationType::TransitiveEqualityFromStatements, Some(left_statement), Some(right_statement), _, @@ -769,12 +669,14 @@ impl OperationType { ) => match (left_statement, right_statement) { ( Statement { + name: _, predicate: StatementPredicate::Equal, origin1: ll_origin, key1: ll_key_name, origin2: Some(Origin { origin_id: lr_origin_id, + origin_name: _, gadget_id: _, }), key2: Some(lr_key_name), @@ -783,10 +685,12 @@ impl OperationType { optional_value: _, }, Statement { + name: _, predicate: StatementPredicate::Equal, origin1: Origin { origin_id: rl_origin_id, + origin_name: _, gadget_id: _, }, key1: rl_key_name, @@ -798,10 +702,11 @@ impl OperationType { }, ) if (lr_origin_id, &lr_key_name) == ((rl_origin_id, &rl_key_name)) => { Some(Statement { + name: self.output_statement_name.clone(), predicate: StatementPredicate::Equal, - origin1: *ll_origin, + origin1: ll_origin.clone(), key1: ll_key_name.clone(), - origin2: *rr_origin, + origin2: rr_origin.clone(), key2: rr_key_name.clone(), origin3: None, key3: None, @@ -810,8 +715,10 @@ impl OperationType { } _ => None, }, - (Self::GtToNonequality, Some(left_statement), _, _, _) => match left_statement { + (OperationType::GtToNonequality, Some(left_statement), _, _, _) => match left_statement + { Statement { + name: _, predicate: StatementPredicate::Gt, origin1: left_origin, key1: left_key_name, @@ -821,10 +728,11 @@ impl OperationType { key3: None, optional_value: _, } => Some(Statement { + name: self.output_statement_name.clone(), predicate: StatementPredicate::NotEqual, - origin1: *left_origin, + origin1: left_origin.clone(), key1: left_key_name.clone(), - origin2: *right_origin, + origin2: right_origin.clone(), key2: right_key_name.clone(), origin3: None, key3: None, @@ -832,8 +740,74 @@ impl OperationType { }), _ => None, }, - // TODO. also first need to make it so statement values can be vectors - (Self::Contains, _, _, _, _) => None, + (OperationType::Contains, Some(left_entry), Some(right_entry), _, _) => { + match ( + left_entry.predicate, + left_entry.optional_value, + right_entry.predicate, + right_entry.optional_value, + ) { + ( + StatementPredicate::ValueOf, + Some(ScalarOrVec::Vector(vec1)), + StatementPredicate::ValueOf, + Some(ScalarOrVec::Scalar(val)), + ) => { + if vec1.contains(&val) { + return Some(Statement { + name: self.output_statement_name.clone(), + predicate: StatementPredicate::Contains, + origin1: left_entry.origin1, + key1: left_entry.key1.clone(), + origin2: Some(right_entry.origin1), + key2: Some(right_entry.key1.clone()), + origin3: None, + key3: None, + optional_value: None, + }); + } + return None; + } + _ => { + return None; + } + } + } + // SumOf <=> statement 1's value = statement 2's value + statement 3's value + (OperationType::SumOf, Some(statement1), Some(statement2), Some(statement3), _) => { + match ( + statement1.predicate, + statement1.optional_value, + statement2.predicate, + statement2.optional_value, + statement3.predicate, + statement3.optional_value, + ) { + ( + StatementPredicate::ValueOf, + Some(ScalarOrVec::Scalar(sum)), + StatementPredicate::ValueOf, + Some(ScalarOrVec::Scalar(left_addend)), + StatementPredicate::ValueOf, + Some(ScalarOrVec::Scalar(right_addend)), + ) if (sum == left_addend + right_addend) => { + return Some(Statement { + name: self.output_statement_name.clone(), + predicate: StatementPredicate::SumOf, + origin1: statement1.origin1, + key1: statement1.key1.clone(), + origin2: Some(statement2.origin1), + key2: Some(statement2.key1.clone()), + origin3: Some(statement3.origin1), + key3: Some(statement3.key1.clone()), + optional_value: None, + }); + } + _ => { + return None; + } + } + } _ => None, } } From 0a7b18e582958d21359a539a3aa7711f33598272 Mon Sep 17 00:00:00 2001 From: gubsheep Date: Sun, 13 Oct 2024 04:09:20 -0700 Subject: [PATCH 3/8] copy operation should rename statement --- src/pod.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/pod.rs b/src/pod.rs index 03c1248..c6f9ccd 100644 --- a/src/pod.rs +++ b/src/pod.rs @@ -580,7 +580,11 @@ impl OperationCmd { return Some(Statement::from_entry(&entry, gadget_id)); } // A statement is copied from a single (left) statement. - (OperationType::CopyStatement, Some(statement), _, _, _) => Some(statement.clone()), + (OperationType::CopyStatement, Some(statement), _, _, _) => { + let mut cloned = statement.clone(); + cloned.name = self.output_statement_name.clone(); + return Some(cloned); + } // Eq <=> Left entry = right entry (OperationType::EqualityFromEntries, Some(left_entry), Some(right_entry), _, _) => { match (left_entry.predicate, right_entry.predicate) { From 8f82d00fa6652d575183dc3a27bbd7a83afc06bb Mon Sep 17 00:00:00 2001 From: gubsheep Date: Sun, 13 Oct 2024 04:15:00 -0700 Subject: [PATCH 4/8] add comment --- src/pod.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/pod.rs b/src/pod.rs index c6f9ccd..724b215 100644 --- a/src/pod.rs +++ b/src/pod.rs @@ -304,6 +304,10 @@ impl POD { } } + // returns a map from input POD name to (map from statement name to statement) + // the inner statements have their old origin names and IDs are replaced with + // the new origin names as specified by inputs.origin_renaming_map + // and with new origin IDs which correspond to the lexicographic order of the new origin names fn remap_origin_ids_by_name( inputs: GPGInput, ) -> Result>, Error> { @@ -476,7 +480,6 @@ impl POD { pub struct GPGInput { pub pods_list: Vec<(String, POD)>, // ORDERED list of pods, ordered by names - pub pods_map: HashMap, // map from pod name to pod // map from (pod name, old origin name) to new origin name pub origin_renaming_map: HashMap<(String, String), String>, @@ -495,7 +498,6 @@ impl GPGInput { return Self { pods_list: pods_and_names_list.clone(), - pods_map: named_pods.clone(), origin_renaming_map: origin_renaming_map.clone(), }; } From eb8edb7f1cab93fdda9ff3908e6fa1410e8bbfb8 Mon Sep 17 00:00:00 2001 From: gubsheep Date: Sun, 13 Oct 2024 04:24:42 -0700 Subject: [PATCH 5/8] move origin remapping logic into gpginput impl --- src/pod.rs | 151 ++++++++++++++++++++++++++--------------------------- 1 file changed, 75 insertions(+), 76 deletions(-) diff --git a/src/pod.rs b/src/pod.rs index 724b215..f6dfaa6 100644 --- a/src/pod.rs +++ b/src/pod.rs @@ -304,15 +304,84 @@ impl POD { } } + pub fn execute_oracle_gadget(input: GPGInput, cmds: &Vec) -> Result { + let mut statements = input.remap_origin_ids_by_name(); + match &mut statements { + Ok(statements) => { + statements.insert("_SELF".to_string(), HashMap::new()); + for cmd in cmds { + let new_statement = cmd.execute(GadgetID::ORACLE, statements); + match new_statement { + Some(new_statement) => { + statements + .get_mut("_SELF") + .unwrap() + .insert(cmd.output_statement_name.clone(), new_statement); + } + None => { + return Err("operation failed to execute".into()); + } + } + } + let out_statements = statements.get("_SELF").unwrap(); + let out_payload = PODPayload::new(out_statements); + let mut rng: rand::rngs::ThreadRng = rand::thread_rng(); + let protocol = SchnorrSigner::new(); + let payload_hash = out_payload.hash_payload(); + let payload_hash_vec = vec![payload_hash]; + + // signature is a hardcoded skey (currently 0) + // todo is to build a limited version of this with a ZKP + // would start by making it so that the ZKP only allows + // a max number of input PODs, max number of entries/statements per input POD, + // max number of statements for output POD, and some max number of each type of operation + let proof = protocol.sign(&payload_hash_vec, &SchnorrSecretKey { sk: 0 }, &mut rng); + Ok(Self { + payload: out_payload, + proof: PODProof::Oracle(proof), + proof_type: GadgetID::ORACLE, + }) + } + Err(e) => panic!("Error: {:?}", e), + } + } +} + +// Operations + +pub struct GPGInput { + pub pods_list: Vec<(String, POD)>, // ORDERED list of pods, ordered by names + + // map from (pod name, old origin name) to new origin name + pub origin_renaming_map: HashMap<(String, String), String>, +} + +impl GPGInput { + pub fn new( + named_pods: HashMap, + origin_renaming_map: HashMap<(String, String), String>, + ) -> Self { + let mut pods_and_names_list = Vec::new(); + for (name, pod) in named_pods.iter() { + pods_and_names_list.push((name.clone(), pod.clone())); + } + pods_and_names_list.sort_by(|a, b| a.0.cmp(&b.0)); + + return Self { + pods_list: pods_and_names_list.clone(), + origin_renaming_map: origin_renaming_map.clone(), + }; + } + // returns a map from input POD name to (map from statement name to statement) // the inner statements have their old origin names and IDs are replaced with // the new origin names as specified by inputs.origin_renaming_map // and with new origin IDs which correspond to the lexicographic order of the new origin names fn remap_origin_ids_by_name( - inputs: GPGInput, + &self, ) -> Result>, Error> { let mut new_origin_name_list = Vec::new(); - for (_, new_name) in inputs.origin_renaming_map.iter() { + for (_, new_name) in self.origin_renaming_map.iter() { new_origin_name_list.push(new_name.clone()); } new_origin_name_list.sort(); @@ -324,14 +393,13 @@ impl POD { let mut statements_with_renamed_origins = HashMap::new(); - for (pod_idx, (pod_name, pod)) in inputs.pods_list.iter().enumerate() { + for (_, (pod_name, pod)) in self.pods_list.iter().enumerate() { let mut inner_map = HashMap::new(); for statement in pod.payload.statements_list.iter() { let mut statement_with_remapped_origins = statement.clone(); - let pod_name_clone = pod_name.clone(); // origin 1 - let new_origin1_name = inputs + let new_origin1_name = self .origin_renaming_map .get(&(pod_name.clone(), statement.origin1.origin_name.clone())); match new_origin1_name { @@ -362,7 +430,7 @@ impl POD { } // origin 2 if let Some(old_origin2) = &statement.origin2 { - let new_origin2_name = inputs + let new_origin2_name = self .origin_renaming_map .get(&(pod_name.clone(), old_origin2.origin_name.clone())); match new_origin2_name { @@ -394,7 +462,7 @@ impl POD { } // origin 3 if let Some(old_origin3) = &statement.origin3 { - let new_origin3_name = inputs + let new_origin3_name = self .origin_renaming_map .get(&(pod_name.clone(), old_origin3.origin_name.clone())); match new_origin3_name { @@ -432,75 +500,6 @@ impl POD { Ok(statements_with_renamed_origins) } - - pub fn execute_oracle_gadget(input: GPGInput, cmds: &Vec) -> Result { - let mut statements = POD::remap_origin_ids_by_name(input); - match &mut statements { - Ok(statements) => { - statements.insert("_SELF".to_string(), HashMap::new()); - for cmd in cmds { - let new_statement = cmd.execute(GadgetID::ORACLE, statements); - match new_statement { - Some(new_statement) => { - statements - .get_mut("_SELF") - .unwrap() - .insert(cmd.output_statement_name.clone(), new_statement); - } - None => { - return Err("operation failed to execute".into()); - } - } - } - let out_statements = statements.get("_SELF").unwrap(); - let out_payload = PODPayload::new(out_statements); - let mut rng: rand::rngs::ThreadRng = rand::thread_rng(); - let protocol = SchnorrSigner::new(); - let payload_hash = out_payload.hash_payload(); - let payload_hash_vec = vec![payload_hash]; - - // signature is a hardcoded skey (currently 0) - // todo is to build a limited version of this with a ZKP - // would start by making it so that the ZKP only allows - // a max number of input PODs, max number of entries/statements per input POD, - // max number of statements for output POD, and some max number of each type of operation - let proof = protocol.sign(&payload_hash_vec, &SchnorrSecretKey { sk: 0 }, &mut rng); - Ok(Self { - payload: out_payload, - proof: PODProof::Oracle(proof), - proof_type: GadgetID::ORACLE, - }) - } - Err(e) => panic!("Error: {:?}", e), - } - } -} - -// Operations - -pub struct GPGInput { - pub pods_list: Vec<(String, POD)>, // ORDERED list of pods, ordered by names - - // map from (pod name, old origin name) to new origin name - pub origin_renaming_map: HashMap<(String, String), String>, -} - -impl GPGInput { - pub fn new( - named_pods: HashMap, - origin_renaming_map: HashMap<(String, String), String>, - ) -> Self { - let mut pods_and_names_list = Vec::new(); - for (name, pod) in named_pods.iter() { - pods_and_names_list.push((name.clone(), pod.clone())); - } - pods_and_names_list.sort_by(|a, b| a.0.cmp(&b.0)); - - return Self { - pods_list: pods_and_names_list.clone(), - origin_renaming_map: origin_renaming_map.clone(), - }; - } } #[derive(Copy, Clone, Debug)] From 8bac825cfcd98b357e32aedd753f793a8066bb5f Mon Sep 17 00:00:00 2001 From: gubsheep Date: Sun, 13 Oct 2024 18:07:56 -0700 Subject: [PATCH 6/8] remove name from statements and op_test works again --- src/pod.rs | 679 +++++++++++++++++++++++++++-------------------------- 1 file changed, 351 insertions(+), 328 deletions(-) diff --git a/src/pod.rs b/src/pod.rs index f6dfaa6..2ba738b 100644 --- a/src/pod.rs +++ b/src/pod.rs @@ -62,6 +62,22 @@ pub struct Entry { pub value: ScalarOrVec, } +impl Entry { + fn newFromScalar(key: String, value: GoldilocksField) -> Self { + Entry { + key, + value: ScalarOrVec::Scalar(value), + } + } + + fn newFromVec(key: String, value: Vec) -> Self { + Entry { + key, + value: ScalarOrVec::Vector(value), + } + } +} + // An Origin, which represents a reference to an ancestor POD. #[derive(Clone, Debug, PartialEq)] @@ -96,7 +112,6 @@ pub enum StatementPredicate { #[derive(Clone, Debug, PartialEq)] pub struct Statement { - pub name: String, // human-readable name that can be referenced in operations pub predicate: StatementPredicate, pub origin1: Origin, pub key1: String, @@ -110,7 +125,6 @@ pub struct Statement { impl Statement { pub fn from_entry(entry: &Entry, this_gadget_id: GadgetID) -> Self { Statement { - name: entry.key.to_string(), predicate: StatementPredicate::ValueOf, origin1: Origin { origin_id: GoldilocksField(1), @@ -140,19 +154,19 @@ pub trait HashablePayload: Clone + PartialEq { #[derive(Clone, Debug, PartialEq)] pub struct PODPayload { - pub statements_list: Vec, // ORDERED list of statements, ordered by names + statements_list: Vec<(String, Statement)>, // ORDERED list of statements, ordered by names pub statements_map: HashMap, } impl PODPayload { pub fn new(statements: &HashMap) -> Self { - let mut statements_list = Vec::new(); - for (_, statement) in statements.iter() { - statements_list.push(statement.clone()); + let mut statements_and_names_list = Vec::new(); + for (name, statement) in statements.iter() { + statements_and_names_list.push((name.clone(), statement.clone())); } - statements_list.sort_by(|a, b| a.name.cmp(&b.name)); + statements_and_names_list.sort_by(|a, b| a.0.cmp(&b.0)); Self { - statements_list, + statements_list: statements_and_names_list, statements_map: statements.clone(), } } @@ -199,7 +213,11 @@ impl HashablePayload for Vec { impl HashablePayload for PODPayload { fn to_field_vec(&self) -> Vec { - self.statements_list.to_field_vec() + let mut statements_vec = Vec::new(); + for (_, statement) in self.statements_list.iter() { + statements_vec.push(statement.clone()); + } + statements_vec.to_field_vec() } } @@ -235,21 +253,13 @@ impl POD { let payload_hash_vec = vec![payload_hash]; let protocol = SchnorrSigner::new(); - let wrapped_pk = self - .payload - .statements_list - .iter() - .filter(|&statement| { - statement.predicate == StatementPredicate::ValueOf - && statement.key1 == "_signer" - }) - .collect::>(); + let wrapped_pk = self.payload.statements_map.get("entry-_signer"); - if wrapped_pk.len() == 0 { + if wrapped_pk == None { return Err("No signer found in payload".into()); } - let pk = match wrapped_pk[0].optional_value { + let pk = match wrapped_pk.unwrap().optional_value { Some(ScalarOrVec::Vector(_)) => Err(Error::from("Signer is a vector")), Some(ScalarOrVec::Scalar(s)) => Ok(s), _ => Err("_signer key found but no corresponding value".into()), @@ -288,7 +298,7 @@ impl POD { for entry in kv_pairs { statement_map.insert( - entry.key.clone(), + "entry-".to_owned() + &entry.key, Statement::from_entry(&entry, GadgetID::SCHNORR16), ); } @@ -396,7 +406,7 @@ impl GPGInput { for (_, (pod_name, pod)) in self.pods_list.iter().enumerate() { let mut inner_map = HashMap::new(); - for statement in pod.payload.statements_list.iter() { + for (name, statement) in pod.payload.statements_map.iter() { let mut statement_with_remapped_origins = statement.clone(); // origin 1 let new_origin1_name = self @@ -493,7 +503,7 @@ impl GPGInput { } } - inner_map.insert(statement.name.clone(), statement_with_remapped_origins); + inner_map.insert(name.clone(), statement_with_remapped_origins); } statements_with_renamed_origins.insert(pod_name.clone(), inner_map); } @@ -569,13 +579,26 @@ impl OperationCmd { ); let optional_entry = self.optional_entry.clone(); - match ( - self.operation_type, + self.operation_type.apply_operation( + gadget_id, statement1, statement2, statement3, optional_entry, - ) { + ) + } +} + +impl OperationType { + pub fn apply_operation( + &self, + gadget_id: GadgetID, + statement1: Option, + statement2: Option, + statement3: Option, + optional_entry: Option, + ) -> Option { + match (self, statement1, statement2, statement3, optional_entry) { // A new statement is created from a single `Entry`. (OperationType::NewEntry, _, _, _, Some(entry)) => { return Some(Statement::from_entry(&entry, gadget_id)); @@ -583,7 +606,6 @@ impl OperationCmd { // A statement is copied from a single (left) statement. (OperationType::CopyStatement, Some(statement), _, _, _) => { let mut cloned = statement.clone(); - cloned.name = self.output_statement_name.clone(); return Some(cloned); } // Eq <=> Left entry = right entry @@ -593,7 +615,6 @@ impl OperationCmd { if left_entry.optional_value == right_entry.optional_value => { return Some(Statement { - name: self.output_statement_name.clone(), predicate: StatementPredicate::Equal, origin1: left_entry.origin1, key1: left_entry.key1.clone(), @@ -616,7 +637,6 @@ impl OperationCmd { if left_entry.optional_value != right_entry.optional_value => { return Some(Statement { - name: self.output_statement_name.clone(), predicate: StatementPredicate::NotEqual, origin1: left_entry.origin1, key1: left_entry.key1.clone(), @@ -647,7 +667,6 @@ impl OperationCmd { Some(ScalarOrVec::Scalar(right_value)), ) if left_value.to_canonical_u64() > right_value.to_canonical_u64() => { return Some(Statement { - name: self.output_statement_name.clone(), predicate: StatementPredicate::Gt, origin1: left_entry.origin1, key1: left_entry.key1.clone(), @@ -674,7 +693,6 @@ impl OperationCmd { ) => match (left_statement, right_statement) { ( Statement { - name: _, predicate: StatementPredicate::Equal, origin1: ll_origin, key1: ll_key_name, @@ -690,7 +708,6 @@ impl OperationCmd { optional_value: _, }, Statement { - name: _, predicate: StatementPredicate::Equal, origin1: Origin { @@ -707,7 +724,6 @@ impl OperationCmd { }, ) if (lr_origin_id, &lr_key_name) == ((rl_origin_id, &rl_key_name)) => { Some(Statement { - name: self.output_statement_name.clone(), predicate: StatementPredicate::Equal, origin1: ll_origin.clone(), key1: ll_key_name.clone(), @@ -723,7 +739,6 @@ impl OperationCmd { (OperationType::GtToNonequality, Some(left_statement), _, _, _) => match left_statement { Statement { - name: _, predicate: StatementPredicate::Gt, origin1: left_origin, key1: left_key_name, @@ -733,7 +748,6 @@ impl OperationCmd { key3: None, optional_value: _, } => Some(Statement { - name: self.output_statement_name.clone(), predicate: StatementPredicate::NotEqual, origin1: left_origin.clone(), key1: left_key_name.clone(), @@ -760,7 +774,6 @@ impl OperationCmd { ) => { if vec1.contains(&val) { return Some(Statement { - name: self.output_statement_name.clone(), predicate: StatementPredicate::Contains, origin1: left_entry.origin1, key1: left_entry.key1.clone(), @@ -797,7 +810,6 @@ impl OperationCmd { Some(ScalarOrVec::Scalar(right_addend)), ) if (sum == left_addend + right_addend) => { return Some(Statement { - name: self.output_statement_name.clone(), predicate: StatementPredicate::SumOf, origin1: statement1.origin1, key1: statement1.key1.clone(), @@ -827,40 +839,40 @@ fn op_test() -> Result<(), Error> { let vector_value = vec![scalar1, scalar2]; // Create entries - let entry1 = Entry::new("some key", scalar1); - let entry2 = Entry::new("some other key", scalar2); - let entry3 = Entry::new("vector entry", vector_value.clone()); - let entry4 = Entry::new("another scalar1", scalar1); - let entry5 = Entry::new("yet another scalar1", scalar1); - let entry6 = Entry::new("scalar3", scalar3); + let entry1 = Entry::newFromScalar("some key".to_string(), scalar1); + let entry2 = Entry::newFromScalar("some other key".to_string(), scalar2); + let entry3 = Entry::newFromVec("vector entry".to_string(), vector_value.clone()); + let entry4 = Entry::newFromScalar("another scalar1".to_string(), scalar1); + let entry5 = Entry::newFromScalar("yet another scalar1".to_string(), scalar1); + let entry6 = Entry::newFromScalar("scalar3".to_string(), scalar3); // Create entry statements. - let entry_statement1 = entry1.into(); - let entry_statement2 = entry2.into(); - let entry_statement3 = entry3.into(); - let entry_statement4 = entry4.into(); - let entry_statement5 = entry5.into(); - let entry_statement6 = entry6.into(); + let entry_statement1 = Statement::from_entry(&entry1, GadgetID::NONE); + let entry_statement2 = Statement::from_entry(&entry2, GadgetID::NONE); + let entry_statement3 = Statement::from_entry(&entry3, GadgetID::NONE); + let entry_statement4 = Statement::from_entry(&entry4, GadgetID::NONE); + let entry_statement5 = Statement::from_entry(&entry5, GadgetID::NONE); + let entry_statement6 = Statement::from_entry(&entry6, GadgetID::NONE); // Entry 2's value = entry 1's value + entry 6's value let sum_of_statement = OperationType::SumOf .apply_operation( - GadgetID::GOD, - Some(&entry_statement2), - Some(&entry_statement1), - Some(&entry_statement6), - >>::None, + GadgetID::ORACLE, + Some(entry_statement2.clone()), + Some(entry_statement1.clone()), + Some(entry_statement6.clone()), + >::None, ) .unwrap(); assert!( sum_of_statement == Statement { predicate: StatementPredicate::SumOf, - origin1: entry_statement2.origin1, + origin1: entry_statement2.origin1.clone(), key1: entry_statement2.key1.clone(), - origin2: Some(entry_statement1.origin1), + origin2: Some(entry_statement1.origin1.clone()), key2: Some(entry_statement1.key1.clone()), - origin3: Some(entry_statement6.origin1), + origin3: Some(entry_statement6.origin1.clone()), key3: Some(entry_statement6.key1.clone()), optional_value: None } @@ -871,35 +883,43 @@ fn op_test() -> Result<(), Error> { // Copy statements and check for equality of entries. entries.into_iter().for_each(|statement| { let copy = OperationType::CopyStatement - .apply_operation::(GadgetID::GOD, Some(statement), None, None, None) + .apply_operation(GadgetID::NONE, Some(statement.clone()), None, None, None) .expect("This value should exist."); assert!(© == statement); }); // Equality checks - println!( - "{:?}", - OperationType::EqualityFromEntries.apply_operation::( - GadgetID::GOD, - Some(&entry_statement1), - Some(&entry_statement2), + assert!( + OperationType::EqualityFromEntries.apply_operation( + GadgetID::NONE, + Some(entry_statement1.clone()), + Some(entry_statement4.clone()), None, - None - ) + None, + ) == Some(Statement { + predicate: StatementPredicate::Equal, + origin1: entry_statement1.origin1.clone(), + key1: entry_statement1.key1.clone(), + origin2: Some(entry_statement4.origin1.clone()), + key2: Some(entry_statement4.key1.clone()), + origin3: None, + key3: None, + optional_value: None + }) ); entries.into_iter().for_each(|statement| { assert!( - OperationType::EqualityFromEntries.apply_operation::( - GadgetID::GOD, - Some(statement), - Some(statement), + OperationType::EqualityFromEntries.apply_operation( + GadgetID::NONE, + Some(statement.clone()), + Some(statement.clone()), + None, None, - None ) == Some(Statement { predicate: StatementPredicate::Equal, - origin1: statement.origin1, + origin1: statement.origin1.clone(), key1: statement.key1.clone(), - origin2: Some(statement.origin1), + origin2: Some(statement.origin1.clone()), key2: Some(statement.key1.clone()), origin3: None, key3: None, @@ -907,36 +927,39 @@ fn op_test() -> Result<(), Error> { }) ); }); - // assert!( - // Operation::NonequalityFromEntries.apply_operation::( - // GadgetID::GOD, - // Some(&entry_statement1), - // Some(&entry_statement2), - // None - // ) == Some(Statement { - // predicate: StatementPredicate::Equal, - // left_origin: entry_statement1.left_origin, - // left_key_name: entry_statement1.left_key_name.clone(), - // right_origin: Some(entry_statement2.left_origin), - // right_key_name: Some(entry_statement2.left_key_name.clone()), - // optional_value: None - // }) - // ); assert!( - OperationType::EqualityFromEntries.apply_operation::( - GadgetID::GOD, - Some(&entry_statement1), - Some(&entry_statement2), + OperationType::NonequalityFromEntries.apply_operation( + GadgetID::NONE, + Some(entry_statement1.clone()), + Some(entry_statement2.clone()), + None, + None + ) == Some(Statement { + predicate: StatementPredicate::NotEqual, + origin1: entry_statement1.origin1.clone(), + key1: entry_statement1.key1.clone(), + origin2: Some(entry_statement2.origin1.clone()), + key2: Some(entry_statement2.key1.clone()), + origin3: None, + key3: None, + optional_value: None + }) + ); + assert!( + OperationType::EqualityFromEntries.apply_operation( + GadgetID::NONE, + Some(entry_statement1.clone()), + Some(entry_statement2.clone()), None, None ) == None ); // Gt check - let gt_statement = OperationType::GtFromEntries.apply_operation::( - GadgetID::GOD, - Some(&entry_statement2), - Some(&entry_statement1), + let gt_statement = OperationType::GtFromEntries.apply_operation( + GadgetID::NONE, + Some(entry_statement2.clone()), + Some(entry_statement1.clone()), None, None, ); @@ -944,9 +967,9 @@ fn op_test() -> Result<(), Error> { gt_statement == Some(Statement { predicate: StatementPredicate::Gt, - origin1: entry_statement2.origin1, + origin1: entry_statement2.origin1.clone(), key1: entry_statement2.key1.clone(), - origin2: Some(entry_statement1.origin1), + origin2: Some(entry_statement1.origin1.clone()), key2: Some(entry_statement1.key1.clone()), origin3: None, key3: None, @@ -956,38 +979,38 @@ fn op_test() -> Result<(), Error> { // Eq transitivity check let eq_statement1 = OperationType::EqualityFromEntries - .apply_operation::( - GadgetID::GOD, - Some(&entry_statement4), - Some(&entry_statement1), + .apply_operation( + GadgetID::NONE, + Some(entry_statement4.clone()), + Some(entry_statement1.clone()), None, None, ) .unwrap(); let eq_statement2 = OperationType::EqualityFromEntries - .apply_operation::( - GadgetID::GOD, - Some(&entry_statement1), - Some(&entry_statement5), + .apply_operation( + GadgetID::NONE, + Some(entry_statement1.clone()), + Some(entry_statement5.clone()), None, None, ) .unwrap(); let eq_statement3 = OperationType::EqualityFromEntries - .apply_operation::( - GadgetID::GOD, - Some(&entry_statement4), - Some(&entry_statement5), + .apply_operation( + GadgetID::NONE, + Some(entry_statement4.clone()), + Some(entry_statement5.clone()), None, None, ) .unwrap(); assert!( - OperationType::TransitiveEqualityFromStatements.apply_operation::( - GadgetID::GOD, - Some(&eq_statement1), - Some(&eq_statement2), + OperationType::TransitiveEqualityFromStatements.apply_operation( + GadgetID::NONE, + Some(eq_statement1.clone()), + Some(eq_statement2.clone()), None, None ) == Some(eq_statement3) @@ -998,9 +1021,9 @@ fn op_test() -> Result<(), Error> { let mut expected_statement = unwrapped_gt_statement.clone(); expected_statement.predicate = StatementPredicate::NotEqual; assert!( - OperationType::GtToNonequality.apply_operation::( - GadgetID::GOD, - Some(&unwrapped_gt_statement), + OperationType::GtToNonequality.apply_operation( + GadgetID::NONE, + Some(unwrapped_gt_statement.clone()), None, None, None @@ -1009,214 +1032,214 @@ fn op_test() -> Result<(), Error> { Ok(()) } -#[test] -fn schnorr_pod_test() -> Result<(), Error> { - // Start with some values. - let scalar1 = GoldilocksField(36); - let scalar2 = GoldilocksField(52); - let vector_value = vec![scalar1, scalar2]; - - let entry1 = Entry::new("some key", ScalarOrVec::Scalar(scalar1)); - let entry2 = Entry::new("some other key", ScalarOrVec::Scalar(scalar2)); - let entry3 = Entry::new("vector entry", ScalarOrVec::Vector(vector_value.clone())); - - let schnorrPOD1 = SchnorrPOD::gadget( - &vec![entry1.clone(), entry2.clone()], - &SchnorrSecretKey { sk: 25 }, - ); - - let schnorrPOD2 = SchnorrPOD::gadget( - &vec![entry2.clone(), entry3.clone()], - &SchnorrSecretKey { sk: 42 }, - ); - - let schnorrPOD3 = SchnorrPOD::gadget(&vec![entry1.clone()], &SchnorrSecretKey { sk: 25 }); - - // println!( - // "verify schnorrpod1: {:?}", - // schnorrPOD1.clone().payload.to_field_vec() - // ); - // println!("verify schnorrpod2: {:?}", schnorrPOD2.verify()); - - assert!(schnorrPOD1.verify()? == true); - assert!(schnorrPOD2.verify()? == true); - - // // ZK verification of SchnorrPOD 3. - // let (builder, targets) = pod2_circuit(1, 2, 0, 0)?; - - // // Assign witnesses - // const D: usize = 2; - // type C = PoseidonGoldilocksConfig; - // type F = >::F; - // let mut pw: PartialWitness = PartialWitness::new(); - // pw.set_target(targets.input_is_schnorr[0], GoldilocksField(1))?; - // pw.set_target(targets.input_is_gpg[0], GoldilocksField::ZERO)?; - // pw.set_target( - // targets.input_payload_hash[0], - // schnorrPOD3.payload.hash_payload(), - // )?; - // pw.set_target(targets.pk_index[0], GoldilocksField(1))?; - // targets.input_proof[0].set_witness(&mut pw, &schnorrPOD3.proof)?; - // targets.input_entries[0][0].set_witness(&mut pw, &schnorrPOD3.payload[0])?; - // targets.input_entries[0][1].set_witness(&mut pw, &schnorrPOD3.payload[1])?; - // let data = builder.build::(); - // let proof = data.prove(pw)?; - - Ok(()) -} - -#[test] -fn god_pod_from_schnorr_test() -> Result<(), Error> { - // Start with some values. - let scalar1 = GoldilocksField(36); - let scalar2 = GoldilocksField(52); - let scalar3 = GoldilocksField(90); - let vector_value = vec![scalar1, scalar2]; - - // make entries - let entry1 = Entry::new("some key", ScalarOrVec::Scalar(scalar1)); - let entry2 = Entry::new("some other key", ScalarOrVec::Scalar(scalar2)); - let entry3 = Entry::new("vector entry", ScalarOrVec::Vector(vector_value.clone())); - let entry4 = Entry::new("new key", ScalarOrVec::Scalar(scalar2)); - let entry5 = Entry::new("foo", ScalarOrVec::Scalar(GoldilocksField(100))); - let entry6 = Entry::new("baz", ScalarOrVec::Scalar(GoldilocksField(120))); - let entry7 = Entry::new("yum", ScalarOrVec::Scalar(scalar2)); - let entry9 = Entry::new("godpod introduced entry key", ScalarOrVec::Scalar(scalar3)); - - // three schnorr pods - let schnorrPOD1 = SchnorrPOD::gadget( - &vec![entry1.clone(), entry2.clone()], - &SchnorrSecretKey { sk: 25 }, - ); - - let schnorrPOD2 = SchnorrPOD::gadget( - &vec![entry3.clone(), entry4.clone()], - &SchnorrSecretKey { sk: 42 }, - ); - - let schnorrPOD3 = SchnorrPOD::gadget( - &vec![entry5.clone(), entry6.clone(), entry7.clone()], - &SchnorrSecretKey { sk: 83 }, - ); - - // make a GODPOD using from_pods called on the two schnorr PODs - let god_pod_1 = GODPOD::gadget( - &vec![ - &SchnorrOrGODPOD::SchnorrPOD(schnorrPOD1.clone()), - &SchnorrOrGODPOD::SchnorrPOD(schnorrPOD2.clone()), - &SchnorrOrGODPOD::SchnorrPOD(schnorrPOD3.clone()), - ], - &vec![ - (OperationType::CopyStatement, Some(0), None, None, None), - (OperationType::CopyStatement, Some(1), None, None, None), - (OperationType::CopyStatement, Some(2), None, None, None), - (OperationType::CopyStatement, Some(3), None, None, None), - (OperationType::CopyStatement, Some(4), None, None, None), - (OperationType::CopyStatement, Some(5), None, None, None), - (OperationType::NewEntry, None, None, None, Some(&entry9)), - ( - OperationType::EqualityFromEntries, - Some(1), - Some(4), - None, - None, - ), - ( - OperationType::EqualityFromEntries, - Some(4), - Some(8), - None, - None, - ), - ( - OperationType::NonequalityFromEntries, - Some(0), - Some(1), - None, - None, - ), - (OperationType::GtFromEntries, Some(1), Some(0), None, None), - ], - ); - println!("GODPOD1: {:?}", god_pod_1); - assert!(god_pod_1.verify()? == true); - - // another GODPOD from the first GODPOD and another schnorr POD - - let god_pod_2 = GODPOD::gadget( - &vec![ - &SchnorrOrGODPOD::GODPOD(god_pod_1.clone()), - &SchnorrOrGODPOD::SchnorrPOD(schnorrPOD3.clone()), - ], - &vec![ - (OperationType::CopyStatement, Some(8), None, None, None), - (OperationType::CopyStatement, Some(9), None, None, None), - (OperationType::CopyStatement, Some(3), None, None, None), - (OperationType::GtFromEntries, Some(6), Some(0), None, None), - ( - OperationType::TransitiveEqualityFromStatements, - Some(7), - Some(8), - None, - None, - ), - (OperationType::GtToNonequality, Some(10), None, None, None), - ], - ); - println!("GODPOD2: {:?}", god_pod_2); - - // println!( - // "verify schnorrpod1: {:?}", - // schnorrPOD1.clone().payload.to_field_vec() - // ); - // println!("verify schnorrpod2: {:?}", schnorrPOD2.verify()); - - assert!(god_pod_2.verify()? == true); - - Ok(()) -} - -#[test] -#[should_panic] -fn god_pod_should_panic() { - // Start with some values. - let scalar1 = GoldilocksField(36); - let scalar2 = GoldilocksField(52); - let scalar3 = GoldilocksField(90); - let vector_value = vec![scalar1, scalar2]; - - // make entries - let entry1 = Entry::new("some key", ScalarOrVec::Scalar(scalar1)); - let entry2 = Entry::new("some other key", ScalarOrVec::Scalar(scalar2)); - let entry3 = Entry::new("vector entry", ScalarOrVec::Vector(vector_value.clone())); - let entry4 = Entry::new("new key", ScalarOrVec::Scalar(scalar2)); - let entry5 = Entry::new("foo", ScalarOrVec::Scalar(GoldilocksField(100))); - let entry6 = Entry::new("foo", ScalarOrVec::Scalar(GoldilocksField(120))); - let entry9 = Entry::new("godpod introduced entry key", ScalarOrVec::Scalar(scalar3)); - - // three schnorr pods - let schnorrPOD1 = SchnorrPOD::gadget( - &vec![entry1.clone(), entry2.clone()], - &SchnorrSecretKey { sk: 25 }, - ); - - let schnorrPOD2 = SchnorrPOD::gadget( - &vec![entry3.clone(), entry4.clone()], - &SchnorrSecretKey { sk: 42 }, - ); - - let schnorrPOD3 = SchnorrPOD::gadget( - &vec![entry5.clone(), entry6.clone()], - &SchnorrSecretKey { sk: 83 }, - ); - - // make a GODPOD using from_pods called on the two schnorr PODs - let god_pod_1 = GODPOD::gadget( - &vec![ - &SchnorrOrGODPOD::SchnorrPOD(schnorrPOD1.clone()), - &SchnorrOrGODPOD::SchnorrPOD(schnorrPOD2.clone()), - ], - // this Gt operation should fail because 36 is not gt 52 - &vec![(OperationType::GtFromEntries, Some(0), Some(1), None, None)], - ); -} +// #[test] +// fn schnorr_pod_test() -> Result<(), Error> { +// // Start with some values. +// let scalar1 = GoldilocksField(36); +// let scalar2 = GoldilocksField(52); +// let vector_value = vec![scalar1, scalar2]; + +// let entry1 = Entry::new("some key", ScalarOrVec::Scalar(scalar1)); +// let entry2 = Entry::new("some other key", ScalarOrVec::Scalar(scalar2)); +// let entry3 = Entry::new("vector entry", ScalarOrVec::Vector(vector_value.clone())); + +// let schnorrPOD1 = SchnorrPOD::gadget( +// &vec![entry1.clone(), entry2.clone()], +// &SchnorrSecretKey { sk: 25 }, +// ); + +// let schnorrPOD2 = SchnorrPOD::gadget( +// &vec![entry2.clone(), entry3.clone()], +// &SchnorrSecretKey { sk: 42 }, +// ); + +// let schnorrPOD3 = SchnorrPOD::gadget(&vec![entry1.clone()], &SchnorrSecretKey { sk: 25 }); + +// // println!( +// // "verify schnorrpod1: {:?}", +// // schnorrPOD1.clone().payload.to_field_vec() +// // ); +// // println!("verify schnorrpod2: {:?}", schnorrPOD2.verify()); + +// assert!(schnorrPOD1.verify()? == true); +// assert!(schnorrPOD2.verify()? == true); + +// // // ZK verification of SchnorrPOD 3. +// // let (builder, targets) = pod2_circuit(1, 2, 0, 0)?; + +// // // Assign witnesses +// // const D: usize = 2; +// // type C = PoseidonGoldilocksConfig; +// // type F = >::F; +// // let mut pw: PartialWitness = PartialWitness::new(); +// // pw.set_target(targets.input_is_schnorr[0], GoldilocksField(1))?; +// // pw.set_target(targets.input_is_gpg[0], GoldilocksField::ZERO)?; +// // pw.set_target( +// // targets.input_payload_hash[0], +// // schnorrPOD3.payload.hash_payload(), +// // )?; +// // pw.set_target(targets.pk_index[0], GoldilocksField(1))?; +// // targets.input_proof[0].set_witness(&mut pw, &schnorrPOD3.proof)?; +// // targets.input_entries[0][0].set_witness(&mut pw, &schnorrPOD3.payload[0])?; +// // targets.input_entries[0][1].set_witness(&mut pw, &schnorrPOD3.payload[1])?; +// // let data = builder.build::(); +// // let proof = data.prove(pw)?; + +// Ok(()) +// } + +// #[test] +// fn god_pod_from_schnorr_test() -> Result<(), Error> { +// // Start with some values. +// let scalar1 = GoldilocksField(36); +// let scalar2 = GoldilocksField(52); +// let scalar3 = GoldilocksField(90); +// let vector_value = vec![scalar1, scalar2]; + +// // make entries +// let entry1 = Entry::new("some key", ScalarOrVec::Scalar(scalar1)); +// let entry2 = Entry::new("some other key", ScalarOrVec::Scalar(scalar2)); +// let entry3 = Entry::new("vector entry", ScalarOrVec::Vector(vector_value.clone())); +// let entry4 = Entry::new("new key", ScalarOrVec::Scalar(scalar2)); +// let entry5 = Entry::new("foo", ScalarOrVec::Scalar(GoldilocksField(100))); +// let entry6 = Entry::new("baz", ScalarOrVec::Scalar(GoldilocksField(120))); +// let entry7 = Entry::new("yum", ScalarOrVec::Scalar(scalar2)); +// let entry9 = Entry::new("godpod introduced entry key", ScalarOrVec::Scalar(scalar3)); + +// // three schnorr pods +// let schnorrPOD1 = SchnorrPOD::gadget( +// &vec![entry1.clone(), entry2.clone()], +// &SchnorrSecretKey { sk: 25 }, +// ); + +// let schnorrPOD2 = SchnorrPOD::gadget( +// &vec![entry3.clone(), entry4.clone()], +// &SchnorrSecretKey { sk: 42 }, +// ); + +// let schnorrPOD3 = SchnorrPOD::gadget( +// &vec![entry5.clone(), entry6.clone(), entry7.clone()], +// &SchnorrSecretKey { sk: 83 }, +// ); + +// // make a GODPOD using from_pods called on the two schnorr PODs +// let god_pod_1 = GODPOD::gadget( +// &vec![ +// &SchnorrOrGODPOD::SchnorrPOD(schnorrPOD1.clone()), +// &SchnorrOrGODPOD::SchnorrPOD(schnorrPOD2.clone()), +// &SchnorrOrGODPOD::SchnorrPOD(schnorrPOD3.clone()), +// ], +// &vec![ +// (OperationType::CopyStatement, Some(0), None, None, None), +// (OperationType::CopyStatement, Some(1), None, None, None), +// (OperationType::CopyStatement, Some(2), None, None, None), +// (OperationType::CopyStatement, Some(3), None, None, None), +// (OperationType::CopyStatement, Some(4), None, None, None), +// (OperationType::CopyStatement, Some(5), None, None, None), +// (OperationType::NewEntry, None, None, None, Some(&entry9)), +// ( +// OperationType::EqualityFromEntries, +// Some(1), +// Some(4), +// None, +// None, +// ), +// ( +// OperationType::EqualityFromEntries, +// Some(4), +// Some(8), +// None, +// None, +// ), +// ( +// OperationType::NonequalityFromEntries, +// Some(0), +// Some(1), +// None, +// None, +// ), +// (OperationType::GtFromEntries, Some(1), Some(0), None, None), +// ], +// ); +// println!("GODPOD1: {:?}", god_pod_1); +// assert!(god_pod_1.verify()? == true); + +// // another GODPOD from the first GODPOD and another schnorr POD + +// let god_pod_2 = GODPOD::gadget( +// &vec![ +// &SchnorrOrGODPOD::GODPOD(god_pod_1.clone()), +// &SchnorrOrGODPOD::SchnorrPOD(schnorrPOD3.clone()), +// ], +// &vec![ +// (OperationType::CopyStatement, Some(8), None, None, None), +// (OperationType::CopyStatement, Some(9), None, None, None), +// (OperationType::CopyStatement, Some(3), None, None, None), +// (OperationType::GtFromEntries, Some(6), Some(0), None, None), +// ( +// OperationType::TransitiveEqualityFromStatements, +// Some(7), +// Some(8), +// None, +// None, +// ), +// (OperationType::GtToNonequality, Some(10), None, None, None), +// ], +// ); +// println!("GODPOD2: {:?}", god_pod_2); + +// // println!( +// // "verify schnorrpod1: {:?}", +// // schnorrPOD1.clone().payload.to_field_vec() +// // ); +// // println!("verify schnorrpod2: {:?}", schnorrPOD2.verify()); + +// assert!(god_pod_2.verify()? == true); + +// Ok(()) +// } + +// #[test] +// #[should_panic] +// fn god_pod_should_panic() { +// // Start with some values. +// let scalar1 = GoldilocksField(36); +// let scalar2 = GoldilocksField(52); +// let scalar3 = GoldilocksField(90); +// let vector_value = vec![scalar1, scalar2]; + +// // make entries +// let entry1 = Entry::new("some key", ScalarOrVec::Scalar(scalar1)); +// let entry2 = Entry::new("some other key", ScalarOrVec::Scalar(scalar2)); +// let entry3 = Entry::new("vector entry", ScalarOrVec::Vector(vector_value.clone())); +// let entry4 = Entry::new("new key", ScalarOrVec::Scalar(scalar2)); +// let entry5 = Entry::new("foo", ScalarOrVec::Scalar(GoldilocksField(100))); +// let entry6 = Entry::new("foo", ScalarOrVec::Scalar(GoldilocksField(120))); +// let entry9 = Entry::new("godpod introduced entry key", ScalarOrVec::Scalar(scalar3)); + +// // three schnorr pods +// let schnorrPOD1 = SchnorrPOD::gadget( +// &vec![entry1.clone(), entry2.clone()], +// &SchnorrSecretKey { sk: 25 }, +// ); + +// let schnorrPOD2 = SchnorrPOD::gadget( +// &vec![entry3.clone(), entry4.clone()], +// &SchnorrSecretKey { sk: 42 }, +// ); + +// let schnorrPOD3 = SchnorrPOD::gadget( +// &vec![entry5.clone(), entry6.clone()], +// &SchnorrSecretKey { sk: 83 }, +// ); + +// // make a GODPOD using from_pods called on the two schnorr PODs +// let god_pod_1 = GODPOD::gadget( +// &vec![ +// &SchnorrOrGODPOD::SchnorrPOD(schnorrPOD1.clone()), +// &SchnorrOrGODPOD::SchnorrPOD(schnorrPOD2.clone()), +// ], +// // this Gt operation should fail because 36 is not gt 52 +// &vec![(OperationType::GtFromEntries, Some(0), Some(1), None, None)], +// ); +// } From 290afac0d581277d29467eee7854ccd922fcff48 Mon Sep 17 00:00:00 2001 From: gubsheep Date: Mon, 14 Oct 2024 09:06:35 -0700 Subject: [PATCH 7/8] an oracle test passes --- src/pod.rs | 468 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 305 insertions(+), 163 deletions(-) diff --git a/src/pod.rs b/src/pod.rs index 2ba738b..7be19bc 100644 --- a/src/pod.rs +++ b/src/pod.rs @@ -314,7 +314,10 @@ impl POD { } } - pub fn execute_oracle_gadget(input: GPGInput, cmds: &Vec) -> Result { + pub fn execute_oracle_gadget( + input: &GPGInput, + cmds: &Vec, + ) -> Result { let mut statements = input.remap_origin_ids_by_name(); match &mut statements { Ok(statements) => { @@ -329,6 +332,7 @@ impl POD { .insert(cmd.output_statement_name.clone(), new_statement); } None => { + print!("{:?}", cmd); return Err("operation failed to execute".into()); } } @@ -359,6 +363,7 @@ impl POD { // Operations +#[derive(Clone, Debug)] pub struct GPGInput { pub pods_list: Vec<(String, POD)>, // ORDERED list of pods, ordered by names @@ -522,18 +527,18 @@ pub enum OperationType { GtFromEntries = 5, TransitiveEqualityFromStatements = 6, GtToNonequality = 7, - Contains = 8, + ContainsFromEntries = 8, SumOf = 9, } #[derive(Clone, Debug)] pub struct OperationCmd { pub operation_type: OperationType, - pub statement_1_origin: Option, + pub statement_1_parent: Option, pub statement_1_name: Option, - pub statement_2_origin: Option, + pub statement_2_parent: Option, pub statement_2_name: Option, - pub statement_3_origin: Option, + pub statement_3_parent: Option, pub statement_3_name: Option, pub optional_entry: Option, pub output_statement_name: String, @@ -564,18 +569,18 @@ impl OperationCmd { ) -> Option { let statement1 = OperationCmd::get_statement_with_origin_and_name( statements, + self.statement_1_parent.clone(), self.statement_1_name.clone(), - self.statement_1_origin.clone(), ); let statement2 = OperationCmd::get_statement_with_origin_and_name( statements, + self.statement_2_parent.clone(), self.statement_2_name.clone(), - self.statement_2_origin.clone(), ); let statement3 = OperationCmd::get_statement_with_origin_and_name( statements, + self.statement_3_parent.clone(), self.statement_3_name.clone(), - self.statement_3_origin.clone(), ); let optional_entry = self.optional_entry.clone(); @@ -759,7 +764,7 @@ impl OperationType { }), _ => None, }, - (OperationType::Contains, Some(left_entry), Some(right_entry), _, _) => { + (OperationType::ContainsFromEntries, Some(left_entry), Some(right_entry), _, _) => { match ( left_entry.predicate, left_entry.optional_value, @@ -1032,172 +1037,309 @@ fn op_test() -> Result<(), Error> { Ok(()) } -// #[test] -// fn schnorr_pod_test() -> Result<(), Error> { -// // Start with some values. -// let scalar1 = GoldilocksField(36); -// let scalar2 = GoldilocksField(52); -// let vector_value = vec![scalar1, scalar2]; +#[test] +fn schnorr_pod_test() -> Result<(), Error> { + // Start with some values. + let scalar1 = GoldilocksField(36); + let scalar2 = GoldilocksField(52); + let vector_value = vec![scalar1, scalar2]; -// let entry1 = Entry::new("some key", ScalarOrVec::Scalar(scalar1)); -// let entry2 = Entry::new("some other key", ScalarOrVec::Scalar(scalar2)); -// let entry3 = Entry::new("vector entry", ScalarOrVec::Vector(vector_value.clone())); + let entry1 = Entry::newFromScalar("some key".to_string(), scalar1); + let entry2 = Entry::newFromScalar("some other key".to_string(), scalar2); + let entry3 = Entry::newFromVec("vector entry".to_string(), vector_value.clone()); -// let schnorrPOD1 = SchnorrPOD::gadget( -// &vec![entry1.clone(), entry2.clone()], -// &SchnorrSecretKey { sk: 25 }, -// ); + let schnorrPOD1 = POD::execute_schnorr_gadget( + &vec![entry1.clone(), entry2.clone()], + &SchnorrSecretKey { sk: 25 }, + ); -// let schnorrPOD2 = SchnorrPOD::gadget( -// &vec![entry2.clone(), entry3.clone()], -// &SchnorrSecretKey { sk: 42 }, -// ); + let schnorrPOD2 = POD::execute_schnorr_gadget( + &vec![entry2.clone(), entry3.clone()], + &SchnorrSecretKey { sk: 42 }, + ); -// let schnorrPOD3 = SchnorrPOD::gadget(&vec![entry1.clone()], &SchnorrSecretKey { sk: 25 }); - -// // println!( -// // "verify schnorrpod1: {:?}", -// // schnorrPOD1.clone().payload.to_field_vec() -// // ); -// // println!("verify schnorrpod2: {:?}", schnorrPOD2.verify()); - -// assert!(schnorrPOD1.verify()? == true); -// assert!(schnorrPOD2.verify()? == true); - -// // // ZK verification of SchnorrPOD 3. -// // let (builder, targets) = pod2_circuit(1, 2, 0, 0)?; - -// // // Assign witnesses -// // const D: usize = 2; -// // type C = PoseidonGoldilocksConfig; -// // type F = >::F; -// // let mut pw: PartialWitness = PartialWitness::new(); -// // pw.set_target(targets.input_is_schnorr[0], GoldilocksField(1))?; -// // pw.set_target(targets.input_is_gpg[0], GoldilocksField::ZERO)?; -// // pw.set_target( -// // targets.input_payload_hash[0], -// // schnorrPOD3.payload.hash_payload(), -// // )?; -// // pw.set_target(targets.pk_index[0], GoldilocksField(1))?; -// // targets.input_proof[0].set_witness(&mut pw, &schnorrPOD3.proof)?; -// // targets.input_entries[0][0].set_witness(&mut pw, &schnorrPOD3.payload[0])?; -// // targets.input_entries[0][1].set_witness(&mut pw, &schnorrPOD3.payload[1])?; -// // let data = builder.build::(); -// // let proof = data.prove(pw)?; - -// Ok(()) -// } + assert!(schnorrPOD1.verify()? == true); + assert!(schnorrPOD2.verify()? == true); + + let mut schnorrPOD3 = + POD::execute_schnorr_gadget(&vec![entry1.clone()], &SchnorrSecretKey { sk: 25 }); + + // modify the internal value of the valueOf statement in schnorrPOD3 + let stmt_in_map = schnorrPOD3.payload.statements_map.get_mut("entry-some key"); + stmt_in_map.unwrap().optional_value = Some(ScalarOrVec::Scalar(GoldilocksField(37))); + schnorrPOD3.payload.statements_list[1].1.optional_value = + Some(ScalarOrVec::Scalar(GoldilocksField(37))); + + // now signature shouldn't verify + assert!(schnorrPOD3.verify()? == false); + + // // ZK verification of SchnorrPOD 3. + // let (builder, targets) = pod2_circuit(1, 2, 0, 0)?; + + // // Assign witnesses + // const D: usize = 2; + // type C = PoseidonGoldilocksConfig; + // type F = >::F; + // let mut pw: PartialWitness = PartialWitness::new(); + // pw.set_target(targets.input_is_schnorr[0], GoldilocksField(1))?; + // pw.set_target(targets.input_is_gpg[0], GoldilocksField::ZERO)?; + // pw.set_target( + // targets.input_payload_hash[0], + // schnorrPOD3.payload.hash_payload(), + // )?; + // pw.set_target(targets.pk_index[0], GoldilocksField(1))?; + // targets.input_proof[0].set_witness(&mut pw, &schnorrPOD3.proof)?; + // targets.input_entries[0][0].set_witness(&mut pw, &schnorrPOD3.payload[0])?; + // targets.input_entries[0][1].set_witness(&mut pw, &schnorrPOD3.payload[1])?; + // let data = builder.build::(); + // let proof = data.prove(pw)?; -// #[test] -// fn god_pod_from_schnorr_test() -> Result<(), Error> { -// // Start with some values. -// let scalar1 = GoldilocksField(36); -// let scalar2 = GoldilocksField(52); -// let scalar3 = GoldilocksField(90); -// let vector_value = vec![scalar1, scalar2]; + Ok(()) +} -// // make entries -// let entry1 = Entry::new("some key", ScalarOrVec::Scalar(scalar1)); -// let entry2 = Entry::new("some other key", ScalarOrVec::Scalar(scalar2)); -// let entry3 = Entry::new("vector entry", ScalarOrVec::Vector(vector_value.clone())); -// let entry4 = Entry::new("new key", ScalarOrVec::Scalar(scalar2)); -// let entry5 = Entry::new("foo", ScalarOrVec::Scalar(GoldilocksField(100))); -// let entry6 = Entry::new("baz", ScalarOrVec::Scalar(GoldilocksField(120))); -// let entry7 = Entry::new("yum", ScalarOrVec::Scalar(scalar2)); -// let entry9 = Entry::new("godpod introduced entry key", ScalarOrVec::Scalar(scalar3)); +#[test] +fn god_pod_from_schnorr_test() -> Result<(), Error> { + println!("god_pod_from_schnorr_test"); + // Start with some values. + let scalar1 = GoldilocksField(36); + let scalar2 = GoldilocksField(52); + let scalar3 = GoldilocksField(90); + let vector_value = vec![scalar1, scalar2]; -// // three schnorr pods -// let schnorrPOD1 = SchnorrPOD::gadget( -// &vec![entry1.clone(), entry2.clone()], -// &SchnorrSecretKey { sk: 25 }, -// ); + // make entries + let entry1 = Entry::newFromScalar("some key".to_string(), scalar1); + let entry2 = Entry::newFromScalar("some other key".to_string(), scalar2); + let entry3 = Entry::newFromVec("vector entry".to_string(), vector_value.clone()); + let entry4 = Entry::newFromScalar("new key".to_string(), scalar2); + let entry5 = Entry::newFromScalar("foo".to_string(), GoldilocksField(100)); + let entry6 = Entry::newFromScalar("baz".to_string(), GoldilocksField(120)); + let entry7 = Entry::newFromScalar("yum".to_string(), scalar2); + let entry9 = Entry::newFromScalar("godpod introduced entry key".to_string(), scalar3); + + // three schnorr pods + let schnorrPOD1 = POD::execute_schnorr_gadget( + &vec![entry1.clone(), entry2.clone()], + &SchnorrSecretKey { sk: 25 }, + ); -// let schnorrPOD2 = SchnorrPOD::gadget( -// &vec![entry3.clone(), entry4.clone()], -// &SchnorrSecretKey { sk: 42 }, -// ); + let schnorrPOD2 = POD::execute_schnorr_gadget( + &vec![entry3.clone(), entry4.clone()], + &SchnorrSecretKey { sk: 42 }, + ); -// let schnorrPOD3 = SchnorrPOD::gadget( -// &vec![entry5.clone(), entry6.clone(), entry7.clone()], -// &SchnorrSecretKey { sk: 83 }, -// ); + let schnorrPOD3 = POD::execute_schnorr_gadget( + &vec![entry5.clone(), entry6.clone(), entry7.clone()], + &SchnorrSecretKey { sk: 83 }, + ); -// // make a GODPOD using from_pods called on the two schnorr PODs -// let god_pod_1 = GODPOD::gadget( -// &vec![ -// &SchnorrOrGODPOD::SchnorrPOD(schnorrPOD1.clone()), -// &SchnorrOrGODPOD::SchnorrPOD(schnorrPOD2.clone()), -// &SchnorrOrGODPOD::SchnorrPOD(schnorrPOD3.clone()), -// ], -// &vec![ -// (OperationType::CopyStatement, Some(0), None, None, None), -// (OperationType::CopyStatement, Some(1), None, None, None), -// (OperationType::CopyStatement, Some(2), None, None, None), -// (OperationType::CopyStatement, Some(3), None, None, None), -// (OperationType::CopyStatement, Some(4), None, None, None), -// (OperationType::CopyStatement, Some(5), None, None, None), -// (OperationType::NewEntry, None, None, None, Some(&entry9)), -// ( -// OperationType::EqualityFromEntries, -// Some(1), -// Some(4), -// None, -// None, -// ), -// ( -// OperationType::EqualityFromEntries, -// Some(4), -// Some(8), -// None, -// None, -// ), -// ( -// OperationType::NonequalityFromEntries, -// Some(0), -// Some(1), -// None, -// None, -// ), -// (OperationType::GtFromEntries, Some(1), Some(0), None, None), -// ], -// ); -// println!("GODPOD1: {:?}", god_pod_1); -// assert!(god_pod_1.verify()? == true); + // make an OraclePOD using from_pods called on the two schnorr PODs -// // another GODPOD from the first GODPOD and another schnorr POD + // first make the GPG input -// let god_pod_2 = GODPOD::gadget( -// &vec![ -// &SchnorrOrGODPOD::GODPOD(god_pod_1.clone()), -// &SchnorrOrGODPOD::SchnorrPOD(schnorrPOD3.clone()), -// ], -// &vec![ -// (OperationType::CopyStatement, Some(8), None, None, None), -// (OperationType::CopyStatement, Some(9), None, None, None), -// (OperationType::CopyStatement, Some(3), None, None, None), -// (OperationType::GtFromEntries, Some(6), Some(0), None, None), -// ( -// OperationType::TransitiveEqualityFromStatements, -// Some(7), -// Some(8), -// None, -// None, -// ), -// (OperationType::GtToNonequality, Some(10), None, None, None), -// ], -// ); -// println!("GODPOD2: {:?}", god_pod_2); + // make a map of named POD inputs + let mut named_input_pods = HashMap::new(); + named_input_pods.insert("schnorrPOD1".to_string(), schnorrPOD1.clone()); + named_input_pods.insert("schnorrPOD2".to_string(), schnorrPOD2.clone()); + named_input_pods.insert("schnorrPOD3".to_string(), schnorrPOD3.clone()); -// // println!( -// // "verify schnorrpod1: {:?}", -// // schnorrPOD1.clone().payload.to_field_vec() -// // ); -// // println!("verify schnorrpod2: {:?}", schnorrPOD2.verify()); + // make a map of (pod name, old origin name) to new origin name + let mut origin_renaming_map = HashMap::new(); + origin_renaming_map.insert( + ("schnorrPOD1".to_string(), "_SELF".to_string()), + "schnorrPOD1".to_string(), + ); + origin_renaming_map.insert( + ("schnorrPOD2".to_string(), "_SELF".to_string()), + "schnorrPOD2".to_string(), + ); -// assert!(god_pod_2.verify()? == true); + let gpg_input = GPGInput::new(named_input_pods, origin_renaming_map); + + // make a list of the operations we want to call + let ops = vec![ + OperationCmd { + operation_type: OperationType::CopyStatement, + statement_1_parent: Some("schnorrPOD1".to_string()), + statement_1_name: Some("entry-some key".to_string()), + statement_2_parent: None, + statement_2_name: None, + statement_3_parent: None, + statement_3_name: None, + optional_entry: None, + output_statement_name: "schnorrPOD1-some key".to_string(), + }, + OperationCmd { + operation_type: OperationType::CopyStatement, + statement_1_parent: Some("schnorrPOD1".to_string()), + statement_1_name: Some("entry-some other key".to_string()), + statement_2_parent: None, + statement_2_name: None, + statement_3_parent: None, + statement_3_name: None, + optional_entry: None, + output_statement_name: "schnorrPOD1-some other key".to_string(), + }, + OperationCmd { + operation_type: OperationType::CopyStatement, + statement_1_parent: Some("schnorrPOD1".to_string()), + statement_1_name: Some("entry-_signer".to_string()), + statement_2_parent: None, + statement_2_name: None, + statement_3_parent: None, + statement_3_name: None, + optional_entry: None, + output_statement_name: "schnorrPOD1-signer".to_string(), + }, + OperationCmd { + operation_type: OperationType::CopyStatement, + statement_1_parent: Some("schnorrPOD2".to_string()), + statement_1_name: Some("entry-vector entry".to_string()), + statement_2_parent: None, + statement_2_name: None, + statement_3_parent: None, + statement_3_name: None, + optional_entry: None, + output_statement_name: "schnorrPOD2-vec-entry".to_string(), + }, + OperationCmd { + operation_type: OperationType::CopyStatement, + statement_1_parent: Some("schnorrPOD2".to_string()), + statement_1_name: Some("entry-new key".to_string()), + statement_2_parent: None, + statement_2_name: None, + statement_3_parent: None, + statement_3_name: None, + optional_entry: None, + output_statement_name: "schnorrPOD2-new key".to_string(), + }, + OperationCmd { + operation_type: OperationType::CopyStatement, + statement_1_parent: Some("schnorrPOD2".to_string()), + statement_1_name: Some("entry-_signer".to_string()), + statement_2_parent: None, + statement_2_name: None, + statement_3_parent: None, + statement_3_name: None, + optional_entry: None, + output_statement_name: "schnorrPOD2-signer".to_string(), + }, + OperationCmd { + operation_type: OperationType::CopyStatement, + statement_1_parent: Some("schnorrPOD3".to_string()), + statement_1_name: Some("entry-yum".to_string()), + statement_2_parent: None, + statement_2_name: None, + statement_3_parent: None, + statement_3_name: None, + optional_entry: None, + output_statement_name: "schnorrPOD3-yum".to_string(), + }, + OperationCmd { + operation_type: OperationType::EqualityFromEntries, + statement_1_parent: Some("schnorrPOD1".to_string()), + statement_1_name: Some("entry-some other key".to_string()), + statement_2_parent: Some("schnorrPOD2".to_string()), + statement_2_name: Some("entry-new key".to_string()), + statement_3_parent: None, + statement_3_name: None, + optional_entry: None, + output_statement_name: "eq1".to_string(), + }, + OperationCmd { + operation_type: OperationType::ContainsFromEntries, + statement_1_parent: Some("_SELF".to_string()), + statement_1_name: Some("schnorrPOD2-vec-entry".to_string()), + statement_2_parent: Some("schnorrPOD1".to_string()), + statement_2_name: Some("entry-some key".to_string()), + statement_3_parent: None, + statement_3_name: None, + optional_entry: None, + output_statement_name: "contains test".to_string(), + }, + ]; + + let oracle_pod = POD::execute_oracle_gadget(&gpg_input, &ops); + let statements = &oracle_pod.unwrap(); + for statement in statements.payload.statements_list.iter() { + println!("statement: {:?}", statement); + } + // assert!(oracle_pod.unwrap().verify()? == true); + + // let god_pod_1 = GODPOD::gadget( + // &vec![ + // &SchnorrOrGODPOD::SchnorrPOD(schnorrPOD1.clone()), + // &SchnorrOrGODPOD::SchnorrPOD(schnorrPOD2.clone()), + // &SchnorrOrGODPOD::SchnorrPOD(schnorrPOD3.clone()), + // ], + // &vec![ + // (OperationType::CopyStatement, Some(0), None, None, None), + // (OperationType::CopyStatement, Some(1), None, None, None), + // (OperationType::CopyStatement, Some(2), None, None, None), + // (OperationType::CopyStatement, Some(3), None, None, None), + // (OperationType::CopyStatement, Some(4), None, None, None), + // (OperationType::CopyStatement, Some(5), None, None, None), + // (OperationType::NewEntry, None, None, None, Some(&entry9)), + // ( + // OperationType::EqualityFromEntries, + // Some(1), + // Some(4), + // None, + // None, + // ), + // ( + // OperationType::EqualityFromEntries, + // Some(4), + // Some(8), + // None, + // None, + // ), + // ( + // OperationType::NonequalityFromEntries, + // Some(0), + // Some(1), + // None, + // None, + // ), + // (OperationType::GtFromEntries, Some(1), Some(0), None, None), + // ], + // ); + // println!("GODPOD1: {:?}", god_pod_1); + // assert!(god_pod_1.verify()? == true); + + // // another GODPOD from the first GODPOD and another schnorr POD + + // let god_pod_2 = GODPOD::gadget( + // &vec![ + // &SchnorrOrGODPOD::GODPOD(god_pod_1.clone()), + // &SchnorrOrGODPOD::SchnorrPOD(schnorrPOD3.clone()), + // ], + // &vec![ + // (OperationType::CopyStatement, Some(8), None, None, None), + // (OperationType::CopyStatement, Some(9), None, None, None), + // (OperationType::CopyStatement, Some(3), None, None, None), + // (OperationType::GtFromEntries, Some(6), Some(0), None, None), + // ( + // OperationType::TransitiveEqualityFromStatements, + // Some(7), + // Some(8), + // None, + // None, + // ), + // (OperationType::GtToNonequality, Some(10), None, None, None), + // ], + // ); + // println!("GODPOD2: {:?}", god_pod_2); + + // // println!( + // // "verify schnorrpod1: {:?}", + // // schnorrPOD1.clone().payload.to_field_vec() + // // ); + // // println!("verify schnorrpod2: {:?}", schnorrPOD2.verify()); + + // assert!(god_pod_2.verify()? == true); -// Ok(()) -// } + Ok(()) +} // #[test] // #[should_panic] @@ -1218,17 +1360,17 @@ fn op_test() -> Result<(), Error> { // let entry9 = Entry::new("godpod introduced entry key", ScalarOrVec::Scalar(scalar3)); // // three schnorr pods -// let schnorrPOD1 = SchnorrPOD::gadget( +// let schnorrPOD1 = POD::execute_schnorr_gadget( // &vec![entry1.clone(), entry2.clone()], // &SchnorrSecretKey { sk: 25 }, // ); -// let schnorrPOD2 = SchnorrPOD::gadget( +// let schnorrPOD2 = POD::execute_schnorr_gadget( // &vec![entry3.clone(), entry4.clone()], // &SchnorrSecretKey { sk: 42 }, // ); -// let schnorrPOD3 = SchnorrPOD::gadget( +// let schnorrPOD3 = POD::execute_schnorr_gadget( // &vec![entry5.clone(), entry6.clone()], // &SchnorrSecretKey { sk: 83 }, // ); From c3a81aeb74a7e5e0613b1bc99fc74ca54358db2a Mon Sep 17 00:00:00 2001 From: gubsheep Date: Mon, 14 Oct 2024 12:39:15 -0700 Subject: [PATCH 8/8] good boy pod test --- src/pod.rs | 952 +++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 769 insertions(+), 183 deletions(-) diff --git a/src/pod.rs b/src/pod.rs index 7be19bc..dcd51b6 100644 --- a/src/pod.rs +++ b/src/pod.rs @@ -110,6 +110,18 @@ pub enum StatementPredicate { SumOf = 6, } +pub fn predicate_name(predicate: StatementPredicate) -> String { + match predicate { + StatementPredicate::None => "NONE".to_string(), + StatementPredicate::ValueOf => "VALUEOF".to_string(), + StatementPredicate::Equal => "EQUAL".to_string(), + StatementPredicate::NotEqual => "NOTEQUAL".to_string(), + StatementPredicate::Gt => "GT".to_string(), + StatementPredicate::Contains => "CONTAINS".to_string(), + StatementPredicate::SumOf => "SUMOF".to_string(), + } +} + #[derive(Clone, Debug, PartialEq)] pub struct Statement { pub predicate: StatementPredicate, @@ -253,7 +265,7 @@ impl POD { let payload_hash_vec = vec![payload_hash]; let protocol = SchnorrSigner::new(); - let wrapped_pk = self.payload.statements_map.get("entry-_signer"); + let wrapped_pk = self.payload.statements_map.get("VALUEOF:_signer"); if wrapped_pk == None { return Err("No signer found in payload".into()); @@ -298,7 +310,7 @@ impl POD { for entry in kv_pairs { statement_map.insert( - "entry-".to_owned() + &entry.key, + "VALUEOF:".to_owned() + &entry.key, Statement::from_entry(&entry, GadgetID::SCHNORR16), ); } @@ -326,10 +338,12 @@ impl POD { let new_statement = cmd.execute(GadgetID::ORACLE, statements); match new_statement { Some(new_statement) => { - statements - .get_mut("_SELF") - .unwrap() - .insert(cmd.output_statement_name.clone(), new_statement); + statements.get_mut("_SELF").unwrap().insert( + predicate_name(new_statement.predicate) + + ":" + + &cmd.output_statement_name, + new_statement, + ); } None => { print!("{:?}", cmd); @@ -377,14 +391,15 @@ impl GPGInput { origin_renaming_map: HashMap<(String, String), String>, ) -> Self { let mut pods_and_names_list = Vec::new(); + let mut origin_renaming_map_clone = origin_renaming_map.clone(); for (name, pod) in named_pods.iter() { pods_and_names_list.push((name.clone(), pod.clone())); + origin_renaming_map_clone.insert((name.clone(), "_SELF".to_string()), name.clone()); } pods_and_names_list.sort_by(|a, b| a.0.cmp(&b.0)); - return Self { - pods_list: pods_and_names_list.clone(), - origin_renaming_map: origin_renaming_map.clone(), + pods_list: pods_and_names_list, + origin_renaming_map: origin_renaming_map_clone, }; } @@ -528,7 +543,8 @@ pub enum OperationType { TransitiveEqualityFromStatements = 6, GtToNonequality = 7, ContainsFromEntries = 8, - SumOf = 9, + RenameContainedBy = 9, + SumOf = 10, } #[derive(Clone, Debug)] @@ -796,6 +812,52 @@ impl OperationType { } } } + ( + OperationType::RenameContainedBy, + Some(left_statement), + Some(right_statement), + _, + _, + ) => match (left_statement, right_statement) { + ( + Statement { + predicate: StatementPredicate::Contains, + origin1: ll_origin, + key1: ll_key_name, + origin2: Some(lr_origin), + key2: Some(lr_key_name), + origin3: None, + key3: None, + optional_value: None, + }, + Statement { + predicate: StatementPredicate::Equal, + origin1: rl_origin, + key1: rl_key_name, + origin2: Some(rr_origin), + key2: Some(rr_key_name), + origin3: None, + key3: None, + optional_value: None, + }, + ) if (ll_origin.origin_id, &ll_key_name) + == ((rl_origin.origin_id, &rl_key_name)) => + { + return Some(Statement { + predicate: StatementPredicate::Contains, + origin1: rr_origin.clone(), + key1: rr_key_name.clone(), + origin2: Some(lr_origin.clone()), + key2: Some(lr_key_name.clone()), + origin3: None, + key3: None, + optional_value: None, + }); + } + _ => { + return None; + } + }, // SumOf <=> statement 1's value = statement 2's value + statement 3's value (OperationType::SumOf, Some(statement1), Some(statement2), Some(statement3), _) => { match ( @@ -1065,7 +1127,10 @@ fn schnorr_pod_test() -> Result<(), Error> { POD::execute_schnorr_gadget(&vec![entry1.clone()], &SchnorrSecretKey { sk: 25 }); // modify the internal value of the valueOf statement in schnorrPOD3 - let stmt_in_map = schnorrPOD3.payload.statements_map.get_mut("entry-some key"); + let stmt_in_map = schnorrPOD3 + .payload + .statements_map + .get_mut("VALUEOF:some key"); stmt_in_map.unwrap().optional_value = Some(ScalarOrVec::Scalar(GoldilocksField(37))); schnorrPOD3.payload.statements_list[1].1.optional_value = Some(ScalarOrVec::Scalar(GoldilocksField(37))); @@ -1097,24 +1162,26 @@ fn schnorr_pod_test() -> Result<(), Error> { Ok(()) } +// i haven't written asserts yet to check the correctness of oracle and oracle2 pods +// but i've manually inspected output and it looks good #[test] -fn god_pod_from_schnorr_test() -> Result<(), Error> { - println!("god_pod_from_schnorr_test"); +fn oracle_pod_from_schnorr_test() -> Result<(), Error> { + println!("oracle_pod_from_schnorr_test"); // Start with some values. let scalar1 = GoldilocksField(36); let scalar2 = GoldilocksField(52); - let scalar3 = GoldilocksField(90); + let scalar3 = GoldilocksField(88); let vector_value = vec![scalar1, scalar2]; // make entries - let entry1 = Entry::newFromScalar("some key".to_string(), scalar1); - let entry2 = Entry::newFromScalar("some other key".to_string(), scalar2); + let entry1 = Entry::newFromScalar("apple".to_string(), scalar1); + let entry2 = Entry::newFromScalar("banana".to_string(), scalar2); let entry3 = Entry::newFromVec("vector entry".to_string(), vector_value.clone()); - let entry4 = Entry::newFromScalar("new key".to_string(), scalar2); + let entry4 = Entry::newFromScalar("scalar entry".to_string(), scalar2); let entry5 = Entry::newFromScalar("foo".to_string(), GoldilocksField(100)); let entry6 = Entry::newFromScalar("baz".to_string(), GoldilocksField(120)); - let entry7 = Entry::newFromScalar("yum".to_string(), scalar2); - let entry9 = Entry::newFromScalar("godpod introduced entry key".to_string(), scalar3); + let entry7 = Entry::newFromScalar("bar".to_string(), scalar2); + let entry9 = Entry::newFromScalar("claimed sum".to_string(), scalar3); // three schnorr pods let schnorrPOD1 = POD::execute_schnorr_gadget( @@ -1126,32 +1193,19 @@ fn god_pod_from_schnorr_test() -> Result<(), Error> { &vec![entry3.clone(), entry4.clone()], &SchnorrSecretKey { sk: 42 }, ); - - let schnorrPOD3 = POD::execute_schnorr_gadget( - &vec![entry5.clone(), entry6.clone(), entry7.clone()], - &SchnorrSecretKey { sk: 83 }, - ); - // make an OraclePOD using from_pods called on the two schnorr PODs // first make the GPG input // make a map of named POD inputs let mut named_input_pods = HashMap::new(); - named_input_pods.insert("schnorrPOD1".to_string(), schnorrPOD1.clone()); + named_input_pods.insert("p1".to_string(), schnorrPOD1.clone()); named_input_pods.insert("schnorrPOD2".to_string(), schnorrPOD2.clone()); - named_input_pods.insert("schnorrPOD3".to_string(), schnorrPOD3.clone()); // make a map of (pod name, old origin name) to new origin name let mut origin_renaming_map = HashMap::new(); - origin_renaming_map.insert( - ("schnorrPOD1".to_string(), "_SELF".to_string()), - "schnorrPOD1".to_string(), - ); - origin_renaming_map.insert( - ("schnorrPOD2".to_string(), "_SELF".to_string()), - "schnorrPOD2".to_string(), - ); + // all the inputs are schnorr PODs whose only referenced origin is _SELF + // _SELF is taken care of automatically so origin_renaming_map can be empty let gpg_input = GPGInput::new(named_input_pods, origin_renaming_map); @@ -1159,41 +1213,41 @@ fn god_pod_from_schnorr_test() -> Result<(), Error> { let ops = vec![ OperationCmd { operation_type: OperationType::CopyStatement, - statement_1_parent: Some("schnorrPOD1".to_string()), - statement_1_name: Some("entry-some key".to_string()), + statement_1_parent: Some("p1".to_string()), + statement_1_name: Some("VALUEOF:apple".to_string()), statement_2_parent: None, statement_2_name: None, statement_3_parent: None, statement_3_name: None, optional_entry: None, - output_statement_name: "schnorrPOD1-some key".to_string(), + output_statement_name: "p1-apple".to_string(), }, OperationCmd { operation_type: OperationType::CopyStatement, - statement_1_parent: Some("schnorrPOD1".to_string()), - statement_1_name: Some("entry-some other key".to_string()), + statement_1_parent: Some("p1".to_string()), + statement_1_name: Some("VALUEOF:banana".to_string()), statement_2_parent: None, statement_2_name: None, statement_3_parent: None, statement_3_name: None, optional_entry: None, - output_statement_name: "schnorrPOD1-some other key".to_string(), + output_statement_name: "p1-banana".to_string(), }, OperationCmd { operation_type: OperationType::CopyStatement, - statement_1_parent: Some("schnorrPOD1".to_string()), - statement_1_name: Some("entry-_signer".to_string()), + statement_1_parent: Some("p1".to_string()), + statement_1_name: Some("VALUEOF:_signer".to_string()), statement_2_parent: None, statement_2_name: None, statement_3_parent: None, statement_3_name: None, optional_entry: None, - output_statement_name: "schnorrPOD1-signer".to_string(), + output_statement_name: "p1-signer".to_string(), }, OperationCmd { operation_type: OperationType::CopyStatement, statement_1_parent: Some("schnorrPOD2".to_string()), - statement_1_name: Some("entry-vector entry".to_string()), + statement_1_name: Some("VALUEOF:vector entry".to_string()), statement_2_parent: None, statement_2_name: None, statement_3_parent: None, @@ -1204,18 +1258,18 @@ fn god_pod_from_schnorr_test() -> Result<(), Error> { OperationCmd { operation_type: OperationType::CopyStatement, statement_1_parent: Some("schnorrPOD2".to_string()), - statement_1_name: Some("entry-new key".to_string()), + statement_1_name: Some("VALUEOF:scalar entry".to_string()), statement_2_parent: None, statement_2_name: None, statement_3_parent: None, statement_3_name: None, optional_entry: None, - output_statement_name: "schnorrPOD2-new key".to_string(), + output_statement_name: "a scalar entry".to_string(), }, OperationCmd { operation_type: OperationType::CopyStatement, statement_1_parent: Some("schnorrPOD2".to_string()), - statement_1_name: Some("entry-_signer".to_string()), + statement_1_name: Some("VALUEOF:_signer".to_string()), statement_2_parent: None, statement_2_name: None, statement_3_parent: None, @@ -1223,165 +1277,697 @@ fn god_pod_from_schnorr_test() -> Result<(), Error> { optional_entry: None, output_statement_name: "schnorrPOD2-signer".to_string(), }, + OperationCmd { + operation_type: OperationType::EqualityFromEntries, + statement_1_parent: Some("p1".to_string()), + statement_1_name: Some("VALUEOF:banana".to_string()), + statement_2_parent: Some("schnorrPOD2".to_string()), + statement_2_name: Some("VALUEOF:scalar entry".to_string()), + statement_3_parent: None, + statement_3_name: None, + optional_entry: None, + output_statement_name: "eq1".to_string(), + }, + OperationCmd { + operation_type: OperationType::GtFromEntries, + statement_1_parent: Some("p1".to_string()), + statement_1_name: Some("VALUEOF:banana".to_string()), + statement_2_parent: Some("p1".to_string()), + statement_2_name: Some("VALUEOF:apple".to_string()), + statement_3_parent: None, + statement_3_name: None, + optional_entry: None, + output_statement_name: "apple banana comparison".to_string(), + }, + // this operation creates a statement on top of a statement + // created by an earlier operation + OperationCmd { + operation_type: OperationType::ContainsFromEntries, + statement_1_parent: Some("_SELF".to_string()), + statement_1_name: Some("VALUEOF:schnorrPOD2-vec-entry".to_string()), + statement_2_parent: Some("p1".to_string()), + statement_2_name: Some("VALUEOF:apple".to_string()), + statement_3_parent: None, + statement_3_name: None, + optional_entry: None, + output_statement_name: "CONTAINS:contains1".to_string(), + }, + ]; + + let oracle_pod = POD::execute_oracle_gadget(&gpg_input, &ops).unwrap(); + assert!(oracle_pod.verify()? == true); + + // make another oracle POD which takes that oracle POD and a schnorr POD + + let schnorrPOD3 = POD::execute_schnorr_gadget( + &vec![entry5.clone(), entry6.clone(), entry7.clone()], + &SchnorrSecretKey { sk: 83 }, + ); + + // make the GPG input + + // make a map of named POD inputs + let mut named_input_pods2 = HashMap::new(); + named_input_pods2.insert("oraclePODParent".to_string(), oracle_pod.clone()); + named_input_pods2.insert("p3".to_string(), schnorrPOD3.clone()); + + // make a map of (pod name, old origin name) to new origin name + let mut origin_renaming_map2 = HashMap::new(); + // let's keep the name of the first origin and shorten the name of the second origin + origin_renaming_map2.insert( + ("oraclePODParent".to_string(), "p1".to_string()), + "p1".to_string(), + ); + origin_renaming_map2.insert( + ("oraclePODParent".to_string(), "schnorrPOD2".to_string()), + "p2".to_string(), + ); + + let gpg_input = GPGInput::new(named_input_pods2, origin_renaming_map2); + + // make a list of the operations we want to call + + let ops = vec![ + OperationCmd { + operation_type: OperationType::EqualityFromEntries, + statement_1_parent: Some("oraclePODParent".to_string()), + statement_1_name: Some("VALUEOF:a scalar entry".to_string()), + statement_2_parent: Some("p3".to_string()), + statement_2_name: Some("VALUEOF:bar".to_string()), + statement_3_parent: None, + statement_3_name: None, + optional_entry: None, + output_statement_name: "eq2".to_string(), + }, + OperationCmd { + operation_type: OperationType::TransitiveEqualityFromStatements, + statement_1_parent: Some("oraclePODParent".to_string()), + statement_1_name: Some("EQUAL:eq1".to_string()), + statement_2_parent: Some("_SELF".to_string()), + statement_2_name: Some("EQUAL:eq2".to_string()), + statement_3_parent: None, + statement_3_name: None, + optional_entry: None, + output_statement_name: "EQUAL:transitive eq".to_string(), + }, + OperationCmd { + operation_type: OperationType::NewEntry, + statement_1_parent: None, + statement_1_name: None, + statement_2_parent: None, + statement_2_name: None, + statement_3_parent: None, + statement_3_name: None, + optional_entry: Some(entry9.clone()), + output_statement_name: "entry for claimed sum".to_string(), + }, + OperationCmd { + operation_type: OperationType::SumOf, + statement_1_parent: Some("_SELF".to_string()), + statement_1_name: Some("VALUEOF:entry for claimed sum".to_string()), + statement_2_parent: Some("oraclePODParent".to_string()), + statement_2_name: Some("VALUEOF:p1-apple".to_string()), + statement_3_parent: Some("oraclePODParent".to_string()), + statement_3_name: Some("VALUEOF:a scalar entry".to_string()), + optional_entry: None, + output_statement_name: "sumof entry".to_string(), + }, + OperationCmd { + operation_type: OperationType::CopyStatement, + statement_1_parent: Some("oraclePODParent".to_string()), + statement_1_name: Some("VALUEOF:schnorrPOD2-signer".to_string()), + statement_2_parent: None, + statement_2_name: None, + statement_3_parent: None, + statement_3_name: None, + optional_entry: None, + output_statement_name: "p2-signer".to_string(), + }, + OperationCmd { + operation_type: OperationType::GtToNonequality, + statement_1_parent: Some("oraclePODParent".to_string()), + statement_1_name: Some("GT:apple banana comparison".to_string()), + statement_2_parent: None, + statement_2_name: None, + statement_3_parent: None, + statement_3_name: None, + optional_entry: None, + output_statement_name: "apple banana nonequality".to_string(), + }, + ]; + + let oracle_pod2 = POD::execute_oracle_gadget(&gpg_input, &ops).unwrap(); + for statement in oracle_pod2.payload.statements_list.iter() { + println!("{:?}", statement); + } + assert!(oracle_pod2.verify()? == true); + Ok(()) +} + +#[test] +fn goodboy_test() -> Result<(), Error> { + let protocol = SchnorrSigner::new(); + + let alice_sk = SchnorrSecretKey { sk: 25 }; + let alice_pk = protocol.keygen(&alice_sk).pk; + let bob_sk = SchnorrSecretKey { sk: 26 }; + let bob_pk = protocol.keygen(&bob_sk).pk; + let charlie_sk = SchnorrSecretKey { sk: 27 }; + let charlie_pk = protocol.keygen(&charlie_sk).pk; + + let goog_sk = SchnorrSecretKey { sk: 28 }; + let goog_pk = protocol.keygen(&goog_sk).pk; + let msft_sk = SchnorrSecretKey { sk: 29 }; + let msft_pk = protocol.keygen(&msft_sk).pk; + let fb_sk = SchnorrSecretKey { sk: 30 }; + let fb_pk = protocol.keygen(&fb_sk).pk; + + let known_attestors = vec![goog_pk, msft_pk, fb_pk]; + + let gb1_user = Entry::newFromScalar("user".to_string(), bob_pk); + let gb1_age = Entry::newFromScalar("age".to_string(), GoldilocksField(27)); + let gb1 = POD::execute_schnorr_gadget(&vec![gb1_user.clone(), gb1_age.clone()], &goog_sk); + + let gb2_user = Entry::newFromScalar("user".to_string(), bob_pk); + let gb2 = POD::execute_schnorr_gadget(&vec![gb2_user.clone()], &msft_sk); + + let gb3_user = Entry::newFromScalar("user".to_string(), charlie_pk); + let gb3_age = Entry::newFromScalar("age".to_string(), GoldilocksField(18)); + let gb3 = POD::execute_schnorr_gadget(&vec![gb3_user.clone(), gb3_age.clone()], &msft_sk); + + let gb4_user = Entry::newFromScalar("user".to_string(), charlie_pk); + let gb4 = POD::execute_schnorr_gadget(&vec![gb4_user.clone()], &fb_sk); + + let alice_user_entry = Entry::newFromScalar("user".to_string(), alice_pk); + let known_attestors_entry = + Entry::newFromVec("known_attestors".to_string(), known_attestors.clone()); + + let bob_alice = POD::execute_schnorr_gadget(&vec![alice_user_entry.clone()], &bob_sk); + let charlie_alice = POD::execute_schnorr_gadget(&vec![alice_user_entry.clone()], &charlie_sk); + + // make the "bob trusted friend" POD + let mut bob_tf_input_pods = HashMap::new(); + bob_tf_input_pods.insert("bob-gb1".to_string(), gb1.clone()); + bob_tf_input_pods.insert("bob-gb2".to_string(), gb2.clone()); + bob_tf_input_pods.insert("bob-alice".to_string(), bob_alice.clone()); + + let bob_tf_input = GPGInput::new(bob_tf_input_pods, HashMap::new()); + + let bob_tf_ops = vec![ + OperationCmd { + operation_type: OperationType::CopyStatement, + statement_1_parent: Some("bob-alice".to_string()), + statement_1_name: Some("VALUEOF:_signer".to_string()), + statement_2_parent: None, + statement_2_name: None, + statement_3_parent: None, + statement_3_name: None, + optional_entry: None, + output_statement_name: "bob-alice signer".to_string(), + }, + OperationCmd { + operation_type: OperationType::CopyStatement, + statement_1_parent: Some("bob-alice".to_string()), + statement_1_name: Some("VALUEOF:user".to_string()), + statement_2_parent: None, + statement_2_name: None, + statement_3_parent: None, + statement_3_name: None, + optional_entry: None, + output_statement_name: "bob-alice user".to_string(), + }, OperationCmd { operation_type: OperationType::CopyStatement, - statement_1_parent: Some("schnorrPOD3".to_string()), - statement_1_name: Some("entry-yum".to_string()), + statement_1_parent: Some("bob-gb1".to_string()), + statement_1_name: Some("VALUEOF:age".to_string()), statement_2_parent: None, statement_2_name: None, statement_3_parent: None, statement_3_name: None, optional_entry: None, - output_statement_name: "schnorrPOD3-yum".to_string(), + output_statement_name: "bob age".to_string(), + }, + OperationCmd { + operation_type: OperationType::NewEntry, + statement_1_parent: None, + statement_1_name: None, + statement_2_parent: None, + statement_2_name: None, + statement_3_parent: None, + statement_3_name: None, + optional_entry: Some(known_attestors_entry.clone()), + output_statement_name: "known_attestors".to_string(), }, OperationCmd { operation_type: OperationType::EqualityFromEntries, - statement_1_parent: Some("schnorrPOD1".to_string()), - statement_1_name: Some("entry-some other key".to_string()), - statement_2_parent: Some("schnorrPOD2".to_string()), - statement_2_name: Some("entry-new key".to_string()), + statement_1_parent: Some("bob-alice".to_string()), + statement_1_name: Some("VALUEOF:_signer".to_string()), + statement_2_parent: Some("bob-gb1".to_string()), + statement_2_name: Some("VALUEOF:user".to_string()), + statement_3_parent: None, + statement_3_name: None, + optional_entry: Some(known_attestors_entry.clone()), + output_statement_name: "gb1 attests to correct user".to_string(), + }, + OperationCmd { + operation_type: OperationType::EqualityFromEntries, + statement_1_parent: Some("bob-alice".to_string()), + statement_1_name: Some("VALUEOF:_signer".to_string()), + statement_2_parent: Some("bob-gb2".to_string()), + statement_2_name: Some("VALUEOF:user".to_string()), + statement_3_parent: None, + statement_3_name: None, + optional_entry: Some(known_attestors_entry.clone()), + output_statement_name: "gb2 attests to correct user".to_string(), + }, + OperationCmd { + operation_type: OperationType::NonequalityFromEntries, + statement_1_parent: Some("bob-gb1".to_string()), + statement_1_name: Some("VALUEOF:_signer".to_string()), + statement_2_parent: Some("bob-gb2".to_string()), + statement_2_name: Some("VALUEOF:_signer".to_string()), + statement_3_parent: None, + statement_3_name: None, + optional_entry: Some(known_attestors_entry.clone()), + output_statement_name: "gb1 and gb2 are different".to_string(), + }, + OperationCmd { + operation_type: OperationType::ContainsFromEntries, + statement_1_parent: Some("_SELF".to_string()), + statement_1_name: Some("VALUEOF:known_attestors".to_string()), + statement_2_parent: Some("bob-gb1".to_string()), + statement_2_name: Some("VALUEOF:_signer".to_string()), + statement_3_parent: None, + statement_3_name: None, + optional_entry: Some(known_attestors_entry.clone()), + output_statement_name: "gb1 has known signer".to_string(), + }, + OperationCmd { + operation_type: OperationType::ContainsFromEntries, + statement_1_parent: Some("_SELF".to_string()), + statement_1_name: Some("VALUEOF:known_attestors".to_string()), + statement_2_parent: Some("bob-gb2".to_string()), + statement_2_name: Some("VALUEOF:_signer".to_string()), + statement_3_parent: None, + statement_3_name: None, + optional_entry: Some(known_attestors_entry.clone()), + output_statement_name: "gb2 has known signer".to_string(), + }, + ]; + + let bob_tf = POD::execute_oracle_gadget(&bob_tf_input, &bob_tf_ops).unwrap(); + assert!(bob_tf.verify()? == true); + + // make the "bob trusted friend" POD + let mut charlie_tf_input_pods = HashMap::new(); + charlie_tf_input_pods.insert("charlie-gb3".to_string(), gb3.clone()); + charlie_tf_input_pods.insert("charlie-gb4".to_string(), gb4.clone()); + charlie_tf_input_pods.insert("charlie-alice".to_string(), charlie_alice.clone()); + + let charlie_tf_input = GPGInput::new(charlie_tf_input_pods, HashMap::new()); + + let charlie_tf_ops = vec![ + OperationCmd { + operation_type: OperationType::CopyStatement, + statement_1_parent: Some("charlie-alice".to_string()), + statement_1_name: Some("VALUEOF:_signer".to_string()), + statement_2_parent: None, + statement_2_name: None, statement_3_parent: None, statement_3_name: None, optional_entry: None, - output_statement_name: "eq1".to_string(), + output_statement_name: "charlie-alice signer".to_string(), + }, + OperationCmd { + operation_type: OperationType::CopyStatement, + statement_1_parent: Some("charlie-alice".to_string()), + statement_1_name: Some("VALUEOF:user".to_string()), + statement_2_parent: None, + statement_2_name: None, + statement_3_parent: None, + statement_3_name: None, + optional_entry: None, + output_statement_name: "charlie-alice user".to_string(), + }, + OperationCmd { + operation_type: OperationType::CopyStatement, + statement_1_parent: Some("charlie-gb3".to_string()), + statement_1_name: Some("VALUEOF:age".to_string()), + statement_2_parent: None, + statement_2_name: None, + statement_3_parent: None, + statement_3_name: None, + optional_entry: None, + output_statement_name: "charlie age".to_string(), + }, + OperationCmd { + operation_type: OperationType::NewEntry, + statement_1_parent: None, + statement_1_name: None, + statement_2_parent: None, + statement_2_name: None, + statement_3_parent: None, + statement_3_name: None, + optional_entry: Some(known_attestors_entry.clone()), + output_statement_name: "known_attestors".to_string(), + }, + OperationCmd { + operation_type: OperationType::EqualityFromEntries, + statement_1_parent: Some("charlie-alice".to_string()), + statement_1_name: Some("VALUEOF:_signer".to_string()), + statement_2_parent: Some("charlie-gb3".to_string()), + statement_2_name: Some("VALUEOF:user".to_string()), + statement_3_parent: None, + statement_3_name: None, + optional_entry: Some(known_attestors_entry.clone()), + output_statement_name: "gb3 attests to correct user".to_string(), + }, + OperationCmd { + operation_type: OperationType::EqualityFromEntries, + statement_1_parent: Some("charlie-alice".to_string()), + statement_1_name: Some("VALUEOF:_signer".to_string()), + statement_2_parent: Some("charlie-gb4".to_string()), + statement_2_name: Some("VALUEOF:user".to_string()), + statement_3_parent: None, + statement_3_name: None, + optional_entry: Some(known_attestors_entry.clone()), + output_statement_name: "gb4 attests to correct user".to_string(), + }, + OperationCmd { + operation_type: OperationType::NonequalityFromEntries, + statement_1_parent: Some("charlie-gb3".to_string()), + statement_1_name: Some("VALUEOF:_signer".to_string()), + statement_2_parent: Some("charlie-gb4".to_string()), + statement_2_name: Some("VALUEOF:_signer".to_string()), + statement_3_parent: None, + statement_3_name: None, + optional_entry: Some(known_attestors_entry.clone()), + output_statement_name: "gb3 and gb4 are different".to_string(), + }, + OperationCmd { + operation_type: OperationType::ContainsFromEntries, + statement_1_parent: Some("_SELF".to_string()), + statement_1_name: Some("VALUEOF:known_attestors".to_string()), + statement_2_parent: Some("charlie-gb3".to_string()), + statement_2_name: Some("VALUEOF:_signer".to_string()), + statement_3_parent: None, + statement_3_name: None, + optional_entry: Some(known_attestors_entry.clone()), + output_statement_name: "gb3 has known signer".to_string(), }, OperationCmd { operation_type: OperationType::ContainsFromEntries, statement_1_parent: Some("_SELF".to_string()), - statement_1_name: Some("schnorrPOD2-vec-entry".to_string()), - statement_2_parent: Some("schnorrPOD1".to_string()), - statement_2_name: Some("entry-some key".to_string()), + statement_1_name: Some("VALUEOF:known_attestors".to_string()), + statement_2_parent: Some("charlie-gb4".to_string()), + statement_2_name: Some("VALUEOF:_signer".to_string()), + statement_3_parent: None, + statement_3_name: None, + optional_entry: Some(known_attestors_entry.clone()), + output_statement_name: "gb4 has known signer".to_string(), + }, + ]; + + let charlie_tf = POD::execute_oracle_gadget(&charlie_tf_input, &charlie_tf_ops).unwrap(); + assert!(charlie_tf.verify()? == true); + + // make the "great boy" POD + let age_bound_entry = Entry::newFromScalar("known_attestors".to_string(), GoldilocksField(17)); + let age_sum_entry = Entry::newFromScalar("age_sum".to_string(), GoldilocksField(45)); + let mut grb_input_pods = HashMap::new(); + grb_input_pods.insert("friend1".to_string(), bob_tf.clone()); + grb_input_pods.insert("friend2".to_string(), charlie_tf.clone()); + + // make a map of (pod name, old origin name) to new origin name + let mut grb_origin_rename_map = HashMap::new(); + // let's keep the name of the first origin and shorten the name of the second origin + grb_origin_rename_map.insert( + ("friend1".to_string(), "bob-gb1".to_string()), + "gb1".to_string(), + ); + grb_origin_rename_map.insert( + ("friend1".to_string(), "bob-gb2".to_string()), + "gb2".to_string(), + ); + grb_origin_rename_map.insert( + ("friend1".to_string(), "bob-alice".to_string()), + "friend1-attest".to_string(), + ); + grb_origin_rename_map.insert( + ("friend2".to_string(), "charlie-gb3".to_string()), + "gb3".to_string(), + ); + grb_origin_rename_map.insert( + ("friend2".to_string(), "charlie-gb4".to_string()), + "gb4".to_string(), + ); + grb_origin_rename_map.insert( + ("friend2".to_string(), "charlie-alice".to_string()), + "friend2-attest".to_string(), + ); + + let grb_input = GPGInput::new(grb_input_pods, grb_origin_rename_map); + + let grb_ops = vec![ + OperationCmd { + operation_type: OperationType::CopyStatement, + statement_1_parent: Some("friend1".to_string()), + statement_1_name: Some("VALUEOF:bob-alice user".to_string()), + statement_2_parent: None, + statement_2_name: None, + statement_3_parent: None, + statement_3_name: None, + optional_entry: None, + output_statement_name: "friend1 attested user".to_string(), + }, + OperationCmd { + operation_type: OperationType::CopyStatement, + statement_1_parent: Some("friend2".to_string()), + statement_1_name: Some("VALUEOF:charlie-alice user".to_string()), + statement_2_parent: None, + statement_2_name: None, + statement_3_parent: None, + statement_3_name: None, + optional_entry: None, + output_statement_name: "friend2 attested user".to_string(), + }, + OperationCmd { + operation_type: OperationType::NewEntry, + statement_1_parent: None, + statement_1_name: None, + statement_2_parent: None, + statement_2_name: None, + statement_3_parent: None, + statement_3_name: None, + optional_entry: Some(age_bound_entry.clone()), + output_statement_name: "age_bound".to_string(), + }, + OperationCmd { + operation_type: OperationType::NewEntry, + statement_1_parent: None, + statement_1_name: None, + statement_2_parent: None, + statement_2_name: None, + statement_3_parent: None, + statement_3_name: None, + optional_entry: Some(age_sum_entry.clone()), + output_statement_name: "age_sum".to_string(), + }, + OperationCmd { + operation_type: OperationType::NewEntry, + statement_1_parent: None, + statement_1_name: None, + statement_2_parent: None, + statement_2_name: None, + statement_3_parent: None, + statement_3_name: None, + optional_entry: Some(known_attestors_entry.clone()), + output_statement_name: "known_attestors".to_string(), + }, + OperationCmd { + operation_type: OperationType::EqualityFromEntries, + statement_1_parent: Some("friend1".to_string()), + statement_1_name: Some("VALUEOF:known_attestors".to_string()), + statement_2_parent: Some("_SELF".to_string()), + statement_2_name: Some("VALUEOF:known_attestors".to_string()), statement_3_parent: None, statement_3_name: None, optional_entry: None, - output_statement_name: "contains test".to_string(), + output_statement_name: "friend1 known_attestors same as _SELF".to_string(), + }, + OperationCmd { + operation_type: OperationType::EqualityFromEntries, + statement_1_parent: Some("friend2".to_string()), + statement_1_name: Some("VALUEOF:known_attestors".to_string()), + statement_2_parent: Some("_SELF".to_string()), + statement_2_name: Some("VALUEOF:known_attestors".to_string()), + statement_3_parent: None, + statement_3_name: None, + optional_entry: None, + output_statement_name: "friend2 known_attestors same as _SELF".to_string(), + }, + OperationCmd { + operation_type: OperationType::CopyStatement, + statement_1_parent: Some("friend1".to_string()), + statement_1_name: Some("EQUAL:gb1 attests to correct user".to_string()), + statement_2_parent: None, + statement_2_name: None, + statement_3_parent: None, + statement_3_name: None, + optional_entry: None, + output_statement_name: "gb1 attests to correct user".to_string(), + }, + OperationCmd { + operation_type: OperationType::RenameContainedBy, + statement_1_parent: Some("friend1".to_string()), + statement_1_name: Some("CONTAINS:gb1 has known signer".to_string()), + statement_2_parent: Some("_SELF".to_string()), + statement_2_name: Some("EQUAL:friend1 known_attestors same as _SELF".to_string()), + statement_3_parent: None, + statement_3_name: None, + optional_entry: None, + output_statement_name: "gb1 has known signer".to_string(), + }, + OperationCmd { + operation_type: OperationType::CopyStatement, + statement_1_parent: Some("friend1".to_string()), + statement_1_name: Some("EQUAL:gb2 attests to correct user".to_string()), + statement_2_parent: None, + statement_2_name: None, + statement_3_parent: None, + statement_3_name: None, + optional_entry: None, + output_statement_name: "gb2 attests to correct user".to_string(), + }, + OperationCmd { + operation_type: OperationType::RenameContainedBy, + statement_1_parent: Some("friend1".to_string()), + statement_1_name: Some("CONTAINS:gb2 has known signer".to_string()), + statement_2_parent: Some("_SELF".to_string()), + statement_2_name: Some("EQUAL:friend1 known_attestors same as _SELF".to_string()), + statement_3_parent: None, + statement_3_name: None, + optional_entry: None, + output_statement_name: "gb2 has known signer".to_string(), + }, + OperationCmd { + operation_type: OperationType::CopyStatement, + statement_1_parent: Some("friend1".to_string()), + statement_1_name: Some("NOTEQUAL:gb1 and gb2 are different".to_string()), + statement_2_parent: None, + statement_2_name: None, + statement_3_parent: None, + statement_3_name: None, + optional_entry: None, + output_statement_name: "gb1 and gb2 are different".to_string(), + }, + OperationCmd { + operation_type: OperationType::CopyStatement, + statement_1_parent: Some("friend2".to_string()), + statement_1_name: Some("EQUAL:gb3 attests to correct user".to_string()), + statement_2_parent: None, + statement_2_name: None, + statement_3_parent: None, + statement_3_name: None, + optional_entry: None, + output_statement_name: "gb3 attests to correct user".to_string(), + }, + OperationCmd { + operation_type: OperationType::RenameContainedBy, + statement_1_parent: Some("friend2".to_string()), + statement_1_name: Some("CONTAINS:gb3 has known signer".to_string()), + statement_2_parent: Some("_SELF".to_string()), + statement_2_name: Some("EQUAL:friend2 known_attestors same as _SELF".to_string()), + statement_3_parent: None, + statement_3_name: None, + optional_entry: None, + output_statement_name: "gb3 has known signer".to_string(), + }, + OperationCmd { + operation_type: OperationType::CopyStatement, + statement_1_parent: Some("friend2".to_string()), + statement_1_name: Some("EQUAL:gb4 attests to correct user".to_string()), + statement_2_parent: None, + statement_2_name: None, + statement_3_parent: None, + statement_3_name: None, + optional_entry: None, + output_statement_name: "gb4 attests to correct user".to_string(), + }, + OperationCmd { + operation_type: OperationType::RenameContainedBy, + statement_1_parent: Some("friend2".to_string()), + statement_1_name: Some("CONTAINS:gb4 has known signer".to_string()), + statement_2_parent: Some("_SELF".to_string()), + statement_2_name: Some("EQUAL:friend2 known_attestors same as _SELF".to_string()), + statement_3_parent: None, + statement_3_name: None, + optional_entry: None, + output_statement_name: "gb4 has known signer".to_string(), + }, + OperationCmd { + operation_type: OperationType::CopyStatement, + statement_1_parent: Some("friend2".to_string()), + statement_1_name: Some("NOTEQUAL:gb3 and gb4 are different".to_string()), + statement_2_parent: None, + statement_2_name: None, + statement_3_parent: None, + statement_3_name: None, + optional_entry: None, + output_statement_name: "gb4 attests to correct user".to_string(), + }, + OperationCmd { + operation_type: OperationType::NonequalityFromEntries, + statement_1_parent: Some("friend1".to_string()), + statement_1_name: Some("VALUEOF:bob-alice signer".to_string()), + statement_2_parent: Some("friend2".to_string()), + statement_2_name: Some("VALUEOF:charlie-alice signer".to_string()), + statement_3_parent: None, + statement_3_name: None, + optional_entry: None, + output_statement_name: "friend1 and friend2 are different".to_string(), + }, + OperationCmd { + operation_type: OperationType::GtFromEntries, + statement_1_parent: Some("friend1".to_string()), + statement_1_name: Some("VALUEOF:bob age".to_string()), + statement_2_parent: Some("_SELF".to_string()), + statement_2_name: Some("VALUEOF:age_bound".to_string()), + statement_3_parent: None, + statement_3_name: None, + optional_entry: None, + output_statement_name: "friend1 is at least 18".to_string(), + }, + OperationCmd { + operation_type: OperationType::GtFromEntries, + statement_1_parent: Some("friend2".to_string()), + statement_1_name: Some("VALUEOF:charlie age".to_string()), + statement_2_parent: Some("_SELF".to_string()), + statement_2_name: Some("VALUEOF:age_bound".to_string()), + statement_3_parent: None, + statement_3_name: None, + optional_entry: None, + output_statement_name: "friend2 is at least 18".to_string(), + }, + OperationCmd { + operation_type: OperationType::SumOf, + statement_1_parent: Some("_SELF".to_string()), + statement_1_name: Some("VALUEOF:age_sum".to_string()), + statement_2_parent: Some("friend1".to_string()), + statement_2_name: Some("VALUEOF:bob age".to_string()), + statement_3_parent: Some("friend2".to_string()), + statement_3_name: Some("VALUEOF:charlie age".to_string()), + optional_entry: None, + output_statement_name: "sum of friend1 and friend2 ages".to_string(), }, ]; - let oracle_pod = POD::execute_oracle_gadget(&gpg_input, &ops); - let statements = &oracle_pod.unwrap(); - for statement in statements.payload.statements_list.iter() { - println!("statement: {:?}", statement); + let alice_grb = POD::execute_oracle_gadget(&grb_input, &grb_ops).unwrap(); + assert!(alice_grb.verify()? == true); + + for statement in alice_grb.payload.statements_list { + println!("{:?}", statement); } - // assert!(oracle_pod.unwrap().verify()? == true); - - // let god_pod_1 = GODPOD::gadget( - // &vec![ - // &SchnorrOrGODPOD::SchnorrPOD(schnorrPOD1.clone()), - // &SchnorrOrGODPOD::SchnorrPOD(schnorrPOD2.clone()), - // &SchnorrOrGODPOD::SchnorrPOD(schnorrPOD3.clone()), - // ], - // &vec![ - // (OperationType::CopyStatement, Some(0), None, None, None), - // (OperationType::CopyStatement, Some(1), None, None, None), - // (OperationType::CopyStatement, Some(2), None, None, None), - // (OperationType::CopyStatement, Some(3), None, None, None), - // (OperationType::CopyStatement, Some(4), None, None, None), - // (OperationType::CopyStatement, Some(5), None, None, None), - // (OperationType::NewEntry, None, None, None, Some(&entry9)), - // ( - // OperationType::EqualityFromEntries, - // Some(1), - // Some(4), - // None, - // None, - // ), - // ( - // OperationType::EqualityFromEntries, - // Some(4), - // Some(8), - // None, - // None, - // ), - // ( - // OperationType::NonequalityFromEntries, - // Some(0), - // Some(1), - // None, - // None, - // ), - // (OperationType::GtFromEntries, Some(1), Some(0), None, None), - // ], - // ); - // println!("GODPOD1: {:?}", god_pod_1); - // assert!(god_pod_1.verify()? == true); - - // // another GODPOD from the first GODPOD and another schnorr POD - - // let god_pod_2 = GODPOD::gadget( - // &vec![ - // &SchnorrOrGODPOD::GODPOD(god_pod_1.clone()), - // &SchnorrOrGODPOD::SchnorrPOD(schnorrPOD3.clone()), - // ], - // &vec![ - // (OperationType::CopyStatement, Some(8), None, None, None), - // (OperationType::CopyStatement, Some(9), None, None, None), - // (OperationType::CopyStatement, Some(3), None, None, None), - // (OperationType::GtFromEntries, Some(6), Some(0), None, None), - // ( - // OperationType::TransitiveEqualityFromStatements, - // Some(7), - // Some(8), - // None, - // None, - // ), - // (OperationType::GtToNonequality, Some(10), None, None, None), - // ], - // ); - // println!("GODPOD2: {:?}", god_pod_2); - - // // println!( - // // "verify schnorrpod1: {:?}", - // // schnorrPOD1.clone().payload.to_field_vec() - // // ); - // // println!("verify schnorrpod2: {:?}", schnorrPOD2.verify()); - - // assert!(god_pod_2.verify()? == true); Ok(()) } - -// #[test] -// #[should_panic] -// fn god_pod_should_panic() { -// // Start with some values. -// let scalar1 = GoldilocksField(36); -// let scalar2 = GoldilocksField(52); -// let scalar3 = GoldilocksField(90); -// let vector_value = vec![scalar1, scalar2]; - -// // make entries -// let entry1 = Entry::new("some key", ScalarOrVec::Scalar(scalar1)); -// let entry2 = Entry::new("some other key", ScalarOrVec::Scalar(scalar2)); -// let entry3 = Entry::new("vector entry", ScalarOrVec::Vector(vector_value.clone())); -// let entry4 = Entry::new("new key", ScalarOrVec::Scalar(scalar2)); -// let entry5 = Entry::new("foo", ScalarOrVec::Scalar(GoldilocksField(100))); -// let entry6 = Entry::new("foo", ScalarOrVec::Scalar(GoldilocksField(120))); -// let entry9 = Entry::new("godpod introduced entry key", ScalarOrVec::Scalar(scalar3)); - -// // three schnorr pods -// let schnorrPOD1 = POD::execute_schnorr_gadget( -// &vec![entry1.clone(), entry2.clone()], -// &SchnorrSecretKey { sk: 25 }, -// ); - -// let schnorrPOD2 = POD::execute_schnorr_gadget( -// &vec![entry3.clone(), entry4.clone()], -// &SchnorrSecretKey { sk: 42 }, -// ); - -// let schnorrPOD3 = POD::execute_schnorr_gadget( -// &vec![entry5.clone(), entry6.clone()], -// &SchnorrSecretKey { sk: 83 }, -// ); - -// // make a GODPOD using from_pods called on the two schnorr PODs -// let god_pod_1 = GODPOD::gadget( -// &vec![ -// &SchnorrOrGODPOD::SchnorrPOD(schnorrPOD1.clone()), -// &SchnorrOrGODPOD::SchnorrPOD(schnorrPOD2.clone()), -// ], -// // this Gt operation should fail because 36 is not gt 52 -// &vec![(OperationType::GtFromEntries, Some(0), Some(1), None, None)], -// ); -// }