1use bitvec::{order::Lsb0, view::AsBits};
2use group::{ff::PrimeField, Curve};
3use incrementalmerkletree::{Hashable, Level};
4use lazy_static::lazy_static;
5use subtle::CtOption;
6
7use alloc::vec::Vec;
8use core::fmt;
9
10use super::{
11 note::ExtractedNoteCommitment,
12 pedersen_hash::{pedersen_hash, Personalization},
13};
14
15pub const NOTE_COMMITMENT_TREE_DEPTH: u8 = 32;
16pub type CommitmentTree =
17 incrementalmerkletree::frontier::CommitmentTree<Node, NOTE_COMMITMENT_TREE_DEPTH>;
18pub type IncrementalWitness =
19 incrementalmerkletree::witness::IncrementalWitness<Node, NOTE_COMMITMENT_TREE_DEPTH>;
20pub type MerklePath = incrementalmerkletree::MerklePath<Node, NOTE_COMMITMENT_TREE_DEPTH>;
21
22lazy_static! {
23 static ref UNCOMMITTED_SAPLING: bls12_381::Scalar = bls12_381::Scalar::one();
24 static ref EMPTY_ROOTS: Vec<Node> = empty_roots();
25}
26
27fn empty_roots() -> Vec<Node> {
28 let mut v = vec![Node::empty_leaf()];
29 for d in 0..NOTE_COMMITMENT_TREE_DEPTH {
30 let next = Node::combine(d.into(), &v[usize::from(d)], &v[usize::from(d)]);
31 v.push(next);
32 }
33 v
34}
35
36pub fn merkle_hash(depth: usize, lhs: &[u8; 32], rhs: &[u8; 32]) -> [u8; 32] {
38 merkle_hash_field(depth, lhs, rhs).to_repr()
39}
40
41fn merkle_hash_field(depth: usize, lhs: &[u8; 32], rhs: &[u8; 32]) -> jubjub::Base {
42 let lhs = {
43 let mut tmp = [false; 256];
44 for (a, b) in tmp.iter_mut().zip(lhs.as_bits::<Lsb0>()) {
45 *a = *b;
46 }
47 tmp
48 };
49
50 let rhs = {
51 let mut tmp = [false; 256];
52 for (a, b) in tmp.iter_mut().zip(rhs.as_bits::<Lsb0>()) {
53 *a = *b;
54 }
55 tmp
56 };
57
58 jubjub::ExtendedPoint::from(pedersen_hash(
59 Personalization::MerkleTree(depth),
60 lhs.iter()
61 .copied()
62 .take(bls12_381::Scalar::NUM_BITS as usize)
63 .chain(
64 rhs.iter()
65 .copied()
66 .take(bls12_381::Scalar::NUM_BITS as usize),
67 ),
68 ))
69 .to_affine()
70 .get_u()
71}
72
73#[derive(Eq, PartialEq, Clone, Copy, Debug)]
75pub struct Anchor(jubjub::Base);
76
77impl From<jubjub::Base> for Anchor {
78 fn from(anchor_field: jubjub::Base) -> Anchor {
79 Anchor(anchor_field)
80 }
81}
82
83impl From<Node> for Anchor {
84 fn from(anchor: Node) -> Anchor {
85 Anchor(anchor.0)
86 }
87}
88
89impl Anchor {
90 pub fn empty_tree() -> Anchor {
96 Anchor(Node::empty_root(NOTE_COMMITMENT_TREE_DEPTH.into()).0)
97 }
98
99 pub(crate) fn inner(&self) -> jubjub::Base {
100 self.0
101 }
102
103 pub fn from_bytes(bytes: [u8; 32]) -> CtOption<Anchor> {
105 jubjub::Base::from_repr(bytes).map(Self)
106 }
107
108 pub fn to_bytes(self) -> [u8; 32] {
110 self.0.to_repr()
111 }
112}
113
114#[derive(Clone, Copy, PartialEq, Eq)]
116pub struct Node(jubjub::Base);
117
118impl fmt::Debug for Node {
119 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
120 f.debug_struct("Node")
121 .field("repr", &hex::encode(self.0.to_bytes()))
122 .finish()
123 }
124}
125
126impl Node {
127 pub fn from_cmu(value: &ExtractedNoteCommitment) -> Self {
129 Node(value.inner())
130 }
131
132 pub fn from_scalar(cmu: bls12_381::Scalar) -> Self {
134 Self(cmu)
135 }
136
137 pub fn from_bytes(bytes: [u8; 32]) -> CtOption<Self> {
141 jubjub::Base::from_repr(bytes).map(Self)
142 }
143
144 pub fn to_bytes(&self) -> [u8; 32] {
146 self.0.to_repr()
147 }
148
149 #[cfg(feature = "circuit")]
151 pub(crate) fn inner(&self) -> &jubjub::Base {
152 &self.0
153 }
154}
155
156impl Hashable for Node {
157 fn empty_leaf() -> Self {
158 Node(*UNCOMMITTED_SAPLING)
159 }
160
161 fn combine(level: Level, lhs: &Self, rhs: &Self) -> Self {
162 Node(merkle_hash_field(
163 level.into(),
164 &lhs.0.to_bytes(),
165 &rhs.0.to_bytes(),
166 ))
167 }
168
169 fn empty_root(level: Level) -> Self {
170 EMPTY_ROOTS[<usize>::from(level)]
171 }
172}
173
174impl From<Node> for bls12_381::Scalar {
175 fn from(node: Node) -> Self {
176 node.0
177 }
178}
179
180#[cfg(any(test, feature = "test-dependencies"))]
181pub(super) mod testing {
182 use ff::Field;
183 use proptest::prelude::*;
184 use rand::distributions::{Distribution, Standard};
185
186 use super::Node;
187 use crate::note::testing::arb_cmu;
188
189 prop_compose! {
190 pub fn arb_node()(cmu in arb_cmu()) -> Node {
191 Node::from_cmu(&cmu)
192 }
193 }
194
195 impl Node {
196 pub fn random(rng: &mut impl RngCore) -> Self {
198 Standard.sample(rng)
199 }
200 }
201
202 impl Distribution<Node> for Standard {
203 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Node {
204 Node::from_scalar(bls12_381::Scalar::random(rng))
205 }
206 }
207}