diff --git a/taiga_halo2/src/action.rs b/taiga_halo2/src/action.rs index 5684df3b..68a3d317 100644 --- a/taiga_halo2/src/action.rs +++ b/taiga_halo2/src/action.rs @@ -10,10 +10,12 @@ use ff::PrimeField; use halo2_proofs::arithmetic::Field; use pasta_curves::pallas; use rand::RngCore; +use rustler::NifStruct; use std::io; /// The action result used in transaction. -#[derive(Copy, Debug, Clone)] +#[derive(Copy, Debug, Clone, NifStruct)] +#[module = "Taiga.Action.Instance"] pub struct ActionInstance { /// The root of the note commitment Merkle tree. pub anchor: pallas::Base, diff --git a/taiga_halo2/src/circuit/vp_circuit.rs b/taiga_halo2/src/circuit/vp_circuit.rs index 17055bdd..21f5d339 100644 --- a/taiga_halo2/src/circuit/vp_circuit.rs +++ b/taiga_halo2/src/circuit/vp_circuit.rs @@ -56,6 +56,9 @@ use vamp_ir::halo2::synth::{make_constant, Halo2Module, PrimeFieldOps}; use vamp_ir::transform::compile; use vamp_ir::util::{read_inputs_from_file, Config}; +use rustler::types::atom; +use rustler::{Decoder, Encoder, Env, NifResult, Term}; + #[derive(Debug, Clone)] pub struct VPVerifyingInfo { pub vk: VerifyingKey, @@ -63,9 +66,61 @@ pub struct VPVerifyingInfo { pub public_inputs: ValidityPredicatePublicInputs, } +rustler::atoms! {verifying_info} + +impl Encoder for VPVerifyingInfo { + fn encode<'a>(&self, env: Env<'a>) -> Term<'a> { + ( + verifying_info().encode(env), + self.vk.to_bytes().encode(env), + self.proof.encode(env), + self.public_inputs.encode(env), + ) + .encode(env) + } +} + +impl<'a> Decoder<'a> for VPVerifyingInfo { + fn decode(term: Term<'a>) -> NifResult { + let (term, vk, proof, public_inputs): ( + atom::Atom, + Vec, + Proof, + ValidityPredicatePublicInputs, + ) = term.decode()?; + if term == verifying_info() { + use crate::circuit::vp_examples::TrivialValidityPredicateCircuit; + let params = SETUP_PARAMS_MAP.get(&VP_CIRCUIT_PARAMS_SIZE).unwrap(); + let vk = VerifyingKey::from_bytes::(&vk, params) + .map_err(|_e| rustler::Error::Atom("failure to decode"))?; + Ok(VPVerifyingInfo { + vk, + proof, + public_inputs, + }) + } else { + Err(rustler::Error::BadArg) + } + } +} + #[derive(Clone, Debug)] pub struct ValidityPredicatePublicInputs([pallas::Base; VP_CIRCUIT_PUBLIC_INPUT_NUM]); +impl Encoder for ValidityPredicatePublicInputs { + fn encode<'a>(&self, env: Env<'a>) -> Term<'a> { + self.0.to_vec().encode(env) + } +} + +impl<'a> Decoder<'a> for ValidityPredicatePublicInputs { + fn decode(term: Term<'a>) -> NifResult { + let val: Vec = Decoder::decode(term)?; + val.try_into() + .map_err(|_e| rustler::Error::Atom("failure to decode")) + } +} + impl VPVerifyingInfo { pub fn verify(&self) -> Result<(), Error> { let params = SETUP_PARAMS_MAP.get(&VP_CIRCUIT_PARAMS_SIZE).unwrap(); diff --git a/taiga_halo2/src/note.rs b/taiga_halo2/src/note.rs index ee84e294..cf7cb6c9 100644 --- a/taiga_halo2/src/note.rs +++ b/taiga_halo2/src/note.rs @@ -24,13 +24,14 @@ use pasta_curves::{ pallas, }; use rand::RngCore; +use rustler::{NifStruct, NifTuple}; use std::{ hash::{Hash, Hasher}, io, }; /// A commitment to a note. -#[derive(Copy, Debug, Clone)] +#[derive(Copy, Debug, Clone, NifTuple)] pub struct NoteCommitment(pallas::Point); impl NoteCommitment { @@ -54,7 +55,8 @@ impl Default for NoteCommitment { } /// A note -#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, NifStruct)] +#[module = "Taiga.Note"] pub struct Note { pub note_type: NoteType, /// app_data_dynamic is the data defined in application vp and will NOT be used to derive type @@ -75,7 +77,8 @@ pub struct Note { } /// The parameters in the NoteType are used to derive note type. -#[derive(Debug, Clone, Copy, Default, Eq)] +#[derive(Debug, Clone, Copy, Default, Eq, NifStruct)] +#[module = "Taiga.NoteType"] pub struct NoteType { /// app_vk is the compressed verifying key of VP pub app_vk: pallas::Base, diff --git a/taiga_halo2/src/nullifier.rs b/taiga_halo2/src/nullifier.rs index 6c766c14..3a6b089c 100644 --- a/taiga_halo2/src/nullifier.rs +++ b/taiga_halo2/src/nullifier.rs @@ -8,14 +8,15 @@ use pasta_curves::group::cofactor::CofactorCurveAffine; use pasta_curves::group::ff::PrimeField; use pasta_curves::pallas; use rand::RngCore; +use rustler::{NifTaggedEnum, NifTuple}; use subtle::CtOption; /// The unique nullifier. -#[derive(Copy, Debug, Clone, PartialEq, Eq)] +#[derive(Copy, Debug, Clone, PartialEq, Eq, NifTuple)] pub struct Nullifier(pallas::Base); /// The NullifierKeyContainer contains the nullifier_key or the nullifier_key commitment -#[derive(Copy, Debug, Clone, PartialEq, Eq)] +#[derive(Copy, Debug, Clone, PartialEq, Eq, NifTaggedEnum)] pub enum NullifierKeyContainer { // The NullifierKeyContainer::Commitment is the commitment of NullifierKeyContainer::Key `nk_com = Commitment(nk, 0)` Commitment(pallas::Base), diff --git a/taiga_halo2/src/proof.rs b/taiga_halo2/src/proof.rs index c6874efe..319c7666 100644 --- a/taiga_halo2/src/proof.rs +++ b/taiga_halo2/src/proof.rs @@ -6,8 +6,9 @@ use halo2_proofs::{ }; use pasta_curves::{pallas, vesta}; use rand::RngCore; +use rustler::NifTuple; -#[derive(Clone, Debug, BorshSerialize, BorshDeserialize)] +#[derive(Clone, Debug, BorshSerialize, BorshDeserialize, NifTuple)] pub struct Proof(Vec); impl Proof { diff --git a/taiga_halo2/src/shielded_ptx.rs b/taiga_halo2/src/shielded_ptx.rs index 22507be0..0af50c4b 100644 --- a/taiga_halo2/src/shielded_ptx.rs +++ b/taiga_halo2/src/shielded_ptx.rs @@ -14,6 +14,7 @@ use borsh::{BorshDeserialize, BorshSerialize}; use halo2_proofs::plonk::Error; use pasta_curves::pallas; use rand::RngCore; +use rustler::NifStruct; #[derive(Debug, Clone)] pub struct ShieldedPartialTransaction { @@ -22,13 +23,15 @@ pub struct ShieldedPartialTransaction { outputs: [NoteVPVerifyingInfoSet; NUM_NOTE], } -#[derive(Debug, Clone, BorshSerialize, BorshDeserialize)] +#[derive(Debug, Clone, BorshSerialize, BorshDeserialize, NifStruct)] +#[module = "Taiga.Action.VerifyingInfo"] pub struct ActionVerifyingInfo { action_proof: Proof, action_instance: ActionInstance, } -#[derive(Debug, Clone, BorshSerialize, BorshDeserialize)] +#[derive(Debug, Clone, BorshSerialize, BorshDeserialize, NifStruct)] +#[module = "Taiga.Note.VerifyingInfo"] pub struct NoteVPVerifyingInfoSet { app_vp_verifying_info: VPVerifyingInfo, app_dynamic_vp_verifying_info: Vec, diff --git a/taiga_halo2/src/transaction.rs b/taiga_halo2/src/transaction.rs index dd21b9ba..fcceb142 100644 --- a/taiga_halo2/src/transaction.rs +++ b/taiga_halo2/src/transaction.rs @@ -13,6 +13,7 @@ use pasta_curves::{ pallas, }; use rand::{CryptoRng, RngCore}; +use rustler::NifStruct; #[derive(Debug, Clone, BorshDeserialize, BorshSerialize)] pub struct Transaction { @@ -34,7 +35,8 @@ pub struct ShieldedPartialTxBundle { partial_txs: Vec, } -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, NifStruct)] +#[module = "Taiga.Transaction.Result"] pub struct ShieldedResult { anchors: Vec, nullifiers: Vec, diff --git a/taiga_halo2/src/value_commitment.rs b/taiga_halo2/src/value_commitment.rs index 1b7206b9..eccfabba 100644 --- a/taiga_halo2/src/value_commitment.rs +++ b/taiga_halo2/src/value_commitment.rs @@ -4,9 +4,10 @@ use halo2_proofs::arithmetic::CurveAffine; use pasta_curves::group::cofactor::CofactorCurveAffine; use pasta_curves::group::{Curve, Group, GroupEncoding}; use pasta_curves::pallas; +use rustler::NifTuple; use subtle::CtOption; -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, NifTuple)] pub struct ValueCommitment(pallas::Point); impl ValueCommitment {