use core::convert::Infallible;
use core::fmt;
use core::marker::PhantomData;
use core::ops::{Deref, DerefMut};
#[cfg(feature = "arbitrary")]
use arbitrary::{Arbitrary, Unstructured};
use encoding::{ByteVecDecoder, ByteVecDecoderError, Encodable};
use internals::write_err;
use super::{encode_scriptnum, Error, Instruction, Script, ScriptEncoder};
#[cfg(feature = "hex")]
use crate::hex;
use crate::opcodes::all::{
OP_1, OP_1NEGATE, OP_CHECKMULTISIG, OP_CHECKMULTISIGVERIFY, OP_CHECKSIG, OP_CHECKSIGVERIFY,
OP_EQUAL, OP_EQUALVERIFY, OP_NUMEQUAL, OP_NUMEQUALVERIFY, OP_PUSHBYTES_0, OP_PUSHDATA1,
OP_PUSHDATA2, OP_PUSHDATA4, OP_VERIFY,
};
use crate::opcodes::Opcode;
use crate::prelude::{Box, Vec};
#[derive(Clone, PartialOrd, Ord, PartialEq, Eq, Hash)]
pub struct ScriptBuf<T>(PhantomData<T>, Vec<u8>);
impl<T> ScriptBuf<T> {
#[inline]
pub const fn new() -> Self {
Self::from_bytes(Vec::new())
}
#[inline]
pub const fn from_bytes(bytes: Vec<u8>) -> Self {
Self(PhantomData, bytes)
}
#[cfg(feature = "hex")]
pub fn from_hex_prefixed(s: &str) -> Result<Self, FromHexError> {
let v = hex::decode_to_vec(s)?;
Ok(encoding::decode_from_slice(&v)?)
}
#[cfg(feature = "hex")]
pub fn from_hex_no_length_prefix(s: &str) -> Result<Self, hex::DecodeVariableLengthBytesError> {
let v = hex::decode_to_vec(s)?;
Ok(Self::from_bytes(v))
}
#[inline]
pub fn as_script(&self) -> &Script<T> {
Script::from_bytes(&self.1)
}
#[inline]
pub fn as_mut_script(&mut self) -> &mut Script<T> {
Script::from_bytes_mut(&mut self.1)
}
#[inline]
pub fn into_bytes(self) -> Vec<u8> {
self.1
}
#[must_use]
#[inline]
pub fn into_boxed_script(self) -> Box<Script<T>> {
Script::from_boxed_bytes(self.into_bytes().into_boxed_slice())
}
#[inline]
pub fn with_capacity(capacity: usize) -> Self {
Self::from_bytes(Vec::with_capacity(capacity))
}
#[inline]
pub fn reserve(&mut self, additional_len: usize) {
self.1.reserve(additional_len);
}
#[inline]
pub fn reserve_exact(&mut self, additional_len: usize) {
self.1.reserve_exact(additional_len);
}
pub(crate) fn as_byte_vec(&mut self) -> &mut Vec<u8> {
&mut self.1
}
#[inline]
pub fn capacity(&self) -> usize {
self.1.capacity()
}
pub fn reserved_len_for_slice(len: usize) -> usize {
len + if len < 0x4c {
1
} else if len <= 0xff {
2
} else if len <= 0xffff {
3
} else {
5
}
}
pub fn push_opcode(&mut self, opcode: Opcode) {
self.as_byte_vec().push(opcode.to_u8());
}
pub fn push_int(&mut self, n: i32) -> Result<(), Error> {
if n == i32::MIN {
Err(Error::NumericOverflow)
} else {
self.push_int_unchecked(n.into());
Ok(())
}
}
pub fn push_int_unchecked(&mut self, n: i64) {
match n {
-1 => self.push_opcode(OP_1NEGATE),
0 => self.push_opcode(OP_PUSHBYTES_0),
1..=16 => self.push_opcode(Opcode::from(n as u8 + (OP_1.to_u8() - 1))),
_ => self.push_int_non_minimal(n),
}
}
pub fn push_int_non_minimal(&mut self, data: i64) {
let buf = encode_scriptnum(data);
let len = buf.len();
self.reserve(Self::reserved_len_for_slice(len));
self.push_slice_no_opt(
<&super::PushBytes>::try_from(buf.as_slice()).expect("scriptint bytes fit PushBytes"),
);
}
pub fn push_slice<D: AsRef<[u8]>>(&mut self, data: D) {
let bytes = data.as_ref();
if bytes.len() == 1 {
match bytes[0] {
0x81 => self.push_opcode(OP_1NEGATE),
1..=16 => self.push_opcode(Opcode::from(bytes[0] + (OP_1.to_u8() - 1))),
_ => self.push_slice_non_minimal(data),
}
} else {
self.push_slice_non_minimal(data);
}
}
pub fn push_slice_non_minimal<D: AsRef<[u8]>>(&mut self, data: D) {
let data =
<&super::PushBytes>::try_from(data.as_ref()).expect("push data length fits PushBytes");
self.reserve(Self::reserved_len_for_slice(data.len()));
self.push_slice_no_opt(data);
}
pub fn push_instruction(&mut self, instruction: Instruction<'_>) {
match instruction {
Instruction::Op(opcode) => self.push_opcode(opcode),
Instruction::PushBytes(bytes) => self.push_slice(bytes),
}
}
pub fn scan_and_push_verify(&mut self) {
match opcode_to_verify(self.last_opcode()) {
Some(opcode) => {
self.as_byte_vec().pop();
self.push_opcode(opcode);
}
None => self.push_opcode(OP_VERIFY),
}
}
fn push_slice_no_opt(&mut self, data: &super::PushBytes) {
let len = data.len();
let bytes = self.as_byte_vec();
match len {
n if n < OP_PUSHDATA1.to_u8() as usize => bytes.push(n as u8),
n if n <= 0xff => {
bytes.push(OP_PUSHDATA1.to_u8());
bytes.push(n as u8);
}
n if n <= 0xffff => {
bytes.push(OP_PUSHDATA2.to_u8());
bytes.extend_from_slice(&(n as u16).to_le_bytes());
}
n => {
bytes.push(OP_PUSHDATA4.to_u8());
bytes.extend_from_slice(&(n as u32).to_le_bytes());
}
}
bytes.extend_from_slice(data.as_bytes());
}
}
fn opcode_to_verify(opcode: Option<Opcode>) -> Option<Opcode> {
opcode.and_then(|opcode| match opcode {
OP_EQUAL => Some(OP_EQUALVERIFY),
OP_NUMEQUAL => Some(OP_NUMEQUALVERIFY),
OP_CHECKSIG => Some(OP_CHECKSIGVERIFY),
OP_CHECKMULTISIG => Some(OP_CHECKMULTISIGVERIFY),
_ => None,
})
}
impl<T> Default for ScriptBuf<T> {
fn default() -> Self {
Self(PhantomData, Vec::new())
}
}
impl<T> Deref for ScriptBuf<T> {
type Target = Script<T>;
#[inline]
fn deref(&self) -> &Self::Target {
self.as_script()
}
}
impl<T> DerefMut for ScriptBuf<T> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
self.as_mut_script()
}
}
impl<T> Encodable for ScriptBuf<T> {
type Encoder<'e>
= ScriptEncoder<'e>
where
Self: 'e;
#[inline]
fn encoder(&self) -> Self::Encoder<'_> {
self.as_script().encoder()
}
}
pub struct ScriptBufDecoder<T>(ByteVecDecoder, PhantomData<T>);
impl<T> ScriptBufDecoder<T> {
pub const fn new() -> Self {
Self(ByteVecDecoder::new(), PhantomData)
}
}
impl<T> Default for ScriptBufDecoder<T> {
fn default() -> Self {
Self::new()
}
}
impl<T> encoding::Decoder for ScriptBufDecoder<T> {
type Output = ScriptBuf<T>;
type Error = ScriptBufDecoderError;
#[inline]
fn push_bytes(&mut self, bytes: &mut &[u8]) -> Result<bool, Self::Error> {
self.0.push_bytes(bytes).map_err(ScriptBufDecoderError)
}
#[inline]
fn end(self) -> Result<Self::Output, Self::Error> {
Ok(ScriptBuf::from_bytes(self.0.end().map_err(ScriptBufDecoderError)?))
}
#[inline]
fn read_limit(&self) -> usize {
self.0.read_limit()
}
}
impl<T> encoding::Decodable for ScriptBuf<T> {
type Decoder = ScriptBufDecoder<T>;
fn decoder() -> Self::Decoder {
ScriptBufDecoder(ByteVecDecoder::new(), PhantomData)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ScriptBufDecoderError(ByteVecDecoderError);
impl From<Infallible> for ScriptBufDecoderError {
fn from(never: Infallible) -> Self {
match never {}
}
}
impl fmt::Display for ScriptBufDecoderError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write_err!(f, "decoder error"; self.0)
}
}
#[cfg(feature = "std")]
impl std::error::Error for ScriptBufDecoderError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
Some(&self.0)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
#[cfg(feature = "hex")]
pub enum FromHexError {
Hex(hex::DecodeVariableLengthBytesError),
Decoder(encoding::DecodeError<ScriptBufDecoderError>),
}
#[cfg(feature = "hex")]
impl From<Infallible> for FromHexError {
fn from(never: Infallible) -> Self {
match never {}
}
}
#[cfg(feature = "hex")]
impl fmt::Display for FromHexError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Self::Hex(ref e) => write_err!(f, "script hex"; e),
Self::Decoder(ref e) => write_err!(f, "script decoder"; e),
}
}
}
#[cfg(all(feature = "std", feature = "hex"))]
impl std::error::Error for FromHexError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match *self {
Self::Hex(ref e) => Some(e),
Self::Decoder(ref e) => Some(e),
}
}
}
#[cfg(feature = "hex")]
impl From<hex::DecodeVariableLengthBytesError> for FromHexError {
fn from(e: hex::DecodeVariableLengthBytesError) -> Self {
Self::Hex(e)
}
}
#[cfg(feature = "hex")]
impl From<encoding::DecodeError<ScriptBufDecoderError>> for FromHexError {
fn from(e: encoding::DecodeError<ScriptBufDecoderError>) -> Self {
Self::Decoder(e)
}
}
#[cfg(feature = "arbitrary")]
impl<'a, T> Arbitrary<'a> for ScriptBuf<T> {
#[inline]
fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
let v = Vec::<u8>::arbitrary(u)?;
Ok(Self::from_bytes(v))
}
}
impl<'a, Tg> core::iter::FromIterator<Instruction<'a>> for ScriptBuf<Tg> {
fn from_iter<T>(iter: T) -> Self
where
T: IntoIterator<Item = Instruction<'a>>,
{
let mut script = Self::new();
script.extend(iter);
script
}
}
impl<'a, Tg> Extend<Instruction<'a>> for ScriptBuf<Tg> {
fn extend<T>(&mut self, iter: T)
where
T: IntoIterator<Item = Instruction<'a>>,
{
let iter = iter.into_iter();
if iter.size_hint().1.is_some_and(|max| max < 6) {
let mut iter = iter.fuse();
let mut head = [None; 5];
let mut total_size = 0;
for (head, instr) in head.iter_mut().zip(&mut iter) {
total_size += instr.script_serialized_len();
*head = Some(instr);
}
assert!(
iter.next().is_none(),
"Buggy implementation of `Iterator` on {} returns invalid upper bound",
core::any::type_name::<T::IntoIter>()
);
self.reserve(total_size);
for instr in head.iter().copied().flatten() {
match instr {
Instruction::Op(opcode) => self.push_opcode(opcode),
Instruction::PushBytes(bytes) => self.push_slice_no_opt(bytes),
}
}
} else {
for instr in iter {
self.push_instruction(instr);
}
}
}
}