diff --git a/taiga_halo2/Cargo.toml b/taiga_halo2/Cargo.toml index 251bfd69..ebdcc3fe 100644 --- a/taiga_halo2/Cargo.toml +++ b/taiga_halo2/Cargo.toml @@ -19,17 +19,16 @@ dyn-clone = "1.0" reddsa = {git = "https://github.com/heliaxdev/reddsa.git", branch = "taiga"} vamp-ir = { git = "https://github.com/anoma/vamp-ir.git", rev = "6d401f8a479951727586ef0c44c42edab3139090"} bincode = "2.0.0-rc.3" -borsh = { version = "0.10", features = ["const-generics"] } byteorder = "1.4" num-bigint = "0.4" +serde = { version = "1.0", features = ["derive"], optional = true } +borsh = { version = "0.10", features = ["const-generics"], optional = true } + [dev-dependencies] criterion = "0.5" proptest = "1.2" - -[features] -default = [] -nif = ["rustler", "pasta_curves/repr-erlang"] +serde_json = "1.0" [[bench]] name = "action_proof" @@ -44,3 +43,9 @@ harness = false [[example]] name = "tx_examples" + +[features] +default = ["borsh", "serde"] +nif = ["rustler", "pasta_curves/repr-erlang"] +serde = ["dep:serde", "pasta_curves/serde"] +borsh = ["dep:borsh"] diff --git a/taiga_halo2/src/action.rs b/taiga_halo2/src/action.rs index 8f2ca5e4..834be741 100644 --- a/taiga_halo2/src/action.rs +++ b/taiga_halo2/src/action.rs @@ -5,19 +5,22 @@ use crate::{ nullifier::Nullifier, value_commitment::ValueCommitment, }; -use borsh::{BorshDeserialize, BorshSerialize}; -use ff::PrimeField; use halo2_proofs::arithmetic::Field; use pasta_curves::pallas; use rand::RngCore; #[cfg(feature = "nif")] use rustler::NifStruct; -use std::io; +#[cfg(feature = "serde")] +use serde; + +#[cfg(feature = "borsh")] +use borsh::{BorshDeserialize, BorshSerialize}; /// The action result used in transaction. #[derive(Copy, Debug, Clone)] #[cfg_attr(feature = "nif", derive(NifStruct))] #[cfg_attr(feature = "nif", module = "Taiga.Action.Instance")] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct ActionInstance { /// The root of the note commitment Merkle tree. pub anchor: pallas::Base, @@ -50,8 +53,10 @@ impl ActionInstance { } } +#[cfg(feature = "borsh")] impl BorshSerialize for ActionInstance { fn serialize(&self, writer: &mut W) -> borsh::maybestd::io::Result<()> { + use ff::PrimeField; writer.write_all(&self.anchor.to_repr())?; writer.write_all(&self.nf.to_bytes())?; writer.write_all(&self.cm_x.to_repr())?; @@ -60,8 +65,11 @@ impl BorshSerialize for ActionInstance { } } +#[cfg(feature = "borsh")] impl BorshDeserialize for ActionInstance { - fn deserialize_reader(reader: &mut R) -> io::Result { + fn deserialize_reader(reader: &mut R) -> std::io::Result { + use ff::PrimeField; + use std::io; let anchor_bytes = <[u8; 32]>::deserialize_reader(reader)?; let anchor = Option::from(pallas::Base::from_repr(anchor_bytes)) .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "anchor not in field"))?; diff --git a/taiga_halo2/src/binding_signature.rs b/taiga_halo2/src/binding_signature.rs index 5dcf5af3..8eaf9778 100644 --- a/taiga_halo2/src/binding_signature.rs +++ b/taiga_halo2/src/binding_signature.rs @@ -1,11 +1,15 @@ use crate::constant::NOTE_COMMITMENT_R_GENERATOR; -use borsh::{BorshDeserialize, BorshSerialize}; use pasta_curves::group::cofactor::CofactorCurveAffine; use pasta_curves::group::{ff::PrimeField, GroupEncoding}; use pasta_curves::pallas; use rand::{CryptoRng, RngCore}; use reddsa::{private, Error, SigType, Signature, SigningKey, VerificationKey}; -use std::io; + +#[cfg(feature = "serde")] +use serde; + +#[cfg(feature = "borsh")] +use borsh::{BorshDeserialize, BorshSerialize}; #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum TaigaBinding {} @@ -29,12 +33,15 @@ impl private::Sealed for TaigaBinding { impl SigType for TaigaBinding {} #[derive(Clone, Debug)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct BindingSignature(Signature); #[derive(Clone, Debug)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct BindingSigningKey(SigningKey); #[derive(Clone, Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct BindingVerificationKey(VerificationKey); impl BindingSignature { @@ -48,14 +55,16 @@ impl BindingSignature { } } +#[cfg(feature = "borsh")] impl BorshSerialize for BindingSignature { - fn serialize(&self, writer: &mut W) -> borsh::maybestd::io::Result<()> { + fn serialize(&self, writer: &mut W) -> std::io::Result<()> { writer.write_all(&self.to_bytes()) } } +#[cfg(feature = "borsh")] impl BorshDeserialize for BindingSignature { - fn deserialize_reader(reader: &mut R) -> io::Result { + fn deserialize_reader(reader: &mut R) -> std::io::Result { let mut sig_bytes = [0u8; 64]; reader.read_exact(&mut sig_bytes)?; Ok(Self::from_bytes(sig_bytes)) @@ -81,14 +90,17 @@ impl BindingSigningKey { } } +#[cfg(feature = "borsh")] impl BorshSerialize for BindingSigningKey { fn serialize(&self, writer: &mut W) -> borsh::maybestd::io::Result<()> { writer.write_all(&self.to_bytes()) } } +#[cfg(feature = "borsh")] impl BorshDeserialize for BindingSigningKey { - fn deserialize_reader(reader: &mut R) -> io::Result { + fn deserialize_reader(reader: &mut R) -> std::io::Result { + use std::io; let mut key_bytes = [0u8; 32]; reader.read_exact(&mut key_bytes)?; Self::from_bytes(key_bytes).map_err(|_| { diff --git a/taiga_halo2/src/circuit/vp_circuit.rs b/taiga_halo2/src/circuit/vp_circuit.rs index 37dd5158..d2ef2bca 100644 --- a/taiga_halo2/src/circuit/vp_circuit.rs +++ b/taiga_halo2/src/circuit/vp_circuit.rs @@ -29,9 +29,8 @@ use crate::{ utils::mod_r_p, vp_vk::ValidityPredicateVerifyingKey, }; -use borsh::{BorshDeserialize, BorshSerialize}; use dyn_clone::{clone_trait_object, DynClone}; -use ff::PrimeField; +//use ff::PrimeField; use group::cofactor::CofactorCurveAffine; use halo2_gadgets::{ecc::chip::EccChip, sinsemilla::chip::SinsemillaChip}; use halo2_proofs::{ @@ -47,7 +46,7 @@ use pasta_curves::{pallas, vesta, EqAffine, Fp}; use rand::{rngs::OsRng, RngCore}; use std::collections::HashMap; use std::fs; -use std::io; +//use std::io; use std::path::PathBuf; use std::rc::Rc; use vamp_ir::ast::Module; @@ -55,6 +54,12 @@ use vamp_ir::halo2::synth::{make_constant, Halo2Module, PrimeFieldOps}; use vamp_ir::transform::compile; use vamp_ir::util::{read_inputs_from_file, Config}; +#[cfg(feature = "serde")] +use serde; + +#[cfg(feature = "borsh")] +use borsh::{BorshDeserialize, BorshSerialize}; + #[cfg(feature = "nif")] use rustler::types::atom; #[cfg(feature = "nif")] @@ -63,7 +68,15 @@ use rustler::{Decoder, Encoder, Env, NifResult, Term}; pub type ValidityPredicate = dyn ValidityPredicateVerifyingInfo; #[derive(Debug, Clone)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct VPVerifyingInfo { + #[cfg_attr( + feature = "serde", + serde( + serialize_with = "serde_serialize_verifying_key", + deserialize_with = "serde_deserialize_verifying_key" + ) + )] pub vk: VerifyingKey, pub proof: Proof, pub public_inputs: ValidityPredicatePublicInputs, @@ -111,6 +124,7 @@ impl<'a> Decoder<'a> for VPVerifyingInfo { } #[derive(Clone, Debug)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct ValidityPredicatePublicInputs([pallas::Base; VP_CIRCUIT_PUBLIC_INPUT_NUM]); #[cfg(feature = "nif")] @@ -160,8 +174,10 @@ impl VPVerifyingInfo { } } +#[cfg(feature = "borsh")] impl BorshSerialize for VPVerifyingInfo { fn serialize(&self, writer: &mut W) -> borsh::maybestd::io::Result<()> { + use ff::PrimeField; // Write vk self.vk.write(writer)?; // Write proof @@ -174,8 +190,11 @@ impl BorshSerialize for VPVerifyingInfo { } } +#[cfg(feature = "borsh")] impl BorshDeserialize for VPVerifyingInfo { - fn deserialize_reader(reader: &mut R) -> io::Result { + fn deserialize_reader(reader: &mut R) -> std::io::Result { + 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(); @@ -199,6 +218,34 @@ impl BorshDeserialize for VPVerifyingInfo { } } +#[cfg(feature = "serde")] +fn serde_serialize_verifying_key( + x: &VerifyingKey, + s: S, +) -> Result +where + S: serde::Serializer, +{ + let mut buf = Vec::new(); + x.write(&mut buf).unwrap(); + s.serialize_bytes(&buf) +} + +#[cfg(feature = "serde")] +fn serde_deserialize_verifying_key<'de, D>(d: D) -> Result, D::Error> +where + D: serde::Deserializer<'de>, +{ + use serde::de::Error; + let buf: Vec = serde::Deserialize::deserialize(d)?; + + use crate::circuit::vp_examples::TrivialValidityPredicateCircuit; + let params = SETUP_PARAMS_MAP.get(&VP_CIRCUIT_PARAMS_SIZE).unwrap(); + let vk = VerifyingKey::read::<_, TrivialValidityPredicateCircuit>(&mut buf.as_slice(), params) + .map_err(|e| Error::custom(format!("Error reading VerifyingKey: {}", e)))?; + Ok(vk) +} + impl ValidityPredicatePublicInputs { pub fn inner(&self) -> &[pallas::Base; VP_CIRCUIT_PUBLIC_INPUT_NUM] { &self.0 @@ -1039,4 +1086,39 @@ mod tests { ) .is_err()); } + + #[cfg(feature = "serde")] + #[test] + fn test_vk_serialize() { + use crate::circuit::{ + vp_circuit::{serde_deserialize_verifying_key, serde_serialize_verifying_key}, + vp_examples::TrivialValidityPredicateCircuit, + }; + use halo2_proofs::plonk::VerifyingKey; + use pasta_curves::vesta; + use serde_json; + + #[derive(serde::Serialize, serde::Deserialize)] + struct TestStruct { + #[serde( + serialize_with = "serde_serialize_verifying_key", + deserialize_with = "serde_deserialize_verifying_key" + )] + vk: VerifyingKey, + } + + let t = TrivialValidityPredicateCircuit::default().get_vp_vk(); + + let a = TestStruct { + vk: t.get_vk().unwrap(), + }; + + let ser = serde_json::to_string(&a).unwrap(); + let deser: TestStruct = serde_json::from_str(&ser).unwrap(); + + let a_bytes = a.vk.to_bytes(); + let deser_bytes = deser.vk.to_bytes(); + + assert_eq!(a_bytes, deser_bytes); + } } diff --git a/taiga_halo2/src/merkle_tree.rs b/taiga_halo2/src/merkle_tree.rs index ceb27235..752618a0 100644 --- a/taiga_halo2/src/merkle_tree.rs +++ b/taiga_halo2/src/merkle_tree.rs @@ -2,8 +2,6 @@ use std::hash::{Hash, Hasher}; use crate::utils::poseidon_hash; use crate::{constant::TAIGA_COMMITMENT_TREE_DEPTH, note::Note}; -use borsh::{BorshDeserialize, BorshSerialize}; -use ff::PrimeField; use halo2_proofs::arithmetic::Field; use pasta_curves::pallas; use rand::{Rng, RngCore}; @@ -11,7 +9,18 @@ use rand::{Rng, RngCore}; use crate::merkle_tree::LR::{L, R}; use rand::distributions::{Distribution, Standard}; -#[derive(Clone, Debug, PartialEq, Eq, Copy, Hash, Default, BorshSerialize, BorshDeserialize)] +#[cfg(feature = "borsh")] +use ff::PrimeField; + +#[cfg(feature = "serde")] +use serde; + +#[cfg(feature = "borsh")] +use borsh::{BorshDeserialize, BorshSerialize}; + +#[derive(Clone, Debug, PartialEq, Eq, Copy, Hash, Default)] +#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum LR { R, #[default] @@ -44,7 +53,9 @@ impl Distribution for Standard { /// A path from a position in a particular commitment tree to the root of that tree. /// In Orchard merkle tree, they are using MerkleCRH(layer, left, right), where MerkleCRH is a sinsemilla. We are using poseidon_hash(left, right). -#[derive(Clone, Debug, PartialEq, Eq, Hash, BorshSerialize, BorshDeserialize)] +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct MerklePath { merkle_path: Vec<(Node, LR)>, } @@ -92,6 +103,7 @@ impl Default for MerklePath { /// A node within the Sapling commitment tree. #[derive(Copy, Clone, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Node(pallas::Base); impl Node { @@ -116,6 +128,7 @@ impl Node { } } +#[cfg(feature = "borsh")] impl BorshSerialize for Node { fn serialize(&self, writer: &mut W) -> std::io::Result<()> { writer.write_all(&self.0.to_repr())?; @@ -123,6 +136,7 @@ impl BorshSerialize for Node { } } +#[cfg(feature = "borsh")] impl BorshDeserialize for Node { fn deserialize_reader(reader: &mut R) -> std::io::Result { let mut repr = [0u8; 32]; diff --git a/taiga_halo2/src/note.rs b/taiga_halo2/src/note.rs index ef3b68e0..aee6b11b 100644 --- a/taiga_halo2/src/note.rs +++ b/taiga_halo2/src/note.rs @@ -14,8 +14,6 @@ use crate::{ }; use bitvec::{array::BitArray, order::Lsb0}; use blake2b_simd::Params as Blake2bParams; -use borsh::{BorshDeserialize, BorshSerialize}; -use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use core::iter; use ff::{FromUniformBytes, PrimeField}; use halo2_proofs::arithmetic::Field; @@ -26,14 +24,18 @@ use pasta_curves::{ use rand::RngCore; #[cfg(feature = "nif")] use rustler::{NifStruct, NifTuple}; -use std::{ - hash::{Hash, Hasher}, - io, -}; +use std::hash::{Hash, Hasher}; + +#[cfg(feature = "serde")] +use serde; + +#[cfg(feature = "borsh")] +use borsh::{BorshDeserialize, BorshSerialize}; /// A commitment to a note. -#[derive(Copy, Debug, Clone)] +#[derive(Copy, Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "nif", derive(NifTuple))] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct NoteCommitment(pallas::Point); impl NoteCommitment { @@ -56,10 +58,37 @@ impl Default for NoteCommitment { } } +#[cfg(feature = "borsh")] +impl BorshSerialize for NoteCommitment { + fn serialize(&self, writer: &mut W) -> std::io::Result<()> { + writer.write_all(&self.0.to_bytes())?; + Ok(()) + } +} + +#[cfg(feature = "borsh")] +impl BorshDeserialize for NoteCommitment { + fn deserialize_reader(reader: &mut R) -> std::io::Result { + let mut repr = [0u8; 32]; + reader.read_exact(&mut repr)?; + let value = Option::from(pallas::Point::from_bytes(&repr)).ok_or_else(|| { + std::io::Error::new(std::io::ErrorKind::InvalidData, "Node value not in field") + })?; + Ok(Self(value)) + } +} + +impl Hash for NoteCommitment { + fn hash(&self, state: &mut H) { + self.0.to_bytes().as_ref().hash(state); + } +} + /// A note #[derive(Debug, Clone, Copy, Default, PartialEq, Eq)] #[cfg_attr(feature = "nif", derive(NifStruct))] #[cfg_attr(feature = "nif", module = "Taiga.Note")] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] 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 @@ -80,9 +109,10 @@ 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, PartialEq, Eq)] #[cfg_attr(feature = "nif", derive(NifStruct))] #[cfg_attr(feature = "nif", module = "Taiga.NoteType")] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct NoteType { /// app_vk is the compressed verifying key of VP pub app_vk: pallas::Base, @@ -90,12 +120,6 @@ pub struct NoteType { pub app_data_static: pallas::Base, } -impl PartialEq for NoteType { - fn eq(&self, other: &Self) -> bool { - self.app_vk == other.app_vk && self.app_data_static == other.app_data_static - } -} - #[derive(Copy, Clone, Debug, Default)] pub struct RandomSeed([u8; 32]); @@ -292,8 +316,10 @@ impl Note { } } +#[cfg(feature = "borsh")] impl BorshSerialize for Note { fn serialize(&self, writer: &mut W) -> borsh::maybestd::io::Result<()> { + use byteorder::{LittleEndian, WriteBytesExt}; // Write app_vk writer.write_all(&self.note_type.app_vk.to_repr())?; // Write app_data_static @@ -326,8 +352,11 @@ impl BorshSerialize for Note { } } +#[cfg(feature = "borsh")] impl BorshDeserialize for Note { - fn deserialize_reader(reader: &mut R) -> io::Result { + fn deserialize_reader(reader: &mut R) -> std::io::Result { + use byteorder::{LittleEndian, ReadBytesExt}; + use std::io; // Read app_vk let mut app_vk_bytes = [0u8; 32]; reader.read_exact(&mut app_vk_bytes)?; @@ -615,10 +644,13 @@ pub mod tests { } } + #[cfg(feature = "borsh")] #[test] - fn note_serialization_test() { + fn note_borsh_serialization_test() { use borsh::{BorshDeserialize, BorshSerialize}; use rand::rngs::OsRng; + + use crate::note::NoteCommitment; let mut rng = OsRng; let input_note = random_input_note(&mut rng); @@ -638,5 +670,25 @@ pub mod tests { let de_note: Note = BorshDeserialize::deserialize(&mut borsh.as_ref()).unwrap(); assert_eq!(output_note, de_note); } + + let icm = input_note.commitment(); + { + // BorshSerialize + let borsh = icm.try_to_vec().unwrap(); + // BorshDeserialize + let de_icm: NoteCommitment = + BorshDeserialize::deserialize(&mut borsh.as_ref()).unwrap(); + assert_eq!(icm, de_icm); + } + + let ocm = output_note.commitment(); + { + // BorshSerialize + let borsh = ocm.try_to_vec().unwrap(); + // BorshDeserialize + let de_ocm: NoteCommitment = + BorshDeserialize::deserialize(&mut borsh.as_ref()).unwrap(); + assert_eq!(ocm, de_ocm); + } } } diff --git a/taiga_halo2/src/nullifier.rs b/taiga_halo2/src/nullifier.rs index c69bf6ba..6c512b0d 100644 --- a/taiga_halo2/src/nullifier.rs +++ b/taiga_halo2/src/nullifier.rs @@ -5,7 +5,6 @@ use crate::{ note::NoteCommitment, utils::{extract_p, mod_r_p, prf_nf}, }; -use borsh::{BorshDeserialize, BorshSerialize}; use halo2_proofs::arithmetic::Field; use pasta_curves::group::cofactor::CofactorCurveAffine; use pasta_curves::group::ff::PrimeField; @@ -15,14 +14,22 @@ use rand::RngCore; use rustler::{NifTaggedEnum, NifTuple}; use subtle::CtOption; +#[cfg(feature = "serde")] +use serde; + +#[cfg(feature = "borsh")] +use borsh::{BorshDeserialize, BorshSerialize}; + /// The unique nullifier. #[derive(Copy, Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "nif", derive(NifTuple))] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Nullifier(pallas::Base); /// The NullifierKeyContainer contains the nullifier_key or the nullifier_key commitment #[derive(Copy, Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "nif", derive(NifTaggedEnum))] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum NullifierKeyContainer { // The NullifierKeyContainer::Commitment is the commitment of NullifierKeyContainer::Key `nk_com = Commitment(nk, 0)` Commitment(pallas::Base), @@ -75,6 +82,7 @@ impl Default for Nullifier { } } +#[cfg(feature = "borsh")] impl BorshSerialize for Nullifier { fn serialize(&self, writer: &mut W) -> std::io::Result<()> { writer.write_all(&self.0.to_repr())?; @@ -82,6 +90,7 @@ impl BorshSerialize for Nullifier { } } +#[cfg(feature = "borsh")] impl BorshDeserialize for Nullifier { fn deserialize_reader(reader: &mut R) -> std::io::Result { let mut repr = [0u8; 32]; diff --git a/taiga_halo2/src/proof.rs b/taiga_halo2/src/proof.rs index c2024a3a..aeff0861 100644 --- a/taiga_halo2/src/proof.rs +++ b/taiga_halo2/src/proof.rs @@ -1,4 +1,3 @@ -use borsh::{BorshDeserialize, BorshSerialize}; use halo2_proofs::{ plonk::{self, Circuit, ProvingKey, SingleVerifier, VerifyingKey}, poly::commitment::Params, @@ -9,8 +8,16 @@ use rand::RngCore; #[cfg(feature = "nif")] use rustler::NifTuple; -#[derive(Clone, Debug, BorshSerialize, BorshDeserialize)] +#[cfg(feature = "serde")] +use serde; + +#[cfg(feature = "borsh")] +use borsh::{BorshDeserialize, BorshSerialize}; + +#[derive(Clone, Debug)] #[cfg_attr(feature = "nif", derive(NifTuple))] +#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Proof(Vec); impl Proof { diff --git a/taiga_halo2/src/shielded_ptx.rs b/taiga_halo2/src/shielded_ptx.rs index 241f1088..f404515f 100644 --- a/taiga_halo2/src/shielded_ptx.rs +++ b/taiga_halo2/src/shielded_ptx.rs @@ -10,29 +10,39 @@ use crate::note::{InputNoteProvingInfo, OutputNoteProvingInfo}; use crate::nullifier::Nullifier; use crate::proof::Proof; use crate::value_commitment::ValueCommitment; -use borsh::{BorshDeserialize, BorshSerialize}; use halo2_proofs::plonk::Error; use pasta_curves::pallas; use rand::RngCore; #[cfg(feature = "nif")] use rustler::{Decoder, Encoder, Env, NifResult, NifStruct, Term}; +#[cfg(feature = "serde")] +use serde; + +#[cfg(feature = "borsh")] +use borsh::{BorshDeserialize, BorshSerialize}; + #[derive(Debug, Clone)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct ShieldedPartialTransaction { actions: [ActionVerifyingInfo; NUM_NOTE], inputs: [NoteVPVerifyingInfoSet; NUM_NOTE], outputs: [NoteVPVerifyingInfoSet; NUM_NOTE], } -#[derive(Debug, Clone, BorshSerialize, BorshDeserialize)] +#[derive(Debug, Clone)] #[cfg_attr(feature = "nif", derive(NifStruct))] #[cfg_attr(feature = "nif", module = "Taiga.Action.VerifyingInfo")] +#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct ActionVerifyingInfo { action_proof: Proof, action_instance: ActionInstance, } -#[derive(Debug, Clone, BorshSerialize, BorshDeserialize)] +#[derive(Debug, Clone)] +#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "nif", derive(NifStruct))] #[cfg_attr(feature = "nif", module = "Taiga.Note.VerifyingInfo")] pub struct NoteVPVerifyingInfoSet { @@ -240,6 +250,7 @@ impl Executable for ShieldedPartialTransaction { } } +#[cfg(feature = "borsh")] impl BorshSerialize for ShieldedPartialTransaction { fn serialize(&self, writer: &mut W) -> borsh::maybestd::io::Result<()> { for action in self.actions.iter() { @@ -258,6 +269,7 @@ impl BorshSerialize for ShieldedPartialTransaction { } } +#[cfg(feature = "borsh")] impl BorshDeserialize for ShieldedPartialTransaction { fn deserialize_reader(reader: &mut R) -> std::io::Result { let actions: Vec<_> = (0..NUM_NOTE) diff --git a/taiga_halo2/src/transaction.rs b/taiga_halo2/src/transaction.rs index 1000ee8a..ab6bb348 100644 --- a/taiga_halo2/src/transaction.rs +++ b/taiga_halo2/src/transaction.rs @@ -7,7 +7,6 @@ use crate::shielded_ptx::ShieldedPartialTransaction; use crate::transparent_ptx::{OutputResource, TransparentPartialTransaction}; use crate::value_commitment::ValueCommitment; use blake2b_simd::Params as Blake2bParams; -use borsh::{BorshDeserialize, BorshSerialize}; use pasta_curves::{ group::{ff::PrimeField, Group}, pallas, @@ -18,7 +17,15 @@ use rustler::types::atom; #[cfg(feature = "nif")] use rustler::{atoms, Decoder, Env, NifRecord, NifResult, NifStruct, Term}; -#[derive(Debug, Clone, BorshDeserialize, BorshSerialize)] +#[cfg(feature = "serde")] +use serde; + +#[cfg(feature = "borsh")] +use borsh::{BorshDeserialize, BorshSerialize}; + +#[derive(Debug, Clone)] +#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Transaction { // TODO: Other parameters to be added. shielded_ptx_bundle: Option, @@ -27,15 +34,19 @@ pub struct Transaction { signature: InProgressBindingSignature, } -#[derive(Debug, Clone, BorshDeserialize, BorshSerialize)] +#[derive(Debug, Clone)] +#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum InProgressBindingSignature { Authorized(BindingSignature), Unauthorized(BindingSigningKey), } -#[derive(Debug, Clone, BorshDeserialize, BorshSerialize)] +#[derive(Debug, Clone)] #[cfg_attr(feature = "nif", derive(NifRecord))] #[cfg_attr(feature = "nif", tag = "bundle")] +#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct ShieldedPartialTxBundle { partial_txs: Vec, } @@ -49,7 +60,9 @@ pub struct ShieldedResult { output_cms: Vec, } -#[derive(Debug, Clone, BorshDeserialize, BorshSerialize)] +#[derive(Debug, Clone)] +#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct TransparentPartialTxBundle { partial_txs: Vec, } @@ -397,7 +410,6 @@ pub mod testing { let rng = OsRng; - // Create shielded partial tx bundle let (shielded_ptx_bundle, r_vec) = create_shielded_ptx_bundle(2); // TODO: add transparent_ptx_bundle test let transparent_ptx_bundle = None; @@ -409,9 +421,12 @@ pub mod testing { ); let (shielded_ret, _) = tx.execute().unwrap(); - let borsh = tx.try_to_vec().unwrap(); - let de_tx: Transaction = BorshDeserialize::deserialize(&mut borsh.as_ref()).unwrap(); - let (de_shielded_ret, _) = de_tx.execute().unwrap(); - assert_eq!(shielded_ret, de_shielded_ret); + #[cfg(feature = "borsh")] + { + let borsh = tx.try_to_vec().unwrap(); + let de_tx: Transaction = BorshDeserialize::deserialize(&mut borsh.as_ref()).unwrap(); + let (de_shielded_ret, _) = de_tx.execute().unwrap(); + assert_eq!(shielded_ret, de_shielded_ret); + } } } diff --git a/taiga_halo2/src/transparent_ptx.rs b/taiga_halo2/src/transparent_ptx.rs index 2bac5a3a..0a6a88a2 100644 --- a/taiga_halo2/src/transparent_ptx.rs +++ b/taiga_halo2/src/transparent_ptx.rs @@ -2,10 +2,17 @@ use crate::{ error::TransactionError, executable::Executable, nullifier::Nullifier, value_commitment::ValueCommitment, }; -use borsh::{BorshDeserialize, BorshSerialize}; use pasta_curves::pallas; -#[derive(Debug, Clone, BorshDeserialize, BorshSerialize)] +#[cfg(feature = "serde")] +use serde; + +#[cfg(feature = "borsh")] +use borsh::{BorshDeserialize, BorshSerialize}; + +#[derive(Debug, Clone)] +#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct TransparentPartialTransaction { pub inputs: Vec, pub outputs: Vec, @@ -34,7 +41,9 @@ impl Executable for TransparentPartialTransaction { } } -#[derive(Debug, Clone, BorshDeserialize, BorshSerialize)] +#[derive(Debug, Clone)] +#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct InputResource { pub resource_logic: ResourceLogic, pub prefix: ContentHash, @@ -43,21 +52,31 @@ pub struct InputResource { pub resource_data_dynamic: ResourceDataDynamic, } -#[derive(Debug, Clone, BorshDeserialize, BorshSerialize)] +#[derive(Debug, Clone)] +#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct OutputResource { pub resource_logic: ResourceLogic, pub resource_data_static: ResourceDataStatic, pub resource_data_dynamic: ResourceDataDynamic, } -#[derive(Debug, Clone, BorshDeserialize, BorshSerialize)] +#[derive(Debug, Clone)] +#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct ResourceLogic {} -#[derive(Debug, Clone, BorshDeserialize, BorshSerialize)] +#[derive(Debug, Clone)] +#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct ContentHash {} -#[derive(Debug, Clone, BorshDeserialize, BorshSerialize)] +#[derive(Debug, Clone)] +#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct ResourceDataStatic {} -#[derive(Debug, Clone, BorshDeserialize, BorshSerialize)] +#[derive(Debug, Clone)] +#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct ResourceDataDynamic {} diff --git a/taiga_halo2/src/value_commitment.rs b/taiga_halo2/src/value_commitment.rs index bf6d0309..444746b0 100644 --- a/taiga_halo2/src/value_commitment.rs +++ b/taiga_halo2/src/value_commitment.rs @@ -8,8 +8,12 @@ use pasta_curves::pallas; use rustler::NifTuple; use subtle::CtOption; +#[cfg(feature = "serde")] +use serde; + #[derive(Copy, Clone, Debug)] #[cfg_attr(feature = "nif", derive(NifTuple))] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct ValueCommitment(pallas::Point); impl ValueCommitment {