Skip to content

Commit 94eea85

Browse files
committed
Use stack allocation in TrSpendInfo
1 parent 0f3a6ad commit 94eea85

1 file changed

Lines changed: 41 additions & 1 deletion

File tree

src/descriptor/tr/spend_info.rs

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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> {
63103
impl<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

Comments
 (0)