Skip to content

Commit e08f7de

Browse files
committed
Implement Script for Witness and Add Tweak in PSBT.
Adding Witness Script and key tweaks makes a Partially Signed Bitcoin Transaction the single data source needed for a Signer to produce valid signatures. A Signer is not required to be able to generate L2 keys, e.g delayed payment basepoint.
1 parent 6264a44 commit e08f7de

File tree

3 files changed

+188
-48
lines changed

3 files changed

+188
-48
lines changed

lightning/src/chain/channelmonitor.rs

+1
Original file line numberDiff line numberDiff line change
@@ -4330,6 +4330,7 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitorImpl<Signer> {
43304330
revocation_pubkey: broadcasted_holder_revokable_script.2,
43314331
channel_keys_id: self.channel_keys_id,
43324332
channel_value_satoshis: self.channel_value_satoshis,
4333+
channel_transaction_parameters: Some(self.onchain_tx_handler.channel_transaction_parameters.clone()),
43334334
}));
43344335
}
43354336
}

lightning/src/ln/channel_keys.rs

+79-31
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,19 @@
1010
//! Keys used to generate commitment transactions.
1111
//! See: <https://github.com/lightning/bolts/blob/master/03-transactions.md#keys>
1212
13-
use bitcoin::hashes::Hash;
14-
use bitcoin::hashes::HashEngine;
15-
use bitcoin::secp256k1::Scalar;
16-
use bitcoin::secp256k1::SecretKey;
17-
use bitcoin::secp256k1::Secp256k1;
18-
use bitcoin::secp256k1;
13+
use crate::io;
1914
use crate::ln::msgs::DecodeError;
2015
use crate::util::ser::Readable;
21-
use crate::io;
22-
use crate::util::ser::Writer;
2316
use crate::util::ser::Writeable;
24-
use bitcoin::secp256k1::PublicKey;
17+
use crate::util::ser::Writer;
2518
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;
2626

2727
macro_rules! doc_comment {
2828
($x:expr, $($tt:tt)*) => {
@@ -37,15 +37,28 @@ macro_rules! basepoint_impl {
3737
pub fn to_public_key(&self) -> PublicKey {
3838
self.0
3939
}
40+
41+
/// Derives a per-commitment-transaction (eg an htlc key or delayed_payment key) private key addition tweak
42+
/// from a basepoint and a per_commitment_point:
43+
/// `privkey = basepoint_secret + SHA256(per_commitment_point || basepoint)`
44+
/// This calculates the hash part in the tweak derivation process, which is used to ensure
45+
/// that each key is unique and cannot be guessed by an external party. It is equivalent
46+
/// to the `from_basepoint` method, but without the addition operation, providing just the
47+
/// tweak from the hash of the per_commitment_point and the basepoint.
48+
pub fn derive_add_tweak(&self, per_commitment_point: &PublicKey) -> [u8; 32] {
49+
let mut sha = Sha256::engine();
50+
sha.input(&per_commitment_point.serialize());
51+
sha.input(&self.to_public_key().serialize());
52+
Sha256::from_engine(sha).to_byte_array()
53+
}
4054
}
4155

4256
impl From<PublicKey> for $BasepointT {
4357
fn from(value: PublicKey) -> Self {
4458
Self(value)
4559
}
4660
}
47-
48-
}
61+
};
4962
}
5063
macro_rules! key_impl {
5164
($BasepointT:ty, $KeyName:expr) => {
@@ -87,11 +100,9 @@ macro_rules! key_read_write {
87100
Ok(Self(key))
88101
}
89102
}
90-
}
103+
};
91104
}
92105

93-
94-
95106
/// Base key used in conjunction with a `per_commitment_point` to generate a [`DelayedPaymentKey`].
96107
///
97108
/// The delayed payment key is used to pay the commitment state broadcaster their
@@ -102,7 +113,6 @@ pub struct DelayedPaymentBasepoint(pub PublicKey);
102113
basepoint_impl!(DelayedPaymentBasepoint);
103114
key_read_write!(DelayedPaymentBasepoint);
104115

105-
106116
/// A derived key built from a [`DelayedPaymentBasepoint`] and `per_commitment_point`.
107117
///
108118
/// The delayed payment key is used to pay the commitment state broadcaster their
@@ -150,14 +160,26 @@ key_read_write!(HtlcKey);
150160
/// Derives a per-commitment-transaction public key (eg an htlc key or a delayed_payment key)
151161
/// from the base point and the per_commitment_key. This is the public equivalent of
152162
/// derive_private_key - using only public keys to derive a public key instead of private keys.
153-
fn derive_public_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>, per_commitment_point: &PublicKey, base_point: &PublicKey) -> PublicKey {
163+
fn derive_public_key<T: secp256k1::Signing>(
164+
secp_ctx: &Secp256k1<T>, per_commitment_point: &PublicKey, base_point: &PublicKey,
165+
) -> PublicKey {
154166
let mut sha = Sha256::engine();
155167
sha.input(&per_commitment_point.serialize());
156168
sha.input(&base_point.serialize());
157169
let res = Sha256::from_engine(sha).to_byte_array();
158170

159-
let hashkey = PublicKey::from_secret_key(&secp_ctx,
160-
&SecretKey::from_slice(&res).expect("Hashes should always be valid keys unless SHA-256 is broken"));
171+
add_public_key_tweak(secp_ctx, base_point, &res)
172+
}
173+
174+
/// Adds a tweak to a public key to derive a new public key.
175+
pub fn add_public_key_tweak<T: secp256k1::Signing>(
176+
secp_ctx: &Secp256k1<T>, base_point: &PublicKey, tweak: &[u8; 32],
177+
) -> PublicKey {
178+
let hashkey = PublicKey::from_secret_key(
179+
&secp_ctx,
180+
&SecretKey::from_slice(tweak)
181+
.expect("Hashes should always be valid keys unless SHA-256 is broken"),
182+
);
161183
base_point.combine(&hashkey)
162184
.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.")
163185
}
@@ -169,7 +191,6 @@ pub struct RevocationBasepoint(pub PublicKey);
169191
basepoint_impl!(RevocationBasepoint);
170192
key_read_write!(RevocationBasepoint);
171193

172-
173194
/// The revocation key is used to allow a channel party to revoke their state - giving their
174195
/// counterparty the required material to claim all of their funds if they broadcast that state.
175196
///
@@ -192,8 +213,7 @@ impl RevocationKey {
192213
///
193214
/// [`chan_utils::derive_private_revocation_key`]: crate::ln::chan_utils::derive_private_revocation_key
194215
pub fn from_basepoint<T: secp256k1::Verification>(
195-
secp_ctx: &Secp256k1<T>,
196-
countersignatory_basepoint: &RevocationBasepoint,
216+
secp_ctx: &Secp256k1<T>, countersignatory_basepoint: &RevocationBasepoint,
197217
per_commitment_point: &PublicKey,
198218
) -> Self {
199219
let rev_append_commit_hash_key = {
@@ -227,28 +247,56 @@ impl RevocationKey {
227247
}
228248
key_read_write!(RevocationKey);
229249

230-
231250
#[cfg(test)]
232251
mod test {
233-
use bitcoin::secp256k1::{Secp256k1, SecretKey, PublicKey};
234-
use bitcoin::hashes::hex::FromHex;
235252
use super::derive_public_key;
253+
use bitcoin::hashes::hex::FromHex;
254+
use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey};
236255

237256
#[test]
238257
fn test_key_derivation() {
239258
// Test vectors from BOLT 3 Appendix E:
240259
let secp_ctx = Secp256k1::new();
241260

242-
let base_secret = SecretKey::from_slice(&<Vec<u8>>::from_hex("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f").unwrap()[..]).unwrap();
243-
let per_commitment_secret = SecretKey::from_slice(&<Vec<u8>>::from_hex("1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100").unwrap()[..]).unwrap();
261+
let base_secret = SecretKey::from_slice(
262+
&<Vec<u8>>::from_hex(
263+
"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
264+
)
265+
.unwrap()[..],
266+
)
267+
.unwrap();
268+
let per_commitment_secret = SecretKey::from_slice(
269+
&<Vec<u8>>::from_hex(
270+
"1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100",
271+
)
272+
.unwrap()[..],
273+
)
274+
.unwrap();
244275

245276
let base_point = PublicKey::from_secret_key(&secp_ctx, &base_secret);
246-
assert_eq!(base_point.serialize()[..], <Vec<u8>>::from_hex("036d6caac248af96f6afa7f904f550253a0f3ef3f5aa2fe6838a95b216691468e2").unwrap()[..]);
277+
assert_eq!(
278+
base_point.serialize()[..],
279+
<Vec<u8>>::from_hex(
280+
"036d6caac248af96f6afa7f904f550253a0f3ef3f5aa2fe6838a95b216691468e2"
281+
)
282+
.unwrap()[..]
283+
);
247284

248285
let per_commitment_point = PublicKey::from_secret_key(&secp_ctx, &per_commitment_secret);
249-
assert_eq!(per_commitment_point.serialize()[..], <Vec<u8>>::from_hex("025f7117a78150fe2ef97db7cfc83bd57b2e2c0d0dd25eaf467a4a1c2a45ce1486").unwrap()[..]);
250-
251-
assert_eq!(derive_public_key(&secp_ctx, &per_commitment_point, &base_point).serialize()[..],
252-
<Vec<u8>>::from_hex("0235f2dbfaa89b57ec7b055afe29849ef7ddfeb1cefdb9ebdc43f5494984db29e5").unwrap()[..]);
286+
assert_eq!(
287+
per_commitment_point.serialize()[..],
288+
<Vec<u8>>::from_hex(
289+
"025f7117a78150fe2ef97db7cfc83bd57b2e2c0d0dd25eaf467a4a1c2a45ce1486"
290+
)
291+
.unwrap()[..]
292+
);
293+
294+
assert_eq!(
295+
derive_public_key(&secp_ctx, &per_commitment_point, &base_point).serialize()[..],
296+
<Vec<u8>>::from_hex(
297+
"0235f2dbfaa89b57ec7b055afe29849ef7ddfeb1cefdb9ebdc43f5494984db29e5"
298+
)
299+
.unwrap()[..]
300+
);
253301
}
254302
}

0 commit comments

Comments
 (0)