bitcoin/blockdata/script/
borrowed.rs

1// SPDX-License-Identifier: CC0-1.0
2
3use core::fmt;
4use core::ops::{
5    Bound, Index, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive,
6};
7
8use hashes::Hash;
9use secp256k1::{Secp256k1, Verification};
10
11use super::PushBytes;
12use crate::blockdata::fee_rate::FeeRate;
13use crate::blockdata::opcodes::all::*;
14use crate::blockdata::opcodes::{self, Opcode};
15use crate::blockdata::script::witness_version::WitnessVersion;
16use crate::blockdata::script::{
17    bytes_to_asm_fmt, Builder, Instruction, InstructionIndices, Instructions, ScriptBuf,
18    ScriptHash, WScriptHash,
19};
20use crate::consensus::Encodable;
21use crate::key::{PublicKey, UntweakedPublicKey, WPubkeyHash};
22use crate::policy::DUST_RELAY_TX_FEE;
23use crate::prelude::*;
24use crate::taproot::{LeafVersion, TapLeafHash, TapNodeHash};
25
26/// Bitcoin script slice.
27///
28/// *[See also the `bitcoin::blockdata::script` module](crate::blockdata::script).*
29///
30/// `Script` is a script slice, the most primitive script type. It's usually seen in its borrowed
31/// form `&Script`. It is always encoded as a series of bytes representing the opcodes and data
32/// pushes.
33///
34/// ## Validity
35///
36/// `Script` does not have any validity invariants - it's essentially just a marked slice of
37/// bytes. This is similar to [`Path`](std::path::Path) vs [`OsStr`](std::ffi::OsStr) where they
38/// are trivially cast-able to each-other and `Path` doesn't guarantee being a usable FS path but
39/// having a newtype still has value because of added methods, readability and basic type checking.
40///
41/// Although at least data pushes could be checked not to overflow the script, bad scripts are
42/// allowed to be in a transaction (outputs just become unspendable) and there even are such
43/// transactions in the chain. Thus we must allow such scripts to be placed in the transaction.
44///
45/// ## Slicing safety
46///
47/// Slicing is similar to how `str` works: some ranges may be incorrect and indexing by
48/// `usize` is not supported. However, as opposed to `std`, we have no way of checking
49/// correctness without causing linear complexity so there are **no panics on invalid
50/// ranges!** If you supply an invalid range, you'll get a garbled script.
51///
52/// The range is considered valid if it's at a boundary of instruction. Care must be taken
53/// especially with push operations because you could get a reference to arbitrary
54/// attacker-supplied bytes that look like a valid script.
55///
56/// It is recommended to use `.instructions()` method to get an iterator over script
57/// instructions and work with that instead.
58///
59/// ## Memory safety
60///
61/// The type is `#[repr(transparent)]` for internal purposes only!
62/// No consumer crate may rely on the representation of the struct!
63///
64/// ## References
65///
66///
67/// ### Bitcoin Core References
68///
69/// * [CScript definition](https://github.com/bitcoin/bitcoin/blob/d492dc1cdaabdc52b0766bf4cba4bd73178325d0/src/script/script.h#L410)
70///
71#[derive(PartialOrd, Ord, PartialEq, Eq, Hash)]
72#[repr(transparent)]
73pub struct Script(pub(in crate::blockdata::script) [u8]);
74
75impl ToOwned for Script {
76    type Owned = ScriptBuf;
77
78    fn to_owned(&self) -> Self::Owned { ScriptBuf(self.0.to_owned()) }
79}
80
81impl Script {
82    /// Creates a new empty script.
83    #[inline]
84    pub fn new() -> &'static Script { Script::from_bytes(&[]) }
85
86    /// Treat byte slice as `Script`
87    #[inline]
88    pub fn from_bytes(bytes: &[u8]) -> &Script {
89        // SAFETY: copied from `std`
90        // The pointer was just created from a reference which is still alive.
91        // Casting slice pointer to a transparent struct wrapping that slice is sound (same
92        // layout).
93        unsafe { &*(bytes as *const [u8] as *const Script) }
94    }
95
96    /// Treat mutable byte slice as `Script`
97    #[inline]
98    pub fn from_bytes_mut(bytes: &mut [u8]) -> &mut Script {
99        // SAFETY: copied from `std`
100        // The pointer was just created from a reference which is still alive.
101        // Casting slice pointer to a transparent struct wrapping that slice is sound (same
102        // layout).
103        // Function signature prevents callers from accessing `bytes` while the returned reference
104        // is alive.
105        unsafe { &mut *(bytes as *mut [u8] as *mut Script) }
106    }
107
108    /// Returns the script data as a byte slice.
109    #[inline]
110    pub fn as_bytes(&self) -> &[u8] { &self.0 }
111
112    /// Returns the script data as a mutable byte slice.
113    #[inline]
114    pub fn as_mut_bytes(&mut self) -> &mut [u8] { &mut self.0 }
115
116    /// Creates a new script builder
117    pub fn builder() -> Builder { Builder::new() }
118
119    /// Returns 160-bit hash of the script.
120    #[inline]
121    pub fn script_hash(&self) -> ScriptHash { ScriptHash::hash(self.as_bytes()) }
122
123    /// Returns 256-bit hash of the script for P2WSH outputs.
124    #[inline]
125    pub fn wscript_hash(&self) -> WScriptHash { WScriptHash::hash(self.as_bytes()) }
126
127    /// Computes leaf hash of tapscript.
128    #[inline]
129    pub fn tapscript_leaf_hash(&self) -> TapLeafHash {
130        TapLeafHash::from_script(self, LeafVersion::TapScript)
131    }
132
133    /// Returns the length in bytes of the script.
134    #[inline]
135    pub fn len(&self) -> usize { self.0.len() }
136
137    /// Returns whether the script is the empty script.
138    #[inline]
139    pub fn is_empty(&self) -> bool { self.0.is_empty() }
140
141    /// Returns a copy of the script data.
142    #[inline]
143    pub fn to_bytes(&self) -> Vec<u8> { self.0.to_owned() }
144
145    /// Returns an iterator over script bytes.
146    #[inline]
147    pub fn bytes(&self) -> Bytes<'_> { Bytes(self.as_bytes().iter().copied()) }
148
149    /// Computes the P2WSH output corresponding to this witnessScript (aka the "witness redeem
150    /// script").
151    #[inline]
152    pub fn to_p2wsh(&self) -> ScriptBuf { ScriptBuf::new_p2wsh(&self.wscript_hash()) }
153
154    /// Computes P2TR output with a given internal key and a single script spending path equal to
155    /// the current script, assuming that the script is a Tapscript.
156    #[inline]
157    pub fn to_p2tr<C: Verification>(
158        &self,
159        secp: &Secp256k1<C>,
160        internal_key: UntweakedPublicKey,
161    ) -> ScriptBuf {
162        let leaf_hash = self.tapscript_leaf_hash();
163        let merkle_root = TapNodeHash::from(leaf_hash);
164        ScriptBuf::new_p2tr(secp, internal_key, Some(merkle_root))
165    }
166
167    /// Returns witness version of the script, if any, assuming the script is a `scriptPubkey`.
168    ///
169    /// # Returns
170    ///
171    /// The witness version if this script is found to conform to the SegWit rules:
172    ///
173    /// > A scriptPubKey (or redeemScript as defined in BIP16/P2SH) that consists of a 1-byte
174    /// > push opcode (for 0 to 16) followed by a data push between 2 and 40 bytes gets a new
175    /// > special meaning. The value of the first push is called the "version byte". The following
176    /// > byte vector pushed is called the "witness program".
177    #[inline]
178    pub fn witness_version(&self) -> Option<WitnessVersion> {
179        let script_len = self.0.len();
180        if !(4..=42).contains(&script_len) {
181            return None;
182        }
183
184        let ver_opcode = Opcode::from(self.0[0]); // Version 0 or PUSHNUM_1-PUSHNUM_16
185        let push_opbyte = self.0[1]; // Second byte push opcode 2-40 bytes
186
187        if push_opbyte < OP_PUSHBYTES_2.to_u8() || push_opbyte > OP_PUSHBYTES_40.to_u8() {
188            return None;
189        }
190        // Check that the rest of the script has the correct size
191        if script_len - 2 != push_opbyte as usize {
192            return None;
193        }
194
195        WitnessVersion::try_from(ver_opcode).ok()
196    }
197
198    /// Checks whether a script pubkey is a P2SH output.
199    #[inline]
200    pub fn is_p2sh(&self) -> bool {
201        self.0.len() == 23
202            && self.0[0] == OP_HASH160.to_u8()
203            && self.0[1] == OP_PUSHBYTES_20.to_u8()
204            && self.0[22] == OP_EQUAL.to_u8()
205    }
206
207    /// Checks whether a script pubkey is a P2PKH output.
208    #[inline]
209    pub fn is_p2pkh(&self) -> bool {
210        self.0.len() == 25
211            && self.0[0] == OP_DUP.to_u8()
212            && self.0[1] == OP_HASH160.to_u8()
213            && self.0[2] == OP_PUSHBYTES_20.to_u8()
214            && self.0[23] == OP_EQUALVERIFY.to_u8()
215            && self.0[24] == OP_CHECKSIG.to_u8()
216    }
217
218    /// Checks whether a script is push only.
219    ///
220    /// Note: `OP_RESERVED` (`0x50`) and all the OP_PUSHNUM operations
221    /// are considered push operations.
222    #[inline]
223    pub fn is_push_only(&self) -> bool {
224        for inst in self.instructions() {
225            match inst {
226                Err(_) => return false,
227                Ok(Instruction::PushBytes(_)) => {}
228                Ok(Instruction::Op(op)) if op.to_u8() <= 0x60 => {}
229                // From Bitcoin Core
230                // if (opcode > OP_PUSHNUM_16 (0x60)) return false
231                Ok(Instruction::Op(_)) => return false,
232            }
233        }
234        true
235    }
236
237    /// Checks whether a script pubkey is a P2PK output.
238    ///
239    /// You can obtain the public key, if its valid,
240    /// by calling [`p2pk_public_key()`](Self::p2pk_public_key)
241    #[inline]
242    pub fn is_p2pk(&self) -> bool { self.p2pk_pubkey_bytes().is_some() }
243
244    /// Returns the public key if this script is P2PK with a **valid** public key.
245    ///
246    /// This may return `None` even when [`is_p2pk()`](Self::is_p2pk) returns true.
247    /// This happens when the public key is invalid (e.g. the point not being on the curve).
248    /// In this situation the script is unspendable.
249    #[inline]
250    pub fn p2pk_public_key(&self) -> Option<PublicKey> {
251        PublicKey::from_slice(self.p2pk_pubkey_bytes()?).ok()
252    }
253
254    /// Returns the bytes of the (possibly invalid) public key if this script is P2PK.
255    #[inline]
256    pub(in crate::blockdata::script) fn p2pk_pubkey_bytes(&self) -> Option<&[u8]> {
257        match self.len() {
258            67 if self.0[0] == OP_PUSHBYTES_65.to_u8() && self.0[66] == OP_CHECKSIG.to_u8() =>
259                Some(&self.0[1..66]),
260            35 if self.0[0] == OP_PUSHBYTES_33.to_u8() && self.0[34] == OP_CHECKSIG.to_u8() =>
261                Some(&self.0[1..34]),
262            _ => None,
263        }
264    }
265
266    /// Checks whether a script pubkey is a bare multisig output.
267    ///
268    /// In a bare multisig pubkey script the keys are not hashed, the script
269    /// is of the form:
270    ///
271    ///    `2 <pubkey1> <pubkey2> <pubkey3> 3 OP_CHECKMULTISIG`
272    #[inline]
273    pub fn is_multisig(&self) -> bool {
274        let required_sigs;
275
276        let mut instructions = self.instructions();
277        if let Some(Ok(Instruction::Op(op))) = instructions.next() {
278            if let Some(pushnum) = op.decode_pushnum() {
279                required_sigs = pushnum;
280            } else {
281                return false;
282            }
283        } else {
284            return false;
285        }
286
287        let mut num_pubkeys: u8 = 0;
288        while let Some(Ok(instruction)) = instructions.next() {
289            match instruction {
290                Instruction::PushBytes(_) => {
291                    num_pubkeys += 1;
292                }
293                Instruction::Op(op) => {
294                    if let Some(pushnum) = op.decode_pushnum() {
295                        if pushnum != num_pubkeys {
296                            return false;
297                        }
298                    }
299                    break;
300                }
301            }
302        }
303
304        if required_sigs > num_pubkeys {
305            return false;
306        }
307
308        if let Some(Ok(Instruction::Op(op))) = instructions.next() {
309            if op != OP_CHECKMULTISIG {
310                return false;
311            }
312        } else {
313            return false;
314        }
315
316        instructions.next().is_none()
317    }
318
319    /// Checks whether a script pubkey is a Segregated Witness (segwit) program.
320    #[inline]
321    pub fn is_witness_program(&self) -> bool { self.witness_version().is_some() }
322
323    /// Checks whether a script pubkey is a P2WSH output.
324    #[inline]
325    pub fn is_p2wsh(&self) -> bool {
326        self.0.len() == 34
327            && self.witness_version() == Some(WitnessVersion::V0)
328            && self.0[1] == OP_PUSHBYTES_32.to_u8()
329    }
330
331    /// Checks whether a script pubkey is a P2WPKH output.
332    #[inline]
333    pub fn is_p2wpkh(&self) -> bool {
334        self.0.len() == 22
335            && self.witness_version() == Some(WitnessVersion::V0)
336            && self.0[1] == OP_PUSHBYTES_20.to_u8()
337    }
338
339    /// Checks whether a script pubkey is a P2TR output.
340    #[inline]
341    pub fn is_p2tr(&self) -> bool {
342        self.0.len() == 34
343            && self.witness_version() == Some(WitnessVersion::V1)
344            && self.0[1] == OP_PUSHBYTES_32.to_u8()
345    }
346
347    /// Check if this is an OP_RETURN output.
348    #[inline]
349    pub fn is_op_return(&self) -> bool {
350        match self.0.first() {
351            Some(b) => *b == OP_RETURN.to_u8(),
352            None => false,
353        }
354    }
355
356    /// Checks whether a script is trivially known to have no satisfying input.
357    ///
358    /// This method has potentially confusing semantics and an unclear purpose, so it's going to be
359    /// removed. Use `is_op_return` if you want `OP_RETURN` semantics.
360    #[deprecated(
361        since = "0.32.0",
362        note = "The method has potentially confusing semantics and is going to be removed, you might want `is_op_return`"
363    )]
364    #[inline]
365    pub fn is_provably_unspendable(&self) -> bool {
366        use crate::blockdata::opcodes::Class::{IllegalOp, ReturnOp};
367
368        match self.0.first() {
369            Some(b) => {
370                let first = Opcode::from(*b);
371                let class = first.classify(opcodes::ClassifyContext::Legacy);
372
373                class == ReturnOp || class == IllegalOp
374            }
375            None => false,
376        }
377    }
378
379    /// Computes the P2SH output corresponding to this redeem script.
380    pub fn to_p2sh(&self) -> ScriptBuf { ScriptBuf::new_p2sh(&self.script_hash()) }
381
382    /// Returns the script code used for spending a P2WPKH output if this script is a script pubkey
383    /// for a P2WPKH output. The `scriptCode` is described in [BIP143].
384    ///
385    /// [BIP143]: <https://github.com/bitcoin/bips/blob/99701f68a88ce33b2d0838eb84e115cef505b4c2/bip-0143.mediawiki>
386    pub fn p2wpkh_script_code(&self) -> Option<ScriptBuf> {
387        if self.is_p2wpkh() {
388            // The `self` script is 0x00, 0x14, <pubkey_hash>
389            let bytes = &self.0[2..];
390            let wpkh = WPubkeyHash::from_slice(bytes).expect("length checked in is_p2wpkh()");
391            Some(ScriptBuf::p2wpkh_script_code(wpkh))
392        } else {
393            None
394        }
395    }
396
397    /// Get redeemScript following BIP16 rules regarding P2SH spending.
398    ///
399    /// This does not guarantee that this represents a P2SH input [`Script`].
400    /// It merely gets the last push of the script. Use
401    /// [`Script::is_p2sh`](crate::blockdata::script::Script::is_p2sh) on the
402    /// scriptPubKey to check whether it is actually a P2SH script.
403    pub fn redeem_script(&self) -> Option<&Script> {
404        // Script must consist entirely of pushes.
405        if self.instructions().any(|i| i.is_err() || i.unwrap().push_bytes().is_none()) {
406            return None;
407        }
408
409        if let Some(Ok(Instruction::PushBytes(b))) = self.instructions().last() {
410            Some(Script::from_bytes(b.as_bytes()))
411        } else {
412            None
413        }
414    }
415
416    /// Returns the minimum value an output with this script should have in order to be
417    /// broadcastable on today’s Bitcoin network.
418    #[deprecated(since = "0.32.0", note = "use minimal_non_dust and friends")]
419    pub fn dust_value(&self) -> crate::Amount { self.minimal_non_dust() }
420
421    /// Returns the minimum value an output with this script should have in order to be
422    /// broadcastable on today's Bitcoin network.
423    ///
424    /// Dust depends on the -dustrelayfee value of the Bitcoin Core node you are broadcasting to.
425    /// This function uses the default value of 0.00003 BTC/kB (3 sat/vByte).
426    ///
427    /// To use a custom value, use [`minimal_non_dust_custom`].
428    ///
429    /// [`minimal_non_dust_custom`]: Script::minimal_non_dust_custom
430    pub fn minimal_non_dust(&self) -> crate::Amount {
431        self.minimal_non_dust_inner(DUST_RELAY_TX_FEE.into())
432    }
433
434    /// Returns the minimum value an output with this script should have in order to be
435    /// broadcastable on today's Bitcoin network.
436    ///
437    /// Dust depends on the -dustrelayfee value of the Bitcoin Core node you are broadcasting to.
438    /// This function lets you set the fee rate used in dust calculation.
439    ///
440    /// The current default value in Bitcoin Core (as of v26) is 3 sat/vByte.
441    ///
442    /// To use the default Bitcoin Core value, use [`minimal_non_dust`].
443    ///
444    /// [`minimal_non_dust`]: Script::minimal_non_dust
445    pub fn minimal_non_dust_custom(&self, dust_relay_fee: FeeRate) -> crate::Amount {
446        self.minimal_non_dust_inner(dust_relay_fee.to_sat_per_kwu() * 4)
447    }
448
449    fn minimal_non_dust_inner(&self, dust_relay_fee: u64) -> crate::Amount {
450        // This must never be lower than Bitcoin Core's GetDustThreshold() (as of v0.21) as it may
451        // otherwise allow users to create transactions which likely can never be broadcast/confirmed.
452        let sats = dust_relay_fee
453            .checked_mul(if self.is_op_return() {
454                0
455            } else if self.is_witness_program() {
456                32 + 4 + 1 + (107 / 4) + 4 + // The spend cost copied from Core
457                    8 + // The serialized size of the TxOut's amount field
458                    self.consensus_encode(&mut sink()).expect("sinks don't error") as u64 // The serialized size of this script_pubkey
459            } else {
460                32 + 4 + 1 + 107 + 4 + // The spend cost copied from Core
461                    8 + // The serialized size of the TxOut's amount field
462                    self.consensus_encode(&mut sink()).expect("sinks don't error") as u64 // The serialized size of this script_pubkey
463            })
464            .expect("dust_relay_fee or script length should not be absurdly large")
465            / 1000; // divide by 1000 like in Core to get value as it cancels out DEFAULT_MIN_RELAY_TX_FEE
466                    // Note: We ensure the division happens at the end, since Core performs the division at the end.
467                    //       This will make sure none of the implicit floor operations mess with the value.
468
469        crate::Amount::from_sat(sats)
470    }
471
472    /// Counts the sigops for this Script using accurate counting.
473    ///
474    /// In Bitcoin Core, there are two ways to count sigops, "accurate" and "legacy".
475    /// This method uses "accurate" counting. This means that OP_CHECKMULTISIG and its
476    /// verify variant count for N sigops where N is the number of pubkeys used in the
477    /// multisig. However, it will count for 20 sigops if CHECKMULTISIG is not preceded by an
478    /// OP_PUSHNUM from 1 - 16 (this would be an invalid script)
479    ///
480    /// Bitcoin Core uses accurate counting for sigops contained within redeemScripts (P2SH)
481    /// and witnessScripts (P2WSH) only. It uses legacy for sigops in scriptSigs and scriptPubkeys.
482    ///
483    /// (Note: taproot scripts don't count toward the sigop count of the block,
484    /// nor do they have CHECKMULTISIG operations. This function does not count OP_CHECKSIGADD,
485    /// so do not use this to try and estimate if a taproot script goes over the sigop budget.)
486    pub fn count_sigops(&self) -> usize { self.count_sigops_internal(true) }
487
488    /// Counts the sigops for this Script using legacy counting.
489    ///
490    /// In Bitcoin Core, there are two ways to count sigops, "accurate" and "legacy".
491    /// This method uses "legacy" counting. This means that OP_CHECKMULTISIG and its
492    /// verify variant count for 20 sigops.
493    ///
494    /// Bitcoin Core uses legacy counting for sigops contained within scriptSigs and
495    /// scriptPubkeys. It uses accurate for redeemScripts (P2SH) and witnessScripts (P2WSH).
496    ///
497    /// (Note: taproot scripts don't count toward the sigop count of the block,
498    /// nor do they have CHECKMULTISIG operations. This function does not count OP_CHECKSIGADD,
499    /// so do not use this to try and estimate if a taproot script goes over the sigop budget.)
500    pub fn count_sigops_legacy(&self) -> usize { self.count_sigops_internal(false) }
501
502    fn count_sigops_internal(&self, accurate: bool) -> usize {
503        let mut n = 0;
504        let mut pushnum_cache = None;
505        for inst in self.instructions() {
506            match inst {
507                Ok(Instruction::Op(opcode)) => {
508                    match opcode {
509                        // p2pk, p2pkh
510                        OP_CHECKSIG | OP_CHECKSIGVERIFY => {
511                            n += 1;
512                        }
513                        OP_CHECKMULTISIG | OP_CHECKMULTISIGVERIFY => {
514                            match (accurate, pushnum_cache) {
515                                (true, Some(pushnum)) => {
516                                    // Add the number of pubkeys in the multisig as sigop count
517                                    n += usize::from(pushnum);
518                                }
519                                _ => {
520                                    // MAX_PUBKEYS_PER_MULTISIG from Bitcoin Core
521                                    // https://github.com/bitcoin/bitcoin/blob/v25.0/src/script/script.h#L29-L30
522                                    n += 20;
523                                }
524                            }
525                        }
526                        _ => {
527                            pushnum_cache = opcode.decode_pushnum();
528                        }
529                    }
530                }
531                Ok(Instruction::PushBytes(_)) => {
532                    pushnum_cache = None;
533                }
534                // In Bitcoin Core it does `if (!GetOp(pc, opcode)) break;`
535                Err(_) => break,
536            }
537        }
538
539        n
540    }
541
542    /// Iterates over the script instructions.
543    ///
544    /// Each returned item is a nested enum covering opcodes, datapushes and errors.
545    /// At most one error will be returned and then the iterator will end. To instead iterate over
546    /// the script as sequence of bytes call the [`bytes`](Self::bytes) method.
547    ///
548    /// To force minimal pushes, use [`instructions_minimal`](Self::instructions_minimal).
549    #[inline]
550    pub fn instructions(&self) -> Instructions {
551        Instructions { data: self.0.iter(), enforce_minimal: false }
552    }
553
554    /// Iterates over the script instructions while enforcing minimal pushes.
555    ///
556    /// This is similar to [`instructions`](Self::instructions) but an error is returned if a push
557    /// is not minimal.
558    #[inline]
559    pub fn instructions_minimal(&self) -> Instructions {
560        Instructions { data: self.0.iter(), enforce_minimal: true }
561    }
562
563    /// Iterates over the script instructions and their indices.
564    ///
565    /// Unless the script contains an error, the returned item consists of an index pointing to the
566    /// position in the script where the instruction begins and the decoded instruction - either an
567    /// opcode or data push.
568    ///
569    /// To force minimal pushes, use [`Self::instruction_indices_minimal`].
570    #[inline]
571    pub fn instruction_indices(&self) -> InstructionIndices {
572        InstructionIndices::from_instructions(self.instructions())
573    }
574
575    /// Iterates over the script instructions and their indices while enforcing minimal pushes.
576    ///
577    /// This is similar to [`instruction_indices`](Self::instruction_indices) but an error is
578    /// returned if a push is not minimal.
579    #[inline]
580    pub fn instruction_indices_minimal(&self) -> InstructionIndices {
581        InstructionIndices::from_instructions(self.instructions_minimal())
582    }
583
584    /// Writes the human-readable assembly representation of the script to the formatter.
585    pub fn fmt_asm(&self, f: &mut dyn fmt::Write) -> fmt::Result {
586        bytes_to_asm_fmt(self.as_ref(), f)
587    }
588
589    /// Returns the human-readable assembly representation of the script.
590    pub fn to_asm_string(&self) -> String {
591        let mut buf = String::new();
592        self.fmt_asm(&mut buf).unwrap();
593        buf
594    }
595
596    /// Formats the script as lower-case hex.
597    ///
598    /// This is a more convenient and performant way to write `format!("{:x}", script)`.
599    /// For better performance you should generally prefer displaying the script but if `String` is
600    /// required (this is common in tests) this method can be used.
601    pub fn to_hex_string(&self) -> String { self.as_bytes().to_lower_hex_string() }
602
603    /// Returns the first opcode of the script (if there is any).
604    pub fn first_opcode(&self) -> Option<Opcode> {
605        self.as_bytes().first().copied().map(From::from)
606    }
607
608    /// Iterates the script to find the last opcode.
609    ///
610    /// Returns `None` is the instruction is data push or if the script is empty.
611    pub(in crate::blockdata::script) fn last_opcode(&self) -> Option<Opcode> {
612        match self.instructions().last() {
613            Some(Ok(Instruction::Op(op))) => Some(op),
614            _ => None,
615        }
616    }
617
618    /// Iterates the script to find the last pushdata.
619    ///
620    /// Returns `None` if the instruction is an opcode or if the script is empty.
621    pub(crate) fn last_pushdata(&self) -> Option<&PushBytes> {
622        match self.instructions().last() {
623            // Handles op codes up to (but excluding) OP_PUSHNUM_NEG.
624            Some(Ok(Instruction::PushBytes(bytes))) => Some(bytes),
625            // OP_16 (0x60) and lower are considered "pushes" by Bitcoin Core (excl. OP_RESERVED).
626            // However we are only interested in the pushdata so we can ignore them.
627            _ => None,
628        }
629    }
630
631    /// Converts a [`Box<Script>`](Box) into a [`ScriptBuf`] without copying or allocating.
632    #[must_use = "`self` will be dropped if the result is not used"]
633    pub fn into_script_buf(self: Box<Self>) -> ScriptBuf {
634        let rw = Box::into_raw(self) as *mut [u8];
635        // SAFETY: copied from `std`
636        // The pointer was just created from a box without deallocating
637        // Casting a transparent struct wrapping a slice to the slice pointer is sound (same
638        // layout).
639        let inner = unsafe { Box::from_raw(rw) };
640        ScriptBuf(Vec::from(inner))
641    }
642}
643
644/// Iterator over bytes of a script
645pub struct Bytes<'a>(core::iter::Copied<core::slice::Iter<'a, u8>>);
646
647impl Iterator for Bytes<'_> {
648    type Item = u8;
649
650    #[inline]
651    fn next(&mut self) -> Option<Self::Item> { self.0.next() }
652
653    #[inline]
654    fn size_hint(&self) -> (usize, Option<usize>) { self.0.size_hint() }
655
656    #[inline]
657    fn nth(&mut self, n: usize) -> Option<Self::Item> { self.0.nth(n) }
658}
659
660impl DoubleEndedIterator for Bytes<'_> {
661    #[inline]
662    fn next_back(&mut self) -> Option<Self::Item> { self.0.next_back() }
663
664    #[inline]
665    fn nth_back(&mut self, n: usize) -> Option<Self::Item> { self.0.nth_back(n) }
666}
667
668impl ExactSizeIterator for Bytes<'_> {}
669impl core::iter::FusedIterator for Bytes<'_> {}
670
671macro_rules! delegate_index {
672    ($($type:ty),* $(,)?) => {
673        $(
674            /// Script subslicing operation - read [slicing safety](#slicing-safety)!
675            impl Index<$type> for Script {
676                type Output = Self;
677
678                #[inline]
679                fn index(&self, index: $type) -> &Self::Output {
680                    Self::from_bytes(&self.0[index])
681                }
682            }
683        )*
684    }
685}
686
687delegate_index!(
688    Range<usize>,
689    RangeFrom<usize>,
690    RangeTo<usize>,
691    RangeFull,
692    RangeInclusive<usize>,
693    RangeToInclusive<usize>,
694    (Bound<usize>, Bound<usize>)
695);
696
697#[cfg(test)]
698mod tests {
699    use super::*;
700    use crate::blockdata::script::witness_program::WitnessProgram;
701
702    #[test]
703    fn shortest_witness_program() {
704        let bytes = [0x00; 2]; // Arbitrary bytes, witprog must be between 2 and 40.
705        let version = WitnessVersion::V15; // Arbitrary version number, intentionally not 0 or 1.
706
707        let p = WitnessProgram::new(version, &bytes).expect("failed to create witness program");
708        let script = ScriptBuf::new_witness_program(&p);
709
710        assert_eq!(script.witness_version(), Some(version));
711    }
712
713    #[test]
714    fn longest_witness_program() {
715        let bytes = [0x00; 40]; // Arbitrary bytes, witprog must be between 2 and 40.
716        let version = WitnessVersion::V16; // Arbitrary version number, intentionally not 0 or 1.
717
718        let p = WitnessProgram::new(version, &bytes).expect("failed to create witness program");
719        let script = ScriptBuf::new_witness_program(&p);
720
721        assert_eq!(script.witness_version(), Some(version));
722    }
723}