Skip to content

Commit

Permalink
Add initial support for KeyExpr
Browse files Browse the repository at this point in the history
  • Loading branch information
kanishk779 committed Jul 5, 2022
1 parent d589fe9 commit af960e9
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 0 deletions.
4 changes: 4 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -775,6 +775,8 @@ pub enum Error {
TrNoScriptCode,
/// No explicit script for Tr descriptors
TrNoExplicitScript,
/// Parsing error for single key
SingleKeyParseError,
}

// https://github.com/sipa/miniscript/pull/5 for discussion on this number
Expand Down Expand Up @@ -848,6 +850,7 @@ impl fmt::Display for Error {
Error::TaprootSpendInfoUnavialable => write!(f, "Taproot Spend Info not computed."),
Error::TrNoScriptCode => write!(f, "No script code for Tr descriptors"),
Error::TrNoExplicitScript => write!(f, "No script code for Tr descriptors"),
Error::SingleKeyParseError => f.write_str("not able to parse the single key"),
}
}
}
Expand Down Expand Up @@ -888,6 +891,7 @@ impl error::Error for Error {
| BareDescriptorAddr
| TaprootSpendInfoUnavialable
| TrNoScriptCode
| SingleKeyParseError
| TrNoExplicitScript => None,
Script(e) => Some(e),
AddrError(e) => Some(e),
Expand Down
1 change: 1 addition & 0 deletions src/miniscript/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ pub mod hash256;
pub mod iter;
pub mod lex;
pub mod limits;
pub mod musig_key;
pub mod satisfy;
pub mod types;

Expand Down
100 changes: 100 additions & 0 deletions src/miniscript/musig_key.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
//! Support for multi-signature keys
use core::fmt;
use core::str::FromStr;

use crate::expression::{FromTree, Tree};
use crate::prelude::*;
use crate::{Error, MiniscriptKey};

#[derive(Clone, PartialEq, PartialOrd, Ord, Eq, Hash)]
/// Enum for representing musig keys in miniscript
pub enum KeyExpr<Pk: MiniscriptKey> {
/// Single-key (e.g pk(a), here 'a' is a single key)
SingleKey(Pk),

/// Collection of keys in used for musig-signature
MuSig(Vec<KeyExpr<Pk>>),
}

impl<Pk: MiniscriptKey + FromStr> FromTree for KeyExpr<Pk> {
fn from_tree(tree: &Tree) -> Result<KeyExpr<Pk>, Error> {
if tree.name == "musig" {
let mut key_expr_vec = vec![];
for sub_tree in tree.args.iter() {
let temp_res = KeyExpr::<Pk>::from_tree(sub_tree)?;
key_expr_vec.push(temp_res);
}
Ok(KeyExpr::MuSig(key_expr_vec))
} else {
let single_key = Pk::from_str(tree.name).map_err(|_| Error::SingleKeyParseError)?;
Ok(KeyExpr::SingleKey(single_key))
}
}
}

impl<Pk: MiniscriptKey + FromStr> FromStr for KeyExpr<Pk> {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let (key_tree, _) = Tree::from_slice(s).unwrap();
FromTree::from_tree(&key_tree)
}
}

impl<Pk: MiniscriptKey> fmt::Debug for KeyExpr<Pk> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
KeyExpr::SingleKey(ref pk) => write!(f, "{:?}", pk),
KeyExpr::MuSig(ref my_vec) => {
write!(f, "musig(")?;
let len = my_vec.len();
for (index, k) in my_vec.iter().enumerate() {
if index == len - 1 {
write!(f, "{:?}", k)?;
} else {
write!(f, "{:?}", k)?;
}
}
f.write_str(")")
}
}
}
}

impl<Pk: MiniscriptKey> fmt::Display for KeyExpr<Pk> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
KeyExpr::SingleKey(ref pk) => write!(f, "{}", pk),
KeyExpr::MuSig(ref my_vec) => {
write!(f, "musig(")?;
let len = my_vec.len();
for (index, k) in my_vec.iter().enumerate() {
if index == len - 1 {
write!(f, "{}", k)?;
} else {
write!(f, "{},", k)?;
}
}
f.write_str(")")
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;

fn test_one(musig_key: &str) {
let pk = KeyExpr::<String>::from_str(musig_key).unwrap();
println!("{}", pk);
dbg!(&pk);
assert_eq!(musig_key, format!("{}", pk))
}

#[test]
fn test_from_str_and_fmt() {
test_one("musig(A,B,musig(C,musig(D,E)))");
test_one("musig(A)");
test_one("A");
test_one("musig(,,)");
}
}

0 comments on commit af960e9

Please sign in to comment.