1 // This file is Copyright its original authors, visible in version control
4 // This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
5 // or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
7 // You may not use this file except in accordance with one or both of these
10 //! Keys used to generate commitment transactions.
11 //! See: <https://github.com/lightning/bolts/blob/master/03-transactions.md#keys>
14 use crate::ln::msgs::DecodeError;
15 use crate::util::ser::Readable;
16 use crate::util::ser::Writeable;
17 use crate::util::ser::Writer;
18 use bitcoin::hashes::sha256::Hash as Sha256;
19 use bitcoin::hashes::Hash;
20 use bitcoin::hashes::HashEngine;
21 use bitcoin::secp256k1;
22 use bitcoin::secp256k1::PublicKey;
23 use bitcoin::secp256k1::Scalar;
24 use bitcoin::secp256k1::Secp256k1;
25 use bitcoin::secp256k1::SecretKey;
27 macro_rules! doc_comment {
28 ($x:expr, $($tt:tt)*) => {
33 macro_rules! basepoint_impl {
34 ($BasepointT:ty $(, $KeyName: expr)?) => {
36 /// Get inner Public Key
37 pub fn to_public_key(&self) -> PublicKey {
43 "Derives the \"tweak\" used in calculate [`", $KeyName, "::from_basepoint`].\n",
45 "[`", $KeyName, "::from_basepoint`] calculates a private key as:\n",
46 "`privkey = basepoint_secret + SHA256(per_commitment_point || basepoint)`\n",
48 "This calculates the hash part in the tweak derivation process, which is used to\n",
49 "ensure that each key is unique and cannot be guessed by an external party."
51 pub fn derive_add_tweak(&self, per_commitment_point: &PublicKey) -> Sha256 {
52 let mut sha = Sha256::engine();
53 sha.input(&per_commitment_point.serialize());
54 sha.input(&self.to_public_key().serialize());
55 Sha256::from_engine(sha)
60 impl From<PublicKey> for $BasepointT {
61 fn from(value: PublicKey) -> Self {
67 macro_rules! key_impl {
68 ($BasepointT:ty, $KeyName:expr) => {
70 concat!("Derive a public ", $KeyName, " using one node's `per_commitment_point` and its countersignatory's `basepoint`"),
71 pub fn from_basepoint<T: secp256k1::Signing>(
72 secp_ctx: &Secp256k1<T>,
73 countersignatory_basepoint: &$BasepointT,
74 per_commitment_point: &PublicKey,
76 Self(derive_public_key(secp_ctx, per_commitment_point, &countersignatory_basepoint.0))
81 concat!("Build a ", $KeyName, " directly from an already-derived private key"),
82 pub fn from_secret_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>, sk: &SecretKey) -> Self {
83 Self(PublicKey::from_secret_key(&secp_ctx, &sk))
87 /// Get inner Public Key
88 pub fn to_public_key(&self) -> PublicKey {
93 macro_rules! key_read_write {
95 impl Writeable for $SelfT {
96 fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
97 self.0.serialize().write(w)
101 impl Readable for $SelfT {
102 fn read<R: io::Read>(r: &mut R) -> Result<Self, DecodeError> {
103 let key: PublicKey = Readable::read(r)?;
110 /// Base key used in conjunction with a `per_commitment_point` to generate a [`DelayedPaymentKey`].
112 /// The delayed payment key is used to pay the commitment state broadcaster their
113 /// non-HTLC-encumbered funds after a delay to give their counterparty a chance to punish if the
114 /// state broadcasted was previously revoked.
115 #[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
116 pub struct DelayedPaymentBasepoint(pub PublicKey);
117 basepoint_impl!(DelayedPaymentBasepoint, "DelayedPaymentKey");
118 key_read_write!(DelayedPaymentBasepoint);
120 /// A derived key built from a [`DelayedPaymentBasepoint`] and `per_commitment_point`.
122 /// The delayed payment key is used to pay the commitment state broadcaster their
123 /// non-HTLC-encumbered funds after a delay. This delay gives their counterparty a chance to
124 /// punish and claim all the channel funds if the state broadcasted was previously revoked.
126 /// [See the BOLT specs]
127 /// (https://github.com/lightning/bolts/blob/master/03-transactions.md#localpubkey-local_htlcpubkey-remote_htlcpubkey-local_delayedpubkey-and-remote_delayedpubkey-derivation)
128 /// for more information on key derivation details.
129 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
130 pub struct DelayedPaymentKey(pub PublicKey);
132 impl DelayedPaymentKey {
133 key_impl!(DelayedPaymentBasepoint, "delayedpubkey");
135 key_read_write!(DelayedPaymentKey);
137 /// Base key used in conjunction with a `per_commitment_point` to generate an [`HtlcKey`].
139 /// HTLC keys are used to ensure only the recipient of an HTLC can claim it on-chain with the HTLC
140 /// preimage and that only the sender of an HTLC can claim it on-chain after it has timed out.
141 /// Thus, both channel counterparties' HTLC keys will appears in each HTLC output's script.
142 #[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
143 pub struct HtlcBasepoint(pub PublicKey);
144 basepoint_impl!(HtlcBasepoint, "HtlcKey");
145 key_read_write!(HtlcBasepoint);
147 /// A derived key built from a [`HtlcBasepoint`] and `per_commitment_point`.
149 /// HTLC keys are used to ensure only the recipient of an HTLC can claim it on-chain with the HTLC
150 /// preimage and that only the sender of an HTLC can claim it on-chain after it has timed out.
151 /// Thus, both channel counterparties' HTLC keys will appears in each HTLC output's script.
153 /// [See the BOLT specs]
154 /// (https://github.com/lightning/bolts/blob/master/03-transactions.md#localpubkey-local_htlcpubkey-remote_htlcpubkey-local_delayedpubkey-and-remote_delayedpubkey-derivation)
155 /// for more information on key derivation details.
156 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
157 pub struct HtlcKey(pub PublicKey);
160 key_impl!(HtlcBasepoint, "htlcpubkey");
162 key_read_write!(HtlcKey);
164 /// Derives a per-commitment-transaction public key (eg an htlc key or a delayed_payment key)
165 /// from the base point and the per_commitment_key. This is the public equivalent of
166 /// derive_private_key - using only public keys to derive a public key instead of private keys.
167 fn derive_public_key<T: secp256k1::Signing>(
168 secp_ctx: &Secp256k1<T>, per_commitment_point: &PublicKey, base_point: &PublicKey,
170 let mut sha = Sha256::engine();
171 sha.input(&per_commitment_point.serialize());
172 sha.input(&base_point.serialize());
173 let res = Sha256::from_engine(sha);
175 add_public_key_tweak(secp_ctx, base_point, &res)
178 /// Adds a tweak to a public key to derive a new public key.
180 /// May panic if `tweak` is not the output of a SHA-256 hash.
181 pub fn add_public_key_tweak<T: secp256k1::Signing>(
182 secp_ctx: &Secp256k1<T>, base_point: &PublicKey, tweak: &Sha256,
184 let hashkey = PublicKey::from_secret_key(
186 &SecretKey::from_slice(tweak.as_byte_array())
187 .expect("Hashes should always be valid keys unless SHA-256 is broken"),
189 base_point.combine(&hashkey)
190 .expect("Addition only fails if the tweak is the inverse of the key. This is not possible when the tweak contains the hash of the key.")
193 /// Master key used in conjunction with per_commitment_point to generate [htlcpubkey](https://github.com/lightning/bolts/blob/master/03-transactions.md#key-derivation) for the latest state of a channel.
194 /// A watcher can be given a [RevocationBasepoint] to generate per commitment [RevocationKey] to create justice transactions.
195 #[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
196 pub struct RevocationBasepoint(pub PublicKey);
197 basepoint_impl!(RevocationBasepoint);
198 key_read_write!(RevocationBasepoint);
200 /// The revocation key is used to allow a channel party to revoke their state - giving their
201 /// counterparty the required material to claim all of their funds if they broadcast that state.
203 /// Each commitment transaction has a revocation key based on the basepoint and
204 /// per_commitment_point which is used in both commitment and HTLC transactions.
206 /// See [the BOLT spec for derivation details]
207 /// (https://github.com/lightning/bolts/blob/master/03-transactions.md#revocationpubkey-derivation)
208 #[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
209 pub struct RevocationKey(pub PublicKey);
212 /// Derives a per-commitment-transaction revocation public key from one party's per-commitment
213 /// point and the other party's [`RevocationBasepoint`]. This is the public equivalent of
214 /// [`chan_utils::derive_private_revocation_key`] - using only public keys to derive a public
215 /// key instead of private keys.
217 /// Note that this is infallible iff we trust that at least one of the two input keys are randomly
218 /// generated (ie our own).
220 /// [`chan_utils::derive_private_revocation_key`]: crate::ln::chan_utils::derive_private_revocation_key
221 pub fn from_basepoint<T: secp256k1::Verification>(
222 secp_ctx: &Secp256k1<T>, countersignatory_basepoint: &RevocationBasepoint,
223 per_commitment_point: &PublicKey,
225 let rev_append_commit_hash_key = {
226 let mut sha = Sha256::engine();
227 sha.input(&countersignatory_basepoint.to_public_key().serialize());
228 sha.input(&per_commitment_point.serialize());
230 Sha256::from_engine(sha).to_byte_array()
232 let commit_append_rev_hash_key = {
233 let mut sha = Sha256::engine();
234 sha.input(&per_commitment_point.serialize());
235 sha.input(&countersignatory_basepoint.to_public_key().serialize());
237 Sha256::from_engine(sha).to_byte_array()
240 let countersignatory_contrib = countersignatory_basepoint.to_public_key().mul_tweak(&secp_ctx, &Scalar::from_be_bytes(rev_append_commit_hash_key).unwrap())
241 .expect("Multiplying a valid public key by a hash is expected to never fail per secp256k1 docs");
242 let broadcaster_contrib = (&per_commitment_point).mul_tweak(&secp_ctx, &Scalar::from_be_bytes(commit_append_rev_hash_key).unwrap())
243 .expect("Multiplying a valid public key by a hash is expected to never fail per secp256k1 docs");
244 let pk = countersignatory_contrib.combine(&broadcaster_contrib)
245 .expect("Addition only fails if the tweak is the inverse of the key. This is not possible when the tweak commits to the key.");
249 /// Get inner Public Key
250 pub fn to_public_key(&self) -> PublicKey {
254 key_read_write!(RevocationKey);
258 use super::derive_public_key;
259 use bitcoin::hashes::hex::FromHex;
260 use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey};
263 fn test_key_derivation() {
264 // Test vectors from BOLT 3 Appendix E:
265 let secp_ctx = Secp256k1::new();
267 let base_secret = SecretKey::from_slice(
268 &<Vec<u8>>::from_hex(
269 "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
274 let per_commitment_secret = SecretKey::from_slice(
275 &<Vec<u8>>::from_hex(
276 "1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100",
282 let base_point = PublicKey::from_secret_key(&secp_ctx, &base_secret);
284 base_point.serialize()[..],
286 "036d6caac248af96f6afa7f904f550253a0f3ef3f5aa2fe6838a95b216691468e2"
291 let per_commitment_point = PublicKey::from_secret_key(&secp_ctx, &per_commitment_secret);
293 per_commitment_point.serialize()[..],
295 "025f7117a78150fe2ef97db7cfc83bd57b2e2c0d0dd25eaf467a4a1c2a45ce1486"
301 derive_public_key(&secp_ctx, &per_commitment_point, &base_point).serialize()[..],
303 "0235f2dbfaa89b57ec7b055afe29849ef7ddfeb1cefdb9ebdc43f5494984db29e5"