Merge rust-bitcoin/rust-bitcoin#1957: Remove deprecated code
50ada8298f
Move EncodeSigningDataResult to sighash module (Tobin C. Harding)1b7dc51ccb
Remove deprecated code (Tobin C. Harding) Pull request description: We only keep deprecated code around for one release so we can now remove code deprecated in v0.30.0 Done in preparation as we gear up for v0.31.0 release. ACKs for top commit: apoelstra: ACK50ada8298f
sanket1729: ACK50ada8298f
Tree-SHA512: 40769258605563e2e12a6118306655fc9a012ae1f86509fca757ca411f0cef74480b7bb7b0db147f30a7d362b8494a077d5ec04f719351661ceb5a0697a5369d
This commit is contained in:
commit
c042b66931
|
@ -718,13 +718,6 @@ impl Address {
|
|||
///
|
||||
pub fn is_spend_standard(&self) -> bool { self.address_type().is_some() }
|
||||
|
||||
/// Checks whether or not the address is following Bitcoin standardness rules.
|
||||
///
|
||||
/// SegWit addresses with unassigned witness versions or non-standard program sizes are
|
||||
/// considered non-standard.
|
||||
#[deprecated(since = "0.30.0", note = "Use Address::is_spend_standard instead")]
|
||||
pub fn is_standard(&self) -> bool { self.address_type().is_some() }
|
||||
|
||||
/// Constructs an [`Address`] from an output script (`scriptPubkey`).
|
||||
pub fn from_script(script: &Script, network: Network) -> Result<Address, Error> {
|
||||
Ok(Address::new(network, Payload::from_script(script)?))
|
||||
|
|
|
@ -35,10 +35,6 @@ static BASE58_DIGITS: [Option<u8>; 128] = [
|
|||
Some(55), Some(56), Some(57), None, None, None, None, None, // 120-127
|
||||
];
|
||||
|
||||
/// Decodes a base58-encoded string into a byte vector.
|
||||
#[deprecated(since = "0.30.0", note = "Use base58::decode() instead")]
|
||||
pub fn from(data: &str) -> Result<Vec<u8>, Error> { decode(data) }
|
||||
|
||||
/// Decodes a base58-encoded string into a byte vector.
|
||||
pub fn decode(data: &str) -> Result<Vec<u8>, Error> {
|
||||
// 11/15 is just over log_256(58)
|
||||
|
@ -70,10 +66,6 @@ pub fn decode(data: &str) -> Result<Vec<u8>, Error> {
|
|||
Ok(ret)
|
||||
}
|
||||
|
||||
/// Decodes a base58check-encoded string into a byte vector verifying the checksum.
|
||||
#[deprecated(since = "0.30.0", note = "Use base58::decode_check() instead")]
|
||||
pub fn from_check(data: &str) -> Result<Vec<u8>, Error> { decode_check(data) }
|
||||
|
||||
/// Decodes a base58check-encoded string into a byte vector verifying the checksum.
|
||||
pub fn decode_check(data: &str) -> Result<Vec<u8>, Error> {
|
||||
let mut ret: Vec<u8> = decode(data)?;
|
||||
|
@ -97,19 +89,9 @@ pub fn decode_check(data: &str) -> Result<Vec<u8>, Error> {
|
|||
Ok(ret)
|
||||
}
|
||||
|
||||
/// Encodes `data` as a base58 string.
|
||||
#[deprecated(since = "0.30.0", note = "Use base58::encode() instead")]
|
||||
pub fn encode_slice(data: &[u8]) -> String { encode(data) }
|
||||
|
||||
/// Encodes `data` as a base58 string (see also `base58::encode_check()`).
|
||||
pub fn encode(data: &[u8]) -> String { encode_iter(data.iter().cloned()) }
|
||||
|
||||
/// Encodes `data` as a base58 string including the checksum.
|
||||
///
|
||||
/// The checksum is the first four bytes of the sha256d of the data, concatenated onto the end.
|
||||
#[deprecated(since = "0.30.0", note = "Use base58::encode_check() instead")]
|
||||
pub fn check_encode_slice(data: &[u8]) -> String { encode_check(data) }
|
||||
|
||||
/// Encodes `data` as a base58 string including the checksum.
|
||||
///
|
||||
/// The checksum is the first four bytes of the sha256d of the data, concatenated onto the end.
|
||||
|
@ -118,14 +100,6 @@ pub fn encode_check(data: &[u8]) -> String {
|
|||
encode_iter(data.iter().cloned().chain(checksum[0..4].iter().cloned()))
|
||||
}
|
||||
|
||||
/// Encodes `data` as base58, including the checksum, into a formatter.
|
||||
///
|
||||
/// The checksum is the first four bytes of the sha256d of the data, concatenated onto the end.
|
||||
#[deprecated(since = "0.30.0", note = "Use base58::encode_check_to_fmt() instead")]
|
||||
pub fn check_encode_slice_to_fmt(fmt: &mut fmt::Formatter, data: &[u8]) -> fmt::Result {
|
||||
encode_check_to_fmt(fmt, data)
|
||||
}
|
||||
|
||||
/// Encodes a slice as base58, including the checksum, into a formatter.
|
||||
///
|
||||
/// The checksum is the first four bytes of the sha256d of the data, concatenated onto the end.
|
||||
|
|
|
@ -182,24 +182,6 @@ pub fn read_scriptbool(v: &[u8]) -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
/// Decodes a script-encoded unsigned integer.
|
||||
///
|
||||
/// ## Errors
|
||||
///
|
||||
/// This function returns an error in these cases:
|
||||
///
|
||||
/// * `data` is shorter than `size` => `EarlyEndOfScript`
|
||||
/// * `size` is greater than `u16::MAX / 8` (8191) => `NumericOverflow`
|
||||
/// * The number being read overflows `usize` => `NumericOverflow`
|
||||
///
|
||||
/// Note that this does **not** return an error for `size` between `core::size_of::<usize>()`
|
||||
/// and `u16::MAX / 8` if there's no overflow.
|
||||
#[inline]
|
||||
#[deprecated(since = "0.30.0", note = "bitcoin integers are signed 32 bits, use read_scriptint")]
|
||||
pub fn read_uint(data: &[u8], size: usize) -> Result<usize, Error> {
|
||||
read_uint_iter(&mut data.iter(), size).map_err(Into::into)
|
||||
}
|
||||
|
||||
// We internally use implementation based on iterator so that it automatically advances as needed
|
||||
// Errors are same as above, just different type.
|
||||
fn read_uint_iter(data: &mut core::slice::Iter<'_, u8>, size: usize) -> Result<usize, UintError> {
|
||||
|
|
|
@ -21,12 +21,11 @@ use internals::write_err;
|
|||
use super::Weight;
|
||||
use crate::blockdata::locktime::absolute::{self, Height, Time};
|
||||
use crate::blockdata::locktime::relative;
|
||||
use crate::blockdata::script::{Script, ScriptBuf};
|
||||
use crate::blockdata::script::ScriptBuf;
|
||||
use crate::blockdata::witness::Witness;
|
||||
#[cfg(feature = "bitcoinconsensus")]
|
||||
pub use crate::consensus::validation::TxVerifyError;
|
||||
use crate::consensus::{encode, Decodable, Encodable};
|
||||
use crate::crypto::sighash::LegacySighash;
|
||||
use crate::hash_types::{Txid, Wtxid};
|
||||
use crate::internal_macros::impl_consensus_encoding;
|
||||
use crate::parse::impl_parse_str_from_int_infallible;
|
||||
|
@ -525,75 +524,6 @@ impl TxOut {
|
|||
}
|
||||
}
|
||||
|
||||
/// Result of [`Transaction::encode_signing_data_to`].
|
||||
///
|
||||
/// This type forces the caller to handle SIGHASH_SINGLE bug case.
|
||||
///
|
||||
/// This corner case can't be expressed using standard `Result`,
|
||||
/// in a way that is both convenient and not-prone to accidental
|
||||
/// mistakes (like calling `.expect("writer never fails")`).
|
||||
#[must_use]
|
||||
pub enum EncodeSigningDataResult<E> {
|
||||
/// Input data is an instance of `SIGHASH_SINGLE` bug
|
||||
SighashSingleBug,
|
||||
/// Operation performed normally.
|
||||
WriteResult(Result<(), E>),
|
||||
}
|
||||
|
||||
impl<E> EncodeSigningDataResult<E> {
|
||||
/// Checks for SIGHASH_SINGLE bug returning error if the writer failed.
|
||||
///
|
||||
/// This method is provided for easy and correct handling of the result because
|
||||
/// SIGHASH_SINGLE bug is a special case that must not be ignored nor cause panicking.
|
||||
/// Since the data is usually written directly into a hasher which never fails,
|
||||
/// the recommended pattern to handle this is:
|
||||
///
|
||||
/// ```rust
|
||||
/// # use bitcoin::consensus::deserialize;
|
||||
/// # use bitcoin::hashes::{Hash, hex::FromHex};
|
||||
/// # use bitcoin::sighash::{LegacySighash, SighashCache};
|
||||
/// # use bitcoin::Transaction;
|
||||
/// # let mut writer = LegacySighash::engine();
|
||||
/// # let input_index = 0;
|
||||
/// # let script_pubkey = bitcoin::ScriptBuf::new();
|
||||
/// # let sighash_u32 = 0u32;
|
||||
/// # const SOME_TX: &'static str = "0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000";
|
||||
/// # let raw_tx = Vec::from_hex(SOME_TX).unwrap();
|
||||
/// # let tx: Transaction = deserialize(&raw_tx).unwrap();
|
||||
/// let cache = SighashCache::new(&tx);
|
||||
/// if cache.legacy_encode_signing_data_to(&mut writer, input_index, &script_pubkey, sighash_u32)
|
||||
/// .is_sighash_single_bug()
|
||||
/// .expect("writer can't fail") {
|
||||
/// // use a hash value of "1", instead of computing the actual hash due to SIGHASH_SINGLE bug
|
||||
/// }
|
||||
/// ```
|
||||
#[allow(clippy::wrong_self_convention)] // E is not Copy so we consume self.
|
||||
pub fn is_sighash_single_bug(self) -> Result<bool, E> {
|
||||
match self {
|
||||
EncodeSigningDataResult::SighashSingleBug => Ok(true),
|
||||
EncodeSigningDataResult::WriteResult(Ok(())) => Ok(false),
|
||||
EncodeSigningDataResult::WriteResult(Err(e)) => Err(e),
|
||||
}
|
||||
}
|
||||
|
||||
/// Maps a `Result<T, E>` to `Result<T, F>` by applying a function to a
|
||||
/// contained [`Err`] value, leaving an [`Ok`] value untouched.
|
||||
///
|
||||
/// Like [`Result::map_err`].
|
||||
pub fn map_err<E2, F>(self, f: F) -> EncodeSigningDataResult<E2>
|
||||
where
|
||||
F: FnOnce(E) -> E2,
|
||||
{
|
||||
match self {
|
||||
EncodeSigningDataResult::SighashSingleBug => EncodeSigningDataResult::SighashSingleBug,
|
||||
EncodeSigningDataResult::WriteResult(Err(e)) =>
|
||||
EncodeSigningDataResult::WriteResult(Err(f(e))),
|
||||
EncodeSigningDataResult::WriteResult(Ok(o)) =>
|
||||
EncodeSigningDataResult::WriteResult(Ok(o)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Bitcoin transaction.
|
||||
///
|
||||
/// An authenticated movement of coins.
|
||||
|
@ -729,101 +659,6 @@ impl Transaction {
|
|||
Wtxid::from_engine(enc)
|
||||
}
|
||||
|
||||
/// Encodes the signing data from which a signature hash for a given input index with a given
|
||||
/// sighash flag can be computed.
|
||||
///
|
||||
/// To actually produce a scriptSig, this hash needs to be run through an ECDSA signer, the
|
||||
/// [`EcdsaSighashType`] appended to the resulting sig, and a script written around this, but
|
||||
/// this is the general (and hard) part.
|
||||
///
|
||||
/// The `sighash_type` supports an arbitrary `u32` value, instead of just [`EcdsaSighashType`],
|
||||
/// because internally 4 bytes are being hashed, even though only the lowest byte is appended to
|
||||
/// signature in a transaction.
|
||||
///
|
||||
/// # Warning
|
||||
///
|
||||
/// - Does NOT attempt to support OP_CODESEPARATOR. In general this would require evaluating
|
||||
/// `script_pubkey` to determine which separators get evaluated and which don't, which we don't
|
||||
/// have the information to determine.
|
||||
/// - Does NOT handle the sighash single bug (see "Returns" section)
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// This function can't handle the SIGHASH_SINGLE bug internally, so it returns [`EncodeSigningDataResult`]
|
||||
/// that must be handled by the caller (see [`EncodeSigningDataResult::is_sighash_single_bug`]).
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// If `input_index` is out of bounds (greater than or equal to `self.input.len()`).
|
||||
#[deprecated(
|
||||
since = "0.30.0",
|
||||
note = "Use SighashCache::legacy_encode_signing_data_to instead"
|
||||
)]
|
||||
pub fn encode_signing_data_to<Write: io::Write, U: Into<u32>>(
|
||||
&self,
|
||||
writer: Write,
|
||||
input_index: usize,
|
||||
script_pubkey: &Script,
|
||||
sighash_type: U,
|
||||
) -> EncodeSigningDataResult<io::Error> {
|
||||
use EncodeSigningDataResult::*;
|
||||
|
||||
use crate::sighash::{self, SighashCache};
|
||||
|
||||
assert!(input_index < self.input.len()); // Panic on OOB
|
||||
|
||||
let cache = SighashCache::new(self);
|
||||
match cache.legacy_encode_signing_data_to(writer, input_index, script_pubkey, sighash_type)
|
||||
{
|
||||
SighashSingleBug => SighashSingleBug,
|
||||
WriteResult(res) => match res {
|
||||
Ok(()) => WriteResult(Ok(())),
|
||||
Err(e) => match e {
|
||||
sighash::Error::Io(e) => WriteResult(Err(e.into())),
|
||||
_ => unreachable!("we check input_index above"),
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Computes a signature hash for a given input index with a given sighash flag.
|
||||
///
|
||||
/// To actually produce a scriptSig, this hash needs to be run through an ECDSA signer, the
|
||||
/// [`EcdsaSighashType`] appended to the resulting sig, and a script written around this, but
|
||||
/// this is the general (and hard) part.
|
||||
///
|
||||
/// The `sighash_type` supports an arbitrary `u32` value, instead of just [`EcdsaSighashType`],
|
||||
/// because internally 4 bytes are being hashed, even though only the lowest byte is appended to
|
||||
/// signature in a transaction.
|
||||
///
|
||||
/// This function correctly handles the sighash single bug by returning the 'one array'. The
|
||||
/// sighash single bug becomes exploitable when one tries to sign a transaction with
|
||||
/// `SIGHASH_SINGLE` and there is not a corresponding output with the same index as the input.
|
||||
///
|
||||
/// # Warning
|
||||
///
|
||||
/// Does NOT attempt to support OP_CODESEPARATOR. In general this would require evaluating
|
||||
/// `script_pubkey` to determine which separators get evaluated and which don't, which we don't
|
||||
/// have the information to determine.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// If `input_index` is out of bounds (greater than or equal to `self.input.len()`).
|
||||
#[deprecated(since = "0.30.0", note = "Use SighashCache::legacy_signature_hash instead")]
|
||||
pub fn signature_hash(
|
||||
&self,
|
||||
input_index: usize,
|
||||
script_pubkey: &Script,
|
||||
sighash_u32: u32,
|
||||
) -> LegacySighash {
|
||||
assert!(input_index < self.input.len()); // Panic on OOB, enables expect below.
|
||||
|
||||
let cache = crate::sighash::SighashCache::new(self);
|
||||
cache
|
||||
.legacy_signature_hash(input_index, script_pubkey, sighash_u32)
|
||||
.expect("cache method doesn't error")
|
||||
}
|
||||
|
||||
/// Returns the "weight" of this transaction, as defined by BIP141.
|
||||
///
|
||||
/// For transactions with an empty witness, this is simply the consensus-serialized size times
|
||||
|
|
|
@ -227,10 +227,6 @@ impl Witness {
|
|||
/// Creates a new empty [`Witness`].
|
||||
pub fn new() -> Self { Witness::default() }
|
||||
|
||||
/// Creates [`Witness`] object from an array of byte-arrays
|
||||
#[deprecated(since = "0.30.0", note = "use `Witness::from_slice()` instead")]
|
||||
pub fn from_vec(vec: Vec<Vec<u8>>) -> Self { Witness::from_slice(&vec) }
|
||||
|
||||
/// Creates a [`Witness`] object from a slice of bytes slices where each slice is a witness item.
|
||||
pub fn from_slice<T: AsRef<[u8]>>(slice: &[T]) -> Self {
|
||||
let witness_elements = slice.len();
|
||||
|
|
|
@ -16,7 +16,6 @@ use core::{fmt, str};
|
|||
|
||||
use hashes::{hash_newtype, sha256, sha256d, sha256t_hash_newtype, Hash};
|
||||
|
||||
use crate::blockdata::transaction::EncodeSigningDataResult;
|
||||
use crate::blockdata::witness::Witness;
|
||||
use crate::consensus::{encode, Encodable};
|
||||
use crate::error::impl_std_error;
|
||||
|
@ -1118,6 +1117,75 @@ fn is_invalid_use_of_sighash_single(sighash: u32, input_index: usize, output_len
|
|||
ty == EcdsaSighashType::Single && input_index >= output_len
|
||||
}
|
||||
|
||||
/// Result of [`SighashCache::legacy_encode_signing_data_to`].
|
||||
///
|
||||
/// This type forces the caller to handle SIGHASH_SINGLE bug case.
|
||||
///
|
||||
/// This corner case can't be expressed using standard `Result`,
|
||||
/// in a way that is both convenient and not-prone to accidental
|
||||
/// mistakes (like calling `.expect("writer never fails")`).
|
||||
#[must_use]
|
||||
pub enum EncodeSigningDataResult<E> {
|
||||
/// Input data is an instance of `SIGHASH_SINGLE` bug
|
||||
SighashSingleBug,
|
||||
/// Operation performed normally.
|
||||
WriteResult(Result<(), E>),
|
||||
}
|
||||
|
||||
impl<E> EncodeSigningDataResult<E> {
|
||||
/// Checks for SIGHASH_SINGLE bug returning error if the writer failed.
|
||||
///
|
||||
/// This method is provided for easy and correct handling of the result because
|
||||
/// SIGHASH_SINGLE bug is a special case that must not be ignored nor cause panicking.
|
||||
/// Since the data is usually written directly into a hasher which never fails,
|
||||
/// the recommended pattern to handle this is:
|
||||
///
|
||||
/// ```rust
|
||||
/// # use bitcoin::consensus::deserialize;
|
||||
/// # use bitcoin::hashes::{Hash, hex::FromHex};
|
||||
/// # use bitcoin::sighash::{LegacySighash, SighashCache};
|
||||
/// # use bitcoin::Transaction;
|
||||
/// # let mut writer = LegacySighash::engine();
|
||||
/// # let input_index = 0;
|
||||
/// # let script_pubkey = bitcoin::ScriptBuf::new();
|
||||
/// # let sighash_u32 = 0u32;
|
||||
/// # const SOME_TX: &'static str = "0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000";
|
||||
/// # let raw_tx = Vec::from_hex(SOME_TX).unwrap();
|
||||
/// # let tx: Transaction = deserialize(&raw_tx).unwrap();
|
||||
/// let cache = SighashCache::new(&tx);
|
||||
/// if cache.legacy_encode_signing_data_to(&mut writer, input_index, &script_pubkey, sighash_u32)
|
||||
/// .is_sighash_single_bug()
|
||||
/// .expect("writer can't fail") {
|
||||
/// // use a hash value of "1", instead of computing the actual hash due to SIGHASH_SINGLE bug
|
||||
/// }
|
||||
/// ```
|
||||
#[allow(clippy::wrong_self_convention)] // E is not Copy so we consume self.
|
||||
pub fn is_sighash_single_bug(self) -> Result<bool, E> {
|
||||
match self {
|
||||
EncodeSigningDataResult::SighashSingleBug => Ok(true),
|
||||
EncodeSigningDataResult::WriteResult(Ok(())) => Ok(false),
|
||||
EncodeSigningDataResult::WriteResult(Err(e)) => Err(e),
|
||||
}
|
||||
}
|
||||
|
||||
/// Maps a `Result<T, E>` to `Result<T, F>` by applying a function to a
|
||||
/// contained [`Err`] value, leaving an [`Ok`] value untouched.
|
||||
///
|
||||
/// Like [`Result::map_err`].
|
||||
pub fn map_err<E2, F>(self, f: F) -> EncodeSigningDataResult<E2>
|
||||
where
|
||||
F: FnOnce(E) -> E2,
|
||||
{
|
||||
match self {
|
||||
EncodeSigningDataResult::SighashSingleBug => EncodeSigningDataResult::SighashSingleBug,
|
||||
EncodeSigningDataResult::WriteResult(Err(e)) =>
|
||||
EncodeSigningDataResult::WriteResult(Err(f(e))),
|
||||
EncodeSigningDataResult::WriteResult(Ok(o)) =>
|
||||
EncodeSigningDataResult::WriteResult(Ok(o)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::str::FromStr;
|
||||
|
|
|
@ -113,7 +113,6 @@ pub mod psbt;
|
|||
pub mod sign_message;
|
||||
pub mod string;
|
||||
pub mod taproot;
|
||||
pub mod util;
|
||||
|
||||
// May depend on crate features and we don't want to bother with it
|
||||
#[allow(unused)]
|
||||
|
|
|
@ -1060,10 +1060,6 @@ impl TaprootMerkleBranch {
|
|||
/// Checks if this merkle proof is empty.
|
||||
pub fn is_empty(&self) -> bool { self.0.is_empty() }
|
||||
|
||||
/// Decodes bytes from control block.
|
||||
#[deprecated(since = "0.30.0", note = "Use decode instead")]
|
||||
pub fn from_slice(sl: &[u8]) -> Result<Self, TaprootError> { Self::decode(sl) }
|
||||
|
||||
/// Decodes bytes from control block.
|
||||
///
|
||||
/// This reads the branch as encoded in the control block: the concatenated 32B byte chunks -
|
||||
|
@ -1199,10 +1195,6 @@ pub struct ControlBlock {
|
|||
}
|
||||
|
||||
impl ControlBlock {
|
||||
/// Constructs a `ControlBlock` from slice.
|
||||
#[deprecated(since = "0.30.0", note = "Use decode instead")]
|
||||
pub fn from_slice(sl: &[u8]) -> Result<ControlBlock, TaprootError> { Self::decode(sl) }
|
||||
|
||||
/// Decodes bytes representing a `ControlBlock`.
|
||||
///
|
||||
/// This is an extra witness element that provides the proof that taproot script pubkey is
|
||||
|
|
|
@ -1,58 +0,0 @@
|
|||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
//! Utility functions.
|
||||
//!
|
||||
//! Functions needed by all parts of the Bitcoin library.
|
||||
//!
|
||||
|
||||
/// The `misc` module was moved and re-named to `sign_message`.
|
||||
pub mod misc {
|
||||
use crate::prelude::*;
|
||||
|
||||
/// Search for `needle` in the vector `haystack` and remove every
|
||||
/// instance of it, returning the number of instances removed.
|
||||
/// Loops through the vector opcode by opcode, skipping pushed data.
|
||||
// For why we deprecated see: https://github.com/rust-bitcoin/rust-bitcoin/pull/1259#discussion_r968613736
|
||||
#[deprecated(since = "0.30.0", note = "No longer supported")]
|
||||
pub fn script_find_and_remove(haystack: &mut Vec<u8>, needle: &[u8]) -> usize {
|
||||
use crate::blockdata::opcodes;
|
||||
|
||||
if needle.len() > haystack.len() {
|
||||
return 0;
|
||||
}
|
||||
if needle.is_empty() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
let mut top = haystack.len() - needle.len();
|
||||
let mut n_deleted = 0;
|
||||
|
||||
let mut i = 0;
|
||||
while i <= top {
|
||||
if &haystack[i..(i + needle.len())] == needle {
|
||||
for j in i..top {
|
||||
haystack.swap(j + needle.len(), j);
|
||||
}
|
||||
n_deleted += 1;
|
||||
// This is ugly but prevents infinite loop in case of overflow
|
||||
let overflow = top < needle.len();
|
||||
top = top.wrapping_sub(needle.len());
|
||||
if overflow {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
i += match opcodes::All::from((*haystack)[i])
|
||||
.classify(opcodes::ClassifyContext::Legacy)
|
||||
{
|
||||
opcodes::Class::PushBytes(n) => n as usize + 1,
|
||||
opcodes::Class::Ordinary(opcodes::Ordinary::OP_PUSHDATA1) => 2,
|
||||
opcodes::Class::Ordinary(opcodes::Ordinary::OP_PUSHDATA2) => 3,
|
||||
opcodes::Class::Ordinary(opcodes::Ordinary::OP_PUSHDATA4) => 5,
|
||||
_ => 1,
|
||||
};
|
||||
}
|
||||
}
|
||||
haystack.truncate(top.wrapping_add(needle.len()));
|
||||
n_deleted
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue