1use std::ops::Deref;
24use std::{slice, vec};
25
26use amplify::num::u7;
27use bc::{
28 ControlBlock, InternalPk, LeafScript, OutputPk, Parity, TapLeafHash, TapMerklePath,
29 TapNodeHash, TapScript,
30};
31use commit_verify::merkle::MerkleBuoy;
32
33use crate::{KeyOrigin, Terminal, XkeyOrigin};
34
35#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Display, Error, From)]
36pub enum InvalidTree {
37 #[from]
38 #[display(doc_comments)]
39 Unfinalized(UnfinalizedTree),
40
41 #[from(FinalizedTree)]
42 #[display("tap tree contains too many script leaves which doesn't fit a single Merkle tree")]
43 MountainRange,
44}
45
46#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Display, Error)]
47#[display("can't add more leaves to an already finalized tap tree")]
48pub struct FinalizedTree;
49
50#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Display, Error)]
51#[display(
52 "unfinalized tap tree containing leaves at level {0} which can't commit into a single Merkle \
53 root"
54)]
55pub struct UnfinalizedTree(pub u7);
56
57#[derive(Clone, Eq, PartialEq, Debug, Default)]
58pub struct TapTreeBuilder {
59 leaves: Vec<LeafInfo>,
60 buoy: MerkleBuoy<u7>,
61 finalized: bool,
62}
63
64impl TapTreeBuilder {
65 pub fn new() -> Self { Self::default() }
66
67 pub fn with_capacity(capacity: usize) -> Self {
68 Self {
69 leaves: Vec::with_capacity(capacity),
70 buoy: zero!(),
71 finalized: false,
72 }
73 }
74
75 pub fn is_finalized(&self) -> bool { self.finalized }
76
77 pub fn push_leaf(&mut self, leaf: LeafInfo) -> Result<bool, FinalizedTree> {
78 if self.finalized {
79 return Err(FinalizedTree);
80 }
81 let depth = leaf.depth;
82 self.leaves.push(leaf);
83 self.buoy.push(depth);
84 if self.buoy.level() == u7::ZERO {
85 self.finalized = true
86 }
87 Ok(self.finalized)
88 }
89
90 pub fn finish(self) -> Result<TapTree, UnfinalizedTree> {
91 if !self.finalized {
92 return Err(UnfinalizedTree(self.buoy.level()));
93 }
94 Ok(TapTree(self.leaves))
95 }
96}
97
98#[derive(Clone, Eq, PartialEq, Hash, Debug, Default)]
100#[cfg_attr(
101 feature = "serde",
102 derive(Serialize, Deserialize),
103 serde(crate = "serde_crate", transparent)
104)]
105pub struct TapTree(Vec<LeafInfo>);
106
107impl Deref for TapTree {
108 type Target = Vec<LeafInfo>;
109 fn deref(&self) -> &Self::Target { &self.0 }
110}
111
112impl IntoIterator for TapTree {
113 type Item = LeafInfo;
114 type IntoIter = vec::IntoIter<LeafInfo>;
115
116 fn into_iter(self) -> Self::IntoIter { self.0.into_iter() }
117}
118
119impl<'a> IntoIterator for &'a TapTree {
120 type Item = &'a LeafInfo;
121 type IntoIter = slice::Iter<'a, LeafInfo>;
122
123 fn into_iter(self) -> Self::IntoIter { self.0.iter() }
124}
125
126impl TapTree {
127 pub fn with_single_leaf(leaf: impl Into<LeafScript>) -> TapTree {
128 Self(vec![LeafInfo {
129 depth: u7::ZERO,
130 script: leaf.into(),
131 }])
132 }
133
134 pub fn from_leaves(leaves: impl IntoIterator<Item = LeafInfo>) -> Result<Self, InvalidTree> {
135 let mut builder = TapTreeBuilder::new();
136 for leaf in leaves {
137 builder.push_leaf(leaf)?;
138 }
139 builder.finish().map_err(InvalidTree::from)
140 }
141
142 pub fn from_builder(builder: TapTreeBuilder) -> Result<Self, UnfinalizedTree> {
143 builder.finish()
144 }
145
146 pub fn merkle_root(&self) -> TapNodeHash {
147 if self.0.len() == 1 {
148 TapLeafHash::with_leaf_script(&self.0[0].script).into()
149 } else {
150 todo!("#10 implement TapTree::merkle_root for trees with more than one leaf")
151 }
152 }
153
154 pub fn into_vec(self) -> Vec<LeafInfo> { self.0 }
155}
156
157#[derive(Clone, Eq, PartialEq, Hash, Debug)]
158#[cfg_attr(
159 feature = "serde",
160 derive(Serialize, Deserialize),
161 serde(crate = "serde_crate", rename_all = "camelCase")
162)]
163pub struct LeafInfo {
164 pub depth: u7,
165 pub script: LeafScript,
166}
167
168impl LeafInfo {
169 pub fn tap_script(depth: u7, script: TapScript) -> Self {
170 LeafInfo {
171 depth,
172 script: LeafScript::from_tap_script(script),
173 }
174 }
175}
176
177#[derive(Getters, Clone, Eq, PartialEq, Debug)]
178#[getter(as_copy)]
179pub struct ControlBlockFactory {
180 internal_pk: InternalPk,
181 output_pk: OutputPk,
182 parity: Parity,
183 merkle_root: TapNodeHash,
184
185 #[getter(skip)]
186 merkle_path: TapMerklePath,
187 #[getter(skip)]
188 remaining_leaves: Vec<LeafInfo>,
189}
190
191impl ControlBlockFactory {
192 #[inline]
193 pub fn with(internal_pk: InternalPk, tap_tree: TapTree) -> Self {
194 let merkle_root = tap_tree.merkle_root();
195 let (output_pk, parity) = internal_pk.to_output_pk(Some(merkle_root));
196 ControlBlockFactory {
197 internal_pk,
198 output_pk,
199 parity,
200 merkle_root,
201 merkle_path: empty!(),
202 remaining_leaves: tap_tree.into_vec(),
203 }
204 }
205
206 #[inline]
207 pub fn into_remaining_leaves(self) -> Vec<LeafInfo> { self.remaining_leaves }
208}
209
210impl Iterator for ControlBlockFactory {
211 type Item = (ControlBlock, LeafScript);
212
213 fn next(&mut self) -> Option<Self::Item> {
214 let leaf = self.remaining_leaves.pop()?;
215 let leaf_script = leaf.script;
216 let control_block = ControlBlock::with(
217 leaf_script.version,
218 self.internal_pk,
219 self.parity,
220 self.merkle_path.clone(),
221 );
222 Some((control_block, leaf_script))
223 }
224}
225
226#[derive(Clone, Eq, PartialEq, Hash, Debug)]
234#[cfg_attr(
235 feature = "serde",
236 derive(Serialize, Deserialize),
237 serde(crate = "serde_crate", rename_all = "camelCase")
238)]
239pub struct TapDerivation {
240 pub leaf_hashes: Vec<TapLeafHash>,
241 pub origin: KeyOrigin,
242}
243
244impl TapDerivation {
245 pub fn with_internal_pk(xpub_origin: XkeyOrigin, terminal: Terminal) -> Self {
246 let origin = KeyOrigin::with(xpub_origin, terminal);
247 TapDerivation {
248 leaf_hashes: empty!(),
249 origin,
250 }
251 }
252}