1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
use ark_crypto_primitives::{crh::CRH, Error};
use ark_ff::{fields::PrimeField, to_bytes};
use ark_std::{marker::PhantomData, rand::Rng};
#[cfg(feature = "r1cs")]
pub mod constraints;
#[derive(Default, Clone)]
pub struct Private<F: PrimeField> {
pub secret: F,
pub nullifier: F,
}
impl<F: PrimeField> Private<F> {
pub fn generate<R: Rng>(rng: &mut R) -> Self {
Self {
secret: F::rand(rng),
nullifier: F::rand(rng),
}
}
pub fn new(secret: F, nullifier: F) -> Self {
Self { secret, nullifier }
}
pub fn secret(&self) -> F {
self.secret
}
pub fn nullifier(&self) -> F {
self.nullifier
}
}
#[derive(Default, Clone)]
pub struct Public<F: PrimeField> {
pub chain_id: F,
}
impl<F: PrimeField> Public<F> {
pub fn new(chain_id: F) -> Self {
Self { chain_id }
}
}
#[derive(Clone)]
pub struct AnchorLeaf<F: PrimeField, H: CRH> {
field: PhantomData<F>,
hasher: PhantomData<H>,
}
impl<F: PrimeField, H: CRH> AnchorLeaf<F, H> {
pub fn create_leaf(
private: &Private<F>,
public: &Public<F>,
h: &H::Parameters,
) -> Result<H::Output, Error> {
let input_bytes = to_bytes![private.secret, private.nullifier, public.chain_id]?;
H::evaluate(h, &input_bytes)
}
pub fn create_nullifier(private: &Private<F>, h: &H::Parameters) -> Result<H::Output, Error> {
let nullifier_bytes = to_bytes![private.nullifier, private.nullifier]?;
H::evaluate(h, &nullifier_bytes)
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::poseidon::CRH;
use ark_bls12_381::Fq;
use ark_crypto_primitives::crh::CRH as CRHTrait;
use ark_ff::One;
use ark_std::test_rng;
use arkworks_utils::utils::common::setup_params_x5_5;
type PoseidonCRH5 = CRH<Fq>;
type Leaf = AnchorLeaf<Fq, PoseidonCRH5>;
#[test]
fn should_crate_anchor_leaf() {
let rng = &mut test_rng();
let curve = arkworks_utils::utils::common::Curve::Bls381;
let private = Private::generate(rng);
let chain_id = Fq::one();
let public = Public::new(chain_id);
let leaf_inputs = to_bytes![private.secret, private.nullifier, public.chain_id].unwrap();
let nullifier_inputs = to_bytes![private.nullifier, private.nullifier].unwrap();
let params = setup_params_x5_5(curve);
let leaf_res = PoseidonCRH5::evaluate(¶ms, &leaf_inputs).unwrap();
let nullifier_res = PoseidonCRH5::evaluate(¶ms, &nullifier_inputs).unwrap();
let leaf_hash = Leaf::create_leaf(&private, &public, ¶ms).unwrap();
let nullifier_hash = Leaf::create_nullifier(&private, ¶ms).unwrap();
assert_eq!(leaf_res, leaf_hash);
assert_eq!(nullifier_res, nullifier_hash);
}
}