lnp/channel/bolt/
keyset.rs

1// LNP/BP Core Library implementing LNPBP specifications & standards
2// Written in 2020-2022 by
3//     Dr. Maxim Orlovsky <orlovsky@pandoracore.com>
4//
5// To the extent possible under law, the author(s) have dedicated all
6// copyright and related and neighboring rights to this software to
7// the public domain worldwide. This software is distributed without
8// any warranty.
9//
10// You should have received a copy of the MIT License
11// along with this software.
12// If not, see <https://opensource.org/licenses/MIT>.
13
14use std::collections::BTreeMap;
15
16use amplify::DumbDefault;
17#[cfg(feature = "serde")]
18use amplify::ToYamlString;
19use bitcoin::util::bip32::{ChildNumber, ExtendedPrivKey, KeySource};
20use bitcoin_scripts::PubkeyScript;
21use p2p::bolt::{AcceptChannel, ChannelType, OpenChannel};
22use secp256k1::{PublicKey, Secp256k1};
23use wallet::hd::HardenedIndex;
24
25/// Key + information about its derivation
26#[derive(Clone, PartialEq, Eq, Debug, StrictEncode, StrictDecode)]
27#[cfg_attr(
28    feature = "serde",
29    derive(Display, Serialize, Deserialize),
30    serde(crate = "serde_crate"),
31    display(LocalPubkey::to_yaml_string)
32)]
33pub struct LocalPubkey {
34    pub key: PublicKey,
35    pub source: KeySource,
36}
37
38impl LocalPubkey {
39    #[inline]
40    pub fn to_bip32_derivation_map(&self) -> BTreeMap<PublicKey, KeySource> {
41        bmap! { self.key => self.source.clone() }
42    }
43
44    #[inline]
45    pub fn to_bitcoin_pk(&self) -> bitcoin::PublicKey {
46        bitcoin::PublicKey::new(self.key)
47    }
48}
49
50/// Set of keys used by the core of the channel. It does not include HTLC
51/// basepoint which is managed separately by [`super::Htlc`] extension.
52#[derive(Clone, PartialEq, Eq, Debug, StrictEncode, StrictDecode)]
53#[cfg_attr(
54    feature = "serde",
55    derive(Display, Serialize, Deserialize),
56    serde(crate = "serde_crate"),
57    display(LocalKeyset::to_yaml_string)
58)]
59pub struct LocalKeyset {
60    /// Public key used in the funding outpoint multisig
61    pub funding_pubkey: LocalPubkey,
62    /// Base point for deriving keys used for penalty spending paths
63    pub revocation_basepoint: LocalPubkey,
64    /// Base point for deriving keys in `to_remote`
65    pub payment_basepoint: LocalPubkey,
66    /// Base point for deriving keys in `to_local` time-locked spending paths
67    pub delayed_payment_basepoint: LocalPubkey,
68    /// Base point for deriving HTLC-related keys
69    pub htlc_basepoint: LocalPubkey,
70    /// Base point for deriving keys used for penalty spending paths
71    pub first_per_commitment_point: LocalPubkey,
72    /// Allows the sending node to commit to where funds will go on mutual
73    /// close, which the remote node should enforce even if a node is
74    /// compromised later.
75    pub shutdown_scriptpubkey: Option<PubkeyScript>,
76    /// If `option_static_remotekey` or `option_anchors` is negotiated, the
77    /// remotepubkey is simply the remote node's payment_basepoint, otherwise
78    /// it is calculated as above using the remote node's payment_basepoint.
79    pub static_remotekey: bool,
80}
81
82/// Set of keys used by the core of the channel. It does not include HTLC
83/// basepoint which is managed separately by [`super::Htlc`] extension.
84#[derive(Clone, PartialEq, Eq, Debug, StrictEncode, StrictDecode)]
85#[cfg_attr(
86    feature = "serde",
87    derive(Display, Serialize, Deserialize),
88    serde(crate = "serde_crate"),
89    display(RemoteKeyset::to_yaml_string)
90)]
91pub struct RemoteKeyset {
92    /// Public key used in the funding outpoint multisig
93    pub funding_pubkey: PublicKey,
94    /// Base point for deriving keys used for penalty spending paths
95    pub revocation_basepoint: PublicKey,
96    /// Base point for deriving keys in `to_remote`
97    pub payment_basepoint: PublicKey,
98    /// Base point for deriving keys in `to_local` time-locked spending paths
99    pub delayed_payment_basepoint: PublicKey,
100    /// Base point for deriving HTLC-related keys
101    pub htlc_basepoint: PublicKey,
102    /// Base point for deriving keys used for penalty spending paths
103    pub first_per_commitment_point: PublicKey,
104    /// Allows the sending node to commit to where funds will go on mutual
105    /// close, which the remote node should enforce even if a node is
106    /// compromised later.
107    pub shutdown_scriptpubkey: Option<PubkeyScript>,
108    /// If `option_static_remotekey` or `option_anchors` is negotiated, the
109    /// remotepubkey is simply the remote node's payment_basepoint, otherwise
110    /// it is calculated as above using the remote node's payment_basepoint.
111    pub static_remotekey: bool,
112}
113
114#[cfg(feature = "serde")]
115impl ToYamlString for LocalPubkey {}
116
117#[cfg(feature = "serde")]
118impl ToYamlString for LocalKeyset {}
119
120#[cfg(feature = "serde")]
121impl ToYamlString for RemoteKeyset {}
122
123impl From<&OpenChannel> for RemoteKeyset {
124    fn from(open_channel: &OpenChannel) -> Self {
125        Self {
126            funding_pubkey: open_channel.funding_pubkey,
127            revocation_basepoint: open_channel.revocation_basepoint,
128            payment_basepoint: open_channel.payment_point,
129            delayed_payment_basepoint: open_channel.delayed_payment_basepoint,
130            htlc_basepoint: open_channel.htlc_basepoint,
131            first_per_commitment_point: open_channel.first_per_commitment_point,
132            shutdown_scriptpubkey: open_channel.shutdown_scriptpubkey.clone(),
133            static_remotekey: false,
134        }
135    }
136}
137
138impl From<&AcceptChannel> for RemoteKeyset {
139    fn from(accept_channel: &AcceptChannel) -> Self {
140        Self {
141            funding_pubkey: accept_channel.funding_pubkey,
142            revocation_basepoint: accept_channel.revocation_basepoint,
143            payment_basepoint: accept_channel.payment_point,
144            delayed_payment_basepoint: accept_channel.delayed_payment_basepoint,
145            htlc_basepoint: accept_channel.htlc_basepoint,
146            first_per_commitment_point: accept_channel
147                .first_per_commitment_point,
148            shutdown_scriptpubkey: accept_channel.shutdown_scriptpubkey.clone(),
149            static_remotekey: accept_channel
150                .channel_type
151                .map(ChannelType::has_static_remotekey)
152                .unwrap_or_default(),
153        }
154    }
155}
156
157impl DumbDefault for LocalPubkey {
158    fn dumb_default() -> Self {
159        LocalPubkey {
160            key: dumb_pubkey!(),
161            source: KeySource::default(),
162        }
163    }
164}
165
166impl DumbDefault for LocalKeyset {
167    fn dumb_default() -> Self {
168        Self {
169            funding_pubkey: DumbDefault::dumb_default(),
170            revocation_basepoint: DumbDefault::dumb_default(),
171            payment_basepoint: DumbDefault::dumb_default(),
172            delayed_payment_basepoint: DumbDefault::dumb_default(),
173            htlc_basepoint: DumbDefault::dumb_default(),
174            first_per_commitment_point: DumbDefault::dumb_default(),
175            shutdown_scriptpubkey: None,
176            static_remotekey: false,
177        }
178    }
179}
180
181impl DumbDefault for RemoteKeyset {
182    fn dumb_default() -> Self {
183        Self {
184            funding_pubkey: dumb_pubkey!(),
185            revocation_basepoint: dumb_pubkey!(),
186            payment_basepoint: dumb_pubkey!(),
187            delayed_payment_basepoint: dumb_pubkey!(),
188            htlc_basepoint: dumb_pubkey!(),
189            first_per_commitment_point: dumb_pubkey!(),
190            shutdown_scriptpubkey: None,
191            static_remotekey: false,
192        }
193    }
194}
195
196impl LocalKeyset {
197    /// Derives keyset from a *channel extended key* using LNPBP-46 standard
198    pub fn with<C: secp256k1::Signing>(
199        secp: &Secp256k1<C>,
200        channel_source: KeySource,
201        channel_xpriv: ExtendedPrivKey,
202        shutdown_scriptpubkey: Option<PubkeyScript>,
203    ) -> Self {
204        let fingerpint = channel_source.0;
205
206        let keys = (0u16..=6)
207            .into_iter()
208            .map(HardenedIndex::from)
209            .map(ChildNumber::from)
210            .map(|index| [index])
211            .map(|path| {
212                let derivation_path = channel_source.1.clone().extend(path);
213                let seckey = channel_xpriv
214                    .derive_priv(secp, &path)
215                    .expect("negligible probability")
216                    .private_key;
217                LocalPubkey {
218                    key: PublicKey::from_secret_key(secp, &seckey),
219                    source: (fingerpint, derivation_path),
220                }
221            })
222            .collect::<Vec<_>>();
223
224        Self {
225            funding_pubkey: keys[0].clone(),
226            revocation_basepoint: keys[3].clone(),
227            payment_basepoint: keys[1].clone(),
228            delayed_payment_basepoint: keys[2].clone(),
229            htlc_basepoint: keys[5].clone(),
230            first_per_commitment_point: keys[4].clone(),
231            shutdown_scriptpubkey,
232            static_remotekey: false,
233        }
234    }
235}