node.rs 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. use bitvec::{order::Lsb0, view::AsBits};
  2. use ff::PrimeField;
  3. use group::Curve;
  4. use lazy_static::lazy_static;
  5. use std::io;
  6. use super::merkle::Hashable;
  7. pub const SAPLING_COMMITMENT_TREE_DEPTH: usize = 4;
  8. /// Compute a parent node in the Sapling commitment tree given its two children.
  9. pub fn merkle_hash(depth: usize, lhs: &[u8; 32], rhs: &[u8; 32]) -> bls12_381::Scalar {
  10. // This thing is nasty lol
  11. let lhs = {
  12. let mut tmp = [false; 256];
  13. for (a, b) in tmp.iter_mut().zip(lhs.as_bits::<Lsb0>()) {
  14. *a = *b;
  15. }
  16. tmp
  17. };
  18. let rhs = {
  19. let mut tmp = [false; 256];
  20. for (a, b) in tmp.iter_mut().zip(rhs.as_bits::<Lsb0>()) {
  21. *a = *b;
  22. }
  23. tmp
  24. };
  25. jubjub::ExtendedPoint::from(zcash_primitives::pedersen_hash::pedersen_hash(
  26. zcash_primitives::pedersen_hash::Personalization::MerkleTree(depth),
  27. lhs.iter()
  28. .copied()
  29. .take(bls12_381::Scalar::NUM_BITS as usize)
  30. .chain(
  31. rhs.iter()
  32. .copied()
  33. .take(bls12_381::Scalar::NUM_BITS as usize),
  34. ),
  35. ))
  36. .to_affine()
  37. .get_u()
  38. }
  39. pub fn hash_coin(coin: [u8; 32]) -> bls12_381::Scalar {
  40. let rhs = {
  41. let mut tmp = [false; 256];
  42. for (a, b) in tmp.iter_mut().zip(coin.as_bits::<Lsb0>()) {
  43. *a = *b;
  44. }
  45. tmp
  46. };
  47. jubjub::ExtendedPoint::from(zcash_primitives::pedersen_hash::pedersen_hash(
  48. zcash_primitives::pedersen_hash::Personalization::NoteCommitment,
  49. rhs.iter().copied(),
  50. ))
  51. .to_affine()
  52. .get_u()
  53. }
  54. /// A node within the Sapling commitment tree.
  55. #[derive(Clone, Copy, Debug, PartialEq)]
  56. pub struct Node {
  57. pub repr: [u8; 32],
  58. }
  59. impl Node {
  60. pub fn new(repr: [u8; 32]) -> Self {
  61. Self { repr }
  62. }
  63. }
  64. impl Hashable for Node {
  65. fn read<R: io::Read>(mut reader: R) -> io::Result<Self> {
  66. let mut repr = [0u8; 32];
  67. reader.read_exact(&mut repr)?;
  68. Ok(Self::new(repr))
  69. }
  70. fn write<W: io::Write>(&self, mut writer: W) -> io::Result<()> {
  71. writer.write_all(self.repr.as_ref())
  72. }
  73. fn combine(depth: usize, lhs: &Self, rhs: &Self) -> Self {
  74. Self {
  75. repr: merkle_hash(depth, &lhs.repr, &rhs.repr).to_repr(),
  76. }
  77. }
  78. fn blank() -> Self {
  79. // The smallest u-coordinate that is not on the curve
  80. // is one.
  81. let uncommitted_note = bls12_381::Scalar::one();
  82. Self {
  83. repr: uncommitted_note.to_repr(),
  84. }
  85. }
  86. fn empty_root(depth: usize) -> Self {
  87. EMPTY_ROOTS[depth]
  88. }
  89. }
  90. impl From<Node> for bls12_381::Scalar {
  91. fn from(node: Node) -> Self {
  92. bls12_381::Scalar::from_repr(node.repr).expect("Tree nodes should be in the prime field")
  93. }
  94. }
  95. lazy_static! {
  96. static ref EMPTY_ROOTS: Vec<Node> = {
  97. let mut v = vec![Node::blank()];
  98. for d in 0..SAPLING_COMMITMENT_TREE_DEPTH {
  99. let next = Node::combine(d, &v[d], &v[d]);
  100. v.push(next);
  101. }
  102. v
  103. };
  104. }