diff --git a/taiga_halo2/src/circuit/vp_circuit.rs b/taiga_halo2/src/circuit/vp_circuit.rs index e6769def..01c62494 100644 --- a/taiga_halo2/src/circuit/vp_circuit.rs +++ b/taiga_halo2/src/circuit/vp_circuit.rs @@ -31,7 +31,7 @@ use crate::{ proof::Proof, resource::{RandomSeed, Resource, ResourceCommitment}, resource_encryption::{ResourceCiphertext, SecretKey}, - utils::mod_r_p, + utils::{mod_r_p, read_base_field}, vp_vk::ValidityPredicateVerifyingKey, }; use dyn_clone::{clone_trait_object, DynClone}; @@ -204,8 +204,6 @@ impl BorshSerialize for VPVerifyingInfo { #[cfg(feature = "borsh")] impl BorshDeserialize for VPVerifyingInfo { 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(); @@ -214,12 +212,7 @@ impl BorshDeserialize for VPVerifyingInfo { 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::>()?; Ok(VPVerifyingInfo { vk, diff --git a/taiga_halo2/src/circuit/vp_examples.rs b/taiga_halo2/src/circuit/vp_examples.rs index 48bda659..6adb3daf 100644 --- a/taiga_halo2/src/circuit/vp_examples.rs +++ b/taiga_halo2/src/circuit/vp_examples.rs @@ -9,6 +9,7 @@ use crate::{ error::TransactionError, proof::Proof, resource::{RandomSeed, Resource}, + utils::read_base_field, vp_commitment::ValidityPredicateCommitment, vp_vk::ValidityPredicateVerifyingKey, }; @@ -133,15 +134,7 @@ impl BorshSerialize for TrivialValidityPredicateCircuit { #[cfg(feature = "borsh")] impl BorshDeserialize for TrivialValidityPredicateCircuit { fn deserialize_reader(reader: &mut R) -> std::io::Result { - 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::>()?; diff --git a/taiga_halo2/src/circuit/vp_examples/cascade_intent.rs b/taiga_halo2/src/circuit/vp_examples/cascade_intent.rs index 431cb815..f6feea9f 100644 --- a/taiga_halo2/src/circuit/vp_examples/cascade_intent.rs +++ b/taiga_halo2/src/circuit/vp_examples/cascade_intent.rs @@ -22,6 +22,7 @@ use crate::{ nullifier::Nullifier, proof::Proof, resource::{RandomSeed, Resource}, + utils::read_base_field, vp_commitment::ValidityPredicateCommitment, vp_vk::ValidityPredicateVerifyingKey, }; @@ -184,28 +185,14 @@ impl BorshSerialize for CascadeIntentValidityPredicateCircuit { impl BorshDeserialize for CascadeIntentValidityPredicateCircuit { 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 owned_resource_id = read_base_field(reader)?; 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 cascade_resource_cm_bytes = <[u8; 32]>::deserialize_reader(reader)?; - let cascade_resource_cm = Option::from(pallas::Base::from_repr(cascade_resource_cm_bytes)) - .ok_or_else(|| { - std::io::Error::new( - std::io::ErrorKind::InvalidData, - "cascade_resource_cm not in field", - ) - })?; + let cascade_resource_cm = read_base_field(reader)?; Ok(Self { owned_resource_id, input_resources: input_resources.try_into().unwrap(), 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 44dfba6c..427b04ff 100644 --- a/taiga_halo2/src/circuit/vp_examples/or_relation_intent.rs +++ b/taiga_halo2/src/circuit/vp_examples/or_relation_intent.rs @@ -23,6 +23,7 @@ use crate::{ proof::Proof, resource::{RandomSeed, Resource}, utils::poseidon_hash_n, + utils::read_base_field, vp_commitment::ValidityPredicateCommitment, vp_vk::ValidityPredicateVerifyingKey, }; @@ -317,14 +318,7 @@ impl BorshSerialize for OrRelationIntentValidityPredicateCircuit { 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 owned_resource_id = read_base_field(reader)?; let input_resources: Vec<_> = (0..NUM_RESOURCE) .map(|_| Resource::deserialize_reader(reader)) .collect::>()?; @@ -333,19 +327,8 @@ impl BorshDeserialize for OrRelationIntentValidityPredicateCircuit { .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", - ) - })?; + 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(), diff --git a/taiga_halo2/src/circuit/vp_examples/partial_fulfillment_intent.rs b/taiga_halo2/src/circuit/vp_examples/partial_fulfillment_intent.rs index dbba58d9..c3d2fb28 100644 --- a/taiga_halo2/src/circuit/vp_examples/partial_fulfillment_intent.rs +++ b/taiga_halo2/src/circuit/vp_examples/partial_fulfillment_intent.rs @@ -21,6 +21,7 @@ use crate::{ error::TransactionError, proof::Proof, resource::{RandomSeed, Resource}, + utils::read_base_field, vp_commitment::ValidityPredicateCommitment, vp_vk::ValidityPredicateVerifyingKey, }; @@ -216,14 +217,7 @@ impl BorshSerialize for PartialFulfillmentIntentValidityPredicateCircuit { impl BorshDeserialize for PartialFulfillmentIntentValidityPredicateCircuit { 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 owned_resource_id = read_base_field(reader)?; let input_resources: Vec<_> = (0..NUM_RESOURCE) .map(|_| Resource::deserialize_reader(reader)) .collect::>()?; diff --git a/taiga_halo2/src/circuit/vp_examples/receiver_vp.rs b/taiga_halo2/src/circuit/vp_examples/receiver_vp.rs index 3035759e..4cead5c9 100644 --- a/taiga_halo2/src/circuit/vp_examples/receiver_vp.rs +++ b/taiga_halo2/src/circuit/vp_examples/receiver_vp.rs @@ -18,7 +18,7 @@ use crate::{ proof::Proof, resource::{RandomSeed, Resource}, resource_encryption::{ResourceCiphertext, ResourcePlaintext, SecretKey}, - utils::mod_r_p, + utils::{mod_r_p, read_base_field, read_point}, vp_commitment::ValidityPredicateCommitment, vp_vk::ValidityPredicateVerifyingKey, }; @@ -321,46 +321,18 @@ impl BorshSerialize for ReceiverValidityPredicateCircuit { impl BorshDeserialize for ReceiverValidityPredicateCircuit { 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 owned_resource_id = read_base_field(reader)?; 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 vp_vk_bytes = <[u8; 32]>::deserialize_reader(reader)?; - let vp_vk = Option::from(pallas::Base::from_repr(vp_vk_bytes)).ok_or_else(|| { - std::io::Error::new(std::io::ErrorKind::InvalidData, "vp_vk not in field") - })?; - let encrypt_nonce_bytes = <[u8; 32]>::deserialize_reader(reader)?; - let encrypt_nonce = - Option::from(pallas::Base::from_repr(encrypt_nonce_bytes)).ok_or_else(|| { - std::io::Error::new( - std::io::ErrorKind::InvalidData, - "encrypt_nonce not in field", - ) - })?; - let sk_bytes = <[u8; 32]>::deserialize_reader(reader)?; - let sk = Option::from(pallas::Base::from_repr(sk_bytes)).ok_or_else(|| { - std::io::Error::new(std::io::ErrorKind::InvalidData, "sk not in field") - })?; - let rcv_pk_bytes = <[u8; 32]>::deserialize_reader(reader)?; - let rcv_pk = Option::from(pallas::Point::from_bytes(&rcv_pk_bytes)).ok_or_else(|| { - std::io::Error::new(std::io::ErrorKind::InvalidData, "rcv_pk not in point") - })?; - - let auth_vp_vk_bytes = <[u8; 32]>::deserialize_reader(reader)?; - let auth_vp_vk = - Option::from(pallas::Base::from_repr(auth_vp_vk_bytes)).ok_or_else(|| { - std::io::Error::new(std::io::ErrorKind::InvalidData, "auth_vp_vk not in field") - })?; + let vp_vk = read_base_field(reader)?; + let encrypt_nonce = read_base_field(reader)?; + let sk = read_base_field(reader)?; + let rcv_pk = read_point(reader)?; + let auth_vp_vk = read_base_field(reader)?; Ok(Self { owned_resource_id, input_resources: input_resources.try_into().unwrap(), diff --git a/taiga_halo2/src/circuit/vp_examples/signature_verification.rs b/taiga_halo2/src/circuit/vp_examples/signature_verification.rs index ecd8302b..7ee323b4 100644 --- a/taiga_halo2/src/circuit/vp_examples/signature_verification.rs +++ b/taiga_halo2/src/circuit/vp_examples/signature_verification.rs @@ -15,7 +15,7 @@ use crate::{ error::TransactionError, proof::Proof, resource::{RandomSeed, Resource}, - utils::{mod_r_p, poseidon_hash_n}, + utils::{mod_r_p, poseidon_hash_n, read_base_field, read_point, read_scalar_field}, vp_commitment::ValidityPredicateCommitment, vp_vk::ValidityPredicateVerifyingKey, }; @@ -326,33 +326,16 @@ impl BorshSerialize for SignatureVerificationValidityPredicateCircuit { impl BorshDeserialize for SignatureVerificationValidityPredicateCircuit { 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 owned_resource_id = read_base_field(reader)?; 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 vp_vk_bytes = <[u8; 32]>::deserialize_reader(reader)?; - let vp_vk = Option::from(pallas::Base::from_repr(vp_vk_bytes)).ok_or_else(|| { - std::io::Error::new(std::io::ErrorKind::InvalidData, "vp_vk not in field") - })?; + let vp_vk = read_base_field(reader)?; let signature = SchnorrSignature::deserialize_reader(reader)?; - let receiver_vp_vk_bytes = <[u8; 32]>::deserialize_reader(reader)?; - let receiver_vp_vk = Option::from(pallas::Base::from_repr(receiver_vp_vk_bytes)) - .ok_or_else(|| { - std::io::Error::new( - std::io::ErrorKind::InvalidData, - "receiver_vp_vk not in field", - ) - })?; + let receiver_vp_vk = read_base_field(reader)?; Ok(Self { owned_resource_id, input_resources: input_resources.try_into().unwrap(), @@ -376,18 +359,9 @@ impl BorshSerialize for SchnorrSignature { impl BorshDeserialize for SchnorrSignature { fn deserialize_reader(reader: &mut R) -> std::io::Result { - let pk_bytes = <[u8; 32]>::deserialize_reader(reader)?; - let pk = Option::from(pallas::Point::from_bytes(&pk_bytes)).ok_or_else(|| { - std::io::Error::new(std::io::ErrorKind::InvalidData, "pk not in point") - })?; - let r_bytes = <[u8; 32]>::deserialize_reader(reader)?; - let r = Option::from(pallas::Point::from_bytes(&r_bytes)).ok_or_else(|| { - std::io::Error::new(std::io::ErrorKind::InvalidData, "r not in point") - })?; - let s_bytes = <[u8; 32]>::deserialize_reader(reader)?; - let s = Option::from(pallas::Scalar::from_repr(s_bytes)).ok_or_else(|| { - std::io::Error::new(std::io::ErrorKind::InvalidData, "s not in field") - })?; + let pk = read_point(reader)?; + let r = read_point(reader)?; + let s = read_scalar_field(reader)?; Ok(Self { pk, r, s }) } } diff --git a/taiga_halo2/src/circuit/vp_examples/token.rs b/taiga_halo2/src/circuit/vp_examples/token.rs index bdc994d2..1b3329b0 100644 --- a/taiga_halo2/src/circuit/vp_examples/token.rs +++ b/taiga_halo2/src/circuit/vp_examples/token.rs @@ -25,7 +25,7 @@ use crate::{ nullifier::Nullifier, proof::Proof, resource::{RandomSeed, Resource, ResourceValidityPredicates}, - utils::poseidon_hash_n, + utils::{poseidon_hash_n, read_base_field, read_point}, vp_commitment::ValidityPredicateCommitment, vp_vk::ValidityPredicateVerifyingKey, }; @@ -547,14 +547,7 @@ impl BorshSerialize for TokenValidityPredicateCircuit { impl BorshDeserialize for TokenValidityPredicateCircuit { 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 owned_resource_id = read_base_field(reader)?; let input_resources: Vec<_> = (0..NUM_RESOURCE) .map(|_| Resource::deserialize_reader(reader)) .collect::>()?; @@ -563,14 +556,7 @@ impl BorshDeserialize for TokenValidityPredicateCircuit { .collect::>()?; let token_name = TokenName::deserialize_reader(reader)?; let auth = TokenAuthorization::deserialize_reader(reader)?; - let receiver_vp_vk_bytes = <[u8; 32]>::deserialize_reader(reader)?; - let receiver_vp_vk = Option::from(pallas::Base::from_repr(receiver_vp_vk_bytes)) - .ok_or_else(|| { - std::io::Error::new( - std::io::ErrorKind::InvalidData, - "receiver_vp_vk not in field", - ) - })?; + let receiver_vp_vk = read_base_field(reader)?; let rseed = RandomSeed::deserialize_reader(reader)?; Ok(Self { owned_resource_id, @@ -594,17 +580,8 @@ impl BorshSerialize for TokenAuthorization { impl BorshDeserialize for TokenAuthorization { fn deserialize_reader(reader: &mut R) -> std::io::Result { - let pk_bytes = <[u8; 32]>::deserialize_reader(reader)?; - let pk = Option::from(pallas::Point::from_bytes(&pk_bytes)).ok_or_else(|| { - std::io::Error::new( - std::io::ErrorKind::InvalidData, - "owned_resource_id not in point", - ) - })?; - let vk_bytes = <[u8; 32]>::deserialize_reader(reader)?; - let vk = Option::from(pallas::Base::from_repr(vk_bytes)).ok_or_else(|| { - std::io::Error::new(std::io::ErrorKind::InvalidData, "vk not in field") - })?; + let pk = read_point(reader)?; + let vk = read_base_field(reader)?; Ok(Self { pk, vk }) } diff --git a/taiga_halo2/src/merkle_tree.rs b/taiga_halo2/src/merkle_tree.rs index 1fe05a1d..4336cbed 100644 --- a/taiga_halo2/src/merkle_tree.rs +++ b/taiga_halo2/src/merkle_tree.rs @@ -2,7 +2,7 @@ use std::hash::{Hash, Hasher}; use crate::merkle_tree::LR::{L, R}; use crate::resource::ResourceCommitment; -use crate::utils::poseidon_hash; +use crate::utils::{poseidon_hash, read_base_field}; use crate::{constant::TAIGA_COMMITMENT_TREE_DEPTH, resource::Resource}; use ff::PrimeField; use halo2_proofs::arithmetic::Field; @@ -68,11 +68,7 @@ impl BorshSerialize for Anchor { #[cfg(feature = "borsh")] impl BorshDeserialize for Anchor { fn deserialize_reader(reader: &mut R) -> std::io::Result { - let mut repr = [0u8; 32]; - reader.read_exact(&mut repr)?; - let value = Option::from(pallas::Base::from_repr(repr)).ok_or_else(|| { - std::io::Error::new(std::io::ErrorKind::InvalidData, "Anchor not in field") - })?; + let value = read_base_field(reader)?; Ok(Self(value)) } } @@ -208,11 +204,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]; - reader.read_exact(&mut repr)?; - let value = Option::from(pallas::Base::from_repr(repr)).ok_or_else(|| { - std::io::Error::new(std::io::ErrorKind::InvalidData, "Node value not in field") - })?; + let value = read_base_field(reader)?; Ok(Self(value)) } } diff --git a/taiga_halo2/src/nullifier.rs b/taiga_halo2/src/nullifier.rs index 45366ea3..d591ee8b 100644 --- a/taiga_halo2/src/nullifier.rs +++ b/taiga_halo2/src/nullifier.rs @@ -2,7 +2,7 @@ use std::hash::Hash; use crate::{ resource::ResourceCommitment, - utils::{poseidon_hash_n, prf_nf}, + utils::{poseidon_hash_n, prf_nf, read_base_field}, }; use halo2_proofs::arithmetic::Field; use pasta_curves::group::ff::PrimeField; @@ -91,11 +91,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]; - reader.read_exact(&mut repr)?; - let value = Option::from(pallas::Base::from_repr(repr)).ok_or_else(|| { - std::io::Error::new(std::io::ErrorKind::InvalidData, "Nullifier not in field") - })?; + let value = read_base_field(reader)?; Ok(Self(value)) } } diff --git a/taiga_halo2/src/resource.rs b/taiga_halo2/src/resource.rs index 8c67dd27..05590a0f 100644 --- a/taiga_halo2/src/resource.rs +++ b/taiga_halo2/src/resource.rs @@ -11,7 +11,7 @@ use crate::{ merkle_tree::{Anchor, MerklePath, Node}, nullifier::{Nullifier, NullifierKeyContainer}, shielded_ptx::ResourceVPVerifyingInfoSet, - utils::{poseidon_hash_n, poseidon_to_curve}, + utils::{poseidon_hash_n, poseidon_to_curve, read_base_field}, }; use blake2b_simd::Params as Blake2bParams; use ff::{FromUniformBytes, PrimeField}; @@ -67,14 +67,7 @@ impl BorshSerialize for ResourceCommitment { #[cfg(feature = "borsh")] impl BorshDeserialize for ResourceCommitment { fn deserialize_reader(reader: &mut R) -> std::io::Result { - let mut repr = [0u8; 32]; - reader.read_exact(&mut repr)?; - let value = Option::from(pallas::Base::from_repr(repr)).ok_or_else(|| { - std::io::Error::new( - std::io::ErrorKind::InvalidData, - "ResourceCommitment value not in field", - ) - })?; + let value = read_base_field(reader)?; Ok(Self(value)) } } @@ -339,30 +332,16 @@ impl BorshDeserialize for Resource { use byteorder::{LittleEndian, ReadBytesExt}; use std::io; // Read logic - let mut logic_bytes = [0u8; 32]; - reader.read_exact(&mut logic_bytes)?; - let logic = Option::from(pallas::Base::from_repr(logic_bytes)) - .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "logic not in field"))?; + let logic = read_base_field(reader)?; // Read label - let mut label_bytes = [0u8; 32]; - reader.read_exact(&mut label_bytes)?; - let label = Option::from(pallas::Base::from_repr(label_bytes)) - .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "label not in field"))?; + let label = read_base_field(reader)?; // Read value - let mut value_bytes = [0u8; 32]; - reader.read_exact(&mut value_bytes)?; - let value = Option::from(pallas::Base::from_repr(value_bytes)) - .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "value not in field"))?; + let value = read_base_field(reader)?; // Read resource quantity let quantity = reader.read_u64::()?; // Read nk_container - let mut nk_container_type = [0u8; 1]; - reader.read_exact(&mut nk_container_type)?; - let nk_container_type = nk_container_type[0]; - let mut nk_container_bytes = [0u8; 32]; - reader.read_exact(&mut nk_container_bytes)?; - let nk = Option::from(pallas::Base::from_repr(nk_container_bytes)) - .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "nk not in field"))?; + let nk_container_type = reader.read_u8()?; + let nk = read_base_field(reader)?; let nk_container = if nk_container_type == 0x01 { NullifierKeyContainer::from_npk(nk) } else { @@ -381,10 +360,8 @@ impl BorshDeserialize for Resource { let is_ephemeral = is_ephemeral_byte == 0x01; // Read rseed - let mut rseed_bytes = [0u8; 32]; - reader.read_exact(&mut rseed_bytes)?; - let rseed = Option::from(pallas::Base::from_repr(rseed_bytes)) - .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "rseed not in field"))?; + let rseed = read_base_field(reader)?; + // Construct resource Ok(Resource::from_full( logic, diff --git a/taiga_halo2/src/shielded_ptx.rs b/taiga_halo2/src/shielded_ptx.rs index 661157b7..1774c454 100644 --- a/taiga_halo2/src/shielded_ptx.rs +++ b/taiga_halo2/src/shielded_ptx.rs @@ -11,6 +11,7 @@ use crate::merkle_tree::Anchor; use crate::nullifier::Nullifier; use crate::proof::Proof; use crate::resource::{ResourceCommitment, ResourceValidityPredicates}; +use crate::utils::read_scalar_field; use halo2_proofs::plonk::Error; use pasta_curves::pallas; use rand::RngCore; @@ -353,14 +354,7 @@ impl BorshDeserialize for ShieldedPartialTransaction { let binding_sig_r = if binding_sig_r_type == 0 { None } else { - let binding_sig_r_bytes = <[u8; 32]>::deserialize_reader(reader)?; - let r = - Option::from(pallas::Scalar::from_repr(binding_sig_r_bytes)).ok_or_else(|| { - std::io::Error::new( - std::io::ErrorKind::InvalidData, - "binding_sig_r not in field", - ) - })?; + let r = read_scalar_field(reader)?; Some(r) }; diff --git a/taiga_halo2/src/utils.rs b/taiga_halo2/src/utils.rs index bfdcb44f..b36a5a7a 100644 --- a/taiga_halo2/src/utils.rs +++ b/taiga_halo2/src/utils.rs @@ -3,7 +3,7 @@ use halo2_gadgets::poseidon::primitives as poseidon; use halo2_proofs::arithmetic::CurveAffine; use pasta_curves::{ arithmetic::CurveExt, - group::{ff::PrimeField, Curve}, + group::{ff::PrimeField, Curve, GroupEncoding}, hashtocurve, pallas, }; @@ -96,3 +96,24 @@ pub fn to_field_elements(bytes: &[u8]) -> Vec { }) .collect::>() } + +pub fn read_base_field(reader: &mut R) -> std::io::Result { + let mut bytes = [0u8; 32]; + reader.read_exact(&mut bytes)?; + Option::from(pallas::Base::from_repr(bytes)) + .ok_or_else(|| std::io::Error::new(std::io::ErrorKind::InvalidData, "invalid base field")) +} + +pub fn read_scalar_field(reader: &mut R) -> std::io::Result { + let mut bytes = [0u8; 32]; + reader.read_exact(&mut bytes)?; + Option::from(pallas::Scalar::from_repr(bytes)) + .ok_or_else(|| std::io::Error::new(std::io::ErrorKind::InvalidData, "invalid scalar field")) +} + +pub fn read_point(reader: &mut R) -> std::io::Result { + let mut bytes = [0u8; 32]; + reader.read_exact(&mut bytes)?; + Option::from(pallas::Point::from_bytes(&bytes)) + .ok_or_else(|| std::io::Error::new(std::io::ErrorKind::InvalidData, "invalid point")) +}