zebra_rpc/methods/trees.rs
1//! Types and functions for note commitment tree RPCs.
2
3use derive_getters::Getters;
4use derive_new::new;
5use zebra_chain::{
6 block::Hash,
7 block::Height,
8 subtree::{NoteCommitmentSubtreeData, NoteCommitmentSubtreeIndex},
9};
10
11/// A subtree data type that can hold Sapling or Orchard subtree roots.
12pub type SubtreeRpcData = NoteCommitmentSubtreeData<String>;
13
14/// Response to a `z_getsubtreesbyindex` RPC request.
15///
16/// Contains the Sapling or Orchard pool label, the index of the first subtree in the list,
17/// and a list of subtree roots and end heights.
18#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, Getters, new)]
19pub struct GetSubtreesByIndexResponse {
20 /// The shielded pool to which the subtrees belong.
21 //
22 // TODO: consider an enum with a string conversion?
23 pub(crate) pool: String,
24
25 /// The index of the first subtree.
26 #[getter(copy)]
27 pub(crate) start_index: NoteCommitmentSubtreeIndex,
28
29 /// A sequential list of complete subtrees, in `index` order.
30 ///
31 /// The generic subtree root type is a hex-encoded Sapling or Orchard subtree root string.
32 //
33 // TODO: is this needed?
34 //#[serde(skip_serializing_if = "Vec::is_empty")]
35 pub(crate) subtrees: Vec<SubtreeRpcData>,
36}
37
38impl Default for GetSubtreesByIndexResponse {
39 fn default() -> Self {
40 Self {
41 pool: "sapling | orchard".to_string(),
42 start_index: NoteCommitmentSubtreeIndex(u16::default()),
43 subtrees: vec![],
44 }
45 }
46}
47
48/// Response to a `z_gettreestate` RPC request.
49///
50/// Contains hex-encoded Sapling & Orchard note commitment trees and their corresponding
51/// [`struct@Hash`], [`Height`], and block time.
52///
53/// The format of the serialized trees represents `CommitmentTree`s from the crate
54/// `incrementalmerkletree` and not `Frontier`s from the same crate, even though `zebrad`'s
55/// `NoteCommitmentTree`s are implemented using `Frontier`s. Zebra follows the former format to stay
56/// consistent with `zcashd`'s RPCs.
57///
58/// The formats are semantically equivalent. The difference is that in `Frontier`s, the vector of
59/// ommers is dense (we know where the gaps are from the position of the leaf in the overall tree);
60/// whereas in `CommitmentTree`, the vector of ommers is sparse with [`None`] values in the gaps.
61///
62/// The dense format might be used in future RPCs.
63#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, Getters, new)]
64pub struct GetTreestateResponse {
65 /// The block hash corresponding to the treestate, hex-encoded.
66 #[serde(with = "hex")]
67 #[getter(copy)]
68 hash: Hash,
69
70 /// The block height corresponding to the treestate, numeric.
71 #[getter(copy)]
72 height: Height,
73
74 /// Unix time when the block corresponding to the treestate was mined,
75 /// numeric.
76 ///
77 /// UTC seconds since the Unix 1970-01-01 epoch.
78 time: u32,
79
80 /// A treestate containing a Sprout note commitment tree, hex-encoded. Zebra
81 /// does not support returning it; but the field is here to enable parsing
82 /// responses from other implementations.
83 #[serde(skip_serializing_if = "Option::is_none")]
84 sprout: Option<Treestate>,
85
86 /// A treestate containing a Sapling note commitment tree, hex-encoded.
87 sapling: Treestate,
88
89 /// A treestate containing an Orchard note commitment tree, hex-encoded.
90 orchard: Treestate,
91}
92
93impl GetTreestateResponse {
94 /// Constructs [`Treestate`] from its constituent parts.
95 #[deprecated(note = "Use `new` instead.")]
96 pub fn from_parts(
97 hash: Hash,
98 height: Height,
99 time: u32,
100 sapling: Option<Vec<u8>>,
101 orchard: Option<Vec<u8>>,
102 ) -> Self {
103 let sapling = Treestate {
104 commitments: Commitments {
105 final_state: sapling,
106 final_root: None,
107 },
108 };
109 let orchard = Treestate {
110 commitments: Commitments {
111 final_state: orchard,
112 final_root: None,
113 },
114 };
115
116 Self {
117 hash,
118 height,
119 time,
120 sprout: None,
121 sapling,
122 orchard,
123 }
124 }
125
126 /// Returns the contents of ['GetTreeState'].
127 #[deprecated(note = "Use getters instead.")]
128 pub fn into_parts(self) -> (Hash, Height, u32, Option<Vec<u8>>, Option<Vec<u8>>) {
129 (
130 self.hash,
131 self.height,
132 self.time,
133 self.sapling.commitments.final_state,
134 self.orchard.commitments.final_state,
135 )
136 }
137}
138
139impl Default for GetTreestateResponse {
140 fn default() -> Self {
141 Self {
142 hash: Hash([0; 32]),
143 height: Height::MIN,
144 time: Default::default(),
145 sprout: Default::default(),
146 sapling: Default::default(),
147 orchard: Default::default(),
148 }
149 }
150}
151
152/// A treestate that is included in the [`z_gettreestate`][1] RPC response.
153///
154/// [1]: https://zcash.github.io/rpc/z_gettreestate.html
155#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, Getters, new)]
156pub struct Treestate {
157 /// Contains an Orchard or Sapling serialized note commitment tree,
158 /// hex-encoded.
159 commitments: Commitments,
160}
161
162impl Treestate {
163 /// Returns a reference to the commitments.
164 #[deprecated(note = "Use `commitments()` instead.")]
165 pub fn inner(&self) -> &Commitments {
166 self.commitments()
167 }
168}
169
170impl Default for Treestate {
171 fn default() -> Self {
172 Self {
173 commitments: Commitments {
174 final_root: None,
175 final_state: None,
176 },
177 }
178 }
179}
180
181/// A wrapper that contains either an Orchard or Sapling note commitment tree.
182///
183/// Note that in the original [`z_gettreestate`][1] RPC, [`Commitments`] also
184/// contains the field `finalRoot`. Zebra does *not* use this field.
185///
186/// [1]: https://zcash.github.io/rpc/z_gettreestate.html
187#[serde_with::serde_as]
188#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, Getters, new)]
189pub struct Commitments {
190 /// Orchard or Sapling serialized note commitment tree root, hex-encoded.
191 #[serde_as(as = "Option<serde_with::hex::Hex>")]
192 #[serde(skip_serializing_if = "Option::is_none")]
193 #[serde(rename = "finalRoot")]
194 final_root: Option<Vec<u8>>,
195 /// Orchard or Sapling serialized note commitment tree, hex-encoded.
196 #[serde_as(as = "Option<serde_with::hex::Hex>")]
197 #[serde(skip_serializing_if = "Option::is_none")]
198 #[serde(rename = "finalState")]
199 final_state: Option<Vec<u8>>,
200}
201
202impl Commitments {
203 /// Returns a reference to the optional `final_state`.
204 #[deprecated(note = "Use `final_state()` instead.")]
205 pub fn inner(&self) -> &Option<Vec<u8>> {
206 &self.final_state
207 }
208}