Skip to main content

md_codec/
tree.rs

1//! Tree (operator AST) per spec §3.6 + §6.
2
3use crate::bitstream::{BitReader, BitWriter};
4use crate::error::Error;
5use crate::tag::Tag;
6
7/// A node in the operator AST: a tag plus its body.
8#[derive(Debug, Clone, PartialEq, Eq)]
9pub struct Node {
10    /// Operator tag identifying this node's kind.
11    pub tag: Tag,
12    /// Body fields and/or children, shape determined by `tag`.
13    pub body: Body,
14}
15
16/// Body shape for a [`Node`], determined by its [`Tag`].
17#[derive(Debug, Clone, PartialEq, Eq)]
18pub enum Body {
19    /// No body fields beyond N child nodes (Class 1 fixed-arity).
20    Children(Vec<Node>),
21    /// Variable-arity body for `Tag::Thresh` only (post-v0.30 Phase C).
22    /// Encodes `k` + N child Nodes. Multi-family tags use [`Body::MultiKeys`]
23    /// per SPEC v0.30 §4.
24    Variable {
25        /// Threshold `k`.
26        k: u8,
27        /// Child nodes; `n = children.len()`.
28        children: Vec<Node>,
29    },
30    /// Multi-family body (`Tag::Multi`, `SortedMulti`, `MultiA`,
31    /// `SortedMultiA`): k-of-n with raw `kiw`-width key indices, NOT full
32    /// child Nodes. Per SPEC v0.30 §4: wire layout is
33    /// `tag | (k-1)(5) | (n-1)(5) | n × index(kiw)`.
34    MultiKeys {
35        /// Threshold `k`.
36        k: u8,
37        /// Placeholder indices `@i`; `n = indices.len()`. Each entry is
38        /// emitted as `kiw` bits.
39        indices: Vec<u8>,
40    },
41    /// Tr's body: NUMS flag, key index, optional tap-script-tree root.
42    /// Per SPEC v0.30 §7: wire shape is
43    /// `Tag::Tr | is_nums(1) | [key_index(kiw) iff !is_nums] | has_tree(1) | [tree iff has_tree]`.
44    /// When `is_nums = true`, the internal key is the BIP-341 NUMS H-point
45    /// `50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0`
46    /// and `key_index` is unused on the wire (encoder writes 0 by convention;
47    /// decoder ignores). When `is_nums = false`, `key_index` is a `0..n`
48    /// placeholder index encoded at `kiw` bits.
49    Tr {
50        /// `true` iff the internal key is the BIP-341 NUMS H-point.
51        is_nums: bool,
52        /// Internal-key index into the descriptor's key table. Unused when
53        /// `is_nums = true` (no wire representation).
54        key_index: u8,
55        /// Optional tap-script-tree root.
56        tree: Option<Box<Node>>,
57    },
58    /// Single key-arg (Pkh, Wpkh, PkK, PkH, multi-family children).
59    /// Wire bit-width for `index` is determined by the parent Descriptor's
60    /// key_index_width(); not carried in the AST.
61    KeyArg {
62        /// Key index into the descriptor's key table.
63        index: u8,
64    },
65    /// 256-bit hash literal (Sha256, Hash256).
66    Hash256Body([u8; 32]),
67    /// 160-bit hash literal (Hash160, Ripemd160, RawPkH).
68    Hash160Body([u8; 20]),
69    /// 32-bit Bitcoin-native u32 (After, Older).
70    Timelock(u32),
71    /// No body (False, True).
72    Empty,
73}
74
75/// Encode a [`Node`] to the bit stream.
76///
77/// `key_index_width` is the bit width used for key-index fields, derived from
78/// the descriptor's path-decl head. Filled in across phases 7-11.
79pub fn write_node(w: &mut BitWriter, node: &Node, key_index_width: u8) -> Result<(), Error> {
80    node.tag.write(w);
81    match &node.body {
82        Body::KeyArg { index } => {
83            w.write_bits(u64::from(*index), key_index_width as usize);
84        }
85        Body::Children(children) => {
86            for c in children {
87                write_node(w, c, key_index_width)?;
88            }
89        }
90        Body::Variable { k, children } => {
91            // Thresh-only post-v0.30 Phase C. Encode k-1 in 5 bits per spec §4.2.
92            if !(1..=32).contains(&(*k as u32)) {
93                return Err(Error::ThresholdOutOfRange { k: *k });
94            }
95            if !(1..=32).contains(&(children.len() as u32)) {
96                return Err(Error::ChildCountOutOfRange {
97                    count: children.len(),
98                });
99            }
100            // Reject k > n at encode, mirroring the decode-side reject below
101            // (KGreaterThanN). Without this the encoder emits a card no decoder
102            // will read back — an engrave-but-can't-restore gap.
103            if *k as usize > children.len() {
104                return Err(Error::KGreaterThanN {
105                    k: *k,
106                    n: children.len(),
107                });
108            }
109            w.write_bits((*k - 1) as u64, 5);
110            w.write_bits((children.len() - 1) as u64, 5);
111            for c in children {
112                write_node(w, c, key_index_width)?;
113            }
114        }
115        Body::MultiKeys { k, indices } => {
116            // Multi-family per SPEC v0.30 §4: k-of-n + raw kiw-width indices.
117            if !(1..=32).contains(&(*k as u32)) {
118                return Err(Error::ThresholdOutOfRange { k: *k });
119            }
120            if !(1..=32).contains(&(indices.len() as u32)) {
121                return Err(Error::ChildCountOutOfRange {
122                    count: indices.len(),
123                });
124            }
125            // Reject k > n at encode, mirroring the decode-side reject below
126            // (KGreaterThanN). Without this the encoder emits a card no decoder
127            // will read back — an engrave-but-can't-restore gap.
128            if *k as usize > indices.len() {
129                return Err(Error::KGreaterThanN {
130                    k: *k,
131                    n: indices.len(),
132                });
133            }
134            w.write_bits((*k - 1) as u64, 5);
135            w.write_bits((indices.len() - 1) as u64, 5);
136            for idx in indices {
137                w.write_bits(u64::from(*idx), key_index_width as usize);
138            }
139        }
140        Body::Tr {
141            is_nums,
142            key_index,
143            tree,
144        } => {
145            // SPEC v0.30 §7: is_nums(1) | [key_index(kiw) iff !is_nums] |
146            // has_tree(1) | [tree iff has_tree].
147            debug_assert!(
148                !(*is_nums && *key_index != 0),
149                "is_nums=true implies key_index=0 (no wire representation otherwise)"
150            );
151            w.write_bits(u64::from(*is_nums), 1);
152            if !*is_nums {
153                w.write_bits(u64::from(*key_index), key_index_width as usize);
154            }
155            w.write_bits(u64::from(tree.is_some()), 1);
156            if let Some(t) = tree {
157                write_node(w, t, key_index_width)?;
158            }
159        }
160        Body::Timelock(v) => {
161            w.write_bits(u64::from(*v), 32);
162        }
163        Body::Hash256Body(h) => {
164            for byte in h {
165                w.write_bits(u64::from(*byte), 8);
166            }
167        }
168        Body::Hash160Body(h) => {
169            for byte in h {
170                w.write_bits(u64::from(*byte), 8);
171            }
172        }
173        Body::Empty => {}
174    }
175    Ok(())
176}
177
178/// Hard cap on `read_node` recursion depth. Shared across all recursive tags
179/// (`Sh`, `AndV`, `AndOr`, `TapTree`, `Multi`, `Tr`, …) as a generic anti-DOS
180/// hardening bound — not a spec-mandated value for non-taproot sites. The
181/// value 128 happens to coincide with BIP-341 `TAPROOT_CONTROL_MAX_NODE_COUNT`,
182/// but its role here is just "any depth a real miniscript expression could
183/// plausibly reach + headroom"; P2WSH script-size limits cap practical
184/// miniscript depth at well under 50.
185pub const MAX_DECODE_DEPTH: u8 = 128;
186
187/// Decode a [`Node`] from the bit stream.
188///
189/// `key_index_width` is the bit width used for key-index fields, derived from
190/// the descriptor's path-decl head. Filled in across phases 7-11.
191///
192/// Top-level entry point. Internally threads a recursion-depth counter that
193/// errors out at [`MAX_DECODE_DEPTH`] before parsing the next node, so a
194/// hostile wire payload nesting recursive tags (`Tag::Sh`, `Tag::AndV`,
195/// `Tag::TapTree`, etc.) arbitrarily deep cannot blow the Rust stack.
196pub fn read_node(r: &mut BitReader, key_index_width: u8) -> Result<Node, Error> {
197    read_node_with_depth(r, key_index_width, 0)
198}
199
200/// Inner recursive form of `read_node` that threads `depth`. Public callers
201/// should use `read_node` instead, which starts at depth 0. Increments
202/// `depth` once per call and errors if it reaches [`MAX_DECODE_DEPTH`].
203fn read_node_with_depth(r: &mut BitReader, key_index_width: u8, depth: u8) -> Result<Node, Error> {
204    if depth >= MAX_DECODE_DEPTH {
205        return Err(Error::DecodeRecursionDepthExceeded {
206            depth,
207            max: MAX_DECODE_DEPTH,
208        });
209    }
210    let tag = Tag::read(r)?;
211    let body = match tag {
212        Tag::PkK | Tag::PkH | Tag::Wpkh | Tag::Pkh => {
213            let index = r.read_bits(key_index_width as usize)? as u8;
214            Body::KeyArg { index }
215        }
216        Tag::Sh
217        | Tag::Wsh
218        | Tag::Check
219        | Tag::Verify
220        | Tag::Swap
221        | Tag::Alt
222        | Tag::DupIf
223        | Tag::NonZero
224        | Tag::ZeroNotEqual => {
225            let child = read_node_with_depth(r, key_index_width, depth + 1)?;
226            Body::Children(vec![child])
227        }
228        Tag::AndV | Tag::AndB | Tag::OrB | Tag::OrC | Tag::OrD | Tag::OrI => {
229            let l = read_node_with_depth(r, key_index_width, depth + 1)?;
230            let r2 = read_node_with_depth(r, key_index_width, depth + 1)?;
231            Body::Children(vec![l, r2])
232        }
233        Tag::AndOr => {
234            let a = read_node_with_depth(r, key_index_width, depth + 1)?;
235            let b = read_node_with_depth(r, key_index_width, depth + 1)?;
236            let c = read_node_with_depth(r, key_index_width, depth + 1)?;
237            Body::Children(vec![a, b, c])
238        }
239        Tag::TapTree => {
240            let l = read_node_with_depth(r, key_index_width, depth + 1)?;
241            let r2 = read_node_with_depth(r, key_index_width, depth + 1)?;
242            Body::Children(vec![l, r2])
243        }
244        Tag::Multi | Tag::SortedMulti | Tag::MultiA | Tag::SortedMultiA => {
245            let k = (r.read_bits(5)? + 1) as u8;
246            let count = (r.read_bits(5)? + 1) as usize;
247            if k as usize > count {
248                return Err(Error::KGreaterThanN { k, n: count });
249            }
250            let mut indices = Vec::with_capacity(count);
251            for _ in 0..count {
252                indices.push(r.read_bits(key_index_width as usize)? as u8);
253            }
254            Body::MultiKeys { k, indices }
255        }
256        Tag::Thresh => {
257            let k = (r.read_bits(5)? + 1) as u8;
258            let count = (r.read_bits(5)? + 1) as usize;
259            if k as usize > count {
260                return Err(Error::KGreaterThanN { k, n: count });
261            }
262            let mut children = Vec::with_capacity(count);
263            for _ in 0..count {
264                children.push(read_node_with_depth(r, key_index_width, depth + 1)?);
265            }
266            Body::Variable { k, children }
267        }
268        Tag::Tr => {
269            // SPEC v0.30 §7: is_nums(1) | [key_index(kiw) iff !is_nums] |
270            // has_tree(1) | [tree iff has_tree].
271            let is_nums = r.read_bits(1)? != 0;
272            let key_index = if is_nums {
273                0
274            } else {
275                r.read_bits(key_index_width as usize)? as u8
276            };
277            let has_tree = r.read_bits(1)? != 0;
278            let tree = if has_tree {
279                Some(Box::new(read_node_with_depth(
280                    r,
281                    key_index_width,
282                    depth + 1,
283                )?))
284            } else {
285                None
286            };
287            Body::Tr {
288                is_nums,
289                key_index,
290                tree,
291            }
292        }
293        Tag::After | Tag::Older => {
294            let v = r.read_bits(32)? as u32;
295            Body::Timelock(v)
296        }
297        Tag::Sha256 => {
298            let mut h = [0u8; 32];
299            for byte in &mut h {
300                *byte = r.read_bits(8)? as u8;
301            }
302            Body::Hash256Body(h)
303        }
304        Tag::Hash160 => {
305            let mut h = [0u8; 20];
306            for byte in &mut h {
307                *byte = r.read_bits(8)? as u8;
308            }
309            Body::Hash160Body(h)
310        }
311        Tag::Hash256 => {
312            let mut h = [0u8; 32];
313            for byte in &mut h {
314                *byte = r.read_bits(8)? as u8;
315            }
316            Body::Hash256Body(h)
317        }
318        Tag::Ripemd160 | Tag::RawPkH => {
319            let mut h = [0u8; 20];
320            for byte in &mut h {
321                *byte = r.read_bits(8)? as u8;
322            }
323            Body::Hash160Body(h)
324        }
325        Tag::False | Tag::True => Body::Empty,
326    };
327    Ok(Node { tag, body })
328}
329
330#[cfg(test)]
331mod tests {
332    use super::*;
333    use crate::bitstream::{BitReader, BitWriter};
334
335    #[test]
336    fn key_arg_n1_zero_bits() {
337        // v0.30: at n=1, kiw = ⌈log₂(1)⌉ = 0; key-arg emits zero bits.
338        let n = Node {
339            tag: Tag::PkK,
340            body: Body::KeyArg { index: 0 },
341        };
342        let mut w = BitWriter::new();
343        write_node(&mut w, &n, 0).unwrap();
344        // Tag::PkK (6 bits) + key-arg (0 bits) = 6 bits total.
345        assert_eq!(w.bit_len(), 6);
346    }
347
348    #[test]
349    fn key_arg_n3_two_bits() {
350        // v0.30: at n=3, kiw = ⌈log₂(3)⌉ = 2.
351        let n = Node {
352            tag: Tag::PkK,
353            body: Body::KeyArg { index: 2 },
354        };
355        let mut w = BitWriter::new();
356        write_node(&mut w, &n, 2).unwrap();
357        // Tag::PkK (6 bits) + key-arg (2 bits) = 8 bits total.
358        assert_eq!(w.bit_len(), 8);
359    }
360
361    #[test]
362    fn key_arg_round_trip() {
363        let n = Node {
364            tag: Tag::PkK,
365            body: Body::KeyArg { index: 1 },
366        };
367        let mut w = BitWriter::new();
368        write_node(&mut w, &n, 2).unwrap();
369        let bytes = w.into_bytes();
370        let mut r = BitReader::new(&bytes);
371        assert_eq!(read_node(&mut r, 2).unwrap(), n);
372    }
373
374    #[test]
375    fn wrapper_chain_v_c_pk_round_trip() {
376        // v:c:pk_k(@0) — three nested wrappers around PkK
377        let n = Node {
378            tag: Tag::Verify,
379            body: Body::Children(vec![Node {
380                tag: Tag::Check,
381                body: Body::Children(vec![Node {
382                    tag: Tag::PkK,
383                    body: Body::KeyArg { index: 0 },
384                }]),
385            }]),
386        };
387        let mut w = BitWriter::new();
388        write_node(&mut w, &n, 2).unwrap();
389        let bytes = w.into_bytes();
390        let mut r = BitReader::new(&bytes);
391        assert_eq!(read_node(&mut r, 2).unwrap(), n);
392    }
393
394    #[test]
395    fn sortedmulti_2of3_round_trip() {
396        let n = Node {
397            tag: Tag::SortedMulti,
398            body: Body::MultiKeys {
399                k: 2,
400                indices: vec![0, 1, 2],
401            },
402        };
403        let mut w = BitWriter::new();
404        write_node(&mut w, &n, 2).unwrap();
405        let bytes = w.into_bytes();
406        let mut r = BitReader::new(&bytes);
407        assert_eq!(read_node(&mut r, 2).unwrap(), n);
408    }
409
410    /// v0.30 Phase C — multi packing bit-cost pin.
411    /// `Tag(6-bit) | k-1(5) | n-1(5) | 3×kiw(2 at n=3) = 22 bits` (SPEC §4.2).
412    /// Saves 14 bits over v0.x's per-child encoding (which was 36 bits).
413    #[test]
414    fn sortedmulti_2of3_bit_cost() {
415        let n = Node {
416            tag: Tag::SortedMulti,
417            body: Body::MultiKeys {
418                k: 2,
419                indices: vec![0, 1, 2],
420            },
421        };
422        let mut w = BitWriter::new();
423        write_node(&mut w, &n, 2).unwrap();
424        assert_eq!(w.bit_len(), 22);
425    }
426
427    /// v0.30 Phase C — `Body::MultiKeys` round-trips under `Tag::Multi`.
428    #[test]
429    fn multi_keys_body_round_trip() {
430        let n = Node {
431            tag: Tag::Multi,
432            body: Body::MultiKeys {
433                k: 2,
434                indices: vec![0, 1, 2],
435            },
436        };
437        let mut w = BitWriter::new();
438        write_node(&mut w, &n, 2).unwrap();
439        let bytes = w.into_bytes();
440        let mut r = BitReader::new(&bytes);
441        assert_eq!(read_node(&mut r, 2).unwrap(), n);
442    }
443
444    /// v0.30 Phase C — `Body::MultiKeys` round-trips under `Tag::SortedMultiA`.
445    #[test]
446    fn sortedmulti_a_indices_round_trip() {
447        let n = Node {
448            tag: Tag::SortedMultiA,
449            body: Body::MultiKeys {
450                k: 2,
451                indices: vec![0, 1, 2],
452            },
453        };
454        let mut w = BitWriter::new();
455        write_node(&mut w, &n, 2).unwrap();
456        let bytes = w.into_bytes();
457        let mut r = BitReader::new(&bytes);
458        assert_eq!(read_node(&mut r, 2).unwrap(), n);
459    }
460
461    #[test]
462    fn tr_bip86_no_tree() {
463        // v0.30: tr(@0) keypath-only at synthetic width=0 (n=1 in Descriptor
464        // would yield kiw=0). Exercises the zero-width edge of write_node /
465        // read_node directly.
466        let n = Node {
467            tag: Tag::Tr,
468            body: Body::Tr {
469                is_nums: false,
470                key_index: 0,
471                tree: None,
472            },
473        };
474        let mut w = BitWriter::new();
475        write_node(&mut w, &n, 0).unwrap();
476        // Tag::Tr (6) + is_nums (1) + key_index (0, kiw=0) + has_tree (1) = 8 bits.
477        assert_eq!(w.bit_len(), 8);
478        let bytes = w.into_bytes();
479        let mut r = BitReader::new(&bytes);
480        assert_eq!(read_node(&mut r, 0).unwrap(), n);
481    }
482
483    #[test]
484    fn thresh_2of3_with_pk_children() {
485        // thresh(2, pk_k(@0), pk_k(@1), pk_k(@2))
486        let n = Node {
487            tag: Tag::Thresh,
488            body: Body::Variable {
489                k: 2,
490                children: vec![
491                    Node {
492                        tag: Tag::PkK,
493                        body: Body::KeyArg { index: 0 },
494                    },
495                    Node {
496                        tag: Tag::PkK,
497                        body: Body::KeyArg { index: 1 },
498                    },
499                    Node {
500                        tag: Tag::PkK,
501                        body: Body::KeyArg { index: 2 },
502                    },
503                ],
504            },
505        };
506        let mut w = BitWriter::new();
507        write_node(&mut w, &n, 2).unwrap();
508        let bytes = w.into_bytes();
509        let mut r = BitReader::new(&bytes);
510        assert_eq!(read_node(&mut r, 2).unwrap(), n);
511    }
512
513    #[test]
514    fn tr_with_single_leaf() {
515        // tr(@0, multi_a(2, @1, @2))
516        let n = Node {
517            tag: Tag::Tr,
518            body: Body::Tr {
519                is_nums: false,
520                key_index: 0,
521                tree: Some(Box::new(Node {
522                    tag: Tag::MultiA,
523                    body: Body::MultiKeys {
524                        k: 2,
525                        indices: vec![1, 2],
526                    },
527                })),
528            },
529        };
530        let mut w = BitWriter::new();
531        write_node(&mut w, &n, 2).unwrap();
532        let bytes = w.into_bytes();
533        let mut r = BitReader::new(&bytes);
534        assert_eq!(read_node(&mut r, 2).unwrap(), n);
535    }
536
537    /// v0.30 Phase F — `Body::Tr { is_nums: true, .. }` round-trips. NUMS
538    /// suppresses the kiw field on the wire entirely.
539    #[test]
540    fn tr_nums_flag_round_trip() {
541        let n = Node {
542            tag: Tag::Tr,
543            body: Body::Tr {
544                is_nums: true,
545                key_index: 0,
546                tree: None,
547            },
548        };
549        let mut w = BitWriter::new();
550        write_node(&mut w, &n, 2).unwrap();
551        let bytes = w.into_bytes();
552        let mut r = BitReader::new(&bytes);
553        assert_eq!(read_node(&mut r, 2).unwrap(), n);
554    }
555
556    /// v0.30 Phase F — `Body::Tr { is_nums: false, key_index, .. }` round-
557    /// trips with explicit key_index written at kiw width.
558    #[test]
559    fn tr_is_nums_false_round_trip() {
560        let n = Node {
561            tag: Tag::Tr,
562            body: Body::Tr {
563                is_nums: false,
564                key_index: 2,
565                tree: None,
566            },
567        };
568        let mut w = BitWriter::new();
569        write_node(&mut w, &n, 2).unwrap();
570        let bytes = w.into_bytes();
571        let mut r = BitReader::new(&bytes);
572        assert_eq!(read_node(&mut r, 2).unwrap(), n);
573    }
574
575    #[test]
576    fn after_700_000_round_trip() {
577        let n = Node {
578            tag: Tag::After,
579            body: Body::Timelock(700_000),
580        };
581        let mut w = BitWriter::new();
582        write_node(&mut w, &n, 0).unwrap();
583        // Tag(6) + u32(32) = 38 bits
584        assert_eq!(w.bit_len(), 38);
585        let bytes = w.into_bytes();
586        let mut r = BitReader::new(&bytes);
587        assert_eq!(read_node(&mut r, 0).unwrap(), n);
588    }
589
590    #[test]
591    fn sha256_round_trip() {
592        let h = [0xab; 32];
593        let n = Node {
594            tag: Tag::Sha256,
595            body: Body::Hash256Body(h),
596        };
597        let mut w = BitWriter::new();
598        write_node(&mut w, &n, 0).unwrap();
599        // Tag(6) + 256 = 262 bits
600        assert_eq!(w.bit_len(), 262);
601        let bytes = w.into_bytes();
602        let mut r = BitReader::new(&bytes);
603        assert_eq!(read_node(&mut r, 0).unwrap(), n);
604    }
605
606    #[test]
607    fn hash160_round_trip() {
608        let h = [0xcd; 20];
609        let n = Node {
610            tag: Tag::Hash160,
611            body: Body::Hash160Body(h),
612        };
613        let mut w = BitWriter::new();
614        write_node(&mut w, &n, 0).unwrap();
615        // Tag(6) + 160 = 166 bits
616        assert_eq!(w.bit_len(), 166);
617        let bytes = w.into_bytes();
618        let mut r = BitReader::new(&bytes);
619        assert_eq!(read_node(&mut r, 0).unwrap(), n);
620    }
621
622    #[test]
623    fn hash256_round_trip() {
624        let h = [0xef; 32];
625        let n = Node {
626            tag: Tag::Hash256,
627            body: Body::Hash256Body(h),
628        };
629        let mut w = BitWriter::new();
630        write_node(&mut w, &n, 0).unwrap();
631        // Tag(6) + 256 = 262 bits (Hash256 primary 0x1F in v0.30).
632        assert_eq!(w.bit_len(), 262);
633        let bytes = w.into_bytes();
634        let mut r = BitReader::new(&bytes);
635        assert_eq!(read_node(&mut r, 0).unwrap(), n);
636    }
637
638    #[test]
639    fn ripemd160_round_trip() {
640        let h = [0x42; 20];
641        let n = Node {
642            tag: Tag::Ripemd160,
643            body: Body::Hash160Body(h),
644        };
645        let mut w = BitWriter::new();
646        write_node(&mut w, &n, 0).unwrap();
647        let bytes = w.into_bytes();
648        let mut r = BitReader::new(&bytes);
649        assert_eq!(read_node(&mut r, 0).unwrap(), n);
650    }
651
652    #[test]
653    fn false_round_trip() {
654        let n = Node {
655            tag: Tag::False,
656            body: Body::Empty,
657        };
658        let mut w = BitWriter::new();
659        write_node(&mut w, &n, 0).unwrap();
660        assert_eq!(w.bit_len(), 6); // Tag(6), no body (False primary 0x22 in v0.30)
661        let bytes = w.into_bytes();
662        let mut r = BitReader::new(&bytes);
663        assert_eq!(read_node(&mut r, 0).unwrap(), n);
664    }
665
666    #[test]
667    fn true_round_trip() {
668        let n = Node {
669            tag: Tag::True,
670            body: Body::Empty,
671        };
672        let mut w = BitWriter::new();
673        write_node(&mut w, &n, 0).unwrap();
674        let bytes = w.into_bytes();
675        let mut r = BitReader::new(&bytes);
676        assert_eq!(read_node(&mut r, 0).unwrap(), n);
677    }
678
679    #[test]
680    fn older_144_round_trip() {
681        let n = Node {
682            tag: Tag::Older,
683            body: Body::Timelock(144),
684        };
685        let mut w = BitWriter::new();
686        write_node(&mut w, &n, 0).unwrap();
687        let bytes = w.into_bytes();
688        let mut r = BitReader::new(&bytes);
689        assert_eq!(read_node(&mut r, 0).unwrap(), n);
690    }
691
692    #[test]
693    fn tr_nums_n_1_bare_round_trip() {
694        // v0.30: tr(<NUMS>) with no script tree at n=1. NUMS is now signalled
695        // via the `is_nums` flag, not a reserved sentinel `key_index`. At n=1
696        // the v0.30 kiw is 0 — but `is_nums=true` suppresses the kiw write
697        // entirely, so the kiw width is irrelevant here.
698        let n = Node {
699            tag: Tag::Tr,
700            body: Body::Tr {
701                is_nums: true,
702                key_index: 0,
703                tree: None,
704            },
705        };
706        let mut w = BitWriter::new();
707        // kiw=0 at n=1 (irrelevant — is_nums=true suppresses the kiw field).
708        write_node(&mut w, &n, 0).unwrap();
709        // Tag::Tr (6) + is_nums (1) + has_tree (1) = 8 bits.
710        assert_eq!(w.bit_len(), 8);
711        let bytes = w.into_bytes();
712        let mut r = BitReader::new(&bytes);
713        assert_eq!(read_node(&mut r, 0).unwrap(), n);
714    }
715
716    #[test]
717    fn tr_nums_n_2_and_v_inheritance_round_trip() {
718        // v0.30: tr(<NUMS>, and_v(v:pk(@0), pk(@1))) — inheritance pattern via
719        // NUMS internal key, signalled by `is_nums = true`. Exercises and_v +
720        // verify wrapper inside the script-path branch.
721        let n = Node {
722            tag: Tag::Tr,
723            body: Body::Tr {
724                is_nums: true,
725                key_index: 0,
726                tree: Some(Box::new(Node {
727                    tag: Tag::AndV,
728                    body: Body::Children(vec![
729                        Node {
730                            tag: Tag::Verify,
731                            body: Body::Children(vec![Node {
732                                tag: Tag::PkK,
733                                body: Body::KeyArg { index: 0 },
734                            }]),
735                        },
736                        Node {
737                            tag: Tag::PkK,
738                            body: Body::KeyArg { index: 1 },
739                        },
740                    ]),
741                })),
742            },
743        };
744        let mut w = BitWriter::new();
745        // v0.30 width at n=2: ⌈log₂(2)⌉ = 1.
746        write_node(&mut w, &n, 1).unwrap();
747        let bytes = w.into_bytes();
748        let mut r = BitReader::new(&bytes);
749        assert_eq!(read_node(&mut r, 1).unwrap(), n);
750    }
751
752    #[test]
753    fn tr_nums_n_3_multi_a_2_of_3_round_trip() {
754        // v0.30: tr(<NUMS>, multi_a(2, @0, @1, @2)) — the canonical 2-of-3
755        // hardware-wallet multisig encoding (the headline use case). NUMS
756        // signalled by `is_nums = true`. At n=3 the v0.30 kiw is 2.
757        let n = Node {
758            tag: Tag::Tr,
759            body: Body::Tr {
760                is_nums: true,
761                key_index: 0,
762                tree: Some(Box::new(Node {
763                    tag: Tag::MultiA,
764                    body: Body::MultiKeys {
765                        k: 2,
766                        indices: vec![0, 1, 2],
767                    },
768                })),
769            },
770        };
771        let mut w = BitWriter::new();
772        write_node(&mut w, &n, 2).unwrap();
773        let bytes = w.into_bytes();
774        let mut r = BitReader::new(&bytes);
775        assert_eq!(read_node(&mut r, 2).unwrap(), n);
776    }
777
778    #[test]
779    fn tr_nums_n_4_bare_round_trip() {
780        // v0.30: tr(<NUMS>) at n=4. NUMS signalled by `is_nums = true`. At
781        // n=4 the v0.30 kiw is ⌈log₂(4)⌉ = 2; is_nums=true suppresses the
782        // kiw field, so it's irrelevant here.
783        let n = Node {
784            tag: Tag::Tr,
785            body: Body::Tr {
786                is_nums: true,
787                key_index: 0,
788                tree: None,
789            },
790        };
791        let mut w = BitWriter::new();
792        // kiw=2 at n=4 (irrelevant — is_nums=true suppresses the kiw field).
793        write_node(&mut w, &n, 2).unwrap();
794        // Tag::Tr (6) + is_nums (1) + has_tree (1) = 8 bits.
795        assert_eq!(w.bit_len(), 8);
796        let bytes = w.into_bytes();
797        let mut r = BitReader::new(&bytes);
798        assert_eq!(read_node(&mut r, 2).unwrap(), n);
799    }
800
801    /// v0.19 — multi-branch tap tree wire-format round-trip. Closes audit
802    /// Concern B (no codec-level tests for `Tag::TapTree` with branching
803    /// existed before v0.19; multi-branch was previously walker-rejected
804    /// so there was no real input that exercised this wire shape).
805    /// `tr(@0, {pk(@1), pk(@2)})` with key_index_width=2.
806    /// Bit-length pin (v0.30): Tag::Tr (6) + is_nums (1) + kiw (2) + has_tree (1)
807    ///                 + Tag::TapTree (6) + 2×(Tag::PkK (6) + kiw (2)) = 32 bits.
808    #[test]
809    fn tap_tree_two_leaf_round_trip() {
810        let n = Node {
811            tag: Tag::Tr,
812            body: Body::Tr {
813                is_nums: false,
814                key_index: 0,
815                tree: Some(Box::new(Node {
816                    tag: Tag::TapTree,
817                    body: Body::Children(vec![
818                        Node {
819                            tag: Tag::PkK,
820                            body: Body::KeyArg { index: 1 },
821                        },
822                        Node {
823                            tag: Tag::PkK,
824                            body: Body::KeyArg { index: 2 },
825                        },
826                    ]),
827                })),
828            },
829        };
830        let mut w = BitWriter::new();
831        write_node(&mut w, &n, 2).unwrap();
832        assert_eq!(w.bit_len(), 32, "2-leaf TapTree wire layout pin");
833        let bytes = w.into_bytes();
834        let mut r = BitReader::new(&bytes);
835        assert_eq!(read_node(&mut r, 2).unwrap(), n);
836    }
837
838    /// v0.19 — 4-leaf nested multi-branch tap tree:
839    /// `tr(@0, {{pk(@1),pk(@2)}, {pk(@3),pk(@4)}})`. Verifies recursion
840    /// through `read_node`/`write_node` on nested Tag::TapTree.
841    #[test]
842    fn tap_tree_nested_four_leaf_round_trip() {
843        let mk_branch = |a: u8, b: u8| Node {
844            tag: Tag::TapTree,
845            body: Body::Children(vec![
846                Node {
847                    tag: Tag::PkK,
848                    body: Body::KeyArg { index: a },
849                },
850                Node {
851                    tag: Tag::PkK,
852                    body: Body::KeyArg { index: b },
853                },
854            ]),
855        };
856        let n = Node {
857            tag: Tag::Tr,
858            body: Body::Tr {
859                is_nums: false,
860                key_index: 0,
861                tree: Some(Box::new(Node {
862                    tag: Tag::TapTree,
863                    body: Body::Children(vec![mk_branch(1, 2), mk_branch(3, 4)]),
864                })),
865            },
866        };
867        let mut w = BitWriter::new();
868        // 5 distinct indices (0..=4) → v0.30 kiw = ⌈log₂(5)⌉ = 3.
869        write_node(&mut w, &n, 3).unwrap();
870        let bytes = w.into_bytes();
871        let mut r = BitReader::new(&bytes);
872        assert_eq!(read_node(&mut r, 3).unwrap(), n);
873    }
874
875    /// v0.19 — 3-leaf unbalanced: `tr(@0, {pk(@1), {pk(@2),pk(@3)}})`.
876    /// Asymmetric shape — the right child is a TapTree, the left is a
877    /// bare PkK leaf. Verifies the wire format doesn't require balanced
878    /// trees.
879    #[test]
880    fn tap_tree_unbalanced_round_trip() {
881        let n = Node {
882            tag: Tag::Tr,
883            body: Body::Tr {
884                is_nums: false,
885                key_index: 0,
886                tree: Some(Box::new(Node {
887                    tag: Tag::TapTree,
888                    body: Body::Children(vec![
889                        Node {
890                            tag: Tag::PkK,
891                            body: Body::KeyArg { index: 1 },
892                        },
893                        Node {
894                            tag: Tag::TapTree,
895                            body: Body::Children(vec![
896                                Node {
897                                    tag: Tag::PkK,
898                                    body: Body::KeyArg { index: 2 },
899                                },
900                                Node {
901                                    tag: Tag::PkK,
902                                    body: Body::KeyArg { index: 3 },
903                                },
904                            ]),
905                        },
906                    ]),
907                })),
908            },
909        };
910        let mut w = BitWriter::new();
911        // v0.30 kiw at n=3: ⌈log₂(3)⌉ = 2.
912        write_node(&mut w, &n, 2).unwrap();
913        let bytes = w.into_bytes();
914        let mut r = BitReader::new(&bytes);
915        assert_eq!(read_node(&mut r, 2).unwrap(), n);
916    }
917
918    /// v0.19 hardening — reject deeply-nested TapTree on the decode side.
919    /// Encode-side has no cap (input here is a programmatically-constructed
920    /// Node tree, not from the walker), but the decode-side cap fires
921    /// when the deepest left-child read attempts at depth MAX_DECODE_DEPTH.
922    #[test]
923    fn read_node_rejects_excessive_taptree_nesting() {
924        let mut left = Node {
925            tag: Tag::PkK,
926            body: Body::KeyArg { index: 0 },
927        };
928        // 128 TapTree wrappers: deepest leaf ends up at depth 128 on the
929        // left chain; cap fires when reading that leaf.
930        for _ in 0..128 {
931            left = Node {
932                tag: Tag::TapTree,
933                body: Body::Children(vec![
934                    left,
935                    Node {
936                        tag: Tag::PkK,
937                        body: Body::KeyArg { index: 0 },
938                    },
939                ]),
940            };
941        }
942        let mut w = BitWriter::new();
943        write_node(&mut w, &left, 0).unwrap();
944        let bytes = w.into_bytes();
945        let mut r = BitReader::new(&bytes);
946        let err = read_node(&mut r, 0).unwrap_err();
947        assert_eq!(
948            err,
949            Error::DecodeRecursionDepthExceeded {
950                depth: 128,
951                max: MAX_DECODE_DEPTH,
952            }
953        );
954    }
955
956    /// v0.19 hardening — cap is tag-agnostic; fires for non-taproot
957    /// recursive tags (AndV chain) the same way it fires for TapTree.
958    #[test]
959    fn read_node_rejects_excessive_andv_chain_nesting() {
960        let mut left = Node {
961            tag: Tag::PkK,
962            body: Body::KeyArg { index: 0 },
963        };
964        // 128 AndV wrappers on the left, with PkK leaves on the right at
965        // each level. Deepest left-leaf at depth 128 triggers the cap.
966        for _ in 0..128 {
967            left = Node {
968                tag: Tag::AndV,
969                body: Body::Children(vec![
970                    left,
971                    Node {
972                        tag: Tag::PkK,
973                        body: Body::KeyArg { index: 0 },
974                    },
975                ]),
976            };
977        }
978        let mut w = BitWriter::new();
979        write_node(&mut w, &left, 0).unwrap();
980        let bytes = w.into_bytes();
981        let mut r = BitReader::new(&bytes);
982        let err = read_node(&mut r, 0).unwrap_err();
983        assert_eq!(
984            err,
985            Error::DecodeRecursionDepthExceeded {
986                depth: 128,
987                max: MAX_DECODE_DEPTH,
988            }
989        );
990    }
991
992    /// v0.19 hardening — depth exactly at the limit (deepest leaf at
993    /// depth 127, one shy of MAX_DECODE_DEPTH) round-trips successfully.
994    #[test]
995    fn read_node_accepts_max_depth_minus_one() {
996        let mut left = Node {
997            tag: Tag::PkK,
998            body: Body::KeyArg { index: 0 },
999        };
1000        // 127 TapTree wrappers: deepest leaf at depth 127, just under cap.
1001        for _ in 0..127 {
1002            left = Node {
1003                tag: Tag::TapTree,
1004                body: Body::Children(vec![
1005                    left,
1006                    Node {
1007                        tag: Tag::PkK,
1008                        body: Body::KeyArg { index: 0 },
1009                    },
1010                ]),
1011            };
1012        }
1013        let mut w = BitWriter::new();
1014        write_node(&mut w, &left, 0).unwrap();
1015        let bytes = w.into_bytes();
1016        let mut r = BitReader::new(&bytes);
1017        let decoded = read_node(&mut r, 0).unwrap();
1018        assert_eq!(decoded, left);
1019    }
1020}