Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

make examples work by vp_byte_code #255

Merged
merged 7 commits into from
Dec 8, 2023
2 changes: 1 addition & 1 deletion taiga_halo2/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,4 @@ default = []
nif = ["dep:rustler", "borsh", "pasta_curves/repr-erlang"]
serde = ["dep:serde", "pasta_curves/serde"]
borsh = ["dep:borsh"]
examples = []
examples = ["borsh"]
77 changes: 76 additions & 1 deletion taiga_halo2/src/circuit/vp_bytecode.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
#[cfg(feature = "borsh")]
use crate::circuit::vp_examples::TrivialValidityPredicateCircuit;
#[cfg(feature = "examples")]
use crate::circuit::vp_examples::{
cascade_intent::CascadeIntentValidityPredicateCircuit,
or_relation_intent::OrRelationIntentValidityPredicateCircuit,
partial_fulfillment_intent::PartialFulfillmentIntentValidityPredicateCircuit,
receiver_vp::ReceiverValidityPredicateCircuit,
signature_verification::SignatureVerificationValidityPredicateCircuit,
token::TokenValidityPredicateCircuit,
};
use crate::error::TransactionError;
use crate::shielded_ptx::ResourceVPVerifyingInfoSet;
use crate::{
Expand Down Expand Up @@ -31,7 +40,13 @@ pub enum ValidityPredicateRepresentation {
// Native halo2 circuits don't have a unified representatioin, enumerate the vp circuit examples for the moment.
// TODO: figure out if we can have a unified circuit presentation. In theory, it's possible to separate the circuit system and proving system.
Trivial,
// TODO: add other vp types here if needed
Token,
SignatureVerification,
Receiver,
PartialFulfillmentIntent,
OrRelationIntent,
CascadeIntent,
// Add other native vp types here if needed
}

#[derive(Clone, Debug)]
Expand Down Expand Up @@ -74,6 +89,36 @@ impl ValidityPredicateByteCode {
let vp = TrivialValidityPredicateCircuit::from_bytes(&self.inputs);
Ok(vp.get_verifying_info())
}
#[cfg(feature = "examples")]
ValidityPredicateRepresentation::Token => {
let vp = TokenValidityPredicateCircuit::from_bytes(&self.inputs);
Ok(vp.get_verifying_info())
}
#[cfg(feature = "examples")]
ValidityPredicateRepresentation::SignatureVerification => {
let vp = SignatureVerificationValidityPredicateCircuit::from_bytes(&self.inputs);
Ok(vp.get_verifying_info())
}
#[cfg(feature = "examples")]
ValidityPredicateRepresentation::Receiver => {
let vp = ReceiverValidityPredicateCircuit::from_bytes(&self.inputs);
Ok(vp.get_verifying_info())
}
#[cfg(feature = "examples")]
ValidityPredicateRepresentation::PartialFulfillmentIntent => {
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())
}
#[cfg(feature = "examples")]
ValidityPredicateRepresentation::CascadeIntent => {
let vp = CascadeIntentValidityPredicateCircuit::from_bytes(&self.inputs);
Ok(vp.get_verifying_info())
}
#[allow(unreachable_patterns)]
_ => Err(TransactionError::InvalidValidityPredicateRepresentation),
}
Expand Down Expand Up @@ -104,6 +149,36 @@ impl ValidityPredicateByteCode {
let vp = TrivialValidityPredicateCircuit::from_bytes(&self.inputs);
vp.verify_transparently()?
}
#[cfg(feature = "examples")]
ValidityPredicateRepresentation::Token => {
let vp = TokenValidityPredicateCircuit::from_bytes(&self.inputs);
vp.verify_transparently()?
}
#[cfg(feature = "examples")]
ValidityPredicateRepresentation::SignatureVerification => {
let vp = SignatureVerificationValidityPredicateCircuit::from_bytes(&self.inputs);
vp.verify_transparently()?
}
#[cfg(feature = "examples")]
ValidityPredicateRepresentation::Receiver => {
let vp = ReceiverValidityPredicateCircuit::from_bytes(&self.inputs);
vp.verify_transparently()?
}
#[cfg(feature = "examples")]
ValidityPredicateRepresentation::PartialFulfillmentIntent => {
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()?
}
#[cfg(feature = "examples")]
ValidityPredicateRepresentation::CascadeIntent => {
let vp = CascadeIntentValidityPredicateCircuit::from_bytes(&self.inputs);
vp.verify_transparently()?
}
#[allow(unreachable_patterns)]
_ => return Err(TransactionError::InvalidValidityPredicateRepresentation),
};
Expand Down
11 changes: 2 additions & 9 deletions taiga_halo2/src/circuit/vp_circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
proof::Proof,
resource::{RandomSeed, Resource, ResourceCommitment},
resource_encryption::{ResourceCiphertext, SecretKey},
utils::mod_r_p,
utils::{mod_r_p, read_base_field},

Check warning on line 34 in taiga_halo2/src/circuit/vp_circuit.rs

View workflow job for this annotation

GitHub Actions / Rustfmt

unused import: `read_base_field`
vp_vk::ValidityPredicateVerifyingKey,
};
use dyn_clone::{clone_trait_object, DynClone};
Expand Down Expand Up @@ -147,7 +147,7 @@
impl<'a> Decoder<'a> for ValidityPredicatePublicInputs {
fn decode(term: Term<'a>) -> NifResult<Self> {
let val: Vec<pallas::Base> = Decoder::decode(term)?;
val.try_into()

Check warning on line 150 in taiga_halo2/src/circuit/vp_circuit.rs

View workflow job for this annotation

GitHub Actions / Clippy (beta)

use of a fallible conversion when an infallible one could be used

warning: use of a fallible conversion when an infallible one could be used --> taiga_halo2/src/circuit/vp_circuit.rs:150:13 | 150 | val.try_into() | ^^^^^^^^ help: use: `into` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_fallible_conversions = note: `-W clippy::unnecessary-fallible-conversions` implied by `-W clippy::all` = help: to override `-W clippy::all` add `#[allow(clippy::unnecessary_fallible_conversions)]`

Check warning on line 150 in taiga_halo2/src/circuit/vp_circuit.rs

View workflow job for this annotation

GitHub Actions / Clippy (beta)

use of a fallible conversion when an infallible one could be used

warning: use of a fallible conversion when an infallible one could be used --> taiga_halo2/src/circuit/vp_circuit.rs:150:13 | 150 | val.try_into() | ^^^^^^^^ help: use: `into` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_fallible_conversions = note: `-W clippy::unnecessary-fallible-conversions` implied by `-W clippy::all` = help: to override `-W clippy::all` add `#[allow(clippy::unnecessary_fallible_conversions)]`
.map_err(|_e| rustler::Error::Atom("failure to decode"))
}
}
Expand Down Expand Up @@ -204,8 +204,6 @@
#[cfg(feature = "borsh")]
impl BorshDeserialize for VPVerifyingInfo {
fn deserialize_reader<R: std::io::Read>(reader: &mut R) -> std::io::Result<Self> {
use ff::PrimeField;
use std::io;
// Read vk
use crate::circuit::vp_examples::TrivialValidityPredicateCircuit;
let params = SETUP_PARAMS_MAP.get(&VP_CIRCUIT_PARAMS_SIZE).unwrap();
Expand All @@ -214,12 +212,7 @@
let proof = Proof::deserialize_reader(reader)?;
// Read public inputs
let public_inputs: Vec<_> = (0..VP_CIRCUIT_PUBLIC_INPUT_NUM)
.map(|_| {
let bytes = <[u8; 32]>::deserialize_reader(reader)?;
Option::from(pallas::Base::from_repr(bytes)).ok_or_else(|| {
io::Error::new(io::ErrorKind::InvalidData, "public input not in field")
})
})
.map(|_| read_base_field(reader))
.collect::<Result<_, _>>()?;
Ok(VPVerifyingInfo {
vk,
Expand Down
11 changes: 2 additions & 9 deletions taiga_halo2/src/circuit/vp_examples.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
error::TransactionError,
proof::Proof,
resource::{RandomSeed, Resource},
utils::read_base_field,

Check warning on line 12 in taiga_halo2/src/circuit/vp_examples.rs

View workflow job for this annotation

GitHub Actions / Rustfmt

unused import: `utils::read_base_field`
vp_commitment::ValidityPredicateCommitment,
vp_vk::ValidityPredicateVerifyingKey,
};
Expand Down Expand Up @@ -133,15 +134,7 @@
#[cfg(feature = "borsh")]
impl BorshDeserialize for TrivialValidityPredicateCircuit {
fn deserialize_reader<R: std::io::Read>(reader: &mut R) -> std::io::Result<Self> {
use ff::PrimeField;
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 owned_resource_id = read_base_field(reader)?;
let input_resources: Vec<_> = (0..NUM_RESOURCE)
.map(|_| Resource::deserialize_reader(reader))
.collect::<Result<_, _>>()?;
Expand Down
62 changes: 61 additions & 1 deletion taiga_halo2/src/circuit/vp_examples/cascade_intent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use crate::{
assign_free_advice,
target_resource_variable::{get_is_input_resource_flag, get_owned_resource_variable},
},
vp_bytecode::{ValidityPredicateByteCode, ValidityPredicateRepresentation},
vp_circuit::{
BasicValidityPredicateVariables, VPVerifyingInfo, ValidityPredicateCircuit,
ValidityPredicateConfig, ValidityPredicatePublicInputs, ValidityPredicateVerifyingInfo,
Expand All @@ -21,16 +22,18 @@ use crate::{
nullifier::Nullifier,
proof::Proof,
resource::{RandomSeed, Resource},
utils::read_base_field,
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;

Expand All @@ -55,6 +58,21 @@ impl CascadeIntentValidityPredicateCircuit {
pub fn encode_label(cascade_resource_cm: pallas::Base) -> pallas::Base {
cascade_resource_cm
}

pub fn to_bytecode(&self) -> ValidityPredicateByteCode {
ValidityPredicateByteCode::new(
ValidityPredicateRepresentation::CascadeIntent,
self.to_bytes(),
)
}

pub fn to_bytes(&self) -> Vec<u8> {
borsh::to_vec(&self).unwrap()
}

pub fn from_bytes(bytes: &Vec<u8>) -> Self {
BorshDeserialize::deserialize(&mut bytes.as_ref()).unwrap()
}
}

impl ValidityPredicateCircuit for CascadeIntentValidityPredicateCircuit {
Expand Down Expand Up @@ -149,6 +167,41 @@ impl ValidityPredicateCircuit for CascadeIntentValidityPredicateCircuit {
vp_circuit_impl!(CascadeIntentValidityPredicateCircuit);
vp_verifying_info_impl!(CascadeIntentValidityPredicateCircuit);

impl BorshSerialize for CascadeIntentValidityPredicateCircuit {
fn serialize<W: std::io::Write>(&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)?;
}

writer.write_all(&self.cascade_resource_cm.to_repr())?;
Ok(())
}
}

impl BorshDeserialize for CascadeIntentValidityPredicateCircuit {
fn deserialize_reader<R: std::io::Read>(reader: &mut R) -> std::io::Result<Self> {
let owned_resource_id = read_base_field(reader)?;
let input_resources: Vec<_> = (0..NUM_RESOURCE)
.map(|_| Resource::deserialize_reader(reader))
.collect::<Result<_, _>>()?;
let output_resources: Vec<_> = (0..NUM_RESOURCE)
.map(|_| Resource::deserialize_reader(reader))
.collect::<Result<_, _>>()?;
let cascade_resource_cm = read_base_field(reader)?;
Ok(Self {
owned_resource_id,
input_resources: input_resources.try_into().unwrap(),
output_resources: output_resources.try_into().unwrap(),
cascade_resource_cm,
})
}
}

pub fn create_intent_resource<R: RngCore>(
mut rng: R,
cascade_resource_cm: pallas::Base,
Expand Down Expand Up @@ -193,6 +246,13 @@ fn test_halo2_cascade_intent_vp_circuit() {
cascade_resource_cm,
}
};

// Test serialization
let circuit = {
let circuit_bytes = circuit.to_bytes();
CascadeIntentValidityPredicateCircuit::from_bytes(&circuit_bytes)
};

let public_inputs = circuit.get_public_inputs(&mut rng);

let prover = MockProver::<pallas::Base>::run(
Expand Down
73 changes: 72 additions & 1 deletion taiga_halo2/src/circuit/vp_examples/or_relation_intent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -22,16 +23,18 @@ use crate::{
proof::Proof,
resource::{RandomSeed, Resource},
utils::poseidon_hash_n,
utils::read_base_field,
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;

Expand Down Expand Up @@ -75,6 +78,21 @@ impl OrRelationIntentValidityPredicateCircuit {
receiver_value,
])
}

pub fn to_bytecode(&self) -> ValidityPredicateByteCode {
ValidityPredicateByteCode::new(
ValidityPredicateRepresentation::OrRelationIntent,
self.to_bytes(),
)
}

pub fn to_bytes(&self) -> Vec<u8> {
borsh::to_vec(&self).unwrap()
}

pub fn from_bytes(bytes: &Vec<u8>) -> Self {
BorshDeserialize::deserialize(&mut bytes.as_ref()).unwrap()
}
}

impl ValidityPredicateCircuit for OrRelationIntentValidityPredicateCircuit {
Expand Down Expand Up @@ -277,6 +295,52 @@ impl ValidityPredicateCircuit for OrRelationIntentValidityPredicateCircuit {
vp_circuit_impl!(OrRelationIntentValidityPredicateCircuit);
vp_verifying_info_impl!(OrRelationIntentValidityPredicateCircuit);

impl BorshSerialize for OrRelationIntentValidityPredicateCircuit {
fn serialize<W: std::io::Write>(&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<R: std::io::Read>(reader: &mut R) -> std::io::Result<Self> {
let owned_resource_id = read_base_field(reader)?;
let input_resources: Vec<_> = (0..NUM_RESOURCE)
.map(|_| Resource::deserialize_reader(reader))
.collect::<Result<_, _>>()?;
let output_resources: Vec<_> = (0..NUM_RESOURCE)
.map(|_| Resource::deserialize_reader(reader))
.collect::<Result<_, _>>()?;
let token_1 = Token::deserialize_reader(reader)?;
let token_2 = Token::deserialize_reader(reader)?;
let receiver_npk = read_base_field(reader)?;
let receiver_value = read_base_field(reader)?;
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<R: RngCore>(
mut rng: R,
token_1: &Token,
Expand Down Expand Up @@ -346,6 +410,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::<pallas::Base>::run(
Expand Down
Loading
Loading