bitcoin/blockdata/script/
mod.rs1mod borrowed;
51mod builder;
52mod instruction;
53mod owned;
54mod push_bytes;
55#[cfg(test)]
56mod tests;
57pub mod witness_program;
58pub mod witness_version;
59
60use alloc::rc::Rc;
61#[cfg(any(not(rust_v_1_60), target_has_atomic = "ptr"))]
62use alloc::sync::Arc;
63use core::cmp::Ordering;
64use core::fmt;
65use core::ops::{Deref, DerefMut};
66
67use hashes::{hash160, sha256};
68use io::{Read, Write};
69
70use crate::blockdata::opcodes::all::*;
71use crate::blockdata::opcodes::{self, Opcode};
72use crate::consensus::{encode, Decodable, Encodable};
73use crate::internal_macros::impl_asref_push_bytes;
74use crate::prelude::*;
75use crate::OutPoint;
76
77#[rustfmt::skip] #[doc(inline)]
79pub use self::{
80 borrowed::*,
81 builder::*,
82 instruction::*,
83 owned::*,
84 push_bytes::*,
85};
86
87hashes::hash_newtype! {
88 pub struct ScriptHash(hash160::Hash);
90 pub struct WScriptHash(sha256::Hash);
92}
93impl_asref_push_bytes!(ScriptHash, WScriptHash);
94
95impl From<ScriptBuf> for ScriptHash {
96 fn from(script: ScriptBuf) -> ScriptHash { script.script_hash() }
97}
98
99impl From<&ScriptBuf> for ScriptHash {
100 fn from(script: &ScriptBuf) -> ScriptHash { script.script_hash() }
101}
102
103impl From<&Script> for ScriptHash {
104 fn from(script: &Script) -> ScriptHash { script.script_hash() }
105}
106
107impl From<ScriptBuf> for WScriptHash {
108 fn from(script: ScriptBuf) -> WScriptHash { script.wscript_hash() }
109}
110
111impl From<&ScriptBuf> for WScriptHash {
112 fn from(script: &ScriptBuf) -> WScriptHash { script.wscript_hash() }
113}
114
115impl From<&Script> for WScriptHash {
116 fn from(script: &Script) -> WScriptHash { script.wscript_hash() }
117}
118
119pub fn write_scriptint(out: &mut [u8; 8], n: i64) -> usize {
128 let mut len = 0;
129 if n == 0 {
130 return len;
131 }
132
133 let neg = n < 0;
134
135 let mut abs = n.unsigned_abs();
136 while abs > 0xFF {
137 out[len] = (abs & 0xFF) as u8;
138 len += 1;
139 abs >>= 8;
140 }
141 if abs & 0x80 != 0 {
144 out[len] = abs as u8;
145 len += 1;
146 out[len] = if neg { 0x80u8 } else { 0u8 };
147 len += 1;
148 }
149 else {
151 abs |= if neg { 0x80 } else { 0 };
152 out[len] = abs as u8;
153 len += 1;
154 }
155 len
156}
157
158pub fn read_scriptint(v: &[u8]) -> Result<i64, Error> {
176 let last = match v.last() {
177 Some(last) => last,
178 None => return Ok(0),
179 };
180 if v.len() > 4 {
181 return Err(Error::NumericOverflow);
182 }
183 if (*last & 0x7f) == 0 {
189 if v.len() <= 1 || (v[v.len() - 2] & 0x80) == 0 {
195 return Err(Error::NonMinimalPush);
196 }
197 }
198
199 Ok(scriptint_parse(v))
200}
201
202pub fn read_scriptint_non_minimal(v: &[u8]) -> Result<i64, Error> {
208 if v.is_empty() {
209 return Ok(0);
210 }
211 if v.len() > 4 {
212 return Err(Error::NumericOverflow);
213 }
214
215 Ok(scriptint_parse(v))
216}
217
218fn scriptint_parse(v: &[u8]) -> i64 {
220 let (mut ret, sh) = v.iter().fold((0, 0), |(acc, sh), n| (acc + ((*n as i64) << sh), sh + 8));
221 if v[v.len() - 1] & 0x80 != 0 {
222 ret &= (1 << (sh - 1)) - 1;
223 ret = -ret;
224 }
225 ret
226}
227
228#[inline]
233pub fn read_scriptbool(v: &[u8]) -> bool {
234 match v.split_last() {
235 Some((last, rest)) => !((last & !0x80 == 0x00) && rest.iter().all(|&b| b == 0)),
236 None => false,
237 }
238}
239
240fn read_uint_iter(data: &mut core::slice::Iter<'_, u8>, size: usize) -> Result<usize, UintError> {
243 if data.len() < size {
244 Err(UintError::EarlyEndOfScript)
245 } else if size > usize::from(u16::MAX / 8) {
246 Err(UintError::NumericOverflow)
248 } else {
249 let mut ret = 0;
250 for (i, item) in data.take(size).enumerate() {
251 ret = usize::from(*item)
252 .checked_shl((i * 8) as u32)
254 .ok_or(UintError::NumericOverflow)?
255 .checked_add(ret)
256 .ok_or(UintError::NumericOverflow)?;
257 }
258 Ok(ret)
259 }
260}
261
262fn opcode_to_verify(opcode: Option<Opcode>) -> Option<Opcode> {
263 opcode.and_then(|opcode| match opcode {
264 OP_EQUAL => Some(OP_EQUALVERIFY),
265 OP_NUMEQUAL => Some(OP_NUMEQUALVERIFY),
266 OP_CHECKSIG => Some(OP_CHECKSIGVERIFY),
267 OP_CHECKMULTISIG => Some(OP_CHECKMULTISIGVERIFY),
268 _ => None,
269 })
270}
271
272impl From<ScriptBuf> for Box<Script> {
275 fn from(v: ScriptBuf) -> Self { v.into_boxed_script() }
276}
277
278impl From<ScriptBuf> for Cow<'_, Script> {
279 fn from(value: ScriptBuf) -> Self { Cow::Owned(value) }
280}
281
282impl<'a> From<Cow<'a, Script>> for ScriptBuf {
283 fn from(value: Cow<'a, Script>) -> Self {
284 match value {
285 Cow::Owned(owned) => owned,
286 Cow::Borrowed(borrwed) => borrwed.into(),
287 }
288 }
289}
290
291impl<'a> From<Cow<'a, Script>> for Box<Script> {
292 fn from(value: Cow<'a, Script>) -> Self {
293 match value {
294 Cow::Owned(owned) => owned.into(),
295 Cow::Borrowed(borrwed) => borrwed.into(),
296 }
297 }
298}
299
300impl<'a> From<&'a Script> for Box<Script> {
301 fn from(value: &'a Script) -> Self { value.to_owned().into() }
302}
303
304impl<'a> From<&'a Script> for ScriptBuf {
305 fn from(value: &'a Script) -> Self { value.to_owned() }
306}
307
308impl<'a> From<&'a Script> for Cow<'a, Script> {
309 fn from(value: &'a Script) -> Self { Cow::Borrowed(value) }
310}
311
312#[cfg(any(not(rust_v_1_60), target_has_atomic = "ptr"))]
314impl<'a> From<&'a Script> for Arc<Script> {
315 fn from(value: &'a Script) -> Self {
316 let rw: *const [u8] = Arc::into_raw(Arc::from(&value.0));
317 unsafe { Arc::from_raw(rw as *const Script) }
322 }
323}
324
325impl<'a> From<&'a Script> for Rc<Script> {
326 fn from(value: &'a Script) -> Self {
327 let rw: *const [u8] = Rc::into_raw(Rc::from(&value.0));
328 unsafe { Rc::from_raw(rw as *const Script) }
333 }
334}
335
336impl From<Vec<u8>> for ScriptBuf {
337 fn from(v: Vec<u8>) -> Self { ScriptBuf(v) }
338}
339
340impl From<ScriptBuf> for Vec<u8> {
341 fn from(v: ScriptBuf) -> Self { v.0 }
342}
343
344impl AsRef<Script> for Script {
345 #[inline]
346 fn as_ref(&self) -> &Script { self }
347}
348
349impl AsRef<Script> for ScriptBuf {
350 fn as_ref(&self) -> &Script { self }
351}
352
353impl AsRef<[u8]> for Script {
354 #[inline]
355 fn as_ref(&self) -> &[u8] { self.as_bytes() }
356}
357
358impl AsRef<[u8]> for ScriptBuf {
359 fn as_ref(&self) -> &[u8] { self.as_bytes() }
360}
361
362impl AsMut<Script> for Script {
363 fn as_mut(&mut self) -> &mut Script { self }
364}
365
366impl AsMut<Script> for ScriptBuf {
367 fn as_mut(&mut self) -> &mut Script { self }
368}
369
370impl AsMut<[u8]> for Script {
371 #[inline]
372 fn as_mut(&mut self) -> &mut [u8] { self.as_mut_bytes() }
373}
374
375impl AsMut<[u8]> for ScriptBuf {
376 fn as_mut(&mut self) -> &mut [u8] { self.as_mut_bytes() }
377}
378
379impl fmt::Debug for Script {
380 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
381 f.write_str("Script(")?;
382 self.fmt_asm(f)?;
383 f.write_str(")")
384 }
385}
386
387impl fmt::Debug for ScriptBuf {
388 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(self.as_script(), f) }
389}
390
391impl fmt::Display for Script {
392 #[inline]
393 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.fmt_asm(f) }
394}
395
396impl fmt::Display for ScriptBuf {
397 #[inline]
398 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(self.as_script(), f) }
399}
400
401impl fmt::LowerHex for Script {
402 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
403 fmt::LowerHex::fmt(&self.as_bytes().as_hex(), f)
404 }
405}
406
407impl fmt::LowerHex for ScriptBuf {
408 #[inline]
409 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(self.as_script(), f) }
410}
411
412impl fmt::UpperHex for Script {
413 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
414 fmt::UpperHex::fmt(&self.as_bytes().as_hex(), f)
415 }
416}
417
418impl fmt::UpperHex for ScriptBuf {
419 #[inline]
420 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::UpperHex::fmt(self.as_script(), f) }
421}
422
423impl Deref for ScriptBuf {
424 type Target = Script;
425
426 fn deref(&self) -> &Self::Target { Script::from_bytes(&self.0) }
427}
428
429impl DerefMut for ScriptBuf {
430 fn deref_mut(&mut self) -> &mut Self::Target { Script::from_bytes_mut(&mut self.0) }
431}
432
433impl Borrow<Script> for ScriptBuf {
434 fn borrow(&self) -> &Script { self }
435}
436
437impl BorrowMut<Script> for ScriptBuf {
438 fn borrow_mut(&mut self) -> &mut Script { self }
439}
440
441impl PartialEq<ScriptBuf> for Script {
442 fn eq(&self, other: &ScriptBuf) -> bool { self.eq(other.as_script()) }
443}
444
445impl PartialEq<Script> for ScriptBuf {
446 fn eq(&self, other: &Script) -> bool { self.as_script().eq(other) }
447}
448
449impl PartialOrd<Script> for ScriptBuf {
450 fn partial_cmp(&self, other: &Script) -> Option<Ordering> {
451 self.as_script().partial_cmp(other)
452 }
453}
454
455impl PartialOrd<ScriptBuf> for Script {
456 fn partial_cmp(&self, other: &ScriptBuf) -> Option<Ordering> {
457 self.partial_cmp(other.as_script())
458 }
459}
460
461#[cfg(feature = "serde")]
462impl serde::Serialize for Script {
463 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
465 where
466 S: serde::Serializer,
467 {
468 if serializer.is_human_readable() {
469 serializer.collect_str(&format_args!("{:x}", self))
470 } else {
471 serializer.serialize_bytes(self.as_bytes())
472 }
473 }
474}
475
476#[cfg(feature = "serde")]
478impl<'de> serde::Deserialize<'de> for &'de Script {
479 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
480 where
481 D: serde::Deserializer<'de>,
482 {
483 if deserializer.is_human_readable() {
484 use crate::serde::de::Error;
485
486 return Err(D::Error::custom(
487 "deserialization of `&Script` from human-readable formats is not possible",
488 ));
489 }
490
491 struct Visitor;
492 impl<'de> serde::de::Visitor<'de> for Visitor {
493 type Value = &'de Script;
494
495 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
496 formatter.write_str("borrowed bytes")
497 }
498
499 fn visit_borrowed_bytes<E>(self, v: &'de [u8]) -> Result<Self::Value, E>
500 where
501 E: serde::de::Error,
502 {
503 Ok(Script::from_bytes(v))
504 }
505 }
506 deserializer.deserialize_bytes(Visitor)
507 }
508}
509
510#[cfg(feature = "serde")]
511impl serde::Serialize for ScriptBuf {
512 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
514 where
515 S: serde::Serializer,
516 {
517 (**self).serialize(serializer)
518 }
519}
520
521#[cfg(feature = "serde")]
522impl<'de> serde::Deserialize<'de> for ScriptBuf {
523 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
524 where
525 D: serde::Deserializer<'de>,
526 {
527 use core::fmt::Formatter;
528
529 use hex::FromHex;
530
531 if deserializer.is_human_readable() {
532 struct Visitor;
533 impl<'de> serde::de::Visitor<'de> for Visitor {
534 type Value = ScriptBuf;
535
536 fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
537 formatter.write_str("a script hex")
538 }
539
540 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
541 where
542 E: serde::de::Error,
543 {
544 let v = Vec::from_hex(v).map_err(E::custom)?;
545 Ok(ScriptBuf::from(v))
546 }
547 }
548 deserializer.deserialize_str(Visitor)
549 } else {
550 struct BytesVisitor;
551
552 impl<'de> serde::de::Visitor<'de> for BytesVisitor {
553 type Value = ScriptBuf;
554
555 fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
556 formatter.write_str("a script Vec<u8>")
557 }
558
559 fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
560 where
561 E: serde::de::Error,
562 {
563 Ok(ScriptBuf::from(v.to_vec()))
564 }
565
566 fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
567 where
568 E: serde::de::Error,
569 {
570 Ok(ScriptBuf::from(v))
571 }
572 }
573 deserializer.deserialize_byte_buf(BytesVisitor)
574 }
575 }
576}
577
578impl Encodable for Script {
579 #[inline]
580 fn consensus_encode<W: Write + ?Sized>(&self, w: &mut W) -> Result<usize, io::Error> {
581 crate::consensus::encode::consensus_encode_with_size(&self.0, w)
582 }
583}
584
585impl Encodable for ScriptBuf {
586 #[inline]
587 fn consensus_encode<W: Write + ?Sized>(&self, w: &mut W) -> Result<usize, io::Error> {
588 self.0.consensus_encode(w)
589 }
590}
591
592impl Decodable for ScriptBuf {
593 #[inline]
594 fn consensus_decode_from_finite_reader<R: Read + ?Sized>(
595 r: &mut R,
596 ) -> Result<Self, encode::Error> {
597 Ok(ScriptBuf(Decodable::consensus_decode_from_finite_reader(r)?))
598 }
599}
600
601pub(super) fn bytes_to_asm_fmt(script: &[u8], f: &mut dyn fmt::Write) -> fmt::Result {
603 macro_rules! read_push_data_len {
605 ($iter:expr, $len:literal, $formatter:expr) => {
606 match read_uint_iter($iter, $len) {
607 Ok(n) => {
608 n
609 },
610 Err(UintError::EarlyEndOfScript) => {
611 $formatter.write_str("<unexpected end>")?;
612 break;
613 }
614 Err(UintError::NumericOverflow) => {
619 $formatter.write_str("<push past end>")?;
620 break;
621 }
622 }
623 }
624 }
625
626 let mut iter = script.iter();
627 let mut at_least_one = false;
629 while let Some(byte) = iter.next() {
632 let opcode = Opcode::from(*byte);
633
634 let data_len = if let opcodes::Class::PushBytes(n) =
635 opcode.classify(opcodes::ClassifyContext::Legacy)
636 {
637 n as usize
638 } else {
639 match opcode {
640 OP_PUSHDATA1 => {
641 read_push_data_len!(&mut iter, 1, f)
643 }
644 OP_PUSHDATA2 => {
645 read_push_data_len!(&mut iter, 2, f)
647 }
648 OP_PUSHDATA4 => {
649 read_push_data_len!(&mut iter, 4, f)
651 }
652 _ => 0,
653 }
654 };
655
656 if at_least_one {
657 f.write_str(" ")?;
658 } else {
659 at_least_one = true;
660 }
661 if opcode == OP_PUSHBYTES_0 {
663 f.write_str("OP_0")?;
664 } else {
665 write!(f, "{:?}", opcode)?;
666 }
667 if data_len > 0 {
669 f.write_str(" ")?;
670 if data_len <= iter.len() {
671 for ch in iter.by_ref().take(data_len) {
672 write!(f, "{:02x}", ch)?;
673 }
674 } else {
675 f.write_str("<push past end>")?;
676 break;
677 }
678 }
679 }
680 Ok(())
681}
682
683#[derive(Debug, Clone, PartialEq, Eq)]
687#[non_exhaustive]
688pub enum Error {
689 NonMinimalPush,
692 EarlyEndOfScript,
694 NumericOverflow,
696 UnknownSpentOutput(OutPoint),
698 Serialization,
700}
701
702internals::impl_from_infallible!(Error);
703
704impl fmt::Display for Error {
705 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
706 use Error::*;
707
708 match *self {
709 NonMinimalPush => f.write_str("non-minimal datapush"),
710 EarlyEndOfScript => f.write_str("unexpected end of script"),
711 NumericOverflow =>
712 f.write_str("numeric overflow (number on stack larger than 4 bytes)"),
713 UnknownSpentOutput(ref point) => write!(f, "unknown spent output: {}", point),
714 Serialization =>
715 f.write_str("can not serialize the spending transaction in Transaction::verify()"),
716 }
717 }
718}
719
720#[cfg(feature = "std")]
721impl std::error::Error for Error {
722 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
723 use Error::*;
724
725 match *self {
726 NonMinimalPush
727 | EarlyEndOfScript
728 | NumericOverflow
729 | UnknownSpentOutput(_)
730 | Serialization => None,
731 }
732 }
733}
734
735enum UintError {
738 EarlyEndOfScript,
739 NumericOverflow,
740}
741
742internals::impl_from_infallible!(UintError);
743
744impl From<UintError> for Error {
745 fn from(error: UintError) -> Self {
746 match error {
747 UintError::EarlyEndOfScript => Error::EarlyEndOfScript,
748 UintError::NumericOverflow => Error::NumericOverflow,
749 }
750 }
751}