Skip to content

Commit 7a23c0c

Browse files
author
Antoine Riard
committed
Remove SecretKey from DynamicOuputP2WPKH descriptor
Add sign_payment_transaction in ChanSigner to be able to spend SpendableOutputDescriptor in test framework
1 parent 13a6604 commit 7a23c0c

File tree

4 files changed

+46
-33
lines changed

4 files changed

+46
-33
lines changed

lightning/src/chain/keysinterface.rs

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use bitcoin::blockdata::script::{Script, Builder};
77
use bitcoin::blockdata::opcodes;
88
use bitcoin::network::constants::Network;
99
use bitcoin::util::bip32::{ExtendedPrivKey, ExtendedPubKey, ChildNumber};
10+
use bitcoin::util::address::Address;
1011
use bitcoin::util::bip143;
1112

1213
use bitcoin_hashes::{Hash, HashEngine};
@@ -84,7 +85,7 @@ pub enum SpendableOutputDescriptor {
8485
/// The outpoint which is spendable
8586
outpoint: OutPoint,
8687
/// The secret key which must be used to sign the spending transaction
87-
key: SecretKey,
88+
per_commitment_point: PublicKey,
8889
/// The output which is reference by the given outpoint
8990
output: TxOut,
9091
}
@@ -106,10 +107,10 @@ impl Writeable for SpendableOutputDescriptor {
106107
to_self_delay.write(writer)?;
107108
output.write(writer)?;
108109
},
109-
&SpendableOutputDescriptor::DynamicOutputP2WPKH { ref outpoint, ref key, ref output } => {
110+
&SpendableOutputDescriptor::DynamicOutputP2WPKH { ref outpoint, ref per_commitment_point, ref output } => {
110111
2u8.write(writer)?;
111112
outpoint.write(writer)?;
112-
key.write(writer)?;
113+
per_commitment_point.write(writer)?;
113114
output.write(writer)?;
114115
},
115116
}
@@ -133,7 +134,7 @@ impl Readable for SpendableOutputDescriptor {
133134
}),
134135
2u8 => Ok(SpendableOutputDescriptor::DynamicOutputP2WPKH {
135136
outpoint: Readable::read(reader)?,
136-
key: Readable::read(reader)?,
137+
per_commitment_point: Readable::read(reader)?,
137138
output: Readable::read(reader)?,
138139
}),
139140
_ => Err(DecodeError::InvalidValue),
@@ -261,6 +262,9 @@ pub trait ChannelKeys : Send+Clone {
261262
/// Create a signature for a delayed transaction.
262263
fn sign_delayed_transaction<T: secp256k1::Signing>(&self, spend_tx: &mut Transaction, input: usize, witness_script: &Script, amount: u64, per_commitment_point: &PublicKey, secp_ctx: &Secp256k1<T>);
263264

265+
/// Create a signture for a payment transaction spending a to_remote output on a remote commitment tx.
266+
fn sign_payment_transaction<T: secp256k1::Signing>(&self, spend_tx: &mut Transaction, input: usize, amount: u64, per_commitment_point: &PublicKey, network: Network, secp_ctx: &Secp256k1<T>);
267+
264268
/// Signs a channel announcement message with our funding key, proving it comes from one
265269
/// of the channel participants.
266270
///
@@ -461,6 +465,19 @@ impl ChannelKeys for InMemoryChannelKeys {
461465
}
462466
}
463467

468+
fn sign_payment_transaction<T: secp256k1::Signing>(&self, spend_tx: &mut Transaction, input: usize, amount: u64, per_commitment_point: &PublicKey, network: Network, secp_ctx: &Secp256k1<T>) {
469+
if let Ok(payment_key) = chan_utils::derive_private_key(&secp_ctx, &per_commitment_point, &self.payment_base_key) {
470+
let remotepubkey = PublicKey::from_secret_key(&secp_ctx, &payment_key);
471+
let witness_script = Address::p2pkh(&::bitcoin::PublicKey{compressed: true, key: remotepubkey}, network).script_pubkey();
472+
let sighash_parts = bip143::SighashComponents::new(&spend_tx);
473+
let sighash = hash_to_message!(&sighash_parts.sighash_all(&spend_tx.input[input], &witness_script, amount)[..]);
474+
let remotesig = secp_ctx.sign(&sighash, &payment_key);
475+
spend_tx.input[0].witness.push(remotesig.serialize_der().to_vec());
476+
spend_tx.input[0].witness[0].push(SigHashType::All as u8);
477+
spend_tx.input[0].witness.push(remotepubkey.serialize().to_vec());
478+
}
479+
}
480+
464481
fn sign_channel_announcement<T: secp256k1::Signing>(&self, msg: &msgs::UnsignedChannelAnnouncement, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()> {
465482
let msghash = hash_to_message!(&Sha256dHash::hash(&msg.encode()[..])[..]);
466483
Ok(secp_ctx.sign(&msghash, &self.funding_key))

lightning/src/ln/channelmonitor.rs

Lines changed: 17 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -714,7 +714,7 @@ pub struct ChannelMonitor<ChanSigner: ChannelKeys> {
714714

715715
destination_script: Script,
716716
broadcasted_local_revokable_script: Option<(Script, PublicKey, Script)>,
717-
broadcasted_remote_payment_script: Option<(Script, SecretKey)>,
717+
broadcasted_remote_payment_script: Option<(Script, PublicKey)>,
718718
shutdown_script: Script,
719719

720720
keys: ChanSigner,
@@ -1232,9 +1232,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
12321232
let to_remote_script = Builder::new().push_opcode(opcodes::all::OP_PUSHBYTES_0)
12331233
.push_slice(&Hash160::hash(&payment_key.serialize())[..])
12341234
.into_script();
1235-
if let Ok(to_remote_key) = chan_utils::derive_private_key(&self.secp_ctx, &their_revocation_point, &self.keys.payment_base_key()) {
1236-
self.broadcasted_remote_payment_script = Some((to_remote_script, to_remote_key));
1237-
}
1235+
self.broadcasted_remote_payment_script = Some((to_remote_script, their_revocation_point));
12381236
}
12391237
}
12401238

@@ -1447,18 +1445,17 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
14471445
let per_commitment_key = ignore_error!(SecretKey::from_slice(&secret));
14481446
let per_commitment_point = PublicKey::from_secret_key(&self.secp_ctx, &per_commitment_key);
14491447
let revocation_pubkey = ignore_error!(chan_utils::derive_public_revocation_key(&self.secp_ctx, &per_commitment_point, &self.keys.pubkeys().revocation_basepoint));
1450-
let local_payment_key = ignore_error!(chan_utils::derive_private_key(&self.secp_ctx, &per_commitment_point, &self.keys.payment_base_key()));
14511448
let delayed_key = ignore_error!(chan_utils::derive_public_key(&self.secp_ctx, &PublicKey::from_secret_key(&self.secp_ctx, &per_commitment_key), &self.their_delayed_payment_base_key));
14521449

14531450
let revokeable_redeemscript = chan_utils::get_revokeable_redeemscript(&revocation_pubkey, self.our_to_self_delay, &delayed_key);
14541451
let revokeable_p2wsh = revokeable_redeemscript.to_v0_p2wsh();
14551452

1456-
self.broadcasted_remote_payment_script = {
1457-
// Note that the Network here is ignored as we immediately drop the address for the
1458-
// script_pubkey version
1459-
let payment_hash160 = Hash160::hash(&PublicKey::from_secret_key(&self.secp_ctx, &local_payment_key).serialize());
1460-
Some((Builder::new().push_opcode(opcodes::all::OP_PUSHBYTES_0).push_slice(&payment_hash160[..]).into_script(), local_payment_key))
1461-
};
1453+
self.broadcasted_remote_payment_script = if let Ok(payment_key) = chan_utils::derive_public_key(&self.secp_ctx, &per_commitment_point, &self.keys.pubkeys().payment_basepoint) {
1454+
let payment_script = Builder::new().push_opcode(opcodes::all::OP_PUSHBYTES_0)
1455+
.push_slice(&Hash160::hash(&payment_key.serialize())[..])
1456+
.into_script();
1457+
Some((payment_script, per_commitment_point))
1458+
} else { None };
14621459

14631460
// First, process non-htlc outputs (to_local & to_remote)
14641461
for (idx, outp) in tx.output.iter().enumerate() {
@@ -1594,14 +1591,13 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
15941591
if revocation_points.0 == commitment_number + 1 { Some(point) } else { None }
15951592
} else { None };
15961593
if let Some(revocation_point) = revocation_point_option {
1597-
let local_payment_key = ignore_error!(chan_utils::derive_private_key(&self.secp_ctx, revocation_point, &self.keys.payment_base_key()));
15981594

1599-
self.broadcasted_remote_payment_script = {
1600-
// Note that the Network here is ignored as we immediately drop the address for the
1601-
// script_pubkey version
1602-
let payment_hash160 = Hash160::hash(&PublicKey::from_secret_key(&self.secp_ctx, &local_payment_key).serialize());
1603-
Some((Builder::new().push_opcode(opcodes::all::OP_PUSHBYTES_0).push_slice(&payment_hash160[..]).into_script(), local_payment_key))
1604-
};
1595+
self.broadcasted_remote_payment_script = if let Ok(payment_key) = chan_utils::derive_public_key(&self.secp_ctx, &revocation_point, &self.keys.pubkeys().payment_basepoint) {
1596+
let payment_script = Builder::new().push_opcode(opcodes::all::OP_PUSHBYTES_0)
1597+
.push_slice(&Hash160::hash(&payment_key.serialize())[..])
1598+
.into_script();
1599+
Some((payment_script, *revocation_point))
1600+
} else { None };
16051601

16061602
// Then, try to find htlc outputs
16071603
for (_, &(ref htlc, _)) in per_commitment_data.iter().enumerate() {
@@ -2170,7 +2166,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
21702166
if broadcasted_remote_payment_script.0 == outp.script_pubkey {
21712167
spendable_output = Some(SpendableOutputDescriptor::DynamicOutputP2WPKH {
21722168
outpoint: BitcoinOutPoint { txid: tx.txid(), vout: i as u32 },
2173-
key: broadcasted_remote_payment_script.1,
2169+
per_commitment_point: broadcasted_remote_payment_script.1,
21742170
output: outp.clone(),
21752171
});
21762172
break;
@@ -2233,8 +2229,8 @@ impl<ChanSigner: ChannelKeys + Readable> ReadableArgs<Arc<Logger>> for (Sha256dH
22332229
let broadcasted_remote_payment_script = match <u8 as Readable>::read(reader)? {
22342230
0 => {
22352231
let payment_address = Readable::read(reader)?;
2236-
let payment_key = Readable::read(reader)?;
2237-
Some((payment_address, payment_key))
2232+
let per_commitment_point = Readable::read(reader)?;
2233+
Some((payment_address, per_commitment_point))
22382234
},
22392235
1 => { None },
22402236
_ => return Err(DecodeError::InvalidValue),

lightning/src/ln/functional_tests.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4096,7 +4096,7 @@ macro_rules! check_spendable_outputs {
40964096
Event::SpendableOutputs { ref outputs } => {
40974097
for outp in outputs {
40984098
match *outp {
4099-
SpendableOutputDescriptor::DynamicOutputP2WPKH { ref outpoint, ref key, ref output } => {
4099+
SpendableOutputDescriptor::DynamicOutputP2WPKH { ref outpoint, ref per_commitment_point, ref output } => {
41004100
let input = TxIn {
41014101
previous_output: outpoint.clone(),
41024102
script_sig: Script::new(),
@@ -4114,13 +4114,7 @@ macro_rules! check_spendable_outputs {
41144114
output: vec![outp],
41154115
};
41164116
let secp_ctx = Secp256k1::new();
4117-
let remotepubkey = PublicKey::from_secret_key(&secp_ctx, &key);
4118-
let witness_script = Address::p2pkh(&::bitcoin::PublicKey{compressed: true, key: remotepubkey}, Network::Testnet).script_pubkey();
4119-
let sighash = Message::from_slice(&bip143::SighashComponents::new(&spend_tx).sighash_all(&spend_tx.input[0], &witness_script, output.value)[..]).unwrap();
4120-
let remotesig = secp_ctx.sign(&sighash, key);
4121-
spend_tx.input[0].witness.push(remotesig.serialize_der().to_vec());
4122-
spend_tx.input[0].witness[0].push(SigHashType::All as u8);
4123-
spend_tx.input[0].witness.push(remotepubkey.serialize().to_vec());
4117+
$chan_signer.sign_payment_transaction(&mut spend_tx, 0, output.value, per_commitment_point, Network::Testnet, &secp_ctx);
41244118
txn.push(spend_tx);
41254119
},
41264120
SpendableOutputDescriptor::DynamicOutputP2WSH { ref outpoint, ref per_commitment_point, ref witness_script, ref to_self_delay, ref output } => {

lightning/src/util/enforcing_trait_impls.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ use std::sync::{Mutex, Arc};
99
use bitcoin::blockdata::transaction::Transaction;
1010
use bitcoin::blockdata::script::Script;
1111
use bitcoin::util::bip143;
12+
use bitcoin::network::constants::Network;
13+
1214

1315
use secp256k1;
1416
use secp256k1::key::{SecretKey, PublicKey};
@@ -119,6 +121,10 @@ impl ChannelKeys for EnforcingChannelKeys {
119121
self.inner.sign_delayed_transaction(spend_tx, input, witness_script, amount, per_commitment_point, secp_ctx);
120122
}
121123

124+
fn sign_payment_transaction<T: secp256k1::Signing>(&self, spend_tx: &mut Transaction, input: usize, amount: u64, per_commitment_point: &PublicKey, network: Network, secp_ctx: &Secp256k1<T>) {
125+
self.inner.sign_payment_transaction(spend_tx, input, amount, per_commitment_point, network, secp_ctx);
126+
}
127+
122128
fn sign_closing_transaction<T: secp256k1::Signing>(&self, closing_tx: &Transaction, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()> {
123129
Ok(self.inner.sign_closing_transaction(closing_tx, secp_ctx).unwrap())
124130
}

0 commit comments

Comments
 (0)