mod borrowed;
mod builder;
mod owned;
mod push_bytes;
pub mod witness_program;
pub mod witness_version;
use core::convert::Infallible;
use core::fmt;
use self::witness_version::WitnessVersion;
use crate::key::WPubkeyHash;
use crate::opcodes::all::*;
use crate::OutPoint;
#[rustfmt::skip] #[doc(inline)]
pub use self::{
borrowed::{ScriptExt, ScriptPubKeyExt, WitnessScriptExt, ScriptSigExt},
builder::Builder,
owned::{ScriptBufExt, ScriptPubKeyBufExt},
push_bytes::PushBytesErrorReport,
};
#[doc(no_inline)]
pub use primitives::script::ScriptBufDecoderError;
#[doc(inline)]
pub use primitives::script::{
read_scriptbool, read_scriptint_non_minimal, write_scriptint, Instruction, InstructionIndices,
Instructions, PushBytes, PushBytesBuf, PushBytesError, RedeemScript, RedeemScriptBuf,
RedeemScriptSizeError, RedeemScriptTag, Script, ScriptBuf, ScriptBufDecoder, ScriptEncoder,
ScriptHash, ScriptHashableTag, ScriptIntError, ScriptPubKey, ScriptPubKeyBuf, ScriptPubKeyTag,
ScriptSig, ScriptSigBuf, ScriptSigTag, Tag, WScriptHash, WitnessScript, WitnessScriptBuf,
WitnessScriptSizeError, WitnessScriptTag,
};
pub fn p2wpkh_script_code(wpkh: WPubkeyHash) -> WitnessScriptBuf {
Builder::new()
.push_opcode(OP_DUP)
.push_opcode(OP_HASH160)
.push_slice(wpkh)
.push_opcode(OP_EQUALVERIFY)
.push_opcode(OP_CHECKSIG)
.into_script()
}
pub(crate) fn new_witness_program_unchecked<T: AsRef<[u8]>, Tg>(
version: WitnessVersion,
program: T,
) -> ScriptBuf<Tg> {
let program =
<&PushBytes>::try_from(program.as_ref()).expect("witness program length fits PushBytes");
debug_assert!(program.len() >= 2 && program.len() <= 64);
debug_assert!(version != WitnessVersion::V0 || program.len() == 20 || program.len() == 32);
Builder::new().push_opcode(version.into()).push_slice(program).into_script()
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum Error {
NonMinimalPush,
EarlyEndOfScript,
NumericOverflow,
UnknownSpentOutput(OutPoint),
Serialization,
}
impl From<Infallible> for Error {
fn from(never: Infallible) -> Self {
match never {}
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::NonMinimalPush => f.write_str("non-minimal datapush"),
Self::EarlyEndOfScript => f.write_str("unexpected end of script"),
Self::NumericOverflow => {
f.write_str("numeric overflow (number on stack larger than 4 bytes)")
}
Self::UnknownSpentOutput(ref point) => write!(f, "unknown spent output: {}", point),
Self::Serialization => {
f.write_str("can not serialize the spending transaction in Transaction::verify()")
}
}
}
}
impl From<primitives::script::Error> for Error {
fn from(err: primitives::script::Error) -> Self {
match err {
primitives::script::Error::NonMinimalPush => Self::NonMinimalPush,
primitives::script::Error::EarlyEndOfScript => Self::EarlyEndOfScript,
primitives::script::Error::NumericOverflow => Self::NumericOverflow,
}
}
}
#[cfg(feature = "std")]
impl std::error::Error for Error {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::NonMinimalPush
| Self::EarlyEndOfScript
| Self::NumericOverflow
| Self::UnknownSpentOutput(_)
| Self::Serialization => None,
}
}
}