use std::collections::BTreeSet;
use std::iter;
use derive::{
CompressedPk, Derive, DeriveXOnly, DerivedScript, InternalPk, KeyOrigin, Keychain, NormalIndex,
TapDerivation, Terminal, XOnlyPk, XpubDerivable, XpubSpec,
};
use indexmap::IndexMap;
use crate::{Descriptor, SpkClass};
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate",))]
#[derive(Clone, Eq, PartialEq, Hash, Debug, From)]
pub struct TrKey<K: DeriveXOnly = XpubDerivable>(K);
impl<K: DeriveXOnly> TrKey<K> {
pub fn as_internal_key(&self) -> &K { &self.0 }
pub fn into_internal_key(self) -> K { self.0 }
}
impl<K: DeriveXOnly> Derive<DerivedScript> for TrKey<K> {
#[inline]
fn default_keychain(&self) -> Keychain { self.0.default_keychain() }
#[inline]
fn keychains(&self) -> BTreeSet<Keychain> { self.0.keychains() }
fn derive(
&self,
keychain: impl Into<Keychain>,
index: impl Into<NormalIndex>,
) -> DerivedScript {
let internal_key = self.0.derive(keychain, index);
DerivedScript::TaprootKeyOnly(InternalPk::from_unchecked(internal_key))
}
}
impl<K: DeriveXOnly> Descriptor<K> for TrKey<K> {
type KeyIter<'k> = iter::Once<&'k K> where Self: 'k, K: 'k;
type VarIter<'v> = iter::Empty<&'v ()> where Self: 'v, (): 'v;
type XpubIter<'x> = iter::Once<&'x XpubSpec> where Self: 'x;
fn class(&self) -> SpkClass { SpkClass::P2tr }
fn keys(&self) -> Self::KeyIter<'_> { iter::once(&self.0) }
fn vars(&self) -> Self::VarIter<'_> { iter::empty() }
fn xpubs(&self) -> Self::XpubIter<'_> { iter::once(self.0.xpub_spec()) }
fn compr_keyset(&self, _terminal: Terminal) -> IndexMap<CompressedPk, KeyOrigin> {
IndexMap::new()
}
fn xonly_keyset(&self, terminal: Terminal) -> IndexMap<XOnlyPk, TapDerivation> {
let mut map = IndexMap::with_capacity(1);
let key = self.0.derive(terminal.keychain, terminal.index);
map.insert(
key,
TapDerivation::with_internal_pk(self.0.xpub_spec().origin().clone(), terminal),
);
map
}
}