Skip to content

Commit 5b24d3e

Browse files
authored
Merge pull request #597 from TheBlueMatt/2020-04-more-chanmon-cleanups
Few more ChannelMonitor Cleanups
2 parents 99a34e1 + 80055d4 commit 5b24d3e

12 files changed

+531
-708
lines changed

fuzz/src/chanmon_deser.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,6 @@ pub fn do_test(data: &[u8]) {
3232
let deserialized_copy = <(Sha256dHash, channelmonitor::ChannelMonitor<EnforcingChannelKeys>)>::read(&mut Cursor::new(&w.0), logger.clone()).unwrap();
3333
assert!(latest_block_hash == deserialized_copy.0);
3434
assert!(monitor == deserialized_copy.1);
35-
w.0.clear();
36-
monitor.write_for_watchtower(&mut w).unwrap();
3735
}
3836
}
3937

lightning/src/chain/keysinterface.rs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -222,15 +222,15 @@ pub trait ChannelKeys : Send+Clone {
222222
/// TODO: Add more input vars to enable better checking (preferably removing commitment_tx and
223223
/// TODO: Ensure test-only version doesn't enforce uniqueness of signature when it's enforced in this method
224224
/// making the callee generate it via some util function we expose)!
225-
fn sign_local_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, local_commitment_tx: &mut LocalCommitmentTransaction, funding_redeemscript: &Script, channel_value_satoshis: u64, secp_ctx: &Secp256k1<T>);
225+
fn sign_local_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, local_commitment_tx: &mut LocalCommitmentTransaction, secp_ctx: &Secp256k1<T>);
226226

227227
/// Create a signature for a local commitment transaction without enforcing one-time signing.
228228
///
229229
/// Testing revocation logic by our test framework needs to sign multiple local commitment
230230
/// transactions. This unsafe test-only version doesn't enforce one-time signing security
231231
/// requirement.
232232
#[cfg(test)]
233-
fn unsafe_sign_local_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, local_commitment_tx: &mut LocalCommitmentTransaction, funding_redeemscript: &Script, channel_value_satoshis: u64, secp_ctx: &Secp256k1<T>);
233+
fn unsafe_sign_local_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, local_commitment_tx: &mut LocalCommitmentTransaction, secp_ctx: &Secp256k1<T>);
234234

235235
/// Signs a transaction created by build_htlc_transaction. If the transaction is an
236236
/// HTLC-Success transaction, preimage must be set!
@@ -363,13 +363,21 @@ impl ChannelKeys for InMemoryChannelKeys {
363363
Ok((commitment_sig, htlc_sigs))
364364
}
365365

366-
fn sign_local_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, local_commitment_tx: &mut LocalCommitmentTransaction, funding_redeemscript: &Script, channel_value_satoshis: u64, secp_ctx: &Secp256k1<T>) {
367-
local_commitment_tx.add_local_sig(&self.funding_key, funding_redeemscript, channel_value_satoshis, secp_ctx);
366+
fn sign_local_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, local_commitment_tx: &mut LocalCommitmentTransaction, secp_ctx: &Secp256k1<T>) {
367+
let funding_pubkey = PublicKey::from_secret_key(secp_ctx, &self.funding_key);
368+
let remote_channel_pubkeys = self.remote_channel_pubkeys.as_ref().expect("must set remote channel pubkeys before signing");
369+
let channel_funding_redeemscript = make_funding_redeemscript(&funding_pubkey, &remote_channel_pubkeys.funding_pubkey);
370+
371+
local_commitment_tx.add_local_sig(&self.funding_key, &channel_funding_redeemscript, self.channel_value_satoshis, secp_ctx);
368372
}
369373

370374
#[cfg(test)]
371-
fn unsafe_sign_local_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, local_commitment_tx: &mut LocalCommitmentTransaction, funding_redeemscript: &Script, channel_value_satoshis: u64, secp_ctx: &Secp256k1<T>) {
372-
local_commitment_tx.add_local_sig(&self.funding_key, funding_redeemscript, channel_value_satoshis, secp_ctx);
375+
fn unsafe_sign_local_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, local_commitment_tx: &mut LocalCommitmentTransaction, secp_ctx: &Secp256k1<T>) {
376+
let funding_pubkey = PublicKey::from_secret_key(secp_ctx, &self.funding_key);
377+
let remote_channel_pubkeys = self.remote_channel_pubkeys.as_ref().expect("must set remote channel pubkeys before signing");
378+
let channel_funding_redeemscript = make_funding_redeemscript(&funding_pubkey, &remote_channel_pubkeys.funding_pubkey);
379+
380+
local_commitment_tx.add_local_sig(&self.funding_key, &channel_funding_redeemscript, self.channel_value_satoshis, secp_ctx);
373381
}
374382

375383
fn sign_htlc_transaction<T: secp256k1::Signing>(&self, local_commitment_tx: &mut LocalCommitmentTransaction, htlc_index: u32, preimage: Option<PaymentPreimage>, local_csv: u16, secp_ctx: &Secp256k1<T>) {

lightning/src/ln/chan_utils.rs

Lines changed: 28 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -485,9 +485,8 @@ pub fn build_htlc_transaction(prev_hash: &Sha256dHash, feerate_per_kw: u64, to_s
485485
/// just pass in the SecretKeys required.
486486
pub struct LocalCommitmentTransaction {
487487
tx: Transaction,
488-
//TODO: modify Channel methods to integrate HTLC material at LocalCommitmentTransaction generation to drop Option here
489-
local_keys: Option<TxCreationKeys>,
490-
feerate_per_kw: Option<u64>,
488+
pub(crate) local_keys: TxCreationKeys,
489+
pub(crate) feerate_per_kw: u64,
491490
per_htlc: Vec<(HTLCOutputInCommitment, Option<Signature>, Option<Transaction>)>
492491
}
493492
impl LocalCommitmentTransaction {
@@ -502,21 +501,30 @@ impl LocalCommitmentTransaction {
502501
sequence: 0,
503502
witness: vec![vec![], vec![], vec![]]
504503
};
505-
Self { tx: Transaction {
506-
version: 2,
507-
input: vec![dummy_input],
508-
output: Vec::new(),
509-
lock_time: 0,
510-
},
511-
local_keys: None,
512-
feerate_per_kw: None,
504+
let dummy_key = PublicKey::from_secret_key(&Secp256k1::new(), &SecretKey::from_slice(&[42; 32]).unwrap());
505+
Self {
506+
tx: Transaction {
507+
version: 2,
508+
input: vec![dummy_input],
509+
output: Vec::new(),
510+
lock_time: 0,
511+
},
512+
local_keys: TxCreationKeys {
513+
per_commitment_point: dummy_key.clone(),
514+
revocation_key: dummy_key.clone(),
515+
a_htlc_key: dummy_key.clone(),
516+
b_htlc_key: dummy_key.clone(),
517+
a_delayed_payment_key: dummy_key.clone(),
518+
b_payment_key: dummy_key.clone(),
519+
},
520+
feerate_per_kw: 0,
513521
per_htlc: Vec::new()
514522
}
515523
}
516524

517525
/// Generate a new LocalCommitmentTransaction based on a raw commitment transaction,
518526
/// remote signature and both parties keys
519-
pub(crate) fn new_missing_local_sig(mut tx: Transaction, their_sig: &Signature, our_funding_key: &PublicKey, their_funding_key: &PublicKey) -> LocalCommitmentTransaction {
527+
pub(crate) fn new_missing_local_sig(mut tx: Transaction, their_sig: &Signature, our_funding_key: &PublicKey, their_funding_key: &PublicKey, local_keys: TxCreationKeys, feerate_per_kw: u64, mut htlc_data: Vec<(HTLCOutputInCommitment, Option<Signature>)>) -> LocalCommitmentTransaction {
520528
if tx.input.len() != 1 { panic!("Tried to store a commitment transaction that had input count != 1!"); }
521529
if tx.input[0].witness.len() != 0 { panic!("Tried to store a signed commitment transaction?"); }
522530

@@ -533,9 +541,10 @@ impl LocalCommitmentTransaction {
533541
}
534542

535543
Self { tx,
536-
local_keys: None,
537-
feerate_per_kw: None,
538-
per_htlc: Vec::new()
544+
local_keys,
545+
feerate_per_kw,
546+
// TODO: Avoid the conversion of a Vec created likely just for this:
547+
per_htlc: htlc_data.drain(..).map(|(a, b)| (a, b, None)).collect(),
539548
}
540549
}
541550

@@ -594,33 +603,23 @@ impl LocalCommitmentTransaction {
594603
&self.tx
595604
}
596605

597-
/// Set HTLC cache to generate any local HTLC transaction spending one of htlc ouput
598-
/// from this local commitment transaction
599-
pub(crate) fn set_htlc_cache(&mut self, local_keys: TxCreationKeys, feerate_per_kw: u64, htlc_outputs: Vec<(HTLCOutputInCommitment, Option<Signature>, Option<Transaction>)>) {
600-
self.local_keys = Some(local_keys);
601-
self.feerate_per_kw = Some(feerate_per_kw);
602-
self.per_htlc = htlc_outputs;
603-
}
604-
605606
/// Add local signature for a htlc transaction, do nothing if a cached signed transaction is
606607
/// already present
607608
pub fn add_htlc_sig<T: secp256k1::Signing>(&mut self, htlc_base_key: &SecretKey, htlc_index: u32, preimage: Option<PaymentPreimage>, local_csv: u16, secp_ctx: &Secp256k1<T>) {
608-
if self.local_keys.is_none() || self.feerate_per_kw.is_none() { return; }
609-
let local_keys = self.local_keys.as_ref().unwrap();
610609
let txid = self.txid();
611610
for this_htlc in self.per_htlc.iter_mut() {
612-
if this_htlc.0.transaction_output_index.unwrap() == htlc_index {
611+
if this_htlc.0.transaction_output_index == Some(htlc_index) {
613612
if this_htlc.2.is_some() { return; } // we already have a cached htlc transaction at provided index
614-
let mut htlc_tx = build_htlc_transaction(&txid, self.feerate_per_kw.unwrap(), local_csv, &this_htlc.0, &local_keys.a_delayed_payment_key, &local_keys.revocation_key);
613+
let mut htlc_tx = build_htlc_transaction(&txid, self.feerate_per_kw, local_csv, &this_htlc.0, &self.local_keys.a_delayed_payment_key, &self.local_keys.revocation_key);
615614
if !this_htlc.0.offered && preimage.is_none() { return; } // if we don't have preimage for HTLC-Success, don't try to generate
616615
let htlc_secret = if !this_htlc.0.offered { preimage } else { None }; // if we have a preimage for HTLC-Timeout, don't use it that's likely a duplicate HTLC hash
617616
if this_htlc.1.is_none() { return; } // we don't have any remote signature for this htlc
618617
if htlc_tx.input.len() != 1 { return; }
619618
if htlc_tx.input[0].witness.len() != 0 { return; }
620619

621-
let htlc_redeemscript = get_htlc_redeemscript_with_explicit_keys(&this_htlc.0, &local_keys.a_htlc_key, &local_keys.b_htlc_key, &local_keys.revocation_key);
620+
let htlc_redeemscript = get_htlc_redeemscript_with_explicit_keys(&this_htlc.0, &self.local_keys.a_htlc_key, &self.local_keys.b_htlc_key, &self.local_keys.revocation_key);
622621

623-
if let Ok(our_htlc_key) = derive_private_key(secp_ctx, &local_keys.per_commitment_point, htlc_base_key) {
622+
if let Ok(our_htlc_key) = derive_private_key(secp_ctx, &self.local_keys.per_commitment_point, htlc_base_key) {
624623
let sighash = hash_to_message!(&bip143::SighashComponents::new(&htlc_tx).sighash_all(&htlc_tx.input[0], &htlc_redeemscript, this_htlc.0.amount_msat / 1000)[..]);
625624
let our_sig = secp_ctx.sign(&sighash, &our_htlc_key);
626625

lightning/src/ln/chanmon_update_fail_tests.rs

Lines changed: 14 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1629,12 +1629,9 @@ fn monitor_update_claim_fail_no_response() {
16291629
claim_payment(&nodes[0], &[&nodes[1]], payment_preimage_2, 1_000_000);
16301630
}
16311631

1632-
// Note that restore_between_fails with !fail_on_generate is useless
1633-
// Also note that !fail_on_generate && !fail_on_signed is useless
1634-
// Finally, note that !fail_on_signed is not possible with fail_on_generate && !restore_between_fails
16351632
// confirm_a_first and restore_b_before_conf are wholly unrelated to earlier bools and
16361633
// restore_b_before_conf has no meaning if !confirm_a_first
1637-
fn do_during_funding_monitor_fail(fail_on_generate: bool, restore_between_fails: bool, fail_on_signed: bool, confirm_a_first: bool, restore_b_before_conf: bool) {
1634+
fn do_during_funding_monitor_fail(confirm_a_first: bool, restore_b_before_conf: bool) {
16381635
// Test that if the monitor update generated by funding_transaction_generated fails we continue
16391636
// the channel setup happily after the update is restored.
16401637
let chanmon_cfgs = create_chanmon_cfgs(2);
@@ -1648,52 +1645,25 @@ fn do_during_funding_monitor_fail(fail_on_generate: bool, restore_between_fails:
16481645

16491646
let (temporary_channel_id, funding_tx, funding_output) = create_funding_transaction(&nodes[0], 100000, 43);
16501647

1651-
if fail_on_generate {
1652-
*nodes[0].chan_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure);
1653-
}
16541648
nodes[0].node.funding_transaction_generated(&temporary_channel_id, funding_output);
1655-
check_added_monitors!(nodes[0], 1);
1649+
check_added_monitors!(nodes[0], 0);
16561650

16571651
*nodes[1].chan_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure);
16581652
let funding_created_msg = get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id());
16591653
let channel_id = OutPoint { txid: funding_created_msg.funding_txid, index: funding_created_msg.funding_output_index }.to_channel_id();
16601654
nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &funding_created_msg);
16611655
check_added_monitors!(nodes[1], 1);
16621656

1663-
if restore_between_fails {
1664-
assert!(fail_on_generate);
1665-
*nodes[0].chan_monitor.update_ret.lock().unwrap() = Ok(());
1666-
let (outpoint, latest_update) = nodes[0].chan_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone();
1667-
nodes[0].node.channel_monitor_updated(&outpoint, latest_update);
1668-
check_added_monitors!(nodes[0], 0);
1669-
assert!(nodes[0].node.get_and_clear_pending_events().is_empty());
1670-
assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
1671-
}
1672-
1673-
if fail_on_signed {
1674-
*nodes[0].chan_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure);
1675-
} else {
1676-
assert!(restore_between_fails || !fail_on_generate); // We can't switch to good now (there's no monitor update)
1677-
assert!(fail_on_generate); // Somebody has to fail
1678-
}
1657+
*nodes[0].chan_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure);
16791658
nodes[0].node.handle_funding_signed(&nodes[1].node.get_our_node_id(), &get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, nodes[0].node.get_our_node_id()));
1680-
if fail_on_signed || !restore_between_fails {
1681-
assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
1682-
if fail_on_generate && !restore_between_fails {
1683-
nodes[0].logger.assert_log("lightning::ln::channelmanager".to_string(), "Previous monitor update failure prevented funding_signed from allowing funding broadcast".to_string(), 1);
1684-
check_added_monitors!(nodes[0], 1);
1685-
} else {
1686-
nodes[0].logger.assert_log("lightning::ln::channelmanager".to_string(), "Failed to update ChannelMonitor".to_string(), 1);
1687-
check_added_monitors!(nodes[0], 1);
1688-
}
1689-
assert!(nodes[0].node.get_and_clear_pending_events().is_empty());
1690-
*nodes[0].chan_monitor.update_ret.lock().unwrap() = Ok(());
1691-
let (outpoint, latest_update) = nodes[0].chan_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone();
1692-
nodes[0].node.channel_monitor_updated(&outpoint, latest_update);
1693-
check_added_monitors!(nodes[0], 0);
1694-
} else {
1695-
check_added_monitors!(nodes[0], 1);
1696-
}
1659+
assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
1660+
nodes[0].logger.assert_log("lightning::ln::channelmanager".to_string(), "Failed to update ChannelMonitor".to_string(), 1);
1661+
check_added_monitors!(nodes[0], 1);
1662+
assert!(nodes[0].node.get_and_clear_pending_events().is_empty());
1663+
*nodes[0].chan_monitor.update_ret.lock().unwrap() = Ok(());
1664+
let (outpoint, latest_update) = nodes[0].chan_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone();
1665+
nodes[0].node.channel_monitor_updated(&outpoint, latest_update);
1666+
check_added_monitors!(nodes[0], 0);
16971667

16981668
let events = nodes[0].node.get_and_clear_pending_events();
16991669
assert_eq!(events.len(), 1);
@@ -1757,8 +1727,7 @@ fn do_during_funding_monitor_fail(fail_on_generate: bool, restore_between_fails:
17571727

17581728
#[test]
17591729
fn during_funding_monitor_fail() {
1760-
do_during_funding_monitor_fail(false, false, true, true, true);
1761-
do_during_funding_monitor_fail(true, false, true, false, false);
1762-
do_during_funding_monitor_fail(true, true, true, true, false);
1763-
do_during_funding_monitor_fail(true, true, false, false, false);
1730+
do_during_funding_monitor_fail(true, true);
1731+
do_during_funding_monitor_fail(true, false);
1732+
do_during_funding_monitor_fail(false, false);
17641733
}

0 commit comments

Comments
 (0)