use amplify::Slice32;
use bitcoin::hashes::Hash;
use commit_verify::lnpbp4;
use commit_verify::lnpbp4::{Message, ProtocolId};
use strict_encoding::{StrictDecode, StrictEncode};
use crate::{Output, ProprietaryKey, Psbt};
pub const PSBT_LNPBP4_PREFIX: &[u8] = b"LNPBP4";
pub const PSBT_GLOBAL_LNPBP4_PROTOCOL_INFO: u8 = 0x00;
pub const PSBT_OUT_LNPBP4_MESSAGE: u8 = 0x00;
pub const PSBT_OUT_LNPBP4_ENTROPY: u8 = 0x01;
pub const PSBT_OUT_LNPBP4_MIN_TREE_DEPTH: u8 = 0x02;
pub trait ProprietaryKeyLnpbp4 {
fn lnpbp4_message(protocol_id: ProtocolId) -> ProprietaryKey;
fn lnpbp4_entropy() -> ProprietaryKey;
fn lnpbp4_min_tree_depth() -> ProprietaryKey;
fn lnpbp4_protocol_info(protocol_id: ProtocolId) -> ProprietaryKey;
}
impl ProprietaryKeyLnpbp4 for ProprietaryKey {
fn lnpbp4_message(protocol_id: ProtocolId) -> ProprietaryKey {
ProprietaryKey {
prefix: PSBT_LNPBP4_PREFIX.to_vec(),
subtype: PSBT_OUT_LNPBP4_MESSAGE,
key: protocol_id.to_vec(),
}
}
fn lnpbp4_entropy() -> ProprietaryKey {
ProprietaryKey {
prefix: PSBT_LNPBP4_PREFIX.to_vec(),
subtype: PSBT_OUT_LNPBP4_ENTROPY,
key: empty!(),
}
}
fn lnpbp4_min_tree_depth() -> ProprietaryKey {
ProprietaryKey {
prefix: PSBT_LNPBP4_PREFIX.to_vec(),
subtype: PSBT_OUT_LNPBP4_MIN_TREE_DEPTH,
key: empty!(),
}
}
fn lnpbp4_protocol_info(protocol_id: ProtocolId) -> ProprietaryKey {
ProprietaryKey {
prefix: PSBT_LNPBP4_PREFIX.to_vec(),
subtype: PSBT_GLOBAL_LNPBP4_PROTOCOL_INFO,
key: protocol_id.to_vec(),
}
}
}
#[derive(
Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display, Error, From
)]
#[display(doc_comments)]
pub enum Lnpbp4KeyError {
#[from(strict_encoding::Error)]
#[from(bitcoin::hashes::Error)]
InvalidKeyValue,
AlreadySet,
}
#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Default)]
#[derive(StrictEncode, StrictDecode)]
pub struct Lnpbp4Info {
pub hash_tag: Option<String>,
pub inner_id: Option<Slice32>,
}
impl Psbt {
pub fn lnpbp4_protocol_info(
&self,
protocol_id: ProtocolId,
) -> Result<Lnpbp4Info, Lnpbp4KeyError> {
let key = ProprietaryKey::lnpbp4_protocol_info(protocol_id);
Ok(self
.proprietary
.get(&key)
.map(Lnpbp4Info::strict_deserialize)
.transpose()?
.unwrap_or_default())
}
pub fn set_lnpbp4_protocol_info(
&mut self,
protocol_id: ProtocolId,
hash_tag: Option<String>,
inner_id: Option<Slice32>,
) -> Result<bool, Lnpbp4KeyError> {
let key = ProprietaryKey::lnpbp4_protocol_info(protocol_id);
let val = Lnpbp4Info { hash_tag, inner_id }
.strict_serialize()
.expect("memory serializer should not fail");
if let Some(v) = self.proprietary.get(&key) {
if v != &val {
return Err(Lnpbp4KeyError::InvalidKeyValue);
}
return Ok(false);
}
self.proprietary.insert(key, val);
Ok(true)
}
}
impl Output {
pub fn lnpbp4_message_map(&self) -> Result<lnpbp4::MessageMap, Lnpbp4KeyError> {
self.proprietary
.iter()
.filter(|(key, _)| {
key.prefix == PSBT_LNPBP4_PREFIX && key.subtype == PSBT_OUT_LNPBP4_MESSAGE
})
.map(|(key, val)| {
Ok((
ProtocolId::from_slice(&key.key).ok_or(Lnpbp4KeyError::InvalidKeyValue)?,
Message::from_slice(val).map_err(|_| Lnpbp4KeyError::InvalidKeyValue)?,
))
})
.collect()
}
pub fn lnpbp4_message(
&self,
protocol_id: ProtocolId,
) -> Result<Option<Message>, Lnpbp4KeyError> {
let key = ProprietaryKey::lnpbp4_message(protocol_id);
self.proprietary
.get(&key)
.map(Message::strict_deserialize)
.transpose()
.map_err(Lnpbp4KeyError::from)
}
pub fn lnpbp4_entropy(&self) -> Result<Option<u64>, Lnpbp4KeyError> {
let key = ProprietaryKey::lnpbp4_entropy();
self.proprietary
.get(&key)
.map(u64::strict_deserialize)
.transpose()
.map_err(Lnpbp4KeyError::from)
}
pub fn lnpbp4_min_tree_depth(&self) -> Result<Option<u8>, Lnpbp4KeyError> {
let key = ProprietaryKey::lnpbp4_min_tree_depth();
self.proprietary
.get(&key)
.map(u8::strict_deserialize)
.transpose()
.map_err(Lnpbp4KeyError::from)
}
pub fn set_lnpbp4_message(
&mut self,
protocol_id: ProtocolId,
message: Message,
) -> Result<bool, Lnpbp4KeyError> {
let key = ProprietaryKey::lnpbp4_message(protocol_id);
let val = message
.strict_serialize()
.expect("memory serializer should not fail");
if let Some(v) = self.proprietary.get(&key) {
if v != &val {
return Err(Lnpbp4KeyError::InvalidKeyValue);
}
return Ok(false);
}
self.proprietary.insert(key, val);
Ok(true)
}
pub fn set_lnpbp4_entropy(&mut self, entropy: u64) -> Result<bool, Lnpbp4KeyError> {
let key = ProprietaryKey::lnpbp4_entropy();
let val = entropy
.strict_serialize()
.expect("memory serializer should not fail");
if let Some(v) = self.proprietary.get(&key) {
if v != &val {
return Err(Lnpbp4KeyError::InvalidKeyValue);
}
return Ok(false);
}
self.proprietary.insert(key, val);
Ok(true)
}
pub fn set_lnpbp4_min_tree_depth(&mut self, min_depth: u8) -> Option<u8> {
let key = ProprietaryKey::lnpbp4_min_tree_depth();
let val = min_depth
.strict_serialize()
.expect("memory serializer should not fail");
self.proprietary
.insert(key, val)
.and_then(|v| u8::strict_deserialize(v).ok())
}
}