bitcoin/blockdata/script/
owned.rs

1// SPDX-License-Identifier: CC0-1.0
2
3#[cfg(doc)]
4use core::ops::Deref;
5
6use hex::FromHex;
7use secp256k1::{Secp256k1, Verification};
8
9use crate::blockdata::opcodes::all::*;
10use crate::blockdata::opcodes::{self, Opcode};
11use crate::blockdata::script::witness_program::{WitnessProgram, P2A_PROGRAM};
12use crate::blockdata::script::witness_version::WitnessVersion;
13use crate::blockdata::script::{
14    opcode_to_verify, Builder, Instruction, PushBytes, Script, ScriptHash, WScriptHash,
15};
16use crate::key::{
17    PubkeyHash, PublicKey, TapTweak, TweakedPublicKey, UntweakedPublicKey, WPubkeyHash,
18};
19use crate::prelude::*;
20use crate::taproot::TapNodeHash;
21
22/// An owned, growable script.
23///
24/// `ScriptBuf` is the most common script type that has the ownership over the contents of the
25/// script. It has a close relationship with its borrowed counterpart, [`Script`].
26///
27/// Just as other similar types, this implements [`Deref`], so [deref coercions] apply. Also note
28/// that all the safety/validity restrictions that apply to [`Script`] apply to `ScriptBuf` as well.
29///
30/// [deref coercions]: https://doc.rust-lang.org/std/ops/trait.Deref.html#more-on-deref-coercion
31#[derive(Default, Clone, PartialOrd, Ord, PartialEq, Eq, Hash)]
32pub struct ScriptBuf(pub(in crate::blockdata::script) Vec<u8>);
33
34impl ScriptBuf {
35    /// Creates a new empty script.
36    #[inline]
37    pub const fn new() -> Self { ScriptBuf(Vec::new()) }
38
39    /// Creates a new empty script with pre-allocated capacity.
40    pub fn with_capacity(capacity: usize) -> Self { ScriptBuf(Vec::with_capacity(capacity)) }
41
42    /// Pre-allocates at least `additional_len` bytes if needed.
43    ///
44    /// Reserves capacity for at least `additional_len` more bytes to be inserted in the given
45    /// script. The script may reserve more space to speculatively avoid frequent reallocations.
46    /// After calling `reserve`, capacity will be greater than or equal to
47    /// `self.len() + additional_len`. Does nothing if capacity is already sufficient.
48    ///
49    /// # Panics
50    ///
51    /// Panics if the new capacity exceeds `isize::MAX bytes`.
52    pub fn reserve(&mut self, additional_len: usize) { self.0.reserve(additional_len); }
53
54    /// Pre-allocates exactly `additional_len` bytes if needed.
55    ///
56    /// Unlike `reserve`, this will not deliberately over-allocate to speculatively avoid frequent
57    /// allocations. After calling `reserve_exact`, capacity will be greater than or equal to
58    /// `self.len() + additional`. Does nothing if the capacity is already sufficient.
59    ///
60    /// Note that the allocator may give the collection more space than it requests. Therefore,
61    /// capacity can not be relied upon to be precisely minimal. Prefer [`reserve`](Self::reserve)
62    /// if future insertions are expected.
63    ///
64    /// # Panics
65    ///
66    /// Panics if the new capacity exceeds `isize::MAX bytes`.
67    pub fn reserve_exact(&mut self, additional_len: usize) { self.0.reserve_exact(additional_len); }
68
69    /// Returns a reference to unsized script.
70    pub fn as_script(&self) -> &Script { Script::from_bytes(&self.0) }
71
72    /// Returns a mutable reference to unsized script.
73    pub fn as_mut_script(&mut self) -> &mut Script { Script::from_bytes_mut(&mut self.0) }
74
75    /// Creates a new script builder
76    pub fn builder() -> Builder { Builder::new() }
77
78    /// Generates P2PK-type of scriptPubkey.
79    pub fn new_p2pk(pubkey: &PublicKey) -> Self {
80        Builder::new().push_key(pubkey).push_opcode(OP_CHECKSIG).into_script()
81    }
82
83    /// Generates P2PKH-type of scriptPubkey.
84    pub fn new_p2pkh(pubkey_hash: &PubkeyHash) -> Self {
85        Builder::new()
86            .push_opcode(OP_DUP)
87            .push_opcode(OP_HASH160)
88            .push_slice(pubkey_hash)
89            .push_opcode(OP_EQUALVERIFY)
90            .push_opcode(OP_CHECKSIG)
91            .into_script()
92    }
93
94    /// Generates P2SH-type of scriptPubkey with a given hash of the redeem script.
95    pub fn new_p2sh(script_hash: &ScriptHash) -> Self {
96        Builder::new()
97            .push_opcode(OP_HASH160)
98            .push_slice(script_hash)
99            .push_opcode(OP_EQUAL)
100            .into_script()
101    }
102
103    /// Generates P2WPKH-type of scriptPubkey.
104    pub fn new_p2wpkh(pubkey_hash: &WPubkeyHash) -> Self {
105        // pubkey hash is 20 bytes long, so it's safe to use `new_witness_program_unchecked` (Segwitv0)
106        ScriptBuf::new_witness_program_unchecked(WitnessVersion::V0, pubkey_hash)
107    }
108
109    /// Generates P2WSH-type of scriptPubkey with a given hash of the redeem script.
110    pub fn new_p2wsh(script_hash: &WScriptHash) -> Self {
111        // script hash is 32 bytes long, so it's safe to use `new_witness_program_unchecked` (Segwitv0)
112        ScriptBuf::new_witness_program_unchecked(WitnessVersion::V0, script_hash)
113    }
114
115    /// Generates P2TR for script spending path using an internal public key and some optional
116    /// script tree merkle root.
117    pub fn new_p2tr<C: Verification>(
118        secp: &Secp256k1<C>,
119        internal_key: UntweakedPublicKey,
120        merkle_root: Option<TapNodeHash>,
121    ) -> Self {
122        let (output_key, _) = internal_key.tap_tweak(secp, merkle_root);
123        // output key is 32 bytes long, so it's safe to use `new_witness_program_unchecked` (Segwitv1)
124        ScriptBuf::new_witness_program_unchecked(WitnessVersion::V1, output_key.serialize())
125    }
126
127    /// Generates P2TR for key spending path for a known [`TweakedPublicKey`].
128    pub fn new_p2tr_tweaked(output_key: TweakedPublicKey) -> Self {
129        // output key is 32 bytes long, so it's safe to use `new_witness_program_unchecked` (Segwitv1)
130        ScriptBuf::new_witness_program_unchecked(WitnessVersion::V1, output_key.serialize())
131    }
132
133    /// Generates pay to anchor output.
134    pub fn new_p2a() -> Self {
135        ScriptBuf::new_witness_program_unchecked(WitnessVersion::V1, P2A_PROGRAM)
136    }
137
138    /// Generates P2WSH-type of scriptPubkey with a given [`WitnessProgram`].
139    pub fn new_witness_program(witness_program: &WitnessProgram) -> Self {
140        Builder::new()
141            .push_opcode(witness_program.version().into())
142            .push_slice(witness_program.program())
143            .into_script()
144    }
145
146    /// Generates P2WSH-type of scriptPubkey with a given [`WitnessVersion`] and the program bytes.
147    /// Does not do any checks on version or program length.
148    ///
149    /// Convenience method used by `new_p2wpkh`, `new_p2wsh`, `new_p2tr`, and `new_p2tr_tweaked`,
150    /// and `new_p2a`.
151    pub(crate) fn new_witness_program_unchecked<T: AsRef<PushBytes>>(
152        version: WitnessVersion,
153        program: T,
154    ) -> Self {
155        let program = program.as_ref();
156        debug_assert!(program.len() >= 2 && program.len() <= 40);
157        // In SegWit v0, the program must be either 20 (P2WPKH) bytes or 32 (P2WSH) bytes long
158        debug_assert!(version != WitnessVersion::V0 || program.len() == 20 || program.len() == 32);
159        Builder::new().push_opcode(version.into()).push_slice(program).into_script()
160    }
161
162    /// Creates the script code used for spending a P2WPKH output.
163    ///
164    /// The `scriptCode` is described in [BIP143].
165    ///
166    /// [BIP143]: <https://github.com/bitcoin/bips/blob/99701f68a88ce33b2d0838eb84e115cef505b4c2/bip-0143.mediawiki>
167    pub fn p2wpkh_script_code(wpkh: WPubkeyHash) -> ScriptBuf {
168        Builder::new()
169            .push_opcode(OP_DUP)
170            .push_opcode(OP_HASH160)
171            .push_slice(wpkh)
172            .push_opcode(OP_EQUALVERIFY)
173            .push_opcode(OP_CHECKSIG)
174            .into_script()
175    }
176
177    /// Generates OP_RETURN-type of scriptPubkey for the given data.
178    pub fn new_op_return<T: AsRef<PushBytes>>(data: T) -> Self {
179        Builder::new().push_opcode(OP_RETURN).push_slice(data).into_script()
180    }
181
182    /// Creates a [`ScriptBuf`] from a hex string.
183    pub fn from_hex(s: &str) -> Result<Self, hex::HexToBytesError> {
184        let v = Vec::from_hex(s)?;
185        Ok(ScriptBuf::from_bytes(v))
186    }
187
188    /// Converts byte vector into script.
189    ///
190    /// This method doesn't (re)allocate.
191    pub fn from_bytes(bytes: Vec<u8>) -> Self { ScriptBuf(bytes) }
192
193    /// Converts the script into a byte vector.
194    ///
195    /// This method doesn't (re)allocate.
196    pub fn into_bytes(self) -> Vec<u8> { self.0 }
197
198    /// Adds a single opcode to the script.
199    pub fn push_opcode(&mut self, data: Opcode) { self.0.push(data.to_u8()); }
200
201    /// Adds instructions to push some arbitrary data onto the stack.
202    pub fn push_slice<T: AsRef<PushBytes>>(&mut self, data: T) {
203        let data = data.as_ref();
204        self.reserve(Self::reserved_len_for_slice(data.len()));
205        self.push_slice_no_opt(data);
206    }
207
208    /// Pushes the slice without reserving
209    fn push_slice_no_opt(&mut self, data: &PushBytes) {
210        // Start with a PUSH opcode
211        match data.len() as u64 {
212            n if n < opcodes::Ordinary::OP_PUSHDATA1 as u64 => {
213                self.0.push(n as u8);
214            }
215            n if n < 0x100 => {
216                self.0.push(opcodes::Ordinary::OP_PUSHDATA1.to_u8());
217                self.0.push(n as u8);
218            }
219            n if n < 0x10000 => {
220                self.0.push(opcodes::Ordinary::OP_PUSHDATA2.to_u8());
221                self.0.push((n % 0x100) as u8);
222                self.0.push((n / 0x100) as u8);
223            }
224            n if n < 0x100000000 => {
225                self.0.push(opcodes::Ordinary::OP_PUSHDATA4.to_u8());
226                self.0.push((n % 0x100) as u8);
227                self.0.push(((n / 0x100) % 0x100) as u8);
228                self.0.push(((n / 0x10000) % 0x100) as u8);
229                self.0.push((n / 0x1000000) as u8);
230            }
231            _ => panic!("tried to put a 4bn+ sized object into a script!"),
232        }
233        // Then push the raw bytes
234        self.0.extend_from_slice(data.as_bytes());
235    }
236
237    /// Computes the sum of `len` and the length of an appropriate push opcode.
238    pub(in crate::blockdata::script) fn reserved_len_for_slice(len: usize) -> usize {
239        len + match len {
240            0..=0x4b => 1,
241            0x4c..=0xff => 2,
242            0x100..=0xffff => 3,
243            // we don't care about oversized, the other fn will panic anyway
244            _ => 5,
245        }
246    }
247
248    /// Add a single instruction to the script.
249    ///
250    /// ## Panics
251    ///
252    /// The method panics if the instruction is a data push with length greater or equal to
253    /// 0x100000000.
254    pub fn push_instruction(&mut self, instruction: Instruction<'_>) {
255        match instruction {
256            Instruction::Op(opcode) => self.push_opcode(opcode),
257            Instruction::PushBytes(bytes) => self.push_slice(bytes),
258        }
259    }
260
261    /// Like push_instruction, but avoids calling `reserve` to not re-check the length.
262    pub fn push_instruction_no_opt(&mut self, instruction: Instruction<'_>) {
263        match instruction {
264            Instruction::Op(opcode) => self.push_opcode(opcode),
265            Instruction::PushBytes(bytes) => self.push_slice_no_opt(bytes),
266        }
267    }
268
269    /// Adds an `OP_VERIFY` to the script or replaces the last opcode with VERIFY form.
270    ///
271    /// Some opcodes such as `OP_CHECKSIG` have a verify variant that works as if `VERIFY` was
272    /// in the script right after. To save space this function appends `VERIFY` only if
273    /// the most-recently-added opcode *does not* have an alternate `VERIFY` form. If it does
274    /// the last opcode is replaced. E.g., `OP_CHECKSIG` will become `OP_CHECKSIGVERIFY`.
275    ///
276    /// Note that existing `OP_*VERIFY` opcodes do not lead to the instruction being ignored
277    /// because `OP_VERIFY` consumes an item from the stack so ignoring them would change the
278    /// semantics.
279    ///
280    /// This function needs to iterate over the script to find the last instruction. Prefer
281    /// `Builder` if you're creating the script from scratch or if you want to push `OP_VERIFY`
282    /// multiple times.
283    pub fn scan_and_push_verify(&mut self) { self.push_verify(self.last_opcode()); }
284
285    /// Adds an `OP_VERIFY` to the script or changes the most-recently-added opcode to `VERIFY`
286    /// alternative.
287    ///
288    /// See the public fn [`Self::scan_and_push_verify`] to learn more.
289    pub(in crate::blockdata::script) fn push_verify(&mut self, last_opcode: Option<Opcode>) {
290        match opcode_to_verify(last_opcode) {
291            Some(opcode) => {
292                self.0.pop();
293                self.push_opcode(opcode);
294            }
295            None => self.push_opcode(OP_VERIFY),
296        }
297    }
298
299    /// Converts this `ScriptBuf` into a [boxed](Box) [`Script`].
300    ///
301    /// This method reallocates if the capacity is greater than length of the script but should not
302    /// when they are equal. If you know beforehand that you need to create a script of exact size
303    /// use [`reserve_exact`](Self::reserve_exact) before adding data to the script so that the
304    /// reallocation can be avoided.
305    #[must_use = "`self` will be dropped if the result is not used"]
306    #[inline]
307    pub fn into_boxed_script(self) -> Box<Script> {
308        // Copied from PathBuf::into_boxed_path
309        let rw = Box::into_raw(self.0.into_boxed_slice()) as *mut Script;
310        unsafe { Box::from_raw(rw) }
311    }
312}
313
314impl<'a> core::iter::FromIterator<Instruction<'a>> for ScriptBuf {
315    fn from_iter<T>(iter: T) -> Self
316    where
317        T: IntoIterator<Item = Instruction<'a>>,
318    {
319        let mut script = ScriptBuf::new();
320        script.extend(iter);
321        script
322    }
323}
324
325impl<'a> Extend<Instruction<'a>> for ScriptBuf {
326    fn extend<T>(&mut self, iter: T)
327    where
328        T: IntoIterator<Item = Instruction<'a>>,
329    {
330        let iter = iter.into_iter();
331        // Most of Bitcoin scripts have only a few opcodes, so we can avoid reallocations in many
332        // cases.
333        if iter.size_hint().1.map(|max| max < 6).unwrap_or(false) {
334            let mut iter = iter.fuse();
335            // `MaybeUninit` might be faster but we don't want to introduce more `unsafe` than
336            // required.
337            let mut head = [None; 5];
338            let mut total_size = 0;
339            for (head, instr) in head.iter_mut().zip(&mut iter) {
340                total_size += instr.script_serialized_len();
341                *head = Some(instr);
342            }
343            // Incorrect impl of `size_hint` breaks `Iterator` contract so we're free to panic.
344            assert!(
345                iter.next().is_none(),
346                "Buggy implementation of `Iterator` on {} returns invalid upper bound",
347                core::any::type_name::<T::IntoIter>()
348            );
349            self.reserve(total_size);
350            for instr in head.iter().cloned().flatten() {
351                self.push_instruction_no_opt(instr);
352            }
353        } else {
354            for instr in iter {
355                self.push_instruction(instr);
356            }
357        }
358    }
359}