Skip to content

Commit

Permalink
Merge pull request #26 from BP-WG/develop
Browse files Browse the repository at this point in the history
Pending bugfixes in BP standard lib
  • Loading branch information
dr-orlovsky authored May 6, 2024
2 parents a456953 + 3703d40 commit 8ef1c09
Show file tree
Hide file tree
Showing 6 changed files with 382 additions and 49 deletions.
70 changes: 59 additions & 11 deletions derive/src/derive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,6 @@ use crate::{
#[derive(Wrapper, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Default, Debug, Display, From)]
#[wrapper(FromStr)]
#[display(inner)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(crate = "serde_crate", transparent)
)]
pub struct Keychain(u8);

impl From<Keychain> for NormalIndex {
Expand Down Expand Up @@ -76,11 +71,6 @@ impl IdxBase for Keychain {
}

#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Display)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(crate = "serde_crate", rename_all = "camelCase")
)]
#[display("&{keychain}/{index}")]
pub struct Terminal {
pub keychain: Keychain,
Expand Down Expand Up @@ -135,6 +125,65 @@ impl FromStr for Terminal {
}
}

#[cfg(feature = "serde")]
mod _serde {
use serde_crate::de::Error;
use serde_crate::{Deserialize, Deserializer, Serialize, Serializer};

use super::*;

impl Serialize for Keychain {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer {
if serializer.is_human_readable() {
self.0.to_string().serialize(serializer)
} else {
self.0.serialize(serializer)
}
}
}

impl<'de> Deserialize<'de> for Keychain {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer<'de> {
if deserializer.is_human_readable() {
let s = String::deserialize(deserializer)?;
Self::from_str(&s).map_err(D::Error::custom)
} else {
Ok(Self(u8::deserialize(deserializer)?))
}
}
}

impl Serialize for Terminal {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer {
if serializer.is_human_readable() {
self.to_string().serialize(serializer)
} else {
let tuple = (self.keychain, self.index);
tuple.serialize(serializer)
}
}
}

impl<'de> Deserialize<'de> for Terminal {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer<'de> {
if deserializer.is_human_readable() {
let s = String::deserialize(deserializer)?;
Self::from_str(&s).map_err(D::Error::custom)
} else {
let d = <(Keychain, NormalIndex)>::deserialize(deserializer)?;
Ok(Self {
keychain: d.0,
index: d.1,
})
}
}
}
}

#[derive(Clone, Eq, PartialEq, Hash, Debug)]
#[non_exhaustive]
pub enum DerivedScript {
Expand Down Expand Up @@ -234,7 +283,6 @@ impl DerivedScript {
#[display("{addr}{terminal}")]
pub struct DerivedAddr {
pub addr: Address,
#[cfg_attr(feature = "serde", serde(flatten))]
pub terminal: Terminal,
}

Expand Down
37 changes: 13 additions & 24 deletions descriptors/src/descriptor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
// limitations under the License.

use std::collections::BTreeSet;
use std::{iter, vec};
use std::iter;

use derive::{
CompressedPk, Derive, DeriveCompr, DeriveScripts, DeriveSet, DeriveXOnly, DerivedScript,
Expand Down Expand Up @@ -56,24 +56,13 @@ impl SpkClass {
}

pub trait Descriptor<K = XpubDerivable, V = ()>: DeriveScripts {
type KeyIter<'k>: Iterator<Item = &'k K>
where
Self: 'k,
K: 'k;

type VarIter<'v>: Iterator<Item = &'v V>
where
Self: 'v,
V: 'v;

type XpubIter<'x>: Iterator<Item = &'x XpubSpec>
where Self: 'x;

fn class(&self) -> SpkClass;

fn keys(&self) -> Self::KeyIter<'_>;
fn vars(&self) -> Self::VarIter<'_>;
fn xpubs(&self) -> Self::XpubIter<'_>;
fn keys<'a>(&'a self) -> impl Iterator<Item = &'a K>
where K: 'a;
fn vars<'a>(&'a self) -> impl Iterator<Item = &'a V>
where V: 'a;
fn xpubs(&self) -> impl Iterator<Item = &XpubSpec>;

fn compr_keyset(&self, terminal: Terminal) -> IndexMap<CompressedPk, KeyOrigin>;
fn xonly_keyset(&self, terminal: Terminal) -> IndexMap<XOnlyPk, TapDerivation>;
Expand Down Expand Up @@ -195,28 +184,28 @@ impl<S: DeriveSet> Derive<DerivedScript> for StdDescr<S> {
impl<K: DeriveSet<Compr = K, XOnly = K> + DeriveCompr + DeriveXOnly> Descriptor<K> for StdDescr<K>
where Self: Derive<DerivedScript>
{
type KeyIter<'k> = vec::IntoIter<&'k K> where Self: 'k, K: 'k;
type VarIter<'v> = iter::Empty<&'v ()> where Self: 'v, (): 'v;
type XpubIter<'x> = vec::IntoIter<&'x XpubSpec> where Self: 'x;

fn class(&self) -> SpkClass {
match self {
StdDescr::Wpkh(d) => d.class(),
StdDescr::TrKey(d) => d.class(),
}
}

fn keys(&self) -> Self::KeyIter<'_> {
fn keys<'a>(&'a self) -> impl Iterator<Item = &'a K>
where K: 'a {
match self {
StdDescr::Wpkh(d) => d.keys().collect::<Vec<_>>(),
StdDescr::TrKey(d) => d.keys().collect::<Vec<_>>(),
}
.into_iter()
}

fn vars(&self) -> Self::VarIter<'_> { iter::empty() }
fn vars<'a>(&'a self) -> impl Iterator<Item = &'a ()>
where (): 'a {
iter::empty()
}

fn xpubs(&self) -> Self::XpubIter<'_> {
fn xpubs(&self) -> impl Iterator<Item = &XpubSpec> {
match self {
StdDescr::Wpkh(d) => d.xpubs().collect::<Vec<_>>(),
StdDescr::TrKey(d) => d.xpubs().collect::<Vec<_>>(),
Expand Down
16 changes: 9 additions & 7 deletions descriptors/src/segwit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,17 @@ impl<K: DeriveCompr> Derive<DerivedScript> for Wpkh<K> {
}

impl<K: DeriveCompr> Descriptor<K> for Wpkh<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::P2wpkh }

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 keys<'a>(&'a self) -> impl Iterator<Item = &'a K>
where K: 'a {
iter::once(&self.0)
}
fn vars<'a>(&'a self) -> impl Iterator<Item = &'a ()>
where (): 'a {
iter::empty()
}
fn xpubs(&self) -> impl Iterator<Item = &XpubSpec> { iter::once(self.0.xpub_spec()) }

fn compr_keyset(&self, terminal: Terminal) -> IndexMap<CompressedPk, KeyOrigin> {
let mut map = IndexMap::with_capacity(1);
Expand Down
16 changes: 9 additions & 7 deletions descriptors/src/taproot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,17 @@ impl<K: DeriveXOnly> Derive<DerivedScript> for TrKey<K> {
}

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 keys<'a>(&'a self) -> impl Iterator<Item = &'a K>
where K: 'a {
iter::once(&self.0)
}
fn vars<'a>(&'a self) -> impl Iterator<Item = &'a ()>
where (): 'a {
iter::empty()
}
fn xpubs(&self) -> impl Iterator<Item = &XpubSpec> { iter::once(self.0.xpub_spec()) }

fn compr_keyset(&self, _terminal: Terminal) -> IndexMap<CompressedPk, KeyOrigin> {
IndexMap::new()
Expand Down
Loading

0 comments on commit 8ef1c09

Please sign in to comment.