use core::fmt;
use bitcoin::blockdata::script;
use bitcoin::{Address, Network, Script};
use super::checksum::{self, verify_checksum};
use crate::expression::{self, FromTree};
use crate::miniscript::context::ScriptContext;
use crate::policy::{semantic, Liftable};
use crate::prelude::*;
use crate::util::{varint_len, witness_to_scriptsig};
use crate::{
BareCtx, Error, ForEachKey, Miniscript, MiniscriptKey, Satisfier, ToPublicKey, TranslatePk,
Translator,
};
#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
pub struct Bare<Pk: MiniscriptKey> {
ms: Miniscript<Pk, BareCtx>,
}
impl<Pk: MiniscriptKey> Bare<Pk> {
pub fn new(ms: Miniscript<Pk, BareCtx>) -> Result<Self, Error> {
BareCtx::top_level_checks(&ms)?;
Ok(Self { ms })
}
pub fn into_inner(self) -> Miniscript<Pk, BareCtx> {
self.ms
}
pub fn as_inner(&self) -> &Miniscript<Pk, BareCtx> {
&self.ms
}
pub fn sanity_check(&self) -> Result<(), Error> {
self.ms.sanity_check()?;
Ok(())
}
pub fn max_satisfaction_weight(&self) -> Result<usize, Error> {
let scriptsig_len = self.ms.max_satisfaction_size()?;
Ok(4 * (varint_len(scriptsig_len) + scriptsig_len))
}
}
impl<Pk: MiniscriptKey + ToPublicKey> Bare<Pk> {
pub fn script_pubkey(&self) -> Script {
self.ms.encode()
}
pub fn inner_script(&self) -> Script {
self.script_pubkey()
}
pub fn ecdsa_sighash_script_code(&self) -> Script {
self.script_pubkey()
}
pub fn get_satisfaction<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, Script), Error>
where
S: Satisfier<Pk>,
{
let ms = self.ms.satisfy(satisfier)?;
let script_sig = witness_to_scriptsig(&ms);
let witness = vec![];
Ok((witness, script_sig))
}
pub fn get_satisfaction_mall<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, Script), Error>
where
S: Satisfier<Pk>,
{
let ms = self.ms.satisfy_malleable(satisfier)?;
let script_sig = witness_to_scriptsig(&ms);
let witness = vec![];
Ok((witness, script_sig))
}
}
impl<Pk: MiniscriptKey> fmt::Debug for Bare<Pk> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}", self.ms)
}
}
impl<Pk: MiniscriptKey> fmt::Display for Bare<Pk> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use fmt::Write;
let mut wrapped_f = checksum::Formatter::new(f);
write!(wrapped_f, "{}", self.ms)?;
wrapped_f.write_checksum_if_not_alt()
}
}
impl<Pk: MiniscriptKey> Liftable<Pk> for Bare<Pk> {
fn lift(&self) -> Result<semantic::Policy<Pk>, Error> {
self.ms.lift()
}
}
impl_from_tree!(
Bare<Pk>,
fn from_tree(top: &expression::Tree) -> Result<Self, Error> {
let sub = Miniscript::<Pk, BareCtx>::from_tree(top)?;
BareCtx::top_level_checks(&sub)?;
Bare::new(sub)
}
);
impl_from_str!(
Bare<Pk>,
type Err = Error;,
fn from_str(s: &str) -> Result<Self, Self::Err> {
let desc_str = verify_checksum(s)?;
let top = expression::Tree::from_str(desc_str)?;
Self::from_tree(&top)
}
);
impl<Pk: MiniscriptKey> ForEachKey<Pk> for Bare<Pk> {
fn for_each_key<'a, F: FnMut(&'a Pk) -> bool>(&'a self, pred: F) -> bool
where
Pk: 'a,
{
self.ms.for_each_key(pred)
}
}
impl<P, Q> TranslatePk<P, Q> for Bare<P>
where
P: MiniscriptKey,
Q: MiniscriptKey,
{
type Output = Bare<Q>;
fn translate_pk<T, E>(&self, t: &mut T) -> Result<Self::Output, E>
where
T: Translator<P, Q, E>,
{
Ok(Bare::new(self.ms.translate_pk(t)?).expect("Translation cannot fail inside Bare"))
}
}
#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
pub struct Pkh<Pk: MiniscriptKey> {
pk: Pk,
}
impl<Pk: MiniscriptKey> Pkh<Pk> {
pub fn new(pk: Pk) -> Self {
Self { pk }
}
pub fn as_inner(&self) -> &Pk {
&self.pk
}
pub fn into_inner(self) -> Pk {
self.pk
}
pub fn max_satisfaction_weight(&self) -> usize {
4 * (1 + 73 + BareCtx::pk_len(&self.pk))
}
}
impl<Pk: MiniscriptKey + ToPublicKey> Pkh<Pk> {
pub fn script_pubkey(&self) -> Script {
let addr = self.address(Network::Bitcoin);
addr.script_pubkey()
}
pub fn address(&self, network: Network) -> Address {
Address::p2pkh(&self.pk.to_public_key(), network)
}
pub fn inner_script(&self) -> Script {
self.script_pubkey()
}
pub fn ecdsa_sighash_script_code(&self) -> Script {
self.script_pubkey()
}
pub fn get_satisfaction<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, Script), Error>
where
S: Satisfier<Pk>,
{
if let Some(sig) = satisfier.lookup_ecdsa_sig(&self.pk) {
let sig_vec = sig.to_vec();
let script_sig = script::Builder::new()
.push_slice(&sig_vec[..])
.push_key(&self.pk.to_public_key())
.into_script();
let witness = vec![];
Ok((witness, script_sig))
} else {
Err(Error::MissingSig(self.pk.to_public_key()))
}
}
pub fn get_satisfaction_mall<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, Script), Error>
where
S: Satisfier<Pk>,
{
self.get_satisfaction(satisfier)
}
}
impl<Pk: MiniscriptKey> fmt::Debug for Pkh<Pk> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "pkh({:?})", self.pk)
}
}
impl<Pk: MiniscriptKey> fmt::Display for Pkh<Pk> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use fmt::Write;
let mut wrapped_f = checksum::Formatter::new(f);
write!(wrapped_f, "pkh({})", self.pk)?;
wrapped_f.write_checksum_if_not_alt()
}
}
impl<Pk: MiniscriptKey> Liftable<Pk> for Pkh<Pk> {
fn lift(&self) -> Result<semantic::Policy<Pk>, Error> {
Ok(semantic::Policy::Key(self.pk.clone()))
}
}
impl_from_tree!(
Pkh<Pk>,
fn from_tree(top: &expression::Tree) -> Result<Self, Error> {
if top.name == "pkh" && top.args.len() == 1 {
Ok(Pkh::new(expression::terminal(&top.args[0], |pk| {
Pk::from_str(pk)
})?))
} else {
Err(Error::Unexpected(format!(
"{}({} args) while parsing pkh descriptor",
top.name,
top.args.len(),
)))
}
}
);
impl_from_str!(
Pkh<Pk>,
type Err = Error;,
fn from_str(s: &str) -> Result<Self, Self::Err> {
let desc_str = verify_checksum(s)?;
let top = expression::Tree::from_str(desc_str)?;
Self::from_tree(&top)
}
);
impl<Pk: MiniscriptKey> ForEachKey<Pk> for Pkh<Pk> {
fn for_each_key<'a, F: FnMut(&'a Pk) -> bool>(&'a self, mut pred: F) -> bool
where
Pk: 'a,
{
pred(&self.pk)
}
}
impl<P, Q> TranslatePk<P, Q> for Pkh<P>
where
P: MiniscriptKey,
Q: MiniscriptKey,
{
type Output = Pkh<Q>;
fn translate_pk<T, E>(&self, t: &mut T) -> Result<Self::Output, E>
where
T: Translator<P, Q, E>,
{
Ok(Pkh::new(t.pk(&self.pk)?))
}
}