zebra_chain/
subtree.rs

1//! Struct representing Sapling/Orchard note commitment subtrees
2
3use std::{fmt, num::TryFromIntError};
4
5use serde::{Deserialize, Serialize};
6
7use crate::block::Height;
8
9#[cfg(any(test, feature = "proptest-impl"))]
10use proptest_derive::Arbitrary;
11
12/// Height at which Zebra tracks subtree roots
13pub const TRACKED_SUBTREE_HEIGHT: u8 = 16;
14
15/// A note commitment subtree index, used to identify a subtree in a shielded pool.
16/// Also used to count subtrees.
17#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
18#[cfg_attr(any(test, feature = "proptest-impl"), derive(Arbitrary))]
19#[serde(transparent)]
20pub struct NoteCommitmentSubtreeIndex(pub u16);
21
22impl fmt::Display for NoteCommitmentSubtreeIndex {
23    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
24        f.write_str(&self.0.to_string())
25    }
26}
27
28impl From<u16> for NoteCommitmentSubtreeIndex {
29    fn from(value: u16) -> Self {
30        Self(value)
31    }
32}
33
34impl TryFrom<u64> for NoteCommitmentSubtreeIndex {
35    type Error = TryFromIntError;
36
37    fn try_from(value: u64) -> Result<Self, Self::Error> {
38        u16::try_from(value).map(Self)
39    }
40}
41
42// If we want to automatically convert NoteCommitmentSubtreeIndex to the generic integer literal
43// type, we can only implement conversion into u64. (Or u16, but not both.)
44impl From<NoteCommitmentSubtreeIndex> for u64 {
45    fn from(value: NoteCommitmentSubtreeIndex) -> Self {
46        value.0.into()
47    }
48}
49
50// TODO:
51// - consider defining sapling::SubtreeRoot and orchard::SubtreeRoot types or type wrappers,
52//   to avoid type confusion between the leaf Node and subtree root types.
53
54/// Subtree root of Sapling or Orchard note commitment tree,
55/// with its associated block height and subtree index.
56#[derive(Copy, Clone, Debug, Eq, PartialEq)]
57#[cfg_attr(any(test, feature = "proptest-impl"), derive(Arbitrary))]
58pub struct NoteCommitmentSubtree<SubtreeRoot> {
59    /// Index of this subtree
60    pub index: NoteCommitmentSubtreeIndex,
61    /// Root of this subtree.
62    pub root: SubtreeRoot,
63    /// End boundary of this subtree, the block height of its last leaf.
64    pub end_height: Height,
65}
66
67impl<SubtreeRoot> NoteCommitmentSubtree<SubtreeRoot> {
68    /// Creates new [`NoteCommitmentSubtree`]
69    pub fn new(
70        index: impl Into<NoteCommitmentSubtreeIndex>,
71        end_height: Height,
72        root: SubtreeRoot,
73    ) -> Self {
74        let index = index.into();
75        Self {
76            index,
77            end_height,
78            root,
79        }
80    }
81
82    /// Converts struct to [`NoteCommitmentSubtreeData`].
83    pub fn into_data(self) -> NoteCommitmentSubtreeData<SubtreeRoot> {
84        NoteCommitmentSubtreeData::new(self.end_height, self.root)
85    }
86}
87
88/// Subtree root of Sapling or Orchard note commitment tree, with block height, but without the subtree index.
89/// Used for database key-value serialization, where the subtree index is the key, and this struct is the value.
90#[derive(Copy, Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
91#[cfg_attr(any(test, feature = "proptest-impl"), derive(Arbitrary))]
92pub struct NoteCommitmentSubtreeData<SubtreeRoot> {
93    /// Merkle root of the 2^16-leaf subtree.
94    pub root: SubtreeRoot,
95
96    /// Height of the block containing the note that completed this subtree.
97    pub end_height: Height,
98}
99
100impl<SubtreeRoot> NoteCommitmentSubtreeData<SubtreeRoot> {
101    /// Creates new [`NoteCommitmentSubtreeData`]
102    pub fn new(end_height: Height, root: SubtreeRoot) -> Self {
103        Self { end_height, root }
104    }
105
106    /// Creates new [`NoteCommitmentSubtree`] from a [`NoteCommitmentSubtreeData`] and index
107    pub fn with_index(
108        self,
109        index: impl Into<NoteCommitmentSubtreeIndex>,
110    ) -> NoteCommitmentSubtree<SubtreeRoot> {
111        NoteCommitmentSubtree::new(index, self.end_height, self.root)
112    }
113}