Repository: rust-bitcoin/rust-bitcoin
Pull request #4485 (2025-05-10 22:37:27)

Add `Builder::with_capacity()`
Enable the creation of `bitcoin::script::Builder` with a preallocated capacity.

This is pretty minor, but it provides a small speedup if used correctly. I've observed a 0.4% speedup and a 0.7% speedup in two code bases that create lots of outputs (on the order of tens to hundreds of thousands). It provided a much larger speedup (5% or so) in the latter code base before some other optimizations dwarfed it.

I have a branch that also uses it for `ScriptBufExt::new_*()` but while it provides a small performance improvement for all script types except one, `ScriptBufExt::new_p2tr()` actually causes a small performance regression. Since the only use case I have for creating lots and lots of scripts is in taproot with CHECKTEMPLATEVERIFY, I'm holding back that change if/until I figure out what's going on exactly (and hopefully resolve it).

coveralls: ## Pull Request Test Coverage Report for [Build 14949761232](https://coveralls.io/builds/73607673)


### Details

* **6** of **6**   **(100.0%)**  changed or added relevant lines in **2** files are covered.
* **6** unchanged lines in **1** file lost coverage.
* Overall coverage decreased (**-0.02%**) to **84.466%**

---


|  Files with Coverage Reduction | New Missed Lines | % |
| :-----|--------------|--: |
| [bitcoin/src/psbt/mod.rs](https://coveralls.io/builds/73607673/source?filename=bitcoin%2Fsrc%2Fpsbt%2Fmod.rs#L2260) | 6 | 86.08% |
<!-- | **Total:** | **6** |  | -->

|  Totals | [![Coverage Status](https://coveralls.io/builds/73607673/badge)](https://coveralls.io/builds/73607673) |
| :-- | --: |
| Change from base [Build 14932681067](https://coveralls.io/builds/73597162): |  -0.02% |
| Covered Lines: | 23158 |
| Relevant Lines: | 27417 |

---
##### 💛  - [Coveralls](https://coveralls.io)


Patch:
diff --git a/bitcoin/src/blockdata/script/builder.rs b/bitcoin/src/blockdata/script/builder.rs
index 855d04c6..ec842f7c 100644
--- a/bitcoin/src/blockdata/script/builder.rs
+++ b/bitcoin/src/blockdata/script/builder.rs
@@ -21,6 +21,10 @@ impl Builder {
     #[inline]
     pub const fn new() -> Self { Builder(ScriptBuf::new(), None) }
 
+    /// Constructs a new empty script builder with at least the specified capacity.
+    #[inline]
+    pub fn with_capacity(capacity: usize) -> Self { Builder(ScriptBuf::with_capacity(capacity), None) }
+
     /// Returns the length in bytes of the script.
     pub fn len(&self) -> usize { self.0.len() }
 
diff --git a/primitives/src/script/owned.rs b/primitives/src/script/owned.rs
index 1732845e..dc4cd296 100644
--- a/primitives/src/script/owned.rs
+++ b/primitives/src/script/owned.rs
@@ -62,7 +62,7 @@ pub fn into_boxed_script(self) -> Box<Script> {
         Script::from_boxed_bytes(self.into_bytes().into_boxed_slice())
     }
 
-    /// Constructs a new empty script with pre-allocated capacity.
+    /// Constructs a new empty script with at least the specified capacity.
     #[inline]
     pub fn with_capacity(capacity: usize) -> Self {
         ScriptBuf::from_bytes(Vec::with_capacity(capacity))


Test patch:
diff --git a/bitcoin/src/blockdata/script/tests.rs b/bitcoin/src/blockdata/script/tests.rs
index 51d24b25..8fae2428 100644
--- a/bitcoin/src/blockdata/script/tests.rs
+++ b/bitcoin/src/blockdata/script/tests.rs
@@ -209,6 +209,13 @@ fn script_builder() {
     );
 }
 
+#[test]
+fn script_builder_with_capacity() {
+    let script = Builder::with_capacity(42);
+
+    assert!(script.into_script().capacity() >= 42);
+}
+
 #[test]
 fn script_generators() {
     let pubkey = "0234e6a79c5359c613762d537e0e19d86c77c1666d8c9ab050f23acd198e97f93e"