pessimistic_proof_core/
nullifier_tree.rs1use agglayer_primitives::{Digest, FromBool};
2use agglayer_tries::proof::{SmtNonInclusionProof, ToBits};
3use serde::{Deserialize, Serialize};
4use serde_with::serde_as;
5use unified_bridge::{GlobalIndex, NetworkId};
6
7use crate::ProofError;
8
9pub const NULLIFIER_TREE_DEPTH: usize = 64;
11
12#[serde_as]
15#[derive(Clone, Debug, Serialize, Deserialize)]
16pub struct NullifierTree {
17 #[serde_as(as = "_")]
19 pub root: Digest,
20}
21
22pub type NullifierPath = SmtNonInclusionProof<NULLIFIER_TREE_DEPTH>;
23
24#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
25pub struct NullifierKey {
26 pub network_id: NetworkId,
27 pub let_index: u32,
28}
29
30impl From<GlobalIndex> for NullifierKey {
31 fn from(value: GlobalIndex) -> Self {
32 Self {
33 network_id: value.network_id(),
34 let_index: value.leaf_index(),
35 }
36 }
37}
38
39impl ToBits<64> for NullifierKey {
40 fn to_bits(&self) -> [bool; 64] {
41 std::array::from_fn(|i| {
42 if i < 32 {
43 (self.network_id.to_u32() >> i) & 1 == 1
44 } else {
45 (self.let_index >> (i - 32)) & 1 == 1
46 }
47 })
48 }
49}
50
51impl NullifierTree {
52 pub fn verify_and_update(
53 &mut self,
54 key: NullifierKey,
55 path_to_update: &NullifierPath,
56 ) -> Result<(), ProofError> {
57 self.root = path_to_update
58 .verify_and_update(key, Digest::from_bool(true), self.root)
59 .ok_or(ProofError::InvalidNullifierPath)?;
60
61 Ok(())
62 }
63}