diff --git a/taiga_halo2/src/circuit/vp_bytecode.rs b/taiga_halo2/src/circuit/vp_bytecode.rs index fc6b9f43..43cd3daa 100644 --- a/taiga_halo2/src/circuit/vp_bytecode.rs +++ b/taiga_halo2/src/circuit/vp_bytecode.rs @@ -2,6 +2,7 @@ use crate::circuit::vp_examples::TrivialValidityPredicateCircuit; #[cfg(feature = "examples")] use crate::circuit::vp_examples::{ + or_relation_intent::OrRelationIntentValidityPredicateCircuit, partial_fulfillment_intent::PartialFulfillmentIntentValidityPredicateCircuit, receiver_vp::ReceiverValidityPredicateCircuit, signature_verification::SignatureVerificationValidityPredicateCircuit, @@ -42,6 +43,7 @@ pub enum ValidityPredicateRepresentation { SignatureVerification, Receiver, PartialFulfillmentIntent, + OrRelationIntent, // Add other native vp types here if needed } @@ -105,6 +107,11 @@ impl ValidityPredicateByteCode { let vp = PartialFulfillmentIntentValidityPredicateCircuit::from_bytes(&self.inputs); Ok(vp.get_verifying_info()) } + #[cfg(feature = "examples")] + ValidityPredicateRepresentation::OrRelationIntent => { + let vp = OrRelationIntentValidityPredicateCircuit::from_bytes(&self.inputs); + Ok(vp.get_verifying_info()) + } #[allow(unreachable_patterns)] _ => Err(TransactionError::InvalidValidityPredicateRepresentation), } @@ -155,6 +162,11 @@ impl ValidityPredicateByteCode { let vp = PartialFulfillmentIntentValidityPredicateCircuit::from_bytes(&self.inputs); vp.verify_transparently()? } + #[cfg(feature = "examples")] + ValidityPredicateRepresentation::OrRelationIntent => { + let vp = OrRelationIntentValidityPredicateCircuit::from_bytes(&self.inputs); + vp.verify_transparently()? + } #[allow(unreachable_patterns)] _ => return Err(TransactionError::InvalidValidityPredicateRepresentation), }; diff --git a/taiga_halo2/src/circuit/vp_examples/or_relation_intent.rs b/taiga_halo2/src/circuit/vp_examples/or_relation_intent.rs index 11dd25db..44dfba6c 100644 --- a/taiga_halo2/src/circuit/vp_examples/or_relation_intent.rs +++ b/taiga_halo2/src/circuit/vp_examples/or_relation_intent.rs @@ -10,6 +10,7 @@ use crate::{ poseidon_hash::poseidon_hash_gadget, target_resource_variable::{get_is_input_resource_flag, get_owned_resource_variable}, }, + vp_bytecode::{ValidityPredicateByteCode, ValidityPredicateRepresentation}, vp_circuit::{ BasicValidityPredicateVariables, VPVerifyingInfo, ValidityPredicateCircuit, ValidityPredicateConfig, ValidityPredicatePublicInputs, ValidityPredicateVerifyingInfo, @@ -25,13 +26,14 @@ use crate::{ vp_commitment::ValidityPredicateCommitment, vp_vk::ValidityPredicateVerifyingKey, }; +use borsh::{BorshDeserialize, BorshSerialize}; use halo2_proofs::arithmetic::Field; use halo2_proofs::{ circuit::{floor_planner, Layouter, Value}, plonk::{keygen_pk, keygen_vk, Circuit, ConstraintSystem, Error}, }; use lazy_static::lazy_static; -use pasta_curves::pallas; +use pasta_curves::{group::ff::PrimeField, pallas}; use rand::rngs::OsRng; use rand::RngCore; @@ -75,6 +77,21 @@ impl OrRelationIntentValidityPredicateCircuit { receiver_value, ]) } + + pub fn to_bytecode(&self) -> ValidityPredicateByteCode { + ValidityPredicateByteCode::new( + ValidityPredicateRepresentation::OrRelationIntent, + self.to_bytes(), + ) + } + + pub fn to_bytes(&self) -> Vec { + borsh::to_vec(&self).unwrap() + } + + pub fn from_bytes(bytes: &Vec) -> Self { + BorshDeserialize::deserialize(&mut bytes.as_ref()).unwrap() + } } impl ValidityPredicateCircuit for OrRelationIntentValidityPredicateCircuit { @@ -277,6 +294,70 @@ impl ValidityPredicateCircuit for OrRelationIntentValidityPredicateCircuit { vp_circuit_impl!(OrRelationIntentValidityPredicateCircuit); vp_verifying_info_impl!(OrRelationIntentValidityPredicateCircuit); +impl BorshSerialize for OrRelationIntentValidityPredicateCircuit { + fn serialize(&self, writer: &mut W) -> std::io::Result<()> { + writer.write_all(&self.owned_resource_id.to_repr())?; + for input in self.input_resources.iter() { + input.serialize(writer)?; + } + + for output in self.output_resources.iter() { + output.serialize(writer)?; + } + + self.token_1.serialize(writer)?; + self.token_2.serialize(writer)?; + + writer.write_all(&self.receiver_npk.to_repr())?; + writer.write_all(&self.receiver_value.to_repr())?; + + Ok(()) + } +} + +impl BorshDeserialize for OrRelationIntentValidityPredicateCircuit { + fn deserialize_reader(reader: &mut R) -> std::io::Result { + let owned_resource_id_bytes = <[u8; 32]>::deserialize_reader(reader)?; + let owned_resource_id = Option::from(pallas::Base::from_repr(owned_resource_id_bytes)) + .ok_or_else(|| { + std::io::Error::new( + std::io::ErrorKind::InvalidData, + "owned_resource_id not in field", + ) + })?; + let input_resources: Vec<_> = (0..NUM_RESOURCE) + .map(|_| Resource::deserialize_reader(reader)) + .collect::>()?; + let output_resources: Vec<_> = (0..NUM_RESOURCE) + .map(|_| Resource::deserialize_reader(reader)) + .collect::>()?; + let token_1 = Token::deserialize_reader(reader)?; + let token_2 = Token::deserialize_reader(reader)?; + let receiver_npk_bytes = <[u8; 32]>::deserialize_reader(reader)?; + let receiver_npk = + Option::from(pallas::Base::from_repr(receiver_npk_bytes)).ok_or_else(|| { + std::io::Error::new(std::io::ErrorKind::InvalidData, "receiver_npk not in field") + })?; + let receiver_value_bytes = <[u8; 32]>::deserialize_reader(reader)?; + let receiver_value = Option::from(pallas::Base::from_repr(receiver_value_bytes)) + .ok_or_else(|| { + std::io::Error::new( + std::io::ErrorKind::InvalidData, + "receiver_value not in field", + ) + })?; + Ok(Self { + owned_resource_id, + input_resources: input_resources.try_into().unwrap(), + output_resources: output_resources.try_into().unwrap(), + token_1, + token_2, + receiver_npk, + receiver_value, + }) + } +} + pub fn create_intent_resource( mut rng: R, token_1: &Token, @@ -346,6 +427,13 @@ fn test_halo2_or_relation_intent_vp_circuit() { receiver_value: output_resources[0].value, } }; + + // Test serialization + let circuit = { + let circuit_bytes = circuit.to_bytes(); + OrRelationIntentValidityPredicateCircuit::from_bytes(&circuit_bytes) + }; + let public_inputs = circuit.get_public_inputs(&mut rng); let prover = MockProver::::run(