diff --git a/bitcoin/Cargo.toml b/bitcoin/Cargo.toml index e2e748f06..d73832d57 100644 --- a/bitcoin/Cargo.toml +++ b/bitcoin/Cargo.toml @@ -35,13 +35,12 @@ primitives = { package = "bitcoin-primitives", version = "0.100.0", default-feat secp256k1 = { version = "0.29.0", default-features = false, features = ["hashes", "alloc"] } units = { package = "bitcoin-units", version = "0.1.0", default-features = false, features = ["alloc"] } +arbitrary = { version = "1", optional = true } base64 = { version = "0.22.0", optional = true } -ordered = { version = "0.2.0", optional = true } # `bitcoinconsensus` version includes metadata which indicates the version of Core. Use `cargo tree` to see it. bitcoinconsensus = { version = "0.106.0", default-features = false, optional = true } - +ordered = { version = "0.2.0", optional = true } serde = { version = "1.0.103", default-features = false, features = [ "derive", "alloc" ], optional = true } -arbitrary = { version = "1", optional = true } [dev-dependencies] internals = { package = "bitcoin-internals", version = "0.3.0", features = ["test-serde"] } diff --git a/bitcoin/src/blockdata/script/borrowed.rs b/bitcoin/src/blockdata/script/borrowed.rs index c0c4da3e6..fdecffc85 100644 --- a/bitcoin/src/blockdata/script/borrowed.rs +++ b/bitcoin/src/blockdata/script/borrowed.rs @@ -175,13 +175,13 @@ crate::internal_macros::define_extension_trait! { /// > byte vector pushed is called the "witness program". #[inline] fn witness_version(&self) -> Option { - let script_len = self.0.len(); + let script_len = self.len(); if !(4..=42).contains(&script_len) { return None; } - let ver_opcode = Opcode::from(self.0[0]); // Version 0 or PUSHNUM_1-PUSHNUM_16 - let push_opbyte = self.0[1]; // Second byte push opcode 2-40 bytes + let ver_opcode = Opcode::from(self.as_bytes()[0]); // Version 0 or PUSHNUM_1-PUSHNUM_16 + let push_opbyte = self.as_bytes()[1]; // Second byte push opcode 2-40 bytes if push_opbyte < OP_PUSHBYTES_2.to_u8() || push_opbyte > OP_PUSHBYTES_40.to_u8() { return None; @@ -197,21 +197,21 @@ crate::internal_macros::define_extension_trait! { /// Checks whether a script pubkey is a P2SH output. #[inline] fn is_p2sh(&self) -> bool { - self.0.len() == 23 - && self.0[0] == OP_HASH160.to_u8() - && self.0[1] == OP_PUSHBYTES_20.to_u8() - && self.0[22] == OP_EQUAL.to_u8() + self.len() == 23 + && self.as_bytes()[0] == OP_HASH160.to_u8() + && self.as_bytes()[1] == OP_PUSHBYTES_20.to_u8() + && self.as_bytes()[22] == OP_EQUAL.to_u8() } /// Checks whether a script pubkey is a P2PKH output. #[inline] fn is_p2pkh(&self) -> bool { - self.0.len() == 25 - && self.0[0] == OP_DUP.to_u8() - && self.0[1] == OP_HASH160.to_u8() - && self.0[2] == OP_PUSHBYTES_20.to_u8() - && self.0[23] == OP_EQUALVERIFY.to_u8() - && self.0[24] == OP_CHECKSIG.to_u8() + self.len() == 25 + && self.as_bytes()[0] == OP_DUP.to_u8() + && self.as_bytes()[1] == OP_HASH160.to_u8() + && self.as_bytes()[2] == OP_PUSHBYTES_20.to_u8() + && self.as_bytes()[23] == OP_EQUALVERIFY.to_u8() + && self.as_bytes()[24] == OP_CHECKSIG.to_u8() } /// Checks whether a script is push only. @@ -293,25 +293,25 @@ crate::internal_macros::define_extension_trait! { /// Checks whether a script pubkey is a P2WSH output. #[inline] fn is_p2wsh(&self) -> bool { - self.0.len() == 34 + self.len() == 34 && self.witness_version() == Some(WitnessVersion::V0) - && self.0[1] == OP_PUSHBYTES_32.to_u8() + && self.as_bytes()[1] == OP_PUSHBYTES_32.to_u8() } /// Checks whether a script pubkey is a P2WPKH output. #[inline] fn is_p2wpkh(&self) -> bool { - self.0.len() == 22 + self.len() == 22 && self.witness_version() == Some(WitnessVersion::V0) - && self.0[1] == OP_PUSHBYTES_20.to_u8() + && self.as_bytes()[1] == OP_PUSHBYTES_20.to_u8() } /// Checks whether a script pubkey is a P2TR output. #[inline] fn is_p2tr(&self) -> bool { - self.0.len() == 34 + self.len() == 34 && self.witness_version() == Some(WitnessVersion::V1) - && self.0[1] == OP_PUSHBYTES_32.to_u8() + && self.as_bytes()[1] == OP_PUSHBYTES_32.to_u8() } /// Check if this is a consensus-valid OP_RETURN output. @@ -320,7 +320,7 @@ crate::internal_macros::define_extension_trait! { /// [`is_standard_op_return()`](Self::is_standard_op_return) instead. #[inline] fn is_op_return(&self) -> bool { - match self.0.first() { + match self.as_bytes().first() { Some(b) => *b == OP_RETURN.to_u8(), None => false, } @@ -331,7 +331,7 @@ crate::internal_macros::define_extension_trait! { /// What this function considers to be standard may change without warning pending Bitcoin Core /// changes. #[inline] - fn is_standard_op_return(&self) -> bool { self.is_op_return() && self.0.len() <= 80 } + fn is_standard_op_return(&self) -> bool { self.is_op_return() && self.len() <= 80 } /// Checks whether a script is trivially known to have no satisfying input. /// @@ -345,7 +345,7 @@ crate::internal_macros::define_extension_trait! { fn is_provably_unspendable(&self) -> bool { use crate::opcodes::Class::{IllegalOp, ReturnOp}; - match self.0.first() { + match self.as_bytes().first() { Some(b) => { let first = Opcode::from(*b); let class = first.classify(opcodes::ClassifyContext::Legacy); @@ -447,7 +447,7 @@ crate::internal_macros::define_extension_trait! { /// To force minimal pushes, use [`instructions_minimal`](Self::instructions_minimal). #[inline] fn instructions(&self) -> Instructions { - Instructions { data: self.0.iter(), enforce_minimal: false } + Instructions { data: self.as_bytes().iter(), enforce_minimal: false } } /// Iterates over the script instructions while enforcing minimal pushes. @@ -456,7 +456,7 @@ crate::internal_macros::define_extension_trait! { /// is not minimal. #[inline] fn instructions_minimal(&self) -> Instructions { - Instructions { data: self.0.iter(), enforce_minimal: true } + Instructions { data: self.as_bytes().iter(), enforce_minimal: true } } /// Iterates over the script instructions and their indices. @@ -481,14 +481,16 @@ crate::internal_macros::define_extension_trait! { } /// Writes the human-readable assembly representation of the script to the formatter. + #[deprecated(since = "TBD", note = "use the script's Display impl instead")] fn fmt_asm(&self, f: &mut dyn fmt::Write) -> fmt::Result { bytes_to_asm_fmt(self.as_ref(), f) } /// Returns the human-readable assembly representation of the script. + #[deprecated(since = "TBD", note = "use `to_string()` instead")] fn to_asm_string(&self) -> String { let mut buf = String::new(); - self.fmt_asm(&mut buf).unwrap(); + bytes_to_asm_fmt(self.as_ref(), &mut buf).expect("in-memory writers don't fail"); buf } diff --git a/bitcoin/src/blockdata/script/builder.rs b/bitcoin/src/blockdata/script/builder.rs index 5303d37ef..c8465df9f 100644 --- a/bitcoin/src/blockdata/script/builder.rs +++ b/bitcoin/src/blockdata/script/builder.rs @@ -7,7 +7,7 @@ use crate::locktime::absolute; use crate::opcodes::all::*; use crate::opcodes::{self, Opcode}; use crate::prelude::Vec; -use crate::script::{ScriptBufExt as _, ScriptExt as _, ScriptExtPriv as _}; +use crate::script::{ScriptBufExt as _, ScriptBufExtPriv as _, ScriptExtPriv as _}; use crate::Sequence; /// An Object which can be used to construct a script piece by piece. @@ -82,7 +82,7 @@ impl Builder { // "duplicated code" because we need to update `1` field match opcode_to_verify(self.1) { Some(opcode) => { - (self.0).0.pop(); + (self.0).as_byte_vec().pop(); self.push_opcode(opcode) } None => self.push_opcode(OP_VERIFY), @@ -126,7 +126,7 @@ impl From> for Builder { } impl fmt::Display for Builder { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.0.fmt_asm(f) } + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) } } internals::debug_from_display!(Builder); diff --git a/bitcoin/src/blockdata/script/mod.rs b/bitcoin/src/blockdata/script/mod.rs index aee687b28..c0df71c0b 100644 --- a/bitcoin/src/blockdata/script/mod.rs +++ b/bitcoin/src/blockdata/script/mod.rs @@ -415,7 +415,7 @@ impl AsMut<[u8]> for ScriptBuf { impl fmt::Debug for Script { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str("Script(")?; - self.fmt_asm(f)?; + bytes_to_asm_fmt(self.as_ref(), f)?; f.write_str(")") } } @@ -426,7 +426,7 @@ impl fmt::Debug for ScriptBuf { impl fmt::Display for Script { #[inline] - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.fmt_asm(f) } + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { bytes_to_asm_fmt(self.as_ref(), f) } } impl fmt::Display for ScriptBuf { @@ -616,14 +616,14 @@ impl<'de> serde::Deserialize<'de> for ScriptBuf { impl Encodable for Script { #[inline] fn consensus_encode(&self, w: &mut W) -> Result { - crate::consensus::encode::consensus_encode_with_size(&self.0, w) + crate::consensus::encode::consensus_encode_with_size(self.as_bytes(), w) } } impl Encodable for ScriptBuf { #[inline] fn consensus_encode(&self, w: &mut W) -> Result { - self.0.consensus_encode(w) + self.as_script().consensus_encode(w) } } @@ -632,7 +632,8 @@ impl Decodable for ScriptBuf { fn consensus_decode_from_finite_reader( r: &mut R, ) -> Result { - Ok(ScriptBuf(Decodable::consensus_decode_from_finite_reader(r)?)) + let v: Vec = Decodable::consensus_decode_from_finite_reader(r)?; + Ok(ScriptBuf::from_bytes(v)) } } diff --git a/bitcoin/src/blockdata/script/tests.rs b/bitcoin/src/blockdata/script/tests.rs index d2c53f450..7fdc91553 100644 --- a/bitcoin/src/blockdata/script/tests.rs +++ b/bitcoin/src/blockdata/script/tests.rs @@ -483,40 +483,40 @@ fn script_json_serialize() { #[test] fn script_asm() { assert_eq!( - ScriptBuf::from_hex("6363636363686868686800").unwrap().to_asm_string(), + ScriptBuf::from_hex("6363636363686868686800").unwrap().to_string(), "OP_IF OP_IF OP_IF OP_IF OP_IF OP_ENDIF OP_ENDIF OP_ENDIF OP_ENDIF OP_ENDIF OP_0" ); assert_eq!( - ScriptBuf::from_hex("6363636363686868686800").unwrap().to_asm_string(), + ScriptBuf::from_hex("6363636363686868686800").unwrap().to_string(), "OP_IF OP_IF OP_IF OP_IF OP_IF OP_ENDIF OP_ENDIF OP_ENDIF OP_ENDIF OP_ENDIF OP_0" ); - assert_eq!(ScriptBuf::from_hex("2102715e91d37d239dea832f1460e91e368115d8ca6cc23a7da966795abad9e3b699ac").unwrap().to_asm_string(), + assert_eq!(ScriptBuf::from_hex("2102715e91d37d239dea832f1460e91e368115d8ca6cc23a7da966795abad9e3b699ac").unwrap().to_string(), "OP_PUSHBYTES_33 02715e91d37d239dea832f1460e91e368115d8ca6cc23a7da966795abad9e3b699 OP_CHECKSIG"); // Elements Alpha peg-out transaction with some signatures removed for brevity. Mainly to test PUSHDATA1 - assert_eq!(ScriptBuf::from_hex("0047304402202457e78cc1b7f50d0543863c27de75d07982bde8359b9e3316adec0aec165f2f02200203fd331c4e4a4a02f48cf1c291e2c0d6b2f7078a784b5b3649fca41f8794d401004cf1552103244e602b46755f24327142a0517288cebd159eccb6ccf41ea6edf1f601e9af952103bbbacc302d19d29dbfa62d23f37944ae19853cf260c745c2bea739c95328fcb721039227e83246bd51140fe93538b2301c9048be82ef2fb3c7fc5d78426ed6f609ad210229bf310c379b90033e2ecb07f77ecf9b8d59acb623ab7be25a0caed539e2e6472103703e2ed676936f10b3ce9149fa2d4a32060fb86fa9a70a4efe3f21d7ab90611921031e9b7c6022400a6bb0424bbcde14cff6c016b91ee3803926f3440abf5c146d05210334667f975f55a8455d515a2ef1c94fdfa3315f12319a14515d2a13d82831f62f57ae").unwrap().to_asm_string(), + assert_eq!(ScriptBuf::from_hex("0047304402202457e78cc1b7f50d0543863c27de75d07982bde8359b9e3316adec0aec165f2f02200203fd331c4e4a4a02f48cf1c291e2c0d6b2f7078a784b5b3649fca41f8794d401004cf1552103244e602b46755f24327142a0517288cebd159eccb6ccf41ea6edf1f601e9af952103bbbacc302d19d29dbfa62d23f37944ae19853cf260c745c2bea739c95328fcb721039227e83246bd51140fe93538b2301c9048be82ef2fb3c7fc5d78426ed6f609ad210229bf310c379b90033e2ecb07f77ecf9b8d59acb623ab7be25a0caed539e2e6472103703e2ed676936f10b3ce9149fa2d4a32060fb86fa9a70a4efe3f21d7ab90611921031e9b7c6022400a6bb0424bbcde14cff6c016b91ee3803926f3440abf5c146d05210334667f975f55a8455d515a2ef1c94fdfa3315f12319a14515d2a13d82831f62f57ae").unwrap().to_string(), "OP_0 OP_PUSHBYTES_71 304402202457e78cc1b7f50d0543863c27de75d07982bde8359b9e3316adec0aec165f2f02200203fd331c4e4a4a02f48cf1c291e2c0d6b2f7078a784b5b3649fca41f8794d401 OP_0 OP_PUSHDATA1 552103244e602b46755f24327142a0517288cebd159eccb6ccf41ea6edf1f601e9af952103bbbacc302d19d29dbfa62d23f37944ae19853cf260c745c2bea739c95328fcb721039227e83246bd51140fe93538b2301c9048be82ef2fb3c7fc5d78426ed6f609ad210229bf310c379b90033e2ecb07f77ecf9b8d59acb623ab7be25a0caed539e2e6472103703e2ed676936f10b3ce9149fa2d4a32060fb86fa9a70a4efe3f21d7ab90611921031e9b7c6022400a6bb0424bbcde14cff6c016b91ee3803926f3440abf5c146d05210334667f975f55a8455d515a2ef1c94fdfa3315f12319a14515d2a13d82831f62f57ae"); // Various weird scripts found in transaction 6d7ed9914625c73c0288694a6819196a27ef6c08f98e1270d975a8e65a3dc09a // which triggerred overflow bugs on 32-bit machines in script formatting in the past. assert_eq!( - ScriptBuf::from_hex("01").unwrap().to_asm_string(), + ScriptBuf::from_hex("01").unwrap().to_string(), "OP_PUSHBYTES_1 " ); assert_eq!( - ScriptBuf::from_hex("0201").unwrap().to_asm_string(), + ScriptBuf::from_hex("0201").unwrap().to_string(), "OP_PUSHBYTES_2 " ); - assert_eq!(ScriptBuf::from_hex("4c").unwrap().to_asm_string(), ""); + assert_eq!(ScriptBuf::from_hex("4c").unwrap().to_string(), ""); assert_eq!( - ScriptBuf::from_hex("4c0201").unwrap().to_asm_string(), + ScriptBuf::from_hex("4c0201").unwrap().to_string(), "OP_PUSHDATA1 " ); - assert_eq!(ScriptBuf::from_hex("4d").unwrap().to_asm_string(), ""); + assert_eq!(ScriptBuf::from_hex("4d").unwrap().to_string(), ""); assert_eq!( - ScriptBuf::from_hex("4dffff01").unwrap().to_asm_string(), + ScriptBuf::from_hex("4dffff01").unwrap().to_string(), "OP_PUSHDATA2 " ); assert_eq!( - ScriptBuf::from_hex("4effffffff01").unwrap().to_asm_string(), + ScriptBuf::from_hex("4effffffff01").unwrap().to_string(), "OP_PUSHDATA4 " ); } diff --git a/primitives/Cargo.toml b/primitives/Cargo.toml index 64329f9d1..2d4007d39 100644 --- a/primitives/Cargo.toml +++ b/primitives/Cargo.toml @@ -27,7 +27,6 @@ io = { package = "bitcoin-io", version = "0.1.1", default-features = false } units = { package = "bitcoin-units", version = "0.1.0", default-features = false } ordered = { version = "0.2.0", optional = true } - serde = { version = "1.0.103", default-features = false, features = ["derive"], optional = true } [dev-dependencies]