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}