Skip to content

Commit 3fee26d

Browse files
author
Antoine Riard
committed
Remove SecretKey from DynamicOutputP2WSH descriptor
Add sign_delayed_transaction in ChanSigner to be able to spend SpendableOutputDescriptor in test framework.
1 parent 7273eb9 commit 3fee26d

File tree

4 files changed

+59
-34
lines changed

4 files changed

+59
-34
lines changed

lightning/src/chain/keysinterface.rs

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,8 @@ pub enum SpendableOutputDescriptor {
6565
DynamicOutputP2WSH {
6666
/// The outpoint which is spendable
6767
outpoint: OutPoint,
68-
/// The secret key which must be used to sign the spending transaction
69-
key: SecretKey,
68+
/// Per commitment point to derive delayed_payment_key by key holder
69+
per_commitment_point: PublicKey,
7070
/// The witness redeemScript which is hashed to create the script_pubkey in the given output
7171
witness_script: Script,
7272
/// The nSequence value which must be set in the spending input to satisfy the OP_CSV in
@@ -98,10 +98,10 @@ impl Writeable for SpendableOutputDescriptor {
9898
outpoint.write(writer)?;
9999
output.write(writer)?;
100100
},
101-
&SpendableOutputDescriptor::DynamicOutputP2WSH { ref outpoint, ref key, ref witness_script, ref to_self_delay, ref output } => {
101+
&SpendableOutputDescriptor::DynamicOutputP2WSH { ref outpoint, ref per_commitment_point, ref witness_script, ref to_self_delay, ref output } => {
102102
1u8.write(writer)?;
103103
outpoint.write(writer)?;
104-
key.write(writer)?;
104+
per_commitment_point.write(writer)?;
105105
witness_script.write(writer)?;
106106
to_self_delay.write(writer)?;
107107
output.write(writer)?;
@@ -126,7 +126,7 @@ impl Readable for SpendableOutputDescriptor {
126126
}),
127127
1u8 => Ok(SpendableOutputDescriptor::DynamicOutputP2WSH {
128128
outpoint: Readable::read(reader)?,
129-
key: Readable::read(reader)?,
129+
per_commitment_point: Readable::read(reader)?,
130130
witness_script: Readable::read(reader)?,
131131
to_self_delay: Readable::read(reader)?,
132132
output: Readable::read(reader)?,
@@ -239,6 +239,9 @@ pub trait ChannelKeys : Send+Clone {
239239
/// chosen to forgo their output as dust.
240240
fn sign_closing_transaction<T: secp256k1::Signing>(&self, closing_tx: &Transaction, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()>;
241241

242+
/// Create a signature for a delayed transaction.
243+
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>);
244+
242245
/// Signs a channel announcement message with our funding key, proving it comes from one
243246
/// of the channel participants.
244247
///
@@ -469,6 +472,18 @@ impl ChannelKeys for InMemoryChannelKeys {
469472
Ok(secp_ctx.sign(&sighash, &self.funding_key))
470473
}
471474

475+
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>) {
476+
if let Ok(htlc_key) = chan_utils::derive_private_key(&secp_ctx, &per_commitment_point, &self.delayed_payment_base_key) {
477+
let sighash_parts = bip143::SighashComponents::new(&spend_tx);
478+
let sighash = hash_to_message!(&sighash_parts.sighash_all(&spend_tx.input[input], witness_script, amount)[..]);
479+
let local_delaysig = secp_ctx.sign(&sighash, &htlc_key);
480+
spend_tx.input[0].witness.push(local_delaysig.serialize_der().to_vec());
481+
spend_tx.input[0].witness[0].push(SigHashType::All as u8);
482+
spend_tx.input[0].witness.push(vec!(0));
483+
spend_tx.input[0].witness.push(witness_script.clone().into_bytes());
484+
}
485+
}
486+
472487
fn sign_channel_announcement<T: secp256k1::Signing>(&self, msg: &msgs::UnsignedChannelAnnouncement, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()> {
473488
let msghash = hash_to_message!(&Sha256dHash::hash(&msg.encode()[..])[..]);
474489
Ok(secp_ctx.sign(&msghash, &self.funding_key))

lightning/src/ln/channelmonitor.rs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -722,7 +722,7 @@ pub struct ChannelMonitor<ChanSigner: ChannelKeys> {
722722
commitment_transaction_number_obscure_factor: u64,
723723

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

@@ -1644,14 +1644,12 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
16441644
(claimable_outpoints, Some((htlc_txid, tx.output.clone())))
16451645
}
16461646

1647-
fn broadcast_by_local_state(&self, commitment_tx: &Transaction, local_tx: &LocalSignedTx) -> (Vec<ClaimRequest>, Vec<TxOut>, Option<(Script, SecretKey, Script)>) {
1647+
fn broadcast_by_local_state(&self, commitment_tx: &Transaction, local_tx: &LocalSignedTx) -> (Vec<ClaimRequest>, Vec<TxOut>, Option<(Script, PublicKey, Script)>) {
16481648
let mut claim_requests = Vec::with_capacity(local_tx.htlc_outputs.len());
16491649
let mut watch_outputs = Vec::with_capacity(local_tx.htlc_outputs.len());
16501650

16511651
let redeemscript = chan_utils::get_revokeable_redeemscript(&local_tx.revocation_key, self.their_to_self_delay.unwrap(), &local_tx.delayed_payment_key);
1652-
let broadcasted_local_revokable_script = if let Ok(local_delayedkey) = chan_utils::derive_private_key(&self.secp_ctx, &local_tx.per_commitment_point, self.onchain_detection.keys.delayed_payment_base_key()) {
1653-
Some((redeemscript.to_v0_p2wsh(), local_delayedkey, redeemscript))
1654-
} else { None };
1652+
let broadcasted_local_revokable_script = Some((redeemscript.to_v0_p2wsh(), local_tx.per_commitment_point.clone(), redeemscript));
16551653

16561654
for &(ref htlc, _, _) in local_tx.htlc_outputs.iter() {
16571655
if let Some(transaction_output_index) = htlc.transaction_output_index {
@@ -2126,7 +2124,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
21262124
if broadcasted_local_revokable_script.0 == outp.script_pubkey {
21272125
spendable_output = Some(SpendableOutputDescriptor::DynamicOutputP2WSH {
21282126
outpoint: BitcoinOutPoint { txid: tx.txid(), vout: i as u32 },
2129-
key: broadcasted_local_revokable_script.1,
2127+
per_commitment_point: broadcasted_local_revokable_script.1,
21302128
witness_script: broadcasted_local_revokable_script.2.clone(),
21312129
to_self_delay: self.their_to_self_delay.unwrap(),
21322130
output: outp.clone(),
@@ -2190,9 +2188,9 @@ impl<ChanSigner: ChannelKeys + Readable> ReadableArgs<Arc<Logger>> for (Sha256dH
21902188
let broadcasted_local_revokable_script = match <u8 as Readable>::read(reader)? {
21912189
0 => {
21922190
let revokable_address = Readable::read(reader)?;
2193-
let local_delayedkey = Readable::read(reader)?;
2191+
let per_commitment_point = Readable::read(reader)?;
21942192
let revokable_script = Readable::read(reader)?;
2195-
Some((revokable_address, local_delayedkey, revokable_script))
2193+
Some((revokable_address, per_commitment_point, revokable_script))
21962194
},
21972195
1 => { None },
21982196
_ => return Err(DecodeError::InvalidValue),

lightning/src/ln/functional_tests.rs

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3934,7 +3934,7 @@ fn test_manager_serialize_deserialize_inconsistent_monitor() {
39343934
}
39353935

39363936
macro_rules! check_spendable_outputs {
3937-
($node: expr, $der_idx: expr) => {
3937+
($node: expr, $der_idx: expr, $chan_signer: expr) => {
39383938
{
39393939
let events = $node.chan_monitor.simple_monitor.get_and_clear_pending_events();
39403940
let mut txn = Vec::new();
@@ -3970,7 +3970,7 @@ macro_rules! check_spendable_outputs {
39703970
spend_tx.input[0].witness.push(remotepubkey.serialize().to_vec());
39713971
txn.push(spend_tx);
39723972
},
3973-
SpendableOutputDescriptor::DynamicOutputP2WSH { ref outpoint, ref key, ref witness_script, ref to_self_delay, ref output } => {
3973+
SpendableOutputDescriptor::DynamicOutputP2WSH { ref outpoint, ref per_commitment_point, ref witness_script, ref to_self_delay, ref output } => {
39743974
let input = TxIn {
39753975
previous_output: outpoint.clone(),
39763976
script_sig: Script::new(),
@@ -3988,12 +3988,7 @@ macro_rules! check_spendable_outputs {
39883988
output: vec![outp],
39893989
};
39903990
let secp_ctx = Secp256k1::new();
3991-
let sighash = Message::from_slice(&bip143::SighashComponents::new(&spend_tx).sighash_all(&spend_tx.input[0], witness_script, output.value)[..]).unwrap();
3992-
let local_delaysig = secp_ctx.sign(&sighash, key);
3993-
spend_tx.input[0].witness.push(local_delaysig.serialize_der().to_vec());
3994-
spend_tx.input[0].witness[0].push(SigHashType::All as u8);
3995-
spend_tx.input[0].witness.push(vec!(0));
3996-
spend_tx.input[0].witness.push(witness_script.clone().into_bytes());
3991+
$chan_signer.sign_delayed_transaction(&mut spend_tx, 0, &witness_script, output.value, per_commitment_point, &secp_ctx);
39973992
txn.push(spend_tx);
39983993
},
39993994
SpendableOutputDescriptor::StaticOutput { ref outpoint, ref output } => {
@@ -4066,7 +4061,8 @@ fn test_claim_sizeable_push_msat() {
40664061
nodes[1].block_notifier.block_connected(&Block { header, txdata: vec![node_txn[0].clone()] }, 0);
40674062
connect_blocks(&nodes[1].block_notifier, ANTI_REORG_DELAY - 1, 1, true, header.bitcoin_hash());
40684063

4069-
let spend_txn = check_spendable_outputs!(nodes[1], 1);
4064+
let chan_signer = get_chan_signer!(nodes[1], chan.2);
4065+
let spend_txn = check_spendable_outputs!(nodes[1], 1, chan_signer);
40704066
assert_eq!(spend_txn.len(), 1);
40714067
check_spends!(spend_txn[0], node_txn[0]);
40724068
}
@@ -4096,7 +4092,8 @@ fn test_claim_on_remote_sizeable_push_msat() {
40964092
check_added_monitors!(nodes[1], 1);
40974093
connect_blocks(&nodes[1].block_notifier, ANTI_REORG_DELAY - 1, 1, true, header.bitcoin_hash());
40984094

4099-
let spend_txn = check_spendable_outputs!(nodes[1], 1);
4095+
let chan_signer = get_chan_signer!(nodes[1], chan.2);
4096+
let spend_txn = check_spendable_outputs!(nodes[1], 1, chan_signer);
41004097
assert_eq!(spend_txn.len(), 2);
41014098
assert_eq!(spend_txn[0], spend_txn[1]);
41024099
check_spends!(spend_txn[0], node_txn[0]);
@@ -4129,7 +4126,8 @@ fn test_claim_on_remote_revoked_sizeable_push_msat() {
41294126
nodes[1].block_notifier.block_connected(&Block { header: header_1, txdata: vec![node_txn[0].clone()] }, 1);
41304127
connect_blocks(&nodes[1].block_notifier, ANTI_REORG_DELAY - 1, 1, true, header.bitcoin_hash());
41314128

4132-
let spend_txn = check_spendable_outputs!(nodes[1], 1);
4129+
let chan_signer = get_chan_signer!(nodes[1], chan.2);
4130+
let spend_txn = check_spendable_outputs!(nodes[1], 1, chan_signer);
41334131
assert_eq!(spend_txn.len(), 3);
41344132
assert_eq!(spend_txn[0], spend_txn[1]); // to_remote output on revoked remote commitment_tx
41354133
check_spends!(spend_txn[0], revoked_local_txn[0]);
@@ -4180,7 +4178,8 @@ fn test_static_spendable_outputs_preimage_tx() {
41804178
nodes[1].block_notifier.block_connected(&Block { header: header_1, txdata: vec![node_txn[0].clone()] }, 1);
41814179
connect_blocks(&nodes[1].block_notifier, ANTI_REORG_DELAY - 1, 1, true, header.bitcoin_hash());
41824180

4183-
let spend_txn = check_spendable_outputs!(nodes[1], 1);
4181+
let chan_signer = get_chan_signer!(nodes[1], chan_1.2);
4182+
let spend_txn = check_spendable_outputs!(nodes[1], 1, chan_signer);
41844183
assert_eq!(spend_txn.len(), 1);
41854184
check_spends!(spend_txn[0], node_txn[0]);
41864185
}
@@ -4234,7 +4233,8 @@ fn test_static_spendable_outputs_timeout_tx() {
42344233
_ => panic!("Unexpected event"),
42354234
}
42364235

4237-
let spend_txn = check_spendable_outputs!(nodes[1], 1);
4236+
let chan_signer = get_chan_signer!(nodes[1], chan_1.2);
4237+
let spend_txn = check_spendable_outputs!(nodes[1], 1, chan_signer);
42384238
assert_eq!(spend_txn.len(), 3); // SpendableOutput: remote_commitment_tx.to_remote (*2), timeout_tx.output (*1)
42394239
check_spends!(spend_txn[2], node_txn[0].clone());
42404240
}
@@ -4270,7 +4270,8 @@ fn test_static_spendable_outputs_justice_tx_revoked_commitment_tx() {
42704270
nodes[1].block_notifier.block_connected(&Block { header: header_1, txdata: vec![node_txn[0].clone()] }, 1);
42714271
connect_blocks(&nodes[1].block_notifier, ANTI_REORG_DELAY - 1, 1, true, header.bitcoin_hash());
42724272

4273-
let spend_txn = check_spendable_outputs!(nodes[1], 1);
4273+
let chan_signer = get_chan_signer!(nodes[1], chan_1.2);
4274+
let spend_txn = check_spendable_outputs!(nodes[1], 1, chan_signer);
42744275
assert_eq!(spend_txn.len(), 1);
42754276
check_spends!(spend_txn[0], node_txn[0]);
42764277
}
@@ -4325,7 +4326,8 @@ fn test_static_spendable_outputs_justice_tx_revoked_htlc_timeout_tx() {
43254326
connect_blocks(&nodes[1].block_notifier, ANTI_REORG_DELAY - 1, 1, true, header.bitcoin_hash());
43264327

43274328
// Check B's ChannelMonitor was able to generate the right spendable output descriptor
4328-
let spend_txn = check_spendable_outputs!(nodes[1], 1);
4329+
let chan_signer = get_chan_signer!(nodes[1], chan_1.2);
4330+
let spend_txn = check_spendable_outputs!(nodes[1], 1, chan_signer);
43294331
assert_eq!(spend_txn.len(), 2);
43304332
check_spends!(spend_txn[0], node_txn[0]);
43314333
check_spends!(spend_txn[1], node_txn[2]);
@@ -4375,7 +4377,8 @@ fn test_static_spendable_outputs_justice_tx_revoked_htlc_success_tx() {
43754377
connect_blocks(&nodes[0].block_notifier, ANTI_REORG_DELAY - 1, 1, true, header.bitcoin_hash());
43764378

43774379
// Check A's ChannelMonitor was able to generate the right spendable output descriptor
4378-
let spend_txn = check_spendable_outputs!(nodes[0], 1);
4380+
let chan_signer = get_chan_signer!(nodes[0], chan_1.2);
4381+
let spend_txn = check_spendable_outputs!(nodes[0], 1, chan_signer);
43794382
assert_eq!(spend_txn.len(), 5); // Duplicated SpendableOutput due to block rescan after revoked htlc output tracking
43804383
assert_eq!(spend_txn[0], spend_txn[1]);
43814384
assert_eq!(spend_txn[0], spend_txn[2]);
@@ -4651,7 +4654,8 @@ fn test_dynamic_spendable_outputs_local_htlc_success_tx() {
46514654
connect_blocks(&nodes[1].block_notifier, ANTI_REORG_DELAY - 1, 201, true, header_201.bitcoin_hash());
46524655

46534656
// Verify that B is able to spend its own HTLC-Success tx thanks to spendable output event given back by its ChannelMonitor
4654-
let spend_txn = check_spendable_outputs!(nodes[1], 1);
4657+
let chan_signer = get_chan_signer!(nodes[1], chan_1.2);
4658+
let spend_txn = check_spendable_outputs!(nodes[1], 1, chan_signer);
46554659
assert_eq!(spend_txn.len(), 2);
46564660
check_spends!(spend_txn[0], node_txn[0]);
46574661
check_spends!(spend_txn[1], node_txn[1]);
@@ -4952,7 +4956,8 @@ fn test_dynamic_spendable_outputs_local_htlc_timeout_tx() {
49524956
}
49534957

49544958
// Verify that A is able to spend its own HTLC-Timeout tx thanks to spendable output event given back by its ChannelMonitor
4955-
let spend_txn = check_spendable_outputs!(nodes[0], 1);
4959+
let chan_signer = get_chan_signer!(nodes[0], chan_1.2);
4960+
let spend_txn = check_spendable_outputs!(nodes[0], 1, chan_signer);
49564961
assert_eq!(spend_txn.len(), 3);
49574962
assert_eq!(spend_txn[0], spend_txn[1]);
49584963
check_spends!(spend_txn[0], local_txn[0]);
@@ -4975,14 +4980,16 @@ fn test_static_output_closing_tx() {
49754980
nodes[0].block_notifier.block_connected(&Block { header, txdata: vec![closing_tx.clone()] }, 0);
49764981
connect_blocks(&nodes[0].block_notifier, ANTI_REORG_DELAY - 1, 0, true, header.bitcoin_hash());
49774982

4978-
let spend_txn = check_spendable_outputs!(nodes[0], 2);
4983+
let chan_signer = get_chan_signer!(nodes[0], chan.2);
4984+
let spend_txn = check_spendable_outputs!(nodes[0], 2, chan_signer);
49794985
assert_eq!(spend_txn.len(), 1);
49804986
check_spends!(spend_txn[0], closing_tx);
49814987

49824988
nodes[1].block_notifier.block_connected(&Block { header, txdata: vec![closing_tx.clone()] }, 0);
49834989
connect_blocks(&nodes[1].block_notifier, ANTI_REORG_DELAY - 1, 0, true, header.bitcoin_hash());
49844990

4985-
let spend_txn = check_spendable_outputs!(nodes[1], 2);
4991+
let chan_signer = get_chan_signer!(nodes[1], chan.2);
4992+
let spend_txn = check_spendable_outputs!(nodes[1], 2, chan_signer);
49864993
assert_eq!(spend_txn.len(), 1);
49874994
check_spends!(spend_txn[0], closing_tx);
49884995
}
@@ -6835,7 +6842,8 @@ fn test_data_loss_protect() {
68356842
let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42};
68366843
nodes[0].block_notifier.block_connected(&Block { header, txdata: vec![node_txn[0].clone()]}, 0);
68376844
connect_blocks(&nodes[0].block_notifier, ANTI_REORG_DELAY - 1, 0, true, header.bitcoin_hash());
6838-
let spend_txn = check_spendable_outputs!(nodes[0], 1);
6845+
let chan_signer = get_chan_signer!(nodes[0], chan.2);
6846+
let spend_txn = check_spendable_outputs!(nodes[0], 1, chan_signer);
68396847
assert_eq!(spend_txn.len(), 1);
68406848
check_spends!(spend_txn[0], node_txn[0]);
68416849
}

lightning/src/util/enforcing_trait_impls.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,10 @@ impl ChannelKeys for EnforcingChannelKeys {
9797
self.inner.sign_remote_htlc_transaction(bumped_tx, input, witness_script, amount, per_commitment_point, preimage, secp_ctx);
9898
}
9999

100+
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>) {
101+
self.inner.sign_delayed_transaction(spend_tx, input, witness_script, amount, per_commitment_point, secp_ctx);
102+
}
103+
100104
fn sign_closing_transaction<T: secp256k1::Signing>(&self, closing_tx: &Transaction, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()> {
101105
Ok(self.inner.sign_closing_transaction(closing_tx, secp_ctx).unwrap())
102106
}

0 commit comments

Comments
 (0)