Skip to content

Commit 3a73ac3

Browse files
committed
migrate range proof pod types
1 parent d1faaf6 commit 3a73ac3

File tree

8 files changed

+241
-92
lines changed

8 files changed

+241
-92
lines changed

zk-sdk-pod/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
pub mod encryption;
22
pub mod errors;
33
pub mod macros;
4+
pub mod range_proof;
45
pub mod sigma_proofs;
56

67
/// Byte length of a compressed Ristretto point or scalar in Curve255519

zk-sdk-pod/src/range_proof.rs

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
//! Plain Old Data types for range proofs.
2+
3+
use {
4+
crate::{
5+
macros::{impl_from_bytes, impl_from_str},
6+
RISTRETTO_POINT_LEN, SCALAR_LEN,
7+
},
8+
base64::{prelude::BASE64_STANDARD, Engine},
9+
bytemuck::{Pod, Zeroable},
10+
std::fmt,
11+
};
12+
13+
/// Byte length of a range proof excluding the inner-product proof component
14+
pub const RANGE_PROOF_MODULO_INNER_PRODUCT_PROOF_LEN: usize =
15+
5 * RISTRETTO_POINT_LEN + 2 * SCALAR_LEN;
16+
17+
/// Byte length of an inner-product proof for a vector of length 64
18+
pub const INNER_PRODUCT_PROOF_U64_LEN: usize = 448;
19+
20+
/// Byte length of a range proof for an unsigned 64-bit number
21+
pub const RANGE_PROOF_U64_LEN: usize =
22+
INNER_PRODUCT_PROOF_U64_LEN + RANGE_PROOF_MODULO_INNER_PRODUCT_PROOF_LEN; // 672 bytes
23+
24+
/// Byte length of an inner-product proof for a vector of length 128
25+
pub const INNER_PRODUCT_PROOF_U128_LEN: usize = 512;
26+
27+
/// Byte length of a range proof for an unsigned 128-bit number
28+
pub const RANGE_PROOF_U128_LEN: usize =
29+
INNER_PRODUCT_PROOF_U128_LEN + RANGE_PROOF_MODULO_INNER_PRODUCT_PROOF_LEN; // 736 bytes
30+
31+
/// Byte length of an inner-product proof for a vector of length 256
32+
pub const INNER_PRODUCT_PROOF_U256_LEN: usize = 576;
33+
34+
/// Byte length of a range proof for an unsigned 256-bit number
35+
pub const RANGE_PROOF_U256_LEN: usize =
36+
INNER_PRODUCT_PROOF_U256_LEN + RANGE_PROOF_MODULO_INNER_PRODUCT_PROOF_LEN; // 800 bytes
37+
38+
/// The `RangeProof` type as a `Pod` restricted to proofs on 64-bit numbers.
39+
#[derive(Clone, Copy)]
40+
#[repr(transparent)]
41+
pub struct PodRangeProofU64(pub [u8; RANGE_PROOF_U64_LEN]);
42+
43+
const RANGE_PROOF_U64_MAX_BASE64_LEN: usize = 896;
44+
45+
impl fmt::Display for PodRangeProofU64 {
46+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
47+
write!(f, "{}", BASE64_STANDARD.encode(self.0))
48+
}
49+
}
50+
51+
impl_from_str!(
52+
TYPE = PodRangeProofU64,
53+
BYTES_LEN = RANGE_PROOF_U64_LEN,
54+
BASE64_LEN = RANGE_PROOF_U64_MAX_BASE64_LEN
55+
);
56+
57+
impl_from_bytes!(TYPE = PodRangeProofU64, BYTES_LEN = RANGE_PROOF_U64_LEN);
58+
59+
/// The `RangeProof` type as a `Pod` restricted to proofs on 128-bit numbers.
60+
#[derive(Clone, Copy)]
61+
#[repr(transparent)]
62+
pub struct PodRangeProofU128(pub [u8; RANGE_PROOF_U128_LEN]);
63+
64+
const RANGE_PROOF_U128_MAX_BASE64_LEN: usize = 984;
65+
66+
impl fmt::Display for PodRangeProofU128 {
67+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
68+
write!(f, "{}", BASE64_STANDARD.encode(self.0))
69+
}
70+
}
71+
72+
impl_from_str!(
73+
TYPE = PodRangeProofU128,
74+
BYTES_LEN = RANGE_PROOF_U128_LEN,
75+
BASE64_LEN = RANGE_PROOF_U128_MAX_BASE64_LEN
76+
);
77+
78+
impl_from_bytes!(TYPE = PodRangeProofU128, BYTES_LEN = RANGE_PROOF_U128_LEN);
79+
80+
/// The `RangeProof` type as a `Pod` restricted to proofs on 256-bit numbers.
81+
#[derive(Clone, Copy)]
82+
#[repr(transparent)]
83+
pub struct PodRangeProofU256(pub [u8; RANGE_PROOF_U256_LEN]);
84+
85+
const RANGE_PROOF_U256_MAX_BASE64_LEN: usize = 1068;
86+
87+
impl fmt::Display for PodRangeProofU256 {
88+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
89+
write!(f, "{}", BASE64_STANDARD.encode(self.0))
90+
}
91+
}
92+
93+
impl_from_str!(
94+
TYPE = PodRangeProofU256,
95+
BYTES_LEN = RANGE_PROOF_U256_LEN,
96+
BASE64_LEN = RANGE_PROOF_U256_MAX_BASE64_LEN
97+
);
98+
99+
impl_from_bytes!(TYPE = PodRangeProofU256, BYTES_LEN = RANGE_PROOF_U256_LEN);
100+
101+
// The range proof pod types are wrappers for byte arrays, which are both `Pod` and `Zeroable`. However,
102+
// the marker traits `bytemuck::Pod` and `bytemuck::Zeroable` can only be derived for power-of-two
103+
// length byte arrays. Directly implement these traits for the range proof pod types.
104+
unsafe impl Zeroable for PodRangeProofU64 {}
105+
unsafe impl Pod for PodRangeProofU64 {}
106+
107+
unsafe impl Zeroable for PodRangeProofU128 {}
108+
unsafe impl Pod for PodRangeProofU128 {}
109+
110+
unsafe impl Zeroable for PodRangeProofU256 {}
111+
unsafe impl Pod for PodRangeProofU256 {}

zk-sdk/src/pod.rs

Lines changed: 0 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -27,38 +27,3 @@ impl From<PodU64> for u64 {
2727
Self::from_le_bytes(pod.0)
2828
}
2929
}
30-
31-
macro_rules! impl_from_str {
32-
(TYPE = $type:ident, BYTES_LEN = $bytes_len:expr, BASE64_LEN = $base64_len:expr) => {
33-
impl std::str::FromStr for $type {
34-
type Err = crate::errors::ParseError;
35-
36-
fn from_str(s: &str) -> Result<Self, Self::Err> {
37-
if s.len() > $base64_len {
38-
return Err(Self::Err::WrongSize);
39-
}
40-
let mut bytes = [0u8; $bytes_len];
41-
let decoded_len = BASE64_STANDARD
42-
.decode_slice(s, &mut bytes)
43-
.map_err(|_| Self::Err::Invalid)?;
44-
if decoded_len != $bytes_len {
45-
Err(Self::Err::WrongSize)
46-
} else {
47-
Ok($type(bytes))
48-
}
49-
}
50-
}
51-
};
52-
}
53-
pub(crate) use impl_from_str;
54-
55-
macro_rules! impl_from_bytes {
56-
(TYPE = $type:ident, BYTES_LEN = $bytes_len:expr) => {
57-
impl std::convert::From<[u8; $bytes_len]> for $type {
58-
fn from(bytes: [u8; $bytes_len]) -> Self {
59-
Self(bytes)
60-
}
61-
}
62-
};
63-
}
64-
pub(crate) use impl_from_bytes;

zk-sdk/src/range_proof/mod.rs

Lines changed: 104 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
1515
#![allow(dead_code)]
1616

17-
use crate::{RISTRETTO_POINT_LEN, SCALAR_LEN};
1817
#[cfg(not(target_os = "solana"))]
1918
use {
2019
crate::{
@@ -25,6 +24,7 @@ use {
2524
inner_product::InnerProductProof,
2625
},
2726
transcript::TranscriptProtocol,
27+
UNIT_LEN,
2828
},
2929
core::iter,
3030
curve25519_dalek::traits::MultiscalarMul,
@@ -35,44 +35,24 @@ use {
3535
},
3636
merlin::Transcript,
3737
rand::rngs::OsRng,
38+
solana_zk_sdk_pod::range_proof::{PodRangeProofU128, PodRangeProofU256, PodRangeProofU64},
3839
subtle::{Choice, ConditionallySelectable},
3940
zeroize::Zeroize,
4041
};
4142

4243
pub mod errors;
43-
pub mod pod;
44-
4544
#[cfg(not(target_os = "solana"))]
4645
pub mod generators;
4746
#[cfg(not(target_os = "solana"))]
4847
pub mod inner_product;
4948
#[cfg(not(target_os = "solana"))]
5049
pub mod util;
5150

52-
/// Byte length of a range proof excluding the inner-product proof component
53-
pub const RANGE_PROOF_MODULO_INNER_PRODUCT_PROOF_LEN: usize =
54-
5 * RISTRETTO_POINT_LEN + 2 * SCALAR_LEN;
55-
56-
/// Byte length of an inner-product proof for a vector of length 64
57-
pub const INNER_PRODUCT_PROOF_U64_LEN: usize = 448;
58-
59-
/// Byte length of a range proof for an unsigned 64-bit number
60-
pub const RANGE_PROOF_U64_LEN: usize =
61-
INNER_PRODUCT_PROOF_U64_LEN + RANGE_PROOF_MODULO_INNER_PRODUCT_PROOF_LEN; // 672 bytes
62-
63-
/// Byte length of an inner-product proof for a vector of length 128
64-
pub const INNER_PRODUCT_PROOF_U128_LEN: usize = 512;
65-
66-
/// Byte length of a range proof for an unsigned 128-bit number
67-
pub const RANGE_PROOF_U128_LEN: usize =
68-
INNER_PRODUCT_PROOF_U128_LEN + RANGE_PROOF_MODULO_INNER_PRODUCT_PROOF_LEN; // 736 bytes
69-
70-
/// Byte length of an inner-product proof for a vector of length 256
71-
pub const INNER_PRODUCT_PROOF_U256_LEN: usize = 576;
72-
73-
/// Byte length of a range proof for an unsigned 256-bit number
74-
pub const RANGE_PROOF_U256_LEN: usize =
75-
INNER_PRODUCT_PROOF_U256_LEN + RANGE_PROOF_MODULO_INNER_PRODUCT_PROOF_LEN; // 800 bytes
51+
pub use solana_zk_sdk_pod::range_proof::{
52+
INNER_PRODUCT_PROOF_U128_LEN, INNER_PRODUCT_PROOF_U256_LEN, INNER_PRODUCT_PROOF_U64_LEN,
53+
RANGE_PROOF_MODULO_INNER_PRODUCT_PROOF_LEN, RANGE_PROOF_U128_LEN, RANGE_PROOF_U256_LEN,
54+
RANGE_PROOF_U64_LEN,
55+
};
7656

7757
/// A Bulletproofs range proof.
7858
#[allow(non_snake_case)]
@@ -491,6 +471,102 @@ impl RangeProof {
491471
}
492472
}
493473

474+
#[cfg(not(target_os = "solana"))]
475+
impl TryFrom<PodRangeProofU64> for RangeProof {
476+
type Error = RangeProofVerificationError;
477+
478+
fn try_from(pod_proof: PodRangeProofU64) -> Result<Self, Self::Error> {
479+
Self::from_bytes(&pod_proof.0)
480+
}
481+
}
482+
483+
#[cfg(not(target_os = "solana"))]
484+
impl TryFrom<RangeProof> for PodRangeProofU64 {
485+
type Error = RangeProofVerificationError;
486+
487+
fn try_from(decoded_proof: RangeProof) -> Result<Self, Self::Error> {
488+
if decoded_proof.ipp_proof.serialized_size() != INNER_PRODUCT_PROOF_U64_LEN {
489+
return Err(RangeProofVerificationError::Deserialization);
490+
}
491+
492+
let mut buf = [0_u8; RANGE_PROOF_U64_LEN];
493+
copy_range_proof_modulo_inner_product_proof(&decoded_proof, &mut buf);
494+
buf[RANGE_PROOF_MODULO_INNER_PRODUCT_PROOF_LEN..RANGE_PROOF_U64_LEN]
495+
.copy_from_slice(&decoded_proof.ipp_proof.to_bytes());
496+
Ok(PodRangeProofU64(buf))
497+
}
498+
}
499+
500+
#[cfg(not(target_os = "solana"))]
501+
impl TryFrom<PodRangeProofU128> for RangeProof {
502+
type Error = RangeProofVerificationError;
503+
504+
fn try_from(pod_proof: PodRangeProofU128) -> Result<Self, Self::Error> {
505+
Self::from_bytes(&pod_proof.0)
506+
}
507+
}
508+
509+
#[cfg(not(target_os = "solana"))]
510+
impl TryFrom<RangeProof> for PodRangeProofU128 {
511+
type Error = RangeProofVerificationError;
512+
513+
fn try_from(decoded_proof: RangeProof) -> Result<Self, Self::Error> {
514+
if decoded_proof.ipp_proof.serialized_size() != INNER_PRODUCT_PROOF_U128_LEN {
515+
return Err(RangeProofVerificationError::Deserialization);
516+
}
517+
518+
let mut buf = [0_u8; RANGE_PROOF_U128_LEN];
519+
copy_range_proof_modulo_inner_product_proof(&decoded_proof, &mut buf);
520+
buf[RANGE_PROOF_MODULO_INNER_PRODUCT_PROOF_LEN..RANGE_PROOF_U128_LEN]
521+
.copy_from_slice(&decoded_proof.ipp_proof.to_bytes());
522+
Ok(PodRangeProofU128(buf))
523+
}
524+
}
525+
526+
#[cfg(not(target_os = "solana"))]
527+
impl TryFrom<PodRangeProofU256> for RangeProof {
528+
type Error = RangeProofVerificationError;
529+
530+
fn try_from(pod_proof: PodRangeProofU256) -> Result<Self, Self::Error> {
531+
Self::from_bytes(&pod_proof.0)
532+
}
533+
}
534+
535+
#[cfg(not(target_os = "solana"))]
536+
impl TryFrom<RangeProof> for PodRangeProofU256 {
537+
type Error = RangeProofVerificationError;
538+
539+
fn try_from(decoded_proof: RangeProof) -> Result<Self, Self::Error> {
540+
if decoded_proof.ipp_proof.serialized_size() != INNER_PRODUCT_PROOF_U256_LEN {
541+
return Err(RangeProofVerificationError::Deserialization);
542+
}
543+
544+
let mut buf = [0_u8; RANGE_PROOF_U256_LEN];
545+
copy_range_proof_modulo_inner_product_proof(&decoded_proof, &mut buf);
546+
buf[RANGE_PROOF_MODULO_INNER_PRODUCT_PROOF_LEN..RANGE_PROOF_U256_LEN]
547+
.copy_from_slice(&decoded_proof.ipp_proof.to_bytes());
548+
Ok(PodRangeProofU256(buf))
549+
}
550+
}
551+
552+
#[cfg(not(target_os = "solana"))]
553+
fn copy_range_proof_modulo_inner_product_proof(proof: &RangeProof, buf: &mut [u8]) {
554+
let mut chunks = buf.chunks_mut(UNIT_LEN);
555+
chunks.next().unwrap().copy_from_slice(proof.A.as_bytes());
556+
chunks.next().unwrap().copy_from_slice(proof.S.as_bytes());
557+
chunks.next().unwrap().copy_from_slice(proof.T_1.as_bytes());
558+
chunks.next().unwrap().copy_from_slice(proof.T_2.as_bytes());
559+
chunks.next().unwrap().copy_from_slice(proof.t_x.as_bytes());
560+
chunks
561+
.next()
562+
.unwrap()
563+
.copy_from_slice(proof.t_x_blinding.as_bytes());
564+
chunks
565+
.next()
566+
.unwrap()
567+
.copy_from_slice(proof.e_blinding.as_bytes());
568+
}
569+
494570
/// Computes the `delta(y,z)` term for the verification equation.
495571
///
496572
/// This term is a function of the challenges `y` and `z` and the proof dimensions.
@@ -514,8 +590,7 @@ fn delta(bit_lengths: &[usize], y: &Scalar, z: &Scalar) -> Scalar {
514590
#[cfg(test)]
515591
mod tests {
516592
use {
517-
super::*, crate::range_proof::pod::PodRangeProofU128,
518-
solana_zk_sdk_pod::encryption::pedersen::PodPedersenCommitment, std::str::FromStr,
593+
super::*, solana_zk_sdk_pod::encryption::pedersen::PodPedersenCommitment, std::str::FromStr,
519594
};
520595

521596
#[test]

zk-sdk/src/sigma_proofs/mod.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,10 @@ pub use solana_zk_sdk_pod::sigma_proofs::{
3535

3636
#[cfg(not(target_os = "solana"))]
3737
use {
38-
crate::{sigma_proofs::errors::SigmaProofVerificationError, RISTRETTO_POINT_LEN, SCALAR_LEN},
38+
crate::{
39+
sigma_proofs::errors::SigmaProofVerificationError, RISTRETTO_POINT_LEN, SCALAR_LEN,
40+
UNIT_LEN,
41+
},
3942
curve25519_dalek::{ristretto::CompressedRistretto, scalar::Scalar},
4043
};
4144

zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u128.rs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
//! The 128-bit batched range proof instruction.
22
3+
use {
4+
crate::zk_elgamal_proof_program::proof_data::{
5+
batched_range_proof::BatchedRangeProofContext, ProofType, ZkProofData,
6+
},
7+
bytemuck_derive::{Pod, Zeroable},
8+
solana_zk_sdk_pod::range_proof::PodRangeProofU128,
9+
};
310
#[cfg(not(target_os = "solana"))]
411
use {
512
crate::{
@@ -12,15 +19,6 @@ use {
1219
},
1320
std::convert::TryInto,
1421
};
15-
use {
16-
crate::{
17-
range_proof::pod::PodRangeProofU128,
18-
zk_elgamal_proof_program::proof_data::{
19-
batched_range_proof::BatchedRangeProofContext, ProofType, ZkProofData,
20-
},
21-
},
22-
bytemuck_derive::{Pod, Zeroable},
23-
};
2422

2523
/// The instruction data that is needed for the
2624
/// `ProofInstruction::VerifyBatchedRangeProofU128` instruction.

0 commit comments

Comments
 (0)