use std::fmt;
use elements::{self, Script};
use super::checksum::verify_checksum;
use super::{Descriptor, TranslatePk};
use crate::descriptor::checksum;
use crate::expression::{self, FromTree};
use crate::extensions::{CovExtArgs, CovenantExt};
use crate::policy::{semantic, Liftable};
use crate::{Error, MiniscriptKey, Satisfier, ToPublicKey, Translator};
#[derive(Clone, Ord, PartialOrd, Eq, PartialEq)]
pub struct Blinded<Pk: MiniscriptKey> {
blinder: Pk,
desc: Descriptor<Pk, CovenantExt<CovExtArgs>>,
}
impl<Pk: MiniscriptKey> Blinded<Pk> {
pub fn new(blinder: Pk, desc: Descriptor<Pk, CovenantExt<CovExtArgs>>) -> Self {
Self { blinder, desc }
}
pub fn blinder(&self) -> &Pk {
&self.blinder
}
pub fn as_unblinded(&self) -> &Descriptor<Pk, CovenantExt<CovExtArgs>> {
&self.desc
}
pub fn into_unblinded(self) -> Descriptor<Pk, CovenantExt<CovExtArgs>> {
self.desc
}
}
impl<Pk: MiniscriptKey> fmt::Debug for Blinded<Pk> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "blinded({:?},{:?})", self.blinder, self.desc)
}
}
impl<Pk: MiniscriptKey> fmt::Display for Blinded<Pk> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use fmt::Write;
let mut wrapped_f = checksum::Formatter::new(f);
write!(wrapped_f, "blinded({},{:#})", self.blinder, self.desc)?;
wrapped_f.write_checksum_if_not_alt()
}
}
impl<Pk: MiniscriptKey> Liftable<Pk> for Blinded<Pk> {
fn lift(&self) -> Result<semantic::Policy<Pk>, Error> {
self.desc.lift()
}
}
impl_from_tree!(
Blinded<Pk>,
fn from_tree(top: &expression::Tree<'_>) -> Result<Self, Error> {
if top.name == "blinded" && top.args.len() == 2 {
let blinder = expression::terminal(&top.args[0], |pk| Pk::from_str(pk))?;
let desc = Descriptor::<Pk, CovenantExt<CovExtArgs>>::from_tree(&top.args[1])?;
if top.args[1].name == "blinded" {
return Err(Error::BadDescriptor(
"Blinding only permitted at root level".to_string(),
));
}
Ok(Blinded { blinder, desc })
} else {
Err(Error::Unexpected(format!(
"{}({} args) while parsing sh descriptor",
top.name,
top.args.len(),
)))
}
}
);
impl_from_str!(
Blinded<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> Blinded<Pk> {
pub fn sanity_check(&self) -> Result<(), Error> {
self.desc.sanity_check()?;
Ok(())
}
pub fn address(
&self,
params: &'static elements::AddressParams,
) -> Result<elements::Address, Error>
where
Pk: ToPublicKey,
{
self.desc
.blinded_address(self.blinder.to_public_key().inner, params)
}
pub fn script_pubkey(&self) -> Script
where
Pk: ToPublicKey,
{
self.desc.script_pubkey()
}
pub fn unsigned_script_sig(&self) -> Script
where
Pk: ToPublicKey,
{
self.desc.unsigned_script_sig()
}
pub fn explicit_script(&self) -> Result<Script, Error>
where
Pk: ToPublicKey,
{
self.desc.explicit_script()
}
pub fn get_satisfaction<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, Script), Error>
where
Pk: ToPublicKey,
S: Satisfier<Pk>,
{
self.desc.get_satisfaction(satisfier)
}
pub fn max_satisfaction_weight(&self) -> Result<usize, Error> {
self.desc.max_weight_to_satisfy()
}
pub fn script_code(&self) -> Result<Script, Error>
where
Pk: ToPublicKey,
{
self.desc.script_code()
}
pub fn get_satisfaction_mall<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, Script), Error>
where
Pk: ToPublicKey,
S: Satisfier<Pk>,
{
self.desc.get_satisfaction_mall(satisfier)
}
}
impl<P: MiniscriptKey, Q: MiniscriptKey> TranslatePk<P, Q> for Blinded<P> {
type Output = Blinded<Q>;
fn translate_pk<T, E>(&self, t: &mut T) -> Result<Self::Output, E>
where
T: Translator<P, Q, E>,
{
Ok(Blinded::new(
t.pk(&self.blinder)?,
self.desc.translate_pk(t)?,
))
}
}