Skip to content

Commit b8db1a7

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 3fee26d commit b8db1a7

File tree

4 files changed

+45
-33
lines changed

4 files changed

+45
-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),
@@ -242,6 +243,9 @@ pub trait ChannelKeys : Send+Clone {
242243
/// Create a signature for a delayed transaction.
243244
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>);
244245

246+
/// Create a signture for a payment transaction spending a to_remote output on a remote commitment tx.
247+
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>);
248+
245249
/// Signs a channel announcement message with our funding key, proving it comes from one
246250
/// of the channel participants.
247251
///
@@ -484,6 +488,19 @@ impl ChannelKeys for InMemoryChannelKeys {
484488
}
485489
}
486490

491+
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>) {
492+
if let Ok(payment_key) = chan_utils::derive_private_key(&secp_ctx, &per_commitment_point, &self.payment_base_key) {
493+
let remotepubkey = PublicKey::from_secret_key(&secp_ctx, &payment_key);
494+
let witness_script = Address::p2pkh(&::bitcoin::PublicKey{compressed: true, key: remotepubkey}, network).script_pubkey();
495+
let sighash_parts = bip143::SighashComponents::new(&spend_tx);
496+
let sighash = hash_to_message!(&sighash_parts.sighash_all(&spend_tx.input[input], &witness_script, amount)[..]);
497+
let remotesig = secp_ctx.sign(&sighash, &payment_key);
498+
spend_tx.input[0].witness.push(remotesig.serialize_der().to_vec());
499+
spend_tx.input[0].witness[0].push(SigHashType::All as u8);
500+
spend_tx.input[0].witness.push(remotepubkey.serialize().to_vec());
501+
}
502+
}
503+
487504
fn sign_channel_announcement<T: secp256k1::Signing>(&self, msg: &msgs::UnsignedChannelAnnouncement, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()> {
488505
let msghash = hash_to_message!(&Sha256dHash::hash(&msg.encode()[..])[..]);
489506
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
@@ -723,7 +723,7 @@ pub struct ChannelMonitor<ChanSigner: ChannelKeys> {
723723

724724
destination_script: Script,
725725
broadcasted_local_revokable_script: Option<(Script, PublicKey, Script)>,
726-
broadcasted_remote_payment_script: Option<(Script, SecretKey)>,
726+
broadcasted_remote_payment_script: Option<(Script, PublicKey)>,
727727
shutdown_script: Script,
728728

729729
onchain_detection: OnchainDetection<ChanSigner>,
@@ -1238,9 +1238,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
12381238
let to_remote_script = Builder::new().push_opcode(opcodes::all::OP_PUSHBYTES_0)
12391239
.push_slice(&Hash160::hash(&payment_key.serialize())[..])
12401240
.into_script();
1241-
if let Ok(to_remote_key) = chan_utils::derive_private_key(&self.secp_ctx, &their_revocation_point, &self.onchain_detection.keys.payment_base_key()) {
1242-
self.broadcasted_remote_payment_script = Some((to_remote_script, to_remote_key));
1243-
}
1241+
self.broadcasted_remote_payment_script = Some((to_remote_script, their_revocation_point));
12441242
}
12451243
}
12461244

@@ -1441,18 +1439,17 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
14411439
let per_commitment_key = ignore_error!(SecretKey::from_slice(&secret));
14421440
let per_commitment_point = PublicKey::from_secret_key(&self.secp_ctx, &per_commitment_key);
14431441
let revocation_pubkey = ignore_error!(chan_utils::derive_public_revocation_key(&self.secp_ctx, &per_commitment_point, &self.onchain_detection.keys.pubkeys().revocation_basepoint));
1444-
let local_payment_key = ignore_error!(chan_utils::derive_private_key(&self.secp_ctx, &per_commitment_point, &self.onchain_detection.keys.payment_base_key()));
14451442
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.unwrap()));
14461443

14471444
let revokeable_redeemscript = chan_utils::get_revokeable_redeemscript(&revocation_pubkey, self.our_to_self_delay, &delayed_key);
14481445
let revokeable_p2wsh = revokeable_redeemscript.to_v0_p2wsh();
14491446

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

14571454
// First, process non-htlc outputs (to_local & to_remote)
14581455
for (idx, outp) in tx.output.iter().enumerate() {
@@ -1588,14 +1585,13 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
15881585
if revocation_points.0 == commitment_number + 1 { Some(point) } else { None }
15891586
} else { None };
15901587
if let Some(revocation_point) = revocation_point_option {
1591-
let local_payment_key = ignore_error!(chan_utils::derive_private_key(&self.secp_ctx, revocation_point, &self.onchain_detection.keys.payment_base_key()));
15921588

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

16001596
// Then, try to find htlc outputs
16011597
for (_, &(ref htlc, _)) in per_commitment_data.iter().enumerate() {
@@ -2135,7 +2131,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
21352131
if broadcasted_remote_payment_script.0 == outp.script_pubkey {
21362132
spendable_output = Some(SpendableOutputDescriptor::DynamicOutputP2WPKH {
21372133
outpoint: BitcoinOutPoint { txid: tx.txid(), vout: i as u32 },
2138-
key: broadcasted_remote_payment_script.1,
2134+
per_commitment_point: broadcasted_remote_payment_script.1,
21392135
output: outp.clone(),
21402136
});
21412137
break;
@@ -2198,8 +2194,8 @@ impl<ChanSigner: ChannelKeys + Readable> ReadableArgs<Arc<Logger>> for (Sha256dH
21982194
let broadcasted_remote_payment_script = match <u8 as Readable>::read(reader)? {
21992195
0 => {
22002196
let payment_address = Readable::read(reader)?;
2201-
let payment_key = Readable::read(reader)?;
2202-
Some((payment_address, payment_key))
2197+
let per_commitment_point = Readable::read(reader)?;
2198+
Some((payment_address, per_commitment_point))
22032199
},
22042200
1 => { None },
22052201
_ => return Err(DecodeError::InvalidValue),

lightning/src/ln/functional_tests.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3943,7 +3943,7 @@ macro_rules! check_spendable_outputs {
39433943
Event::SpendableOutputs { ref outputs } => {
39443944
for outp in outputs {
39453945
match *outp {
3946-
SpendableOutputDescriptor::DynamicOutputP2WPKH { ref outpoint, ref key, ref output } => {
3946+
SpendableOutputDescriptor::DynamicOutputP2WPKH { ref outpoint, ref per_commitment_point, ref output } => {
39473947
let input = TxIn {
39483948
previous_output: outpoint.clone(),
39493949
script_sig: Script::new(),
@@ -3961,13 +3961,7 @@ macro_rules! check_spendable_outputs {
39613961
output: vec![outp],
39623962
};
39633963
let secp_ctx = Secp256k1::new();
3964-
let remotepubkey = PublicKey::from_secret_key(&secp_ctx, &key);
3965-
let witness_script = Address::p2pkh(&::bitcoin::PublicKey{compressed: true, key: remotepubkey}, Network::Testnet).script_pubkey();
3966-
let sighash = Message::from_slice(&bip143::SighashComponents::new(&spend_tx).sighash_all(&spend_tx.input[0], &witness_script, output.value)[..]).unwrap();
3967-
let remotesig = secp_ctx.sign(&sighash, key);
3968-
spend_tx.input[0].witness.push(remotesig.serialize_der().to_vec());
3969-
spend_tx.input[0].witness[0].push(SigHashType::All as u8);
3970-
spend_tx.input[0].witness.push(remotepubkey.serialize().to_vec());
3964+
$chan_signer.sign_payment_transaction(&mut spend_tx, 0, output.value, per_commitment_point, Network::Testnet, &secp_ctx);
39713965
txn.push(spend_tx);
39723966
},
39733967
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: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use std::sync::{Mutex, Arc};
88

99
use bitcoin::blockdata::transaction::Transaction;
1010
use bitcoin::blockdata::script::Script;
11+
use bitcoin::network::constants::Network;
1112

1213

1314
use secp256k1;
@@ -101,6 +102,10 @@ impl ChannelKeys for EnforcingChannelKeys {
101102
self.inner.sign_delayed_transaction(spend_tx, input, witness_script, amount, per_commitment_point, secp_ctx);
102103
}
103104

105+
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>) {
106+
self.inner.sign_payment_transaction(spend_tx, input, amount, per_commitment_point, network, secp_ctx);
107+
}
108+
104109
fn sign_closing_transaction<T: secp256k1::Signing>(&self, closing_tx: &Transaction, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()> {
105110
Ok(self.inner.sign_closing_transaction(closing_tx, secp_ctx).unwrap())
106111
}

0 commit comments

Comments
 (0)