@@ -47,6 +47,46 @@ impl BitStack128 {
4747 }
4848}
4949
50+ /// Stack of `(bool, usize)` elements, with a maximum capacity of 128.
51+ ///
52+ /// Used to replace `Vec<(bool, usize)>` in recursive algorithms to avoid heap allocation.
53+ struct ParentStack {
54+ data : [ ( bool , usize ) ; 128 ] ,
55+ len : usize ,
56+ }
57+
58+ impl ParentStack {
59+ fn new ( ) -> Self {
60+ Self {
61+ data : [ ( false , 0 ) ; 128 ] ,
62+ len : 0 ,
63+ }
64+ }
65+
66+ fn push ( & mut self , val : ( bool , usize ) ) {
67+ // We know that the depth is limited to 128 by the bounds check in `TapTree::combine`
68+ // and other places, so this strictly shouldn't happen with valid trees.
69+ debug_assert ! ( self . len < 128 , "ParentStack overflow" ) ;
70+ if self . len < 128 {
71+ self . data [ self . len ] = val;
72+ self . len += 1 ;
73+ }
74+ }
75+
76+ fn pop ( & mut self ) -> Option < ( bool , usize ) > {
77+ if self . len > 0 {
78+ self . len -= 1 ;
79+ Some ( self . data [ self . len ] )
80+ } else {
81+ None
82+ }
83+ }
84+
85+ fn len ( & self ) -> usize {
86+ self . len
87+ }
88+ }
89+
5090/// A structure which can be used to obtain control blocks and other information
5191/// needed for Taproot spends.
5292///
@@ -63,7 +103,7 @@ pub struct TrSpendInfo<Pk: MiniscriptKey> {
63103impl < Pk : ToPublicKey > TrSpendInfo < Pk > {
64104 fn nodes_from_tap_tree ( tree : & super :: TapTree < Pk > ) -> Vec < TrSpendInfoNode < Pk > > {
65105 let mut nodes = vec ! [ ] ;
66- let mut parent_stack = Vec :: with_capacity ( 128 ) ; // FIXME use ArrayVec here
106+ let mut parent_stack = ParentStack :: new ( ) ;
67107 for leaf in tree. leaves ( ) {
68108 let depth = usize:: from ( leaf. depth ( ) ) ;
69109 let script = leaf. miniscript ( ) . encode ( ) ;
0 commit comments