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