Add byte calculation for divisible ecash
This commit is contained in:
@@ -400,7 +400,7 @@ impl Payment {
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
pub fn to_bytes(&self) -> Vec<u8>{
|
||||
pub fn to_bytes(&self) -> Vec<u8> {
|
||||
let kappa_bytes = self.kappa.to_affine().to_compressed();
|
||||
let sig_bytes = self.sig.to_bytes();
|
||||
let cc_bytes = self.cc.to_affine().to_compressed();
|
||||
|
||||
@@ -87,7 +87,6 @@ fn main() -> Result<(), CompactEcashError> {
|
||||
.unwrap());
|
||||
|
||||
let payment_bytes = payment.to_bytes();
|
||||
println!("{:?}", payment_bytes.len());
|
||||
let payment2 = Payment::try_from(&payment_bytes[..]).unwrap();
|
||||
assert_eq!(payment, payment2);
|
||||
|
||||
|
||||
@@ -8,6 +8,8 @@ use crate::proofs::{ChallengeDigest, compute_challenge, produce_response, produc
|
||||
use crate::scheme::{Phi, VarPhi, Wallet};
|
||||
use crate::scheme::keygen::{SecretKeyUser, VerificationKeyAuth};
|
||||
use crate::scheme::setup::Parameters;
|
||||
use crate::error::{DivisibleEcashError, Result};
|
||||
use crate::utils::{try_deserialize_scalar};
|
||||
|
||||
pub struct SpendInstance {
|
||||
pub kappa: G2Projective,
|
||||
@@ -84,7 +86,7 @@ pub struct SpendWitness {
|
||||
pub rho3: Scalar,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct SpendProof {
|
||||
challenge: Scalar,
|
||||
response_r: Scalar,
|
||||
@@ -106,6 +108,29 @@ pub struct SpendProof {
|
||||
}
|
||||
|
||||
impl SpendProof {
|
||||
pub fn to_bytes(&self) -> Vec<u8> {
|
||||
let mut bytes: Vec<u8> = Vec::with_capacity(32 * 17); // 17 fields, each 32 bytes
|
||||
|
||||
bytes.extend_from_slice(&self.challenge.to_bytes());
|
||||
bytes.extend_from_slice(&self.response_r.to_bytes());
|
||||
bytes.extend_from_slice(&self.response_r_sk_u.to_bytes());
|
||||
bytes.extend_from_slice(&self.response_r_v.to_bytes());
|
||||
bytes.extend_from_slice(&self.response_r_r.to_bytes());
|
||||
bytes.extend_from_slice(&self.response_r_r1.to_bytes());
|
||||
bytes.extend_from_slice(&self.response_r_r2.to_bytes());
|
||||
bytes.extend_from_slice(&self.response_r_varsig1.to_bytes());
|
||||
bytes.extend_from_slice(&self.response_r_theta1.to_bytes());
|
||||
bytes.extend_from_slice(&self.response_r_varsig2.to_bytes());
|
||||
bytes.extend_from_slice(&self.response_r_theta2.to_bytes());
|
||||
bytes.extend_from_slice(&self.response_r_rr.to_bytes());
|
||||
bytes.extend_from_slice(&self.response_r_ss.to_bytes());
|
||||
bytes.extend_from_slice(&self.response_r_tt.to_bytes());
|
||||
bytes.extend_from_slice(&self.response_r_rho1.to_bytes());
|
||||
bytes.extend_from_slice(&self.response_r_rho2.to_bytes());
|
||||
bytes.extend_from_slice(&self.response_r_rho3.to_bytes());
|
||||
|
||||
bytes
|
||||
}
|
||||
pub fn construct(
|
||||
params: &Parameters,
|
||||
instance: &SpendInstance,
|
||||
@@ -279,6 +304,142 @@ impl SpendProof {
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&[u8]> for SpendProof {
|
||||
type Error = DivisibleEcashError;
|
||||
|
||||
fn try_from(bytes: &[u8]) -> Result<Self> {
|
||||
const FIELD_SIZE: usize = 32; // Each Scalar field is 32 bytes
|
||||
|
||||
if bytes.len() != FIELD_SIZE * 17 {
|
||||
return Err(DivisibleEcashError::Deserialization(
|
||||
"Invalid byte array for SpendProof deserialization".to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
let challenge_bytes = bytes[0..FIELD_SIZE].try_into().unwrap();
|
||||
let challenge = try_deserialize_scalar(
|
||||
&challenge_bytes,
|
||||
DivisibleEcashError::Deserialization("Failed to deserialize challenge".to_string()),
|
||||
)?;
|
||||
|
||||
let response_r_bytes = bytes[FIELD_SIZE..FIELD_SIZE * 2].try_into().unwrap();
|
||||
let response_r = try_deserialize_scalar(
|
||||
&response_r_bytes,
|
||||
DivisibleEcashError::Deserialization("Failed to deserialize response_r".to_string()),
|
||||
)?;
|
||||
|
||||
let response_r_sk_u_bytes = bytes[FIELD_SIZE * 2..FIELD_SIZE * 3].try_into().unwrap();
|
||||
let response_r_sk_u = try_deserialize_scalar(
|
||||
&response_r_sk_u_bytes,
|
||||
DivisibleEcashError::Deserialization("Failed to deserialize response_r_sk_u".to_string()),
|
||||
)?;
|
||||
|
||||
let response_r_v_bytes = bytes[FIELD_SIZE * 3..FIELD_SIZE * 4].try_into().unwrap();
|
||||
let response_r_v = try_deserialize_scalar(
|
||||
&response_r_v_bytes,
|
||||
DivisibleEcashError::Deserialization("Failed to deserialize response_r_v".to_string()),
|
||||
)?;
|
||||
|
||||
let response_r_r_bytes = bytes[FIELD_SIZE * 4..FIELD_SIZE * 5].try_into().unwrap();
|
||||
let response_r_r = try_deserialize_scalar(
|
||||
&response_r_r_bytes,
|
||||
DivisibleEcashError::Deserialization("Failed to deserialize response_r_r".to_string()),
|
||||
)?;
|
||||
|
||||
let response_r_r1_bytes = bytes[FIELD_SIZE * 5..FIELD_SIZE * 6].try_into().unwrap();
|
||||
let response_r_r1 = try_deserialize_scalar(
|
||||
&response_r_r1_bytes,
|
||||
DivisibleEcashError::Deserialization("Failed to deserialize response_r_r1".to_string()),
|
||||
)?;
|
||||
|
||||
let response_r_r2_bytes = bytes[FIELD_SIZE * 6..FIELD_SIZE * 7].try_into().unwrap();
|
||||
let response_r_r2 = try_deserialize_scalar(
|
||||
&response_r_r2_bytes,
|
||||
DivisibleEcashError::Deserialization("Failed to deserialize response_r_r2".to_string()),
|
||||
)?;
|
||||
|
||||
let response_r_varsig1_bytes = bytes[FIELD_SIZE * 7..FIELD_SIZE * 8].try_into().unwrap();
|
||||
let response_r_varsig1 = try_deserialize_scalar(
|
||||
response_r_varsig1_bytes,
|
||||
DivisibleEcashError::Deserialization("Failed to deserialize response_r_varsig1".to_string()),
|
||||
)?;
|
||||
|
||||
let response_r_theta1_bytes = bytes[FIELD_SIZE * 8..FIELD_SIZE * 9].try_into().unwrap();
|
||||
let response_r_theta1 = try_deserialize_scalar(
|
||||
&response_r_theta1_bytes,
|
||||
DivisibleEcashError::Deserialization("Failed to deserialize response_r_theta1".to_string()),
|
||||
)?;
|
||||
|
||||
let response_r_varsig2_bytes = bytes[FIELD_SIZE * 9..FIELD_SIZE * 10].try_into().unwrap();
|
||||
let response_r_varsig2 = try_deserialize_scalar(
|
||||
&response_r_varsig2_bytes,
|
||||
DivisibleEcashError::Deserialization("Failed to deserialize response_r_varsig2".to_string()),
|
||||
)?;
|
||||
|
||||
let response_r_theta2_bytes = bytes[FIELD_SIZE * 10..FIELD_SIZE * 11].try_into().unwrap();
|
||||
let response_r_theta2 = try_deserialize_scalar(
|
||||
&response_r_theta2_bytes,
|
||||
DivisibleEcashError::Deserialization("Failed to deserialize response_r_theta2".to_string()),
|
||||
)?;
|
||||
|
||||
let response_r_rr_bytes = bytes[FIELD_SIZE * 11..FIELD_SIZE * 12].try_into().unwrap();
|
||||
let response_r_rr = try_deserialize_scalar(
|
||||
&response_r_rr_bytes,
|
||||
DivisibleEcashError::Deserialization("Failed to deserialize response_r_rr".to_string()),
|
||||
)?;
|
||||
|
||||
let response_r_ss_bytes = bytes[FIELD_SIZE * 12..FIELD_SIZE * 13].try_into().unwrap();
|
||||
let response_r_ss = try_deserialize_scalar(
|
||||
&response_r_ss_bytes,
|
||||
DivisibleEcashError::Deserialization("Failed to deserialize response_r_ss".to_string()),
|
||||
)?;
|
||||
|
||||
let response_r_tt_bytes = bytes[FIELD_SIZE * 13..FIELD_SIZE * 14].try_into().unwrap();
|
||||
let response_r_tt = try_deserialize_scalar(
|
||||
&response_r_tt_bytes,
|
||||
DivisibleEcashError::Deserialization("Failed to deserialize response_r_tt".to_string()),
|
||||
)?;
|
||||
|
||||
let response_r_rho1_bytes = bytes[FIELD_SIZE * 14..FIELD_SIZE * 15].try_into().unwrap();
|
||||
let response_r_rho1 = try_deserialize_scalar(
|
||||
&response_r_rho1_bytes,
|
||||
DivisibleEcashError::Deserialization("Failed to deserialize response_r_rho1".to_string()),
|
||||
)?;
|
||||
|
||||
let response_r_rho2_bytes = bytes[FIELD_SIZE * 15..FIELD_SIZE * 16].try_into().unwrap();
|
||||
let response_r_rho2 = try_deserialize_scalar(
|
||||
&response_r_rho2_bytes,
|
||||
DivisibleEcashError::Deserialization("Failed to deserialize response_r_rho2".to_string()),
|
||||
)?;
|
||||
|
||||
let response_r_rho3_bytes = bytes[FIELD_SIZE * 16..FIELD_SIZE * 17].try_into().unwrap();
|
||||
let response_r_rho3 = try_deserialize_scalar(
|
||||
&response_r_rho3_bytes,
|
||||
DivisibleEcashError::Deserialization("Failed to deserialize response_r_rho3".to_string()),
|
||||
)?;
|
||||
|
||||
Ok(SpendProof {
|
||||
challenge,
|
||||
response_r,
|
||||
response_r_sk_u,
|
||||
response_r_v,
|
||||
response_r_r,
|
||||
response_r_r1,
|
||||
response_r_r2,
|
||||
response_r_varsig1,
|
||||
response_r_theta1,
|
||||
response_r_varsig2,
|
||||
response_r_theta2,
|
||||
response_r_rr,
|
||||
response_r_ss,
|
||||
response_r_tt,
|
||||
response_r_rho1,
|
||||
response_r_rho2,
|
||||
response_r_rho3,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::ops::Neg;
|
||||
@@ -439,7 +600,13 @@ mod tests {
|
||||
|
||||
// compute the zk proof
|
||||
let zk_proof = SpendProof::construct(¶ms, &instance, &witness, &verification_key, vv);
|
||||
assert!(zk_proof.verify(¶ms, &instance, &verification_key, vv))
|
||||
assert!(zk_proof.verify(¶ms, &instance, &verification_key, vv));
|
||||
|
||||
// do a to and from bytes check
|
||||
let zk_proof_bytes = zk_proof.to_bytes();
|
||||
let zk_proof2 = SpendProof::try_from(&zk_proof_bytes[..]).unwrap();
|
||||
assert_eq!(zk_proof, zk_proof2);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ use crate::error::{DivisibleEcashError, Result};
|
||||
use crate::proofs::proof_spend::{SpendInstance, SpendProof, SpendWitness};
|
||||
use crate::scheme::keygen::{SecretKeyUser, VerificationKeyAuth};
|
||||
use crate::scheme::setup::{GroupParameters, Parameters};
|
||||
use crate::utils::{check_bilinear_pairing, hash_to_scalar, Signature, SignerIndex, try_deserialize_g1_projective};
|
||||
use crate::utils::{check_bilinear_pairing, hash_to_scalar, Signature, SignerIndex, try_deserialize_g1_projective, try_deserialize_scalar, try_deserialize_g2_projective};
|
||||
|
||||
pub mod aggregation;
|
||||
pub mod keygen;
|
||||
@@ -116,7 +116,7 @@ pub struct PayInfo {
|
||||
pub info: [u8; 32],
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct Payment {
|
||||
pub kappa: G2Projective,
|
||||
pub sig: Signature,
|
||||
@@ -149,6 +149,152 @@ impl Payment {
|
||||
pub fn get_rr(&self) -> Scalar { self.rr }
|
||||
pub fn get_zk_proof(&self) -> SpendProof { self.zk_proof.clone() }
|
||||
pub fn get_vv(&self) -> u64 { self.vv }
|
||||
pub fn to_bytes(&self) -> Vec<u8>{
|
||||
let kappa_bytes = self.kappa.to_affine().to_compressed();
|
||||
let sig_bytes = self.sig.to_bytes();
|
||||
let phi_bytes = self.phi.to_bytes();
|
||||
let varphi_bytes = self.varphi.to_bytes();
|
||||
let varsig_prime1_bytes = self.varsig_prime1.to_affine().to_compressed();
|
||||
let varsig_prime2_bytes = self.varsig_prime2.to_affine().to_compressed();
|
||||
let theta_prime1_bytes = self.theta_prime1.to_affine().to_compressed();
|
||||
let theta_prime2 = self.theta_prime2.to_affine().to_compressed();
|
||||
let rr_prime_bytes = self.rr_prime.to_affine().to_compressed();
|
||||
let ss_prime_bytes = self.ss_prime.to_affine().to_compressed();
|
||||
let tt_prime_bytes = self.tt_prime.to_affine().to_compressed();
|
||||
let rr_bytes = self.rr.to_bytes();
|
||||
let zk_proof_bytes = self.zk_proof.to_bytes();
|
||||
let vv_bytes = self.vv.to_le_bytes();
|
||||
|
||||
let mut bytes: Vec<u8> = Vec::with_capacity(760);
|
||||
bytes.extend_from_slice(&kappa_bytes);
|
||||
bytes.extend_from_slice(&sig_bytes);
|
||||
bytes.extend_from_slice(&phi_bytes);
|
||||
bytes.extend_from_slice(&varphi_bytes);
|
||||
bytes.extend_from_slice(&varsig_prime1_bytes);
|
||||
bytes.extend_from_slice(&varsig_prime2_bytes);
|
||||
bytes.extend_from_slice(&theta_prime1_bytes);
|
||||
bytes.extend_from_slice(&theta_prime2);
|
||||
bytes.extend_from_slice(&rr_prime_bytes);
|
||||
bytes.extend_from_slice(&ss_prime_bytes);
|
||||
bytes.extend_from_slice(&tt_prime_bytes);
|
||||
bytes.extend_from_slice(&rr_bytes);
|
||||
bytes.extend_from_slice(&vv_bytes);
|
||||
bytes.extend_from_slice(&zk_proof_bytes);
|
||||
|
||||
bytes
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&[u8]> for Payment {
|
||||
type Error = DivisibleEcashError;
|
||||
|
||||
fn try_from(bytes: &[u8]) -> Result<Self> {
|
||||
if bytes.len() < 760 {
|
||||
return Err(DivisibleEcashError::Deserialization(
|
||||
"Invalid byte array for Payment deserialization".to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
let mut idx = 0;
|
||||
let kappa_bytes: [u8; 96] = bytes[idx..idx+96].try_into().unwrap();
|
||||
let kappa = try_deserialize_g2_projective(
|
||||
&kappa_bytes,
|
||||
DivisibleEcashError::Deserialization("Failed to deserialize kappa".to_string()),
|
||||
)?;
|
||||
idx += 96;
|
||||
|
||||
let sig_bytes: [u8; 96] = bytes[idx..idx+96].try_into().unwrap();
|
||||
let sig = Signature::try_from(sig_bytes.as_slice())?;
|
||||
idx += 96;
|
||||
|
||||
let phi_bytes: [u8; 96] = bytes[idx..idx+96].try_into().unwrap();
|
||||
let phi = Phi::from_bytes(&phi_bytes).unwrap();
|
||||
idx += 96;
|
||||
|
||||
let varphi_bytes: [u8; 96] = bytes[idx..idx+96].try_into().unwrap();
|
||||
let varphi = VarPhi::from_bytes(&varphi_bytes).unwrap();
|
||||
idx += 96;
|
||||
|
||||
let varsig_prime1_bytes: [u8; 48] = bytes[idx..idx+48].try_into().unwrap();
|
||||
let varsig_prime1 = try_deserialize_g1_projective(
|
||||
&varsig_prime1_bytes,
|
||||
DivisibleEcashError::Deserialization("Failed to deserialize varsig_prime1".to_string()),
|
||||
)?;
|
||||
idx += 48;
|
||||
|
||||
let varsig_prime2_bytes: [u8; 48] = bytes[idx..idx+48].try_into().unwrap();
|
||||
let varsig_prime2 = try_deserialize_g1_projective(
|
||||
&varsig_prime2_bytes,
|
||||
DivisibleEcashError::Deserialization("Failed to deserialize varsig_prime2".to_string()),
|
||||
)?;
|
||||
idx += 48;
|
||||
|
||||
let theta_prime1_bytes: [u8; 48] = bytes[idx..idx+48].try_into().unwrap();
|
||||
let theta_prime1 = try_deserialize_g1_projective(
|
||||
&theta_prime1_bytes,
|
||||
DivisibleEcashError::Deserialization("Failed to deserialize theta_prime1".to_string()),
|
||||
)?;
|
||||
idx += 48;
|
||||
|
||||
let theta_prime2_bytes: [u8; 48] = bytes[idx..idx+48].try_into().unwrap();
|
||||
let theta_prime2 = try_deserialize_g1_projective(
|
||||
&theta_prime2_bytes,
|
||||
DivisibleEcashError::Deserialization("Failed to deserialize theta_prime2".to_string()),
|
||||
)?;
|
||||
idx += 48;
|
||||
|
||||
let rr_prime_bytes: [u8; 48] = bytes[idx..idx+48].try_into().unwrap();
|
||||
let rr_prime = try_deserialize_g1_projective(
|
||||
&rr_prime_bytes,
|
||||
DivisibleEcashError::Deserialization("Failed to deserialize rr_prime".to_string()),
|
||||
)?;
|
||||
idx += 48;
|
||||
|
||||
let ss_prime_bytes: [u8; 48] = bytes[idx..idx+48].try_into().unwrap();
|
||||
let ss_prime = try_deserialize_g1_projective(
|
||||
&ss_prime_bytes,
|
||||
DivisibleEcashError::Deserialization("Failed to deserialize ss_prime".to_string()),
|
||||
)?;
|
||||
idx += 48;
|
||||
|
||||
let tt_prime_bytes: [u8; 96] = bytes[idx..idx+96].try_into().unwrap();
|
||||
let tt_prime = try_deserialize_g2_projective(
|
||||
&tt_prime_bytes,
|
||||
DivisibleEcashError::Deserialization("Failed to deserialize tt_prime".to_string()),
|
||||
)?;
|
||||
idx += 96;
|
||||
|
||||
let rr_bytes: [u8; 32] = bytes[idx..idx+32].try_into().unwrap();
|
||||
let rr = try_deserialize_scalar(
|
||||
&rr_bytes,
|
||||
DivisibleEcashError::Deserialization("Failed to deserialize rr element".to_string()),
|
||||
)?;
|
||||
idx += 32;
|
||||
|
||||
let vv = u64::from_le_bytes(bytes[idx..idx+8].try_into().unwrap());
|
||||
idx += 8;
|
||||
|
||||
// Deserialize the SpendProof struct
|
||||
let zk_proof_bytes = &bytes[idx..];
|
||||
let zk_proof = SpendProof::try_from(zk_proof_bytes)?;
|
||||
|
||||
Ok(Payment{
|
||||
kappa,
|
||||
sig,
|
||||
phi,
|
||||
varphi,
|
||||
varsig_prime1,
|
||||
varsig_prime2,
|
||||
theta_prime1,
|
||||
theta_prime2,
|
||||
rr_prime,
|
||||
ss_prime,
|
||||
tt_prime,
|
||||
rr,
|
||||
zk_proof,
|
||||
vv,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PartialWallet {
|
||||
|
||||
@@ -55,6 +55,9 @@ fn main() -> Result<(), DivisibleEcashError> {
|
||||
|
||||
// SPEND VERIFICATION
|
||||
assert!(payment.spend_verify(¶ms, &verification_key, &pay_info).unwrap());
|
||||
let payment_bytes = payment.to_bytes();
|
||||
let payment2 = Payment::try_from(&payment_bytes[..]).unwrap();
|
||||
assert_eq!(payment, payment2);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -206,8 +206,7 @@ pub fn check_bilinear_pairing(p: &G1Affine, q: &G2Prepared, r: &G1Affine, s: &G2
|
||||
|
||||
pub type SignerIndex = u64;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[cfg_attr(test, derive(PartialEq))]
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub struct Signature(pub(crate) G1Projective, pub(crate) G1Projective);
|
||||
|
||||
pub type PartialSignature = Signature;
|
||||
|
||||
Reference in New Issue
Block a user