Skip to main content

bitcoin/blockdata/script/
owned.rs

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