pod.rs 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. //! Plain Old Data types for range proofs.
  2. #[cfg(not(target_os = "solana"))]
  3. use crate::{
  4. range_proof::{errors::RangeProofVerificationError, RangeProof},
  5. UNIT_LEN,
  6. };
  7. use {
  8. crate::{
  9. pod::{impl_from_bytes, impl_from_str},
  10. range_proof::*,
  11. },
  12. base64::{prelude::BASE64_STANDARD, Engine},
  13. bytemuck::{Pod, Zeroable},
  14. std::fmt,
  15. };
  16. /// The `RangeProof` type as a `Pod` restricted to proofs on 64-bit numbers.
  17. #[derive(Clone, Copy)]
  18. #[repr(transparent)]
  19. pub struct PodRangeProofU64(pub(crate) [u8; RANGE_PROOF_U64_LEN]);
  20. #[cfg(not(target_os = "solana"))]
  21. impl TryFrom<RangeProof> for PodRangeProofU64 {
  22. type Error = RangeProofVerificationError;
  23. fn try_from(decoded_proof: RangeProof) -> Result<Self, Self::Error> {
  24. if decoded_proof.ipp_proof.serialized_size() != INNER_PRODUCT_PROOF_U64_LEN {
  25. return Err(RangeProofVerificationError::Deserialization);
  26. }
  27. let mut buf = [0_u8; RANGE_PROOF_U64_LEN];
  28. copy_range_proof_modulo_inner_product_proof(&decoded_proof, &mut buf);
  29. buf[RANGE_PROOF_MODULO_INNER_PRODUCT_PROOF_LEN..RANGE_PROOF_U64_LEN]
  30. .copy_from_slice(&decoded_proof.ipp_proof.to_bytes());
  31. Ok(PodRangeProofU64(buf))
  32. }
  33. }
  34. #[cfg(not(target_os = "solana"))]
  35. impl TryFrom<PodRangeProofU64> for RangeProof {
  36. type Error = RangeProofVerificationError;
  37. fn try_from(pod_proof: PodRangeProofU64) -> Result<Self, Self::Error> {
  38. Self::from_bytes(&pod_proof.0)
  39. }
  40. }
  41. const RANGE_PROOF_U64_MAX_BASE64_LEN: usize = 896;
  42. impl fmt::Display for PodRangeProofU64 {
  43. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  44. write!(f, "{}", BASE64_STANDARD.encode(self.0))
  45. }
  46. }
  47. impl_from_str!(
  48. TYPE = PodRangeProofU64,
  49. BYTES_LEN = RANGE_PROOF_U64_LEN,
  50. BASE64_LEN = RANGE_PROOF_U64_MAX_BASE64_LEN
  51. );
  52. impl_from_bytes!(TYPE = PodRangeProofU64, BYTES_LEN = RANGE_PROOF_U64_LEN);
  53. /// The `RangeProof` type as a `Pod` restricted to proofs on 128-bit numbers.
  54. #[derive(Clone, Copy)]
  55. #[repr(transparent)]
  56. pub struct PodRangeProofU128(pub(crate) [u8; RANGE_PROOF_U128_LEN]);
  57. #[cfg(not(target_os = "solana"))]
  58. impl TryFrom<RangeProof> for PodRangeProofU128 {
  59. type Error = RangeProofVerificationError;
  60. fn try_from(decoded_proof: RangeProof) -> Result<Self, Self::Error> {
  61. if decoded_proof.ipp_proof.serialized_size() != INNER_PRODUCT_PROOF_U128_LEN {
  62. return Err(RangeProofVerificationError::Deserialization);
  63. }
  64. let mut buf = [0_u8; RANGE_PROOF_U128_LEN];
  65. copy_range_proof_modulo_inner_product_proof(&decoded_proof, &mut buf);
  66. buf[RANGE_PROOF_MODULO_INNER_PRODUCT_PROOF_LEN..RANGE_PROOF_U128_LEN]
  67. .copy_from_slice(&decoded_proof.ipp_proof.to_bytes());
  68. Ok(PodRangeProofU128(buf))
  69. }
  70. }
  71. #[cfg(not(target_os = "solana"))]
  72. impl TryFrom<PodRangeProofU128> for RangeProof {
  73. type Error = RangeProofVerificationError;
  74. fn try_from(pod_proof: PodRangeProofU128) -> Result<Self, Self::Error> {
  75. Self::from_bytes(&pod_proof.0)
  76. }
  77. }
  78. const RANGE_PROOF_U128_MAX_BASE64_LEN: usize = 984;
  79. impl fmt::Display for PodRangeProofU128 {
  80. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  81. write!(f, "{}", BASE64_STANDARD.encode(self.0))
  82. }
  83. }
  84. impl_from_str!(
  85. TYPE = PodRangeProofU128,
  86. BYTES_LEN = RANGE_PROOF_U128_LEN,
  87. BASE64_LEN = RANGE_PROOF_U128_MAX_BASE64_LEN
  88. );
  89. impl_from_bytes!(TYPE = PodRangeProofU128, BYTES_LEN = RANGE_PROOF_U128_LEN);
  90. /// The `RangeProof` type as a `Pod` restricted to proofs on 256-bit numbers.
  91. #[derive(Clone, Copy)]
  92. #[repr(transparent)]
  93. pub struct PodRangeProofU256(pub(crate) [u8; RANGE_PROOF_U256_LEN]);
  94. #[cfg(not(target_os = "solana"))]
  95. impl TryFrom<RangeProof> for PodRangeProofU256 {
  96. type Error = RangeProofVerificationError;
  97. fn try_from(decoded_proof: RangeProof) -> Result<Self, Self::Error> {
  98. if decoded_proof.ipp_proof.serialized_size() != INNER_PRODUCT_PROOF_U256_LEN {
  99. return Err(RangeProofVerificationError::Deserialization);
  100. }
  101. let mut buf = [0_u8; RANGE_PROOF_U256_LEN];
  102. copy_range_proof_modulo_inner_product_proof(&decoded_proof, &mut buf);
  103. buf[RANGE_PROOF_MODULO_INNER_PRODUCT_PROOF_LEN..RANGE_PROOF_U256_LEN]
  104. .copy_from_slice(&decoded_proof.ipp_proof.to_bytes());
  105. Ok(PodRangeProofU256(buf))
  106. }
  107. }
  108. #[cfg(not(target_os = "solana"))]
  109. impl TryFrom<PodRangeProofU256> for RangeProof {
  110. type Error = RangeProofVerificationError;
  111. fn try_from(pod_proof: PodRangeProofU256) -> Result<Self, Self::Error> {
  112. Self::from_bytes(&pod_proof.0)
  113. }
  114. }
  115. const RANGE_PROOF_U256_MAX_BASE64_LEN: usize = 1068;
  116. impl fmt::Display for PodRangeProofU256 {
  117. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  118. write!(f, "{}", BASE64_STANDARD.encode(self.0))
  119. }
  120. }
  121. impl_from_str!(
  122. TYPE = PodRangeProofU256,
  123. BYTES_LEN = RANGE_PROOF_U256_LEN,
  124. BASE64_LEN = RANGE_PROOF_U256_MAX_BASE64_LEN
  125. );
  126. impl_from_bytes!(TYPE = PodRangeProofU256, BYTES_LEN = RANGE_PROOF_U256_LEN);
  127. #[cfg(not(target_os = "solana"))]
  128. fn copy_range_proof_modulo_inner_product_proof(proof: &RangeProof, buf: &mut [u8]) {
  129. let mut chunks = buf.chunks_mut(UNIT_LEN);
  130. chunks.next().unwrap().copy_from_slice(proof.A.as_bytes());
  131. chunks.next().unwrap().copy_from_slice(proof.S.as_bytes());
  132. chunks.next().unwrap().copy_from_slice(proof.T_1.as_bytes());
  133. chunks.next().unwrap().copy_from_slice(proof.T_2.as_bytes());
  134. chunks.next().unwrap().copy_from_slice(proof.t_x.as_bytes());
  135. chunks
  136. .next()
  137. .unwrap()
  138. .copy_from_slice(proof.t_x_blinding.as_bytes());
  139. chunks
  140. .next()
  141. .unwrap()
  142. .copy_from_slice(proof.e_blinding.as_bytes());
  143. }
  144. // The range proof pod types are wrappers for byte arrays, which are both `Pod` and `Zeroable`. However,
  145. // the marker traits `bytemuck::Pod` and `bytemuck::Zeroable` can only be derived for power-of-two
  146. // length byte arrays. Directly implement these traits for the range proof pod types.
  147. unsafe impl Zeroable for PodRangeProofU64 {}
  148. unsafe impl Pod for PodRangeProofU64 {}
  149. unsafe impl Zeroable for PodRangeProofU128 {}
  150. unsafe impl Pod for PodRangeProofU128 {}
  151. unsafe impl Zeroable for PodRangeProofU256 {}
  152. unsafe impl Pod for PodRangeProofU256 {}