sinsemilla.rs 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. //! Sinsemilla generators
  2. use super::OrchardFixedBases;
  3. //use crate::spec::i2lebsp;
  4. use halo2_gadgets::sinsemilla::{CommitDomains, HashDomains};
  5. use pasta_curves::{
  6. arithmetic::{CurveAffine, FieldExt},
  7. pallas,
  8. };
  9. /// Number of bits of each message piece in $\mathsf{SinsemillaHashToPoint}$
  10. pub const K: usize = 10;
  11. /// $\frac{1}{2^K}$
  12. pub const INV_TWO_POW_K: [u8; 32] = [
  13. 1, 0, 192, 196, 160, 229, 70, 82, 221, 165, 74, 202, 85, 7, 62, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  14. 0, 0, 0, 0, 0, 240, 63,
  15. ];
  16. /// The largest integer such that $2^c \leq (r_P - 1) / 2$, where $r_P$ is the order
  17. /// of Pallas.
  18. pub const C: usize = 253;
  19. /// SWU hash-to-curve personalization for the Merkle CRH generator
  20. pub const MERKLE_CRH_PERSONALIZATION: &str = "z.cash:Orchard-MerkleCRH";
  21. // Sinsemilla Q generators
  22. /// SWU hash-to-curve personalization for Sinsemilla $Q$ generators.
  23. pub const Q_PERSONALIZATION: &str = "z.cash:SinsemillaQ";
  24. // Sinsemilla S generators
  25. /// SWU hash-to-curve personalization for Sinsemilla $S$ generators.
  26. pub const S_PERSONALIZATION: &str = "z.cash:SinsemillaS";
  27. /// Generator used in SinsemillaHashToPoint for note commitment
  28. pub const Q_NOTE_COMMITMENT_M_GENERATOR: ([u8; 32], [u8; 32]) = (
  29. [
  30. 93, 116, 168, 64, 9, 186, 14, 50, 42, 221, 70, 253, 90, 15, 150, 197, 93, 237, 176, 121,
  31. 180, 242, 159, 247, 13, 205, 251, 86, 160, 7, 128, 23,
  32. ],
  33. [
  34. 99, 172, 73, 115, 90, 10, 39, 135, 158, 94, 219, 129, 136, 18, 34, 136, 44, 201, 244, 110,
  35. 217, 194, 190, 78, 131, 112, 198, 138, 147, 88, 160, 50,
  36. ],
  37. );
  38. /// Generator used in SinsemillaHashToPoint for IVK commitment
  39. pub const Q_COMMIT_IVK_M_GENERATOR: ([u8; 32], [u8; 32]) = (
  40. [
  41. 242, 130, 15, 121, 146, 47, 203, 107, 50, 162, 40, 81, 36, 204, 27, 66, 250, 65, 162, 90,
  42. 184, 129, 204, 125, 17, 200, 169, 74, 241, 12, 188, 5,
  43. ],
  44. [
  45. 190, 222, 173, 207, 206, 229, 90, 190, 241, 165, 109, 201, 29, 53, 196, 70, 75, 5, 222, 32,
  46. 70, 7, 89, 239, 230, 190, 26, 212, 246, 76, 1, 27,
  47. ],
  48. );
  49. /// Generator used in SinsemillaHashToPoint for Merkle collision-resistant hash
  50. pub const Q_MERKLE_CRH: ([u8; 32], [u8; 32]) = (
  51. [
  52. 160, 198, 41, 127, 249, 199, 185, 248, 112, 16, 141, 192, 85, 185, 190, 201, 153, 14, 137,
  53. 239, 90, 54, 15, 160, 185, 24, 168, 99, 150, 210, 22, 22,
  54. ],
  55. [
  56. 98, 234, 242, 37, 206, 174, 233, 134, 150, 21, 116, 5, 234, 150, 28, 226, 121, 89, 163, 79,
  57. 62, 242, 196, 45, 153, 32, 175, 227, 163, 66, 134, 53,
  58. ],
  59. );
  60. pub fn i2lebsp<const NUM_BITS: usize>(int: u64) -> [bool; NUM_BITS] {
  61. assert!(NUM_BITS <= 64);
  62. super::util::gen_const_array(|mask: usize| (int & (1 << mask)) != 0)
  63. }
  64. #[allow(dead_code)]
  65. fn lebs2ip_k(bits: &[bool]) -> u32 {
  66. assert!(bits.len() == K);
  67. bits.iter()
  68. .enumerate()
  69. .fold(0u32, |acc, (i, b)| acc + if *b { 1 << i } else { 0 })
  70. }
  71. /// The sequence of K bits in little-endian order representing an integer
  72. /// up to `2^K` - 1.
  73. pub fn i2lebsp_k(int: usize) -> [bool; K] {
  74. assert!(int < (1 << K));
  75. i2lebsp(int as u64)
  76. }
  77. #[derive(Clone, Debug, Eq, PartialEq)]
  78. pub enum OrchardHashDomains {
  79. NoteCommit,
  80. CommitIvk,
  81. MerkleCrh,
  82. }
  83. #[allow(non_snake_case)]
  84. impl HashDomains<pallas::Affine> for OrchardHashDomains {
  85. fn Q(&self) -> pallas::Affine {
  86. match self {
  87. OrchardHashDomains::CommitIvk => pallas::Affine::from_xy(
  88. pallas::Base::from_bytes(&Q_COMMIT_IVK_M_GENERATOR.0).unwrap(),
  89. pallas::Base::from_bytes(&Q_COMMIT_IVK_M_GENERATOR.1).unwrap(),
  90. )
  91. .unwrap(),
  92. OrchardHashDomains::NoteCommit => pallas::Affine::from_xy(
  93. pallas::Base::from_bytes(&Q_NOTE_COMMITMENT_M_GENERATOR.0).unwrap(),
  94. pallas::Base::from_bytes(&Q_NOTE_COMMITMENT_M_GENERATOR.1).unwrap(),
  95. )
  96. .unwrap(),
  97. OrchardHashDomains::MerkleCrh => pallas::Affine::from_xy(
  98. pallas::Base::from_bytes(&Q_MERKLE_CRH.0).unwrap(),
  99. pallas::Base::from_bytes(&Q_MERKLE_CRH.1).unwrap(),
  100. )
  101. .unwrap(),
  102. }
  103. }
  104. }
  105. #[derive(Clone, Debug, Eq, PartialEq)]
  106. pub enum OrchardCommitDomains {
  107. NoteCommit,
  108. CommitIvk,
  109. }
  110. impl CommitDomains<pallas::Affine, OrchardFixedBases, OrchardHashDomains> for OrchardCommitDomains {
  111. fn r(&self) -> OrchardFixedBases {
  112. match self {
  113. Self::NoteCommit => OrchardFixedBases::NoteCommitR,
  114. Self::CommitIvk => OrchardFixedBases::CommitIvkR,
  115. }
  116. }
  117. fn hash_domain(&self) -> OrchardHashDomains {
  118. match self {
  119. Self::NoteCommit => OrchardHashDomains::NoteCommit,
  120. Self::CommitIvk => OrchardHashDomains::CommitIvk,
  121. }
  122. }
  123. }
  124. #[cfg(test)]
  125. mod tests {
  126. use super::*;
  127. use crate::crypto::constants::{
  128. fixed_bases::{COMMIT_IVK_PERSONALIZATION, NOTE_COMMITMENT_PERSONALIZATION},
  129. sinsemilla::MERKLE_CRH_PERSONALIZATION,
  130. };
  131. use halo2_gadgets::primitives::sinsemilla::{CommitDomain, HashDomain};
  132. use pasta_curves::{
  133. arithmetic::{CurveAffine, FieldExt},
  134. group::{ff::PrimeField, Curve},
  135. pallas,
  136. };
  137. use rand::{self, rngs::OsRng, Rng};
  138. #[test]
  139. // Nodes in the Merkle tree are Pallas base field elements.
  140. fn l_orchard_merkle() {
  141. assert_eq!(255, pallas::Base::NUM_BITS as usize);
  142. }
  143. #[test]
  144. fn lebs2ip_k_round_trip() {
  145. let mut rng = OsRng;
  146. {
  147. let int = rng.gen_range(0..(1 << K));
  148. assert_eq!(lebs2ip_k(&i2lebsp_k(int)) as usize, int);
  149. }
  150. assert_eq!(lebs2ip_k(&i2lebsp_k(0)) as usize, 0);
  151. assert_eq!(lebs2ip_k(&i2lebsp_k((1 << K) - 1)) as usize, (1 << K) - 1);
  152. }
  153. #[test]
  154. fn i2lebsp_k_round_trip() {
  155. {
  156. let bitstring = (0..K).map(|_| rand::random()).collect::<Vec<_>>();
  157. assert_eq!(
  158. i2lebsp_k(lebs2ip_k(&bitstring) as usize).to_vec(),
  159. bitstring
  160. );
  161. }
  162. {
  163. let bitstring = [false; K];
  164. assert_eq!(
  165. i2lebsp_k(lebs2ip_k(&bitstring) as usize).to_vec(),
  166. bitstring
  167. );
  168. }
  169. {
  170. let bitstring = [true; K];
  171. assert_eq!(
  172. i2lebsp_k(lebs2ip_k(&bitstring) as usize).to_vec(),
  173. bitstring
  174. );
  175. }
  176. }
  177. #[test]
  178. fn q_note_commitment_m() {
  179. let domain = CommitDomain::new(NOTE_COMMITMENT_PERSONALIZATION);
  180. let point = domain.Q();
  181. let coords = point.to_affine().coordinates().unwrap();
  182. assert_eq!(
  183. *coords.x(),
  184. pallas::Base::from_bytes(&Q_NOTE_COMMITMENT_M_GENERATOR.0).unwrap()
  185. );
  186. assert_eq!(
  187. *coords.y(),
  188. pallas::Base::from_bytes(&Q_NOTE_COMMITMENT_M_GENERATOR.1).unwrap()
  189. );
  190. }
  191. #[test]
  192. fn q_commit_ivk_m() {
  193. let domain = CommitDomain::new(COMMIT_IVK_PERSONALIZATION);
  194. let point = domain.Q();
  195. let coords = point.to_affine().coordinates().unwrap();
  196. assert_eq!(
  197. *coords.x(),
  198. pallas::Base::from_bytes(&Q_COMMIT_IVK_M_GENERATOR.0).unwrap()
  199. );
  200. assert_eq!(
  201. *coords.y(),
  202. pallas::Base::from_bytes(&Q_COMMIT_IVK_M_GENERATOR.1).unwrap()
  203. );
  204. }
  205. #[test]
  206. fn q_merkle_crh() {
  207. let domain = HashDomain::new(MERKLE_CRH_PERSONALIZATION);
  208. let point = domain.Q();
  209. let coords = point.to_affine().coordinates().unwrap();
  210. assert_eq!(
  211. *coords.x(),
  212. pallas::Base::from_bytes(&Q_MERKLE_CRH.0).unwrap()
  213. );
  214. assert_eq!(
  215. *coords.y(),
  216. pallas::Base::from_bytes(&Q_MERKLE_CRH.1).unwrap()
  217. );
  218. }
  219. #[test]
  220. fn inv_two_pow_k() {
  221. let two_pow_k = pallas::Base::from_u64(1u64 << K);
  222. let inv_two_pow_k = pallas::Base::from_bytes(&INV_TWO_POW_K).unwrap();
  223. assert_eq!(two_pow_k * inv_two_pow_k, pallas::Base::one());
  224. }
  225. }