penumbra_sdk_tct/internal/complete/
node.rs1use serde::{Deserialize, Serialize};
2
3use crate::prelude::*;
4
5use super::super::frontier;
6
7pub mod children;
8pub use children::Children;
9
10#[derive(Clone, Debug)]
12pub struct Node<Child: Clone> {
13 hash: Hash,
14 forgotten: [Forgotten; 4],
15 children: Children<Child>,
16}
17
18impl<Child: Serialize + Clone> Serialize for Node<Child> {
19 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
20 where
21 S: serde::Serializer,
22 {
23 self.children.serialize(serializer)
24 }
25}
26
27impl<'de, Child: Height + GetHash + Deserialize<'de> + Clone> Deserialize<'de> for Node<Child> {
28 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
29 where
30 D: serde::Deserializer<'de>,
31 {
32 let children = Children::deserialize(deserializer)?;
33 Ok(Self {
34 hash: children.hash(),
35 forgotten: Default::default(),
36 children,
37 })
38 }
39}
40
41impl<Child: Height + Clone> Node<Child> {
42 pub(in super::super) fn from_children_or_else_hash(
43 forgotten: [Forgotten; 4],
44 children: [Insert<Child>; 4],
45 ) -> Insert<Self>
46 where
47 Child: GetHash,
48 {
49 match Children::try_from(children) {
50 Ok(children) => Insert::Keep(Self {
51 hash: children.hash(),
52 forgotten,
53 children,
54 }),
55 Err([a, b, c, d]) => {
56 Insert::Hash(Hash::node(<Self as Height>::Height::HEIGHT, a, b, c, d))
59 }
60 }
61 }
62
63 pub fn children(&self) -> [Insert<&Child>; 4] {
65 self.children.children()
66 }
67
68 pub fn forgotten(&self) -> [Forgotten; 4] {
70 self.forgotten
71 }
72}
73
74impl<Child: Height + Clone> Height for Node<Child> {
75 type Height = Succ<Child::Height>;
76}
77
78impl<Child: Complete + Clone> Complete for Node<Child>
79where
80 Child::Focus: Clone,
81{
82 type Focus = frontier::Node<Child::Focus>;
83}
84
85impl<Child: Height + GetHash + Clone> GetHash for Node<Child> {
86 #[inline]
87 fn hash(&self) -> Hash {
88 self.hash
89 }
90
91 #[inline]
92 fn cached_hash(&self) -> Option<Hash> {
93 Some(self.hash)
94 }
95}
96
97impl<Child: GetHash + Witness + Clone> Witness for Node<Child> {
98 #[inline]
99 fn witness(&self, index: impl Into<u64>) -> Option<(AuthPath<Self>, Hash)> {
100 let index = index.into();
101
102 let (which_way, index) = WhichWay::at(Self::Height::HEIGHT, index);
104
105 let (child, siblings) = which_way.pick(self.children());
107
108 let siblings = siblings.map(|sibling| sibling.hash());
110
111 let (child, leaf) = child.keep()?.witness(index)?;
113
114 Some((path::Node { siblings, child }, leaf))
115 }
116}
117
118impl<Child: GetHash + ForgetOwned + Clone> ForgetOwned for Node<Child> {
119 #[inline]
120 fn forget_owned(
121 self,
122 forgotten: Option<Forgotten>,
123 index: impl Into<u64>,
124 ) -> (Insert<Self>, bool) {
125 let index = index.into();
126
127 let [a, b, c, d]: [Insert<Child>; 4] = self.children.into();
128
129 let (which_way, index) = WhichWay::at(Self::Height::HEIGHT, index);
131
132 let (children, was_forgotten) = match which_way {
134 WhichWay::Leftmost => {
135 let (a, forgotten) = match a {
136 Insert::Keep(a) => a.forget_owned(forgotten, index),
137 Insert::Hash(_) => (a, false),
138 };
139 ([a, b, c, d], forgotten)
140 }
141 WhichWay::Left => {
142 let (b, forgotten) = match b {
143 Insert::Keep(b) => b.forget_owned(forgotten, index),
144 Insert::Hash(_) => (b, false),
145 };
146 ([a, b, c, d], forgotten)
147 }
148 WhichWay::Right => {
149 let (c, forgotten) = match c {
150 Insert::Keep(c) => c.forget_owned(forgotten, index),
151 Insert::Hash(_) => (c, false),
152 };
153 ([a, b, c, d], forgotten)
154 }
155 WhichWay::Rightmost => {
156 let (d, forgotten) = match d {
157 Insert::Keep(d) => d.forget_owned(forgotten, index),
158 Insert::Hash(_) => (d, false),
159 };
160 ([a, b, c, d], forgotten)
161 }
162 };
163
164 let reconstructed = match Children::try_from(children) {
167 Ok(children) => {
168 let mut reconstructed = Self {
169 children,
170 hash: self.hash,
171 forgotten: self.forgotten,
172 };
173 if was_forgotten {
175 if let Some(forgotten) = forgotten {
176 reconstructed.forgotten[which_way] = forgotten.next();
177 }
178 }
179 Insert::Keep(reconstructed)
180 }
181 Err(_) => Insert::Hash(self.hash),
182 };
183
184 (reconstructed, was_forgotten)
185 }
186}
187
188impl<Child: Clone> GetPosition for Node<Child> {
189 fn position(&self) -> Option<u64> {
190 None
191 }
192}
193
194impl<'tree, Child: Height + structure::Any<'tree> + Clone> structure::Any<'tree> for Node<Child> {
195 fn kind(&self) -> Kind {
196 Kind::Internal {
197 height: <Self as Height>::Height::HEIGHT,
198 }
199 }
200
201 fn forgotten(&self) -> Forgotten {
202 self.forgotten.iter().copied().max().unwrap_or_default()
203 }
204
205 fn children(&'tree self) -> Vec<HashOrNode<'tree>> {
206 self.forgotten
207 .iter()
208 .copied()
209 .zip(self.children.children())
210 .map(|(forgotten, child)| match child {
211 Insert::Keep(node) => HashOrNode::Node(node),
212 Insert::Hash(hash) => HashOrNode::Hash(HashedNode {
213 hash,
214 forgotten,
215 height: <Child as Height>::Height::HEIGHT,
216 }),
217 })
218 .collect()
219 }
220}
221
222impl<Child: Height + OutOfOrderOwned + Clone> OutOfOrderOwned for Node<Child> {
223 fn uninitialized_out_of_order_insert_commitment_owned(
224 this: Insert<Self>,
225 index: u64,
226 commitment: StateCommitment,
227 ) -> Self {
228 let (which_way, index) = WhichWay::at(<Self as Height>::Height::HEIGHT, index);
229
230 let (hash, forgotten, mut children) = match this {
231 Insert::Keep(Node {
233 hash,
234 forgotten,
235 children,
236 }) => (hash, forgotten, children.into()),
237 Insert::Hash(hash) => (hash, [Forgotten::default(); 4], {
240 let u = || Insert::Hash(Hash::uninitialized());
244 [u(), u(), u(), u()]
245 }),
246 };
247
248 let child = std::mem::replace(
251 &mut children[which_way],
252 Insert::Hash(Hash::uninitialized()),
253 );
254
255 children[which_way] = Insert::Keep(
257 Child::uninitialized_out_of_order_insert_commitment_owned(child, index, commitment),
258 );
259
260 let children = children.try_into().expect(
264 "adding a commitment to extant children always allows them to be reconstituted",
265 );
266
267 Node {
268 hash,
269 forgotten,
270 children,
271 }
272 }
273}
274
275impl<Child: GetHash + UncheckedSetHash + Clone> UncheckedSetHash for Node<Child> {
276 fn unchecked_set_hash(&mut self, index: u64, height: u8, hash: Hash) {
277 use std::cmp::Ordering::*;
278
279 match height.cmp(&Self::Height::HEIGHT) {
280 Greater => panic!("height too large when setting hash: {height}"),
281 Equal => self.hash = hash,
283 Less => {
285 let (which_way, index) = WhichWay::at(Self::Height::HEIGHT, index);
286 let (child, _) = which_way.pick(self.children.children_mut());
287 match child {
288 InsertMut::Keep(child) => child.unchecked_set_hash(index, height, hash),
289 InsertMut::Hash(child_hash) => {
290 if <Child as Height>::Height::HEIGHT == height {
291 *child_hash = hash
292 }
293 }
294 }
295 }
296 }
297 }
298
299 fn finish_initialize(&mut self) {
300 for child in self.children.children_mut() {
302 match child {
303 InsertMut::Keep(child) => child.finish_initialize(),
304 InsertMut::Hash(hash) => {
305 if hash.is_uninitialized() {
306 *hash = Hash::one();
308 }
309 }
310 }
311 }
312
313 if self.hash.is_uninitialized() {
319 self.hash = self.children.hash();
320 }
321 }
322}
323
324#[cfg(test)]
325mod test {
326 #[test]
327 fn check_node_size() {
328 }
331}