use std::collections::BTreeMap;
use amplify::DumbDefault;
#[cfg(feature = "serde")]
use amplify::ToYamlString;
use bitcoin::util::bip32::{ChildNumber, ExtendedPrivKey, KeySource};
use bitcoin_scripts::PubkeyScript;
use p2p::bolt::{AcceptChannel, ChannelType, OpenChannel};
use secp256k1::{PublicKey, Secp256k1};
use wallet::hd::HardenedIndex;
#[derive(Clone, PartialEq, Eq, Debug, StrictEncode, StrictDecode)]
#[cfg_attr(
feature = "serde",
derive(Display, Serialize, Deserialize),
serde(crate = "serde_crate"),
display(LocalPubkey::to_yaml_string)
)]
pub struct LocalPubkey {
pub key: PublicKey,
pub source: KeySource,
}
impl LocalPubkey {
#[inline]
pub fn to_bip32_derivation_map(&self) -> BTreeMap<PublicKey, KeySource> {
bmap! { self.key => self.source.clone() }
}
#[inline]
pub fn to_bitcoin_pk(&self) -> bitcoin::PublicKey {
bitcoin::PublicKey::new(self.key)
}
}
#[derive(Clone, PartialEq, Eq, Debug, StrictEncode, StrictDecode)]
#[cfg_attr(
feature = "serde",
derive(Display, Serialize, Deserialize),
serde(crate = "serde_crate"),
display(LocalKeyset::to_yaml_string)
)]
pub struct LocalKeyset {
pub funding_pubkey: LocalPubkey,
pub revocation_basepoint: LocalPubkey,
pub payment_basepoint: LocalPubkey,
pub delayed_payment_basepoint: LocalPubkey,
pub htlc_basepoint: LocalPubkey,
pub first_per_commitment_point: LocalPubkey,
pub shutdown_scriptpubkey: Option<PubkeyScript>,
pub static_remotekey: bool,
}
#[derive(Clone, PartialEq, Eq, Debug, StrictEncode, StrictDecode)]
#[cfg_attr(
feature = "serde",
derive(Display, Serialize, Deserialize),
serde(crate = "serde_crate"),
display(RemoteKeyset::to_yaml_string)
)]
pub struct RemoteKeyset {
pub funding_pubkey: PublicKey,
pub revocation_basepoint: PublicKey,
pub payment_basepoint: PublicKey,
pub delayed_payment_basepoint: PublicKey,
pub htlc_basepoint: PublicKey,
pub first_per_commitment_point: PublicKey,
pub shutdown_scriptpubkey: Option<PubkeyScript>,
pub static_remotekey: bool,
}
#[cfg(feature = "serde")]
impl ToYamlString for LocalPubkey {}
#[cfg(feature = "serde")]
impl ToYamlString for LocalKeyset {}
#[cfg(feature = "serde")]
impl ToYamlString for RemoteKeyset {}
impl From<&OpenChannel> for RemoteKeyset {
fn from(open_channel: &OpenChannel) -> Self {
Self {
funding_pubkey: open_channel.funding_pubkey,
revocation_basepoint: open_channel.revocation_basepoint,
payment_basepoint: open_channel.payment_point,
delayed_payment_basepoint: open_channel.delayed_payment_basepoint,
htlc_basepoint: open_channel.htlc_basepoint,
first_per_commitment_point: open_channel.first_per_commitment_point,
shutdown_scriptpubkey: open_channel.shutdown_scriptpubkey.clone(),
static_remotekey: false,
}
}
}
impl From<&AcceptChannel> for RemoteKeyset {
fn from(accept_channel: &AcceptChannel) -> Self {
Self {
funding_pubkey: accept_channel.funding_pubkey,
revocation_basepoint: accept_channel.revocation_basepoint,
payment_basepoint: accept_channel.payment_point,
delayed_payment_basepoint: accept_channel.delayed_payment_basepoint,
htlc_basepoint: accept_channel.htlc_basepoint,
first_per_commitment_point: accept_channel
.first_per_commitment_point,
shutdown_scriptpubkey: accept_channel.shutdown_scriptpubkey.clone(),
static_remotekey: accept_channel
.channel_type
.map(ChannelType::has_static_remotekey)
.unwrap_or_default(),
}
}
}
impl DumbDefault for LocalPubkey {
fn dumb_default() -> Self {
LocalPubkey {
key: dumb_pubkey!(),
source: KeySource::default(),
}
}
}
impl DumbDefault for LocalKeyset {
fn dumb_default() -> Self {
Self {
funding_pubkey: DumbDefault::dumb_default(),
revocation_basepoint: DumbDefault::dumb_default(),
payment_basepoint: DumbDefault::dumb_default(),
delayed_payment_basepoint: DumbDefault::dumb_default(),
htlc_basepoint: DumbDefault::dumb_default(),
first_per_commitment_point: DumbDefault::dumb_default(),
shutdown_scriptpubkey: None,
static_remotekey: false,
}
}
}
impl DumbDefault for RemoteKeyset {
fn dumb_default() -> Self {
Self {
funding_pubkey: dumb_pubkey!(),
revocation_basepoint: dumb_pubkey!(),
payment_basepoint: dumb_pubkey!(),
delayed_payment_basepoint: dumb_pubkey!(),
htlc_basepoint: dumb_pubkey!(),
first_per_commitment_point: dumb_pubkey!(),
shutdown_scriptpubkey: None,
static_remotekey: false,
}
}
}
impl LocalKeyset {
pub fn with<C: secp256k1::Signing>(
secp: &Secp256k1<C>,
channel_source: KeySource,
channel_xpriv: ExtendedPrivKey,
shutdown_scriptpubkey: Option<PubkeyScript>,
) -> Self {
let fingerpint = channel_source.0;
let keys = (0u16..=6)
.into_iter()
.map(HardenedIndex::from)
.map(ChildNumber::from)
.map(|index| [index])
.map(|path| {
let derivation_path = channel_source.1.clone().extend(path);
let seckey = channel_xpriv
.derive_priv(secp, &path)
.expect("negligible probability")
.private_key;
LocalPubkey {
key: PublicKey::from_secret_key(secp, &seckey),
source: (fingerpint, derivation_path),
}
})
.collect::<Vec<_>>();
Self {
funding_pubkey: keys[0].clone(),
revocation_basepoint: keys[3].clone(),
payment_basepoint: keys[1].clone(),
delayed_payment_basepoint: keys[2].clone(),
htlc_basepoint: keys[5].clone(),
first_per_commitment_point: keys[4].clone(),
shutdown_scriptpubkey,
static_remotekey: false,
}
}
}