Skip to content

Commit 1a44317

Browse files
author
Antoine Riard
committed
Remove signing local commitment transaction from ChannelMonitor
1 parent 09fae43 commit 1a44317

File tree

5 files changed

+51
-22
lines changed

5 files changed

+51
-22
lines changed

lightning/src/chain/keysinterface.rs

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//! spendable on-chain outputs which the user owns and is responsible for using just as any other
33
//! on-chain output which is theirs.
44
5-
use bitcoin::blockdata::transaction::{Transaction, OutPoint, TxOut};
5+
use bitcoin::blockdata::transaction::{Transaction, OutPoint, TxOut, SigHashType};
66
use bitcoin::blockdata::script::{Script, Builder};
77
use bitcoin::blockdata::opcodes;
88
use bitcoin::network::constants::Network;
@@ -215,6 +215,13 @@ pub trait ChannelKeys : Send+Clone {
215215
/// making the callee generate it via some util function we expose)!
216216
fn sign_remote_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, feerate_per_kw: u64, commitment_tx: &Transaction, keys: &TxCreationKeys, htlcs: &[&HTLCOutputInCommitment], to_self_delay: u16, secp_ctx: &Secp256k1<T>) -> Result<(Signature, Vec<Signature>), ()>;
217217

218+
/// Create a signature for a local commitment transaction
219+
///
220+
/// TODO: Document the things someone using this interface should enforce before signing.
221+
/// TODO: Add more input vars to enable better checking (preferably removing commitment_tx and
222+
/// making the callee generate it via some util function we expose)!
223+
fn sign_local_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, local_commitment_tx: &mut Transaction, funding_redeemscript: &Script, channel_value_satoshis: u64, secp_ctx: &Secp256k1<T>);
224+
218225
/// Create a signature for a (proposed) closing transaction.
219226
///
220227
/// Note that, due to rounding, there may be one "missing" satoshi, and either party may have
@@ -342,6 +349,35 @@ impl ChannelKeys for InMemoryChannelKeys {
342349
Ok((commitment_sig, htlc_sigs))
343350
}
344351

352+
fn sign_local_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, local_commitment_tx: &mut Transaction, funding_redeemscript: &Script, channel_value_satoshis: u64, secp_ctx: &Secp256k1<T>) {
353+
if local_commitment_tx.input.len() != 1 { panic!("Commitment transactions must have input count == 1!"); }
354+
let has_local_sig = if local_commitment_tx.input[0].witness.len() == 4 {
355+
assert!(!local_commitment_tx.input[0].witness[1].is_empty());
356+
assert!(!local_commitment_tx.input[0].witness[2].is_empty());
357+
true
358+
} else {
359+
assert_eq!(local_commitment_tx.input[0].witness.len(), 3);
360+
assert!(local_commitment_tx.input[0].witness[0].is_empty());
361+
assert!(local_commitment_tx.input[0].witness[1].is_empty() || local_commitment_tx.input[0].witness[2].is_empty());
362+
false
363+
};
364+
if has_local_sig { return; }
365+
366+
let sighash = hash_to_message!(&bip143::SighashComponents::new(&local_commitment_tx)
367+
.sighash_all(&local_commitment_tx.input[0], funding_redeemscript, channel_value_satoshis)[..]);
368+
let our_sig = secp_ctx.sign(&sighash, &self.funding_key);
369+
370+
if local_commitment_tx.input[0].witness[1].is_empty() {
371+
local_commitment_tx.input[0].witness[1] = our_sig.serialize_der().to_vec();
372+
local_commitment_tx.input[0].witness[1].push(SigHashType::All as u8);
373+
} else {
374+
local_commitment_tx.input[0].witness[2] = our_sig.serialize_der().to_vec();
375+
local_commitment_tx.input[0].witness[2].push(SigHashType::All as u8);
376+
}
377+
378+
local_commitment_tx.input[0].witness.push(funding_redeemscript.as_bytes().to_vec());
379+
}
380+
345381
fn sign_closing_transaction<T: secp256k1::Signing>(&self, closing_tx: &Transaction, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()> {
346382
if closing_tx.input.len() != 1 { return Err(()); }
347383
if closing_tx.input[0].witness.len() != 0 { return Err(()); }

lightning/src/ln/chan_utils.rs

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,10 @@ impl LocalCommitmentTransaction {
553553
self.tx.txid()
554554
}
555555

556+
pub fn tx(&mut self) -> &mut Transaction {
557+
&mut self.tx
558+
}
559+
556560
pub fn has_local_sig(&self) -> bool {
557561
if self.tx.input.len() != 1 { panic!("Commitment transactions must have input count == 1!"); }
558562
if self.tx.input[0].witness.len() == 4 {
@@ -567,23 +571,6 @@ impl LocalCommitmentTransaction {
567571
}
568572
}
569573

570-
pub fn add_local_sig<T: secp256k1::Signing>(&mut self, funding_key: &SecretKey, funding_redeemscript: &Script, channel_value_satoshis: u64, secp_ctx: &Secp256k1<T>) {
571-
if self.has_local_sig() { return; }
572-
let sighash = hash_to_message!(&bip143::SighashComponents::new(&self.tx)
573-
.sighash_all(&self.tx.input[0], funding_redeemscript, channel_value_satoshis)[..]);
574-
let our_sig = secp_ctx.sign(&sighash, funding_key);
575-
576-
if self.tx.input[0].witness[1].is_empty() {
577-
self.tx.input[0].witness[1] = our_sig.serialize_der().to_vec();
578-
self.tx.input[0].witness[1].push(SigHashType::All as u8);
579-
} else {
580-
self.tx.input[0].witness[2] = our_sig.serialize_der().to_vec();
581-
self.tx.input[0].witness[2].push(SigHashType::All as u8);
582-
}
583-
584-
self.tx.input[0].witness.push(funding_redeemscript.as_bytes().to_vec());
585-
}
586-
587574
pub fn without_valid_witness(&self) -> &Transaction { &self.tx }
588575
pub fn with_valid_witness(&self) -> &Transaction {
589576
assert!(self.has_local_sig());

lightning/src/ln/channel.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4433,7 +4433,7 @@ mod tests {
44334433

44344434
assert_eq!(PublicKey::from_secret_key(&secp_ctx, chan_keys.funding_key()).serialize()[..],
44354435
hex::decode("023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb").unwrap()[..]);
4436-
let keys_provider = Keys { chan_keys };
4436+
let keys_provider = Keys { chan_keys: chan_keys.clone() };
44374437

44384438
let their_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
44394439
let mut config = UserConfig::default();
@@ -4490,7 +4490,7 @@ mod tests {
44904490
secp_ctx.verify(&sighash, &their_signature, chan.their_funding_pubkey()).unwrap();
44914491

44924492
let mut localtx = LocalCommitmentTransaction::new_missing_local_sig(unsigned_tx.0.clone(), &their_signature, &PublicKey::from_secret_key(&secp_ctx, chan.local_keys.funding_key()), chan.their_funding_pubkey());
4493-
localtx.add_local_sig(chan.local_keys.funding_key(), &redeemscript, chan.channel_value_satoshis, &chan.secp_ctx);
4493+
chan_keys.sign_local_commitment(localtx.tx(), &redeemscript, chan.channel_value_satoshis, &chan.secp_ctx);
44944494

44954495
assert_eq!(serialize(localtx.with_valid_witness())[..],
44964496
hex::decode($tx_hex).unwrap()[..]);

lightning/src/ln/channelmonitor.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1825,7 +1825,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
18251825
// tracking state and panic!()ing if we get an update after force-closure/local-tx signing.
18261826
log_trace!(self, "Getting signed latest local commitment transaction!");
18271827
if let &mut Some(ref mut local_tx) = &mut self.current_local_signed_commitment_tx {
1828-
local_tx.tx.add_local_sig(&self.onchain_detection.funding_key, self.funding_redeemscript.as_ref().unwrap(), self.channel_value_satoshis.unwrap(), &self.secp_ctx);
1828+
self.onchain_detection.keys.sign_local_commitment(local_tx.tx.tx(), self.funding_redeemscript.as_ref().unwrap(), self.channel_value_satoshis.unwrap(), &self.secp_ctx);
18291829
}
18301830
if let &Some(ref local_tx) = &self.current_local_signed_commitment_tx {
18311831
let mut res = vec![local_tx.tx.with_valid_witness().clone()];
@@ -1907,7 +1907,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
19071907
} else { false };
19081908
if let Some(ref mut cur_local_tx) = self.current_local_signed_commitment_tx {
19091909
if should_broadcast {
1910-
cur_local_tx.tx.add_local_sig(&self.onchain_detection.funding_key, self.funding_redeemscript.as_ref().unwrap(), self.channel_value_satoshis.unwrap(), &self.secp_ctx);
1910+
self.onchain_detection.keys.sign_local_commitment(cur_local_tx.tx.tx(), self.funding_redeemscript.as_ref().unwrap(), self.channel_value_satoshis.unwrap(), &mut self.secp_ctx);
19111911
}
19121912
}
19131913
if let Some(ref cur_local_tx) = self.current_local_signed_commitment_tx {

lightning/src/util/enforcing_trait_impls.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ use std::cmp;
66
use std::sync::{Mutex, Arc};
77

88
use bitcoin::blockdata::transaction::Transaction;
9+
use bitcoin::blockdata::script::Script;
10+
911

1012
use secp256k1;
1113
use secp256k1::key::{SecretKey, PublicKey};
@@ -78,6 +80,10 @@ impl ChannelKeys for EnforcingChannelKeys {
7880
Ok(self.inner.sign_remote_commitment(feerate_per_kw, commitment_tx, keys, htlcs, to_self_delay, secp_ctx).unwrap())
7981
}
8082

83+
fn sign_local_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, local_commitment_tx: &mut Transaction, funding_redeemscript: &Script, channel_value_satoshis: u64, secp_ctx: &Secp256k1<T>) {
84+
self.inner.sign_local_commitment(local_commitment_tx, funding_redeemscript, channel_value_satoshis, secp_ctx)
85+
}
86+
8187
fn sign_closing_transaction<T: secp256k1::Signing>(&self, closing_tx: &Transaction, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()> {
8288
Ok(self.inner.sign_closing_transaction(closing_tx, secp_ctx).unwrap())
8389
}

0 commit comments

Comments
 (0)