use std::cell::RefCell; use std::collections::BTreeMap; use bitcoin::secp256k1::Secp256k1; use crate::descriptor::error::Error; use crate::descriptor::keys::{parse_key, DummyKey, Key, KeyAlias, RealKey}; use crate::descriptor::{ExtendedDescriptor, MiniscriptExtractPolicy, Policy, StringDescriptor}; pub trait ParticipantType: Default { fn validate_aliases(aliases: Vec<&String>) -> Result<(), Error>; } #[derive(Default)] pub struct Coordinator {} impl ParticipantType for Coordinator { fn validate_aliases(aliases: Vec<&String>) -> Result<(), Error> { if aliases.into_iter().any(|a| a == "[PEER]") { Err(Error::InvalidAlias("[PEER]".into())) } else { Ok(()) } } } #[derive(Default)] pub struct Peer; impl ParticipantType for Peer { fn validate_aliases(aliases: Vec<&String>) -> Result<(), Error> { if !aliases.into_iter().any(|a| a == "[PEER]") { Err(Error::MissingAlias("[PEER]".into())) } else { Ok(()) } } } pub struct Participant { descriptor: StringDescriptor, parsed_keys: BTreeMap>, received_keys: BTreeMap>, _data: T, } impl Participant { pub fn new(sd: StringDescriptor) -> Result { let parsed_keys = Self::parse_keys(&sd, vec![]); T::validate_aliases(parsed_keys.keys().collect())?; Ok(Participant { descriptor: sd, parsed_keys, received_keys: Default::default(), _data: Default::default(), }) } fn parse_keys( sd: &StringDescriptor, with_secrets: Vec<&str>, ) -> BTreeMap> { let keys: RefCell>> = RefCell::new(BTreeMap::new()); let translatefpk = |string: &String| -> Result<_, Error> { let (key, parsed) = match parse_key(string) { Ok((key, parsed)) => (key, parsed.into_key()), Err(_) => ( string.clone(), KeyAlias::new_boxed(string.as_str(), with_secrets.contains(&string.as_str())), ), }; keys.borrow_mut().insert(key, parsed); Ok(DummyKey::default()) }; let translatefpkh = |string: &String| -> Result<_, Error> { let (key, parsed) = match parse_key(string) { Ok((key, parsed)) => (key, parsed.into_key()), Err(_) => ( string.clone(), KeyAlias::new_boxed(string.as_str(), with_secrets.contains(&string.as_str())), ), }; keys.borrow_mut().insert(key, parsed); Ok(DummyKey::default()) }; sd.translate_pk(translatefpk, translatefpkh).unwrap(); keys.into_inner() } pub fn policy_for(&self, with_secrets: Vec<&str>) -> Result, Error> { let keys = Self::parse_keys(&self.descriptor, with_secrets); self.descriptor.extract_policy(&keys) } fn _missing_keys(&self) -> Vec<&String> { self.parsed_keys .keys() .filter(|k| !self.received_keys.contains_key(*k)) .collect() } pub fn completed(&self) -> bool { self._missing_keys().is_empty() } pub fn finalize(self) -> Result { if !self.completed() { return Err(Error::Incomplete); } let translatefpk = |string: &String| -> Result<_, Error> { Ok(format!( "{}", self.received_keys .get(string) .expect(&format!("Missing key: `{}`", string)) )) }; let translatefpkh = |string: &String| -> Result<_, Error> { Ok(format!( "{}", self.received_keys .get(string) .expect(&format!("Missing key: `{}`", string)) )) }; let internal = self.descriptor.translate_pk(translatefpk, translatefpkh)?; Ok(ExtendedDescriptor { internal, keys: self.received_keys, ctx: Secp256k1::gen_new(), }) } } impl Participant { pub fn descriptor(&self) -> &StringDescriptor { &self.descriptor } pub fn add_key(&mut self, alias: &str, key: Box) -> Result<(), Error> { // TODO: check network if key.has_secret() { return Err(Error::KeyHasSecret); } self.received_keys.insert(alias.into(), key); Ok(()) } pub fn received_keys(&self) -> Vec<&String> { self.received_keys.keys().collect() } pub fn missing_keys(&self) -> Vec<&String> { self._missing_keys() } pub fn descriptor_for(&self, alias: &str) -> Result { if !self.parsed_keys.contains_key(alias) { return Err(Error::MissingAlias(alias.into())); } let map_name = |s: &String| { if s == alias { "[PEER]".into() } else { s.into() } }; let translatefpk = |string: &String| -> Result<_, Error> { Ok(map_name(string)) }; let translatefpkh = |string: &String| -> Result<_, Error> { Ok(map_name(string)) }; Ok(self.descriptor.translate_pk(translatefpk, translatefpkh)?) } pub fn get_map(&self) -> Result, Error> { if !self.completed() { return Err(Error::Incomplete); } Ok(self .received_keys .iter() .map(|(k, v)| (k.into(), format!("{}", v))) .collect()) } } impl Participant { pub fn policy(&self) -> Result, Error> { self.policy_for(vec!["[PEER]"]) } pub fn use_key(&mut self, key: Box) -> Result<(), Error> { let secp = Secp256k1::gen_new(); self.received_keys .insert("[PEER]".into(), key.public(&secp)?); Ok(()) } pub fn my_key(&mut self) -> Option<&Box> { self.received_keys.get("[PEER]".into()) } pub fn apply_map(mut self, map: BTreeMap) -> Result { let mut parsed_map: BTreeMap<_, _> = map .into_iter() .map(|(k, v)| -> Result<_, Error> { let (_, parsed) = parse_key(&v)?; Ok((k, parsed)) }) .collect::>()?; self.received_keys.append(&mut parsed_map); self.finalize() } }