From e9cd26ddeb6dae146c904dc04516b238a99fc21b Mon Sep 17 00:00:00 2001 From: Antoine Riard Date: Thu, 31 Jan 2019 20:59:00 -0500 Subject: [PATCH 1/6] Track HTLC-failure trigger tx until anti-reorg delay reached Broadcasting a commitment tx means that we have to fail inbound HTLC in backward channel. Doing it prematurely would put us at risk in case of reorg. So we delay passing failure update upstream until solving tx mature to HTLC_FAIL_ANTI_ REORG_DELAY. Requirements differ if HTLC is a revoked/non-revoked dust/ non-revoked non-dust one. Add connect_blocks in test_utils to fix broken tests due to anti-reorg delay enforcement Remove anti-duplicate htlc update stuff in ManySimpleChannelMonitor --- src/ln/channelmonitor.rs | 117 ++++++++++++++++++++------------ src/ln/functional_test_utils.rs | 10 +++ src/ln/functional_tests.rs | 13 +++- 3 files changed, 94 insertions(+), 46 deletions(-) diff --git a/src/ln/channelmonitor.rs b/src/ln/channelmonitor.rs index 25f41d88296..931718986d1 100644 --- a/src/ln/channelmonitor.rs +++ b/src/ln/channelmonitor.rs @@ -174,25 +174,7 @@ impl ChainListener for SimpleManyChannelMonit for htlc in htlc_updated_infos.drain(..) { match pending_htlc_updated.entry(htlc.2) { hash_map::Entry::Occupied(mut e) => { - // In case of reorg we may have htlc outputs solved in a different way so - // we prefer to keep claims but don't store duplicate updates for a given - // (payment_hash, HTLCSource) pair. - // TODO: Note that we currently don't really use this as ChannelManager - // will fail/claim backwards after the first block. We really should delay - // a few blocks before failing backwards (but can claim backwards - // immediately) as long as we have a few blocks of headroom. - let mut existing_claim = false; - e.get_mut().retain(|htlc_data| { - if htlc.0 == htlc_data.0 { - if htlc_data.1.is_some() { - existing_claim = true; - true - } else { false } - } else { true } - }); - if !existing_claim { - e.get_mut().push((htlc.0, htlc.1)); - } + e.get_mut().push((htlc.0, htlc.1)); } hash_map::Entry::Vacant(e) => { e.insert(vec![(htlc.0, htlc.1)]); @@ -304,7 +286,6 @@ pub(crate) const HTLC_FAIL_TIMEOUT_BLOCKS: u32 = 3; /// Number of blocks we wait on seeing a confirmed HTLC-Timeout or previous revoked commitment /// transaction before we fail corresponding inbound HTLCs. This prevents us from failing backwards /// and then getting a reorg resulting in us losing money. -//TODO: We currently don't actually use this...we should pub(crate) const HTLC_FAIL_ANTI_REORG_DELAY: u32 = 6; #[derive(Clone, PartialEq)] @@ -390,6 +371,8 @@ pub struct ChannelMonitor { destination_script: Script, + htlc_updated_waiting_threshold_conf: HashMap, PaymentHash)>>, + // We simply modify last_block_hash in Channel's block_connected so that serialization is // consistent but hopefully the users' copy handles block_connected in a consistent way. // (we do *not*, however, update them in insert_combine to ensure any local user copies keep @@ -419,7 +402,8 @@ impl PartialEq for ChannelMonitor { self.current_remote_commitment_number != other.current_remote_commitment_number || self.current_local_signed_commitment_tx != other.current_local_signed_commitment_tx || self.payment_preimages != other.payment_preimages || - self.destination_script != other.destination_script + self.destination_script != other.destination_script || + self.htlc_updated_waiting_threshold_conf != other.htlc_updated_waiting_threshold_conf { false } else { @@ -469,6 +453,8 @@ impl ChannelMonitor { payment_preimages: HashMap::new(), destination_script: destination_script, + htlc_updated_waiting_threshold_conf: HashMap::new(), + last_block_hash: Default::default(), secp_ctx: Secp256k1::new(), logger, @@ -956,6 +942,17 @@ impl ChannelMonitor { self.last_block_hash.write(writer)?; self.destination_script.write(writer)?; + writer.write_all(&byte_utils::be64_to_array(self.htlc_updated_waiting_threshold_conf.len() as u64))?; + for (ref target, ref updates) in self.htlc_updated_waiting_threshold_conf.iter() { + writer.write_all(&byte_utils::be32_to_array(**target))?; + writer.write_all(&byte_utils::be64_to_array(updates.len() as u64))?; + for ref update in updates.iter() { + update.0.write(writer)?; + update.1.write(writer)?; + update.2.write(writer)?; + } + } + Ok(()) } @@ -1019,13 +1016,12 @@ impl ChannelMonitor { /// HTLC-Success/HTLC-Timeout transactions. /// Return updates for HTLC pending in the channel and failed automatically by the broadcast of /// revoked remote commitment tx - fn check_spend_remote_transaction(&mut self, tx: &Transaction, height: u32) -> (Vec, (Sha256dHash, Vec), Vec, Vec<(HTLCSource, Option, PaymentHash)>) { + fn check_spend_remote_transaction(&mut self, tx: &Transaction, height: u32) -> (Vec, (Sha256dHash, Vec), Vec) { // Most secp and related errors trying to create keys means we have no hope of constructing // a spend transaction...so we return no transactions to broadcast let mut txn_to_broadcast = Vec::new(); let mut watch_outputs = Vec::new(); let mut spendable_outputs = Vec::new(); - let mut htlc_updated = Vec::new(); let commitment_txid = tx.txid(); //TODO: This is gonna be a performance bottleneck for watchtowers! let per_commitment_option = self.remote_claimable_outpoints.get(&commitment_txid); @@ -1034,7 +1030,7 @@ impl ChannelMonitor { ( $thing : expr ) => { match $thing { Ok(a) => a, - Err(_) => return (txn_to_broadcast, (commitment_txid, watch_outputs), spendable_outputs, htlc_updated) + Err(_) => return (txn_to_broadcast, (commitment_txid, watch_outputs), spendable_outputs) } }; } @@ -1059,7 +1055,7 @@ impl ChannelMonitor { }; 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())); let a_htlc_key = match self.their_htlc_base_key { - None => return (txn_to_broadcast, (commitment_txid, watch_outputs), spendable_outputs, htlc_updated), + None => return (txn_to_broadcast, (commitment_txid, watch_outputs), spendable_outputs), Some(their_htlc_base_key) => ignore_error!(chan_utils::derive_public_key(&self.secp_ctx, &PublicKey::from_secret_key(&self.secp_ctx, &per_commitment_key), &their_htlc_base_key)), }; @@ -1139,7 +1135,7 @@ impl ChannelMonitor { if transaction_output_index as usize >= tx.output.len() || tx.output[transaction_output_index as usize].value != htlc.amount_msat / 1000 || tx.output[transaction_output_index as usize].script_pubkey != expected_script.to_v0_p2wsh() { - return (txn_to_broadcast, (commitment_txid, watch_outputs), spendable_outputs, htlc_updated); // Corrupted per_commitment_data, fuck this user + return (txn_to_broadcast, (commitment_txid, watch_outputs), spendable_outputs); // Corrupted per_commitment_data, fuck this user } let input = TxIn { previous_output: BitcoinOutPoint { @@ -1179,16 +1175,22 @@ impl ChannelMonitor { watch_outputs.append(&mut tx.output.clone()); self.remote_commitment_txn_on_chain.insert(commitment_txid, (commitment_number, tx.output.iter().map(|output| { output.script_pubkey.clone() }).collect())); - // TODO: We really should only fail backwards after our revocation claims have been - // confirmed, but we also need to do more other tracking of in-flight pre-confirm - // on-chain claims, so we can do that at the same time. macro_rules! check_htlc_fails { ($txid: expr, $commitment_tx: expr) => { if let Some(ref outpoints) = self.remote_claimable_outpoints.get($txid) { for &(ref htlc, ref source_option) in outpoints.iter() { if let &Some(ref source) = source_option { - log_trace!(self, "Failing HTLC with payment_hash {} from {} remote commitment tx due to broadcast of revoked remote commitment transaction", log_bytes!(htlc.payment_hash.0), $commitment_tx); - htlc_updated.push(((**source).clone(), None, htlc.payment_hash.clone())); + log_trace!(self, "Failing HTLC with payment_hash {} from {} remote commitment tx due to broadcast of revoked remote commitment transaction, waiting confirmation until {} height", log_bytes!(htlc.payment_hash.0), $commitment_tx, height + HTLC_FAIL_ANTI_REORG_DELAY - 1); + match self.htlc_updated_waiting_threshold_conf.entry(height + HTLC_FAIL_ANTI_REORG_DELAY - 1) { + hash_map::Entry::Occupied(mut entry) => { + let e = entry.get_mut(); + e.retain(|ref update| update.0 != **source); + e.push(((**source).clone(), None, htlc.payment_hash.clone())); + } + hash_map::Entry::Vacant(entry) => { + entry.insert(vec![((**source).clone(), None, htlc.payment_hash.clone())]); + } + } } } } @@ -1204,7 +1206,7 @@ impl ChannelMonitor { } // No need to check local commitment txn, symmetric HTLCSource must be present as per-htlc data on remote commitment tx } - if inputs.is_empty() { return (txn_to_broadcast, (commitment_txid, watch_outputs), spendable_outputs, htlc_updated); } // Nothing to be done...probably a false positive/local tx + if inputs.is_empty() { return (txn_to_broadcast, (commitment_txid, watch_outputs), spendable_outputs); } // Nothing to be done...probably a false positive/local tx let outputs = vec!(TxOut { script_pubkey: self.destination_script.clone(), @@ -1243,9 +1245,6 @@ impl ChannelMonitor { log_trace!(self, "Got broadcast of non-revoked remote commitment transaction {}", commitment_txid); - // TODO: We really should only fail backwards after our revocation claims have been - // confirmed, but we also need to do more other tracking of in-flight pre-confirm - // on-chain claims, so we can do that at the same time. macro_rules! check_htlc_fails { ($txid: expr, $commitment_tx: expr, $id: tt) => { if let Some(ref latest_outpoints) = self.remote_claimable_outpoints.get($txid) { @@ -1266,7 +1265,16 @@ impl ChannelMonitor { } } log_trace!(self, "Failing HTLC with payment_hash {} from {} remote commitment tx due to broadcast of remote commitment transaction", log_bytes!(htlc.payment_hash.0), $commitment_tx); - htlc_updated.push(((**source).clone(), None, htlc.payment_hash.clone())); + match self.htlc_updated_waiting_threshold_conf.entry(height + HTLC_FAIL_ANTI_REORG_DELAY - 1) { + hash_map::Entry::Occupied(mut entry) => { + let e = entry.get_mut(); + e.retain(|ref update| update.0 != **source); + e.push(((**source).clone(), None, htlc.payment_hash.clone())); + } + hash_map::Entry::Vacant(entry) => { + entry.insert(vec![((**source).clone(), None, htlc.payment_hash.clone())]); + } + } } } } @@ -1299,7 +1307,7 @@ impl ChannelMonitor { }, }; let a_htlc_key = match self.their_htlc_base_key { - None => return (txn_to_broadcast, (commitment_txid, watch_outputs), spendable_outputs, htlc_updated), + None => return (txn_to_broadcast, (commitment_txid, watch_outputs), spendable_outputs), Some(their_htlc_base_key) => ignore_error!(chan_utils::derive_public_key(&self.secp_ctx, revocation_point, &their_htlc_base_key)), }; @@ -1354,7 +1362,7 @@ impl ChannelMonitor { if transaction_output_index as usize >= tx.output.len() || tx.output[transaction_output_index as usize].value != htlc.amount_msat / 1000 || tx.output[transaction_output_index as usize].script_pubkey != expected_script.to_v0_p2wsh() { - return (txn_to_broadcast, (commitment_txid, watch_outputs), spendable_outputs, htlc_updated); // Corrupted per_commitment_data, fuck this user + return (txn_to_broadcast, (commitment_txid, watch_outputs), spendable_outputs); // Corrupted per_commitment_data, fuck this user } if let Some(payment_preimage) = self.payment_preimages.get(&htlc.payment_hash) { let input = TxIn { @@ -1417,7 +1425,7 @@ impl ChannelMonitor { } } - if inputs.is_empty() { return (txn_to_broadcast, (commitment_txid, watch_outputs), spendable_outputs, htlc_updated); } // Nothing to be done...probably a false positive/local tx + if inputs.is_empty() { return (txn_to_broadcast, (commitment_txid, watch_outputs), spendable_outputs); } // Nothing to be done...probably a false positive/local tx let outputs = vec!(TxOut { script_pubkey: self.destination_script.clone(), @@ -1447,7 +1455,7 @@ impl ChannelMonitor { } } - (txn_to_broadcast, (commitment_txid, watch_outputs), spendable_outputs, htlc_updated) + (txn_to_broadcast, (commitment_txid, watch_outputs), spendable_outputs) } /// Attempts to claim a remote HTLC-Success/HTLC-Timeout's outputs using the revocation key @@ -1719,7 +1727,7 @@ impl ChannelMonitor { } }; if funding_txo.is_none() || (prevout.txid == funding_txo.as_ref().unwrap().0.txid && prevout.vout == funding_txo.as_ref().unwrap().0.index as u32) { - let (remote_txn, new_outputs, mut spendable_output, mut updated) = self.check_spend_remote_transaction(tx, height); + let (remote_txn, new_outputs, mut spendable_output) = self.check_spend_remote_transaction(tx, height); txn = remote_txn; spendable_outputs.append(&mut spendable_output); if !new_outputs.1.is_empty() { @@ -1738,9 +1746,6 @@ impl ChannelMonitor { spendable_outputs.push(spendable_output); } } - if updated.len() > 0 { - htlc_updated.append(&mut updated); - } } else { if let Some(&(commitment_number, _)) = self.remote_commitment_txn_on_chain.get(&prevout.txid) { let (tx, spendable_output) = self.check_spend_remote_htlc(tx, commitment_number); @@ -1791,6 +1796,12 @@ impl ChannelMonitor { } } } + if let Some(updates) = self.htlc_updated_waiting_threshold_conf.remove(&height) { + for update in updates { + log_trace!(self, "HTLC {} failure update has get enough confirmation to be pass upstream", log_bytes!((update.2).0)); + htlc_updated.push(update); + } + } self.last_block_hash = block_hash.clone(); (watch_outputs, spendable_outputs, htlc_updated) } @@ -2191,6 +2202,21 @@ impl ReadableArgs> for (Sha256dHash, ChannelM let last_block_hash: Sha256dHash = Readable::read(reader)?; let destination_script = Readable::read(reader)?; + let waiting_threshold_conf_len: u64 = Readable::read(reader)?; + let mut htlc_updated_waiting_threshold_conf = HashMap::with_capacity(cmp::min(waiting_threshold_conf_len as usize, MAX_ALLOC_SIZE / 128)); + for _ in 0..waiting_threshold_conf_len { + let height_target = Readable::read(reader)?; + let updates_len: u64 = Readable::read(reader)?; + let mut updates = Vec::with_capacity(cmp::min(updates_len as usize, MAX_ALLOC_SIZE / 128)); + for _ in 0..updates_len { + let htlc_source = Readable::read(reader)?; + let preimage = Readable::read(reader)?; + let hash = Readable::read(reader)?; + updates.push((htlc_source, preimage, hash)); + } + htlc_updated_waiting_threshold_conf.insert(height_target, updates); + } + Ok((last_block_hash.clone(), ChannelMonitor { commitment_transaction_number_obscure_factor, @@ -2214,6 +2240,9 @@ impl ReadableArgs> for (Sha256dHash, ChannelM payment_preimages, destination_script, + + htlc_updated_waiting_threshold_conf, + last_block_hash, secp_ctx, logger, diff --git a/src/ln/functional_test_utils.rs b/src/ln/functional_test_utils.rs index 387c83761a6..ef247ae921f 100644 --- a/src/ln/functional_test_utils.rs +++ b/src/ln/functional_test_utils.rs @@ -20,6 +20,7 @@ use bitcoin::blockdata::transaction::{Transaction, TxOut}; use bitcoin::network::constants::Network; use bitcoin_hashes::sha256::Hash as Sha256; +use bitcoin_hashes::sha256d::Hash as Sha256d; use bitcoin_hashes::Hash; use secp256k1::Secp256k1; @@ -46,6 +47,15 @@ pub fn confirm_transaction(chain: &chaininterface::ChainWatchInterfaceUtil, tx: } } +pub fn connect_blocks(chain: &chaininterface::ChainWatchInterfaceUtil, depth: u32, height: u32, parent: bool, prev_blockhash: Sha256d) { + let mut header = BlockHeader { version: 0x2000000, prev_blockhash: if parent { prev_blockhash } else { Default::default() }, merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; + chain.block_connected_checked(&header, height + 1, &Vec::new(), &Vec::new()); + for i in 2..depth { + header = BlockHeader { version: 0x20000000, prev_blockhash: header.bitcoin_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; + chain.block_connected_checked(&header, height + i, &Vec::new(), &Vec::new()); + } +} + pub struct Node { pub chain_monitor: Arc, pub tx_broadcaster: Arc, diff --git a/src/ln/functional_tests.rs b/src/ln/functional_tests.rs index 0e82b4e696b..dd3ab6ca3c9 100644 --- a/src/ln/functional_tests.rs +++ b/src/ln/functional_tests.rs @@ -8,7 +8,7 @@ use chain::keysinterface::{KeysInterface, SpendableOutputDescriptor}; use chain::keysinterface; use ln::channel::{COMMITMENT_TX_BASE_WEIGHT, COMMITMENT_TX_WEIGHT_PER_HTLC, BREAKDOWN_TIMEOUT}; use ln::channelmanager::{ChannelManager,ChannelManagerReadArgs,HTLCForwardInfo,RAACommitmentOrder, PaymentPreimage, PaymentHash}; -use ln::channelmonitor::{ChannelMonitor, CLTV_CLAIM_BUFFER, HTLC_FAIL_TIMEOUT_BLOCKS, ManyChannelMonitor}; +use ln::channelmonitor::{ChannelMonitor, CLTV_CLAIM_BUFFER, HTLC_FAIL_TIMEOUT_BLOCKS, ManyChannelMonitor, HTLC_FAIL_ANTI_REORG_DELAY}; use ln::channel::{ACCEPTED_HTLC_SCRIPT_WEIGHT, OFFERED_HTLC_SCRIPT_WEIGHT}; use ln::onion_utils; use ln::router::{Route, RouteHop}; @@ -1871,6 +1871,7 @@ fn claim_htlc_outputs_shared_tx() { let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; nodes[0].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1); nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1); + connect_blocks(&nodes[1].chain_monitor, HTLC_FAIL_ANTI_REORG_DELAY, 1, true, header.bitcoin_hash()); let events = nodes[1].node.get_and_clear_pending_events(); assert_eq!(events.len(), 1); @@ -1938,6 +1939,7 @@ fn claim_htlc_outputs_single_tx() { let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; nodes[0].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 200); nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 200); + connect_blocks(&nodes[1].chain_monitor, HTLC_FAIL_ANTI_REORG_DELAY, 200, true, header.bitcoin_hash()); let events = nodes[1].node.get_and_clear_pending_events(); assert_eq!(events.len(), 1); @@ -1949,7 +1951,7 @@ fn claim_htlc_outputs_single_tx() { } let node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap(); - assert_eq!(node_txn.len(), 12); // ChannelManager : 2, ChannelMontitor: 8 (1 standard revoked output, 2 revocation htlc tx, 1 local commitment tx + 1 htlc timeout tx) * 2 (block-rescan) + assert_eq!(node_txn.len(), 22); // ChannelManager : 2, ChannelMontitor: 8 (1 standard revoked output, 2 revocation htlc tx, 1 local commitment tx + 1 htlc timeout tx) * 2 (block-rescan) + 5 * (1 local commitment tx + 1 htlc timeout tx) assert_eq!(node_txn[0], node_txn[7]); assert_eq!(node_txn[1], node_txn[8]); @@ -1959,6 +1961,10 @@ fn claim_htlc_outputs_single_tx() { assert_eq!(node_txn[3], node_txn[5]); //local commitment tx + htlc timeout tx broadcasted by ChannelManger assert_eq!(node_txn[4], node_txn[6]); + for i in 12..22 { + if i % 2 == 0 { assert_eq!(node_txn[3], node_txn[i]); } else { assert_eq!(node_txn[4], node_txn[i]); } + } + assert_eq!(node_txn[0].input.len(), 1); assert_eq!(node_txn[1].input.len(), 1); assert_eq!(node_txn[2].input.len(), 1); @@ -2293,6 +2299,7 @@ fn test_simple_commitment_revoked_fail_backward() { let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42}; nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1); + connect_blocks(&nodes[1].chain_monitor, HTLC_FAIL_ANTI_REORG_DELAY, 1, true, header.bitcoin_hash()); check_added_monitors!(nodes[1], 0); check_closed_broadcast!(nodes[1]); @@ -2445,6 +2452,7 @@ fn do_test_commitment_revoked_fail_backward_exhaustive(deliver_bs_raa: bool, use let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42}; nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1); + connect_blocks(&nodes[1].chain_monitor, HTLC_FAIL_ANTI_REORG_DELAY, 1, true, header.bitcoin_hash()); let events = nodes[1].node.get_and_clear_pending_events(); assert_eq!(events.len(), if deliver_bs_raa { 1 } else { 2 }); @@ -4106,6 +4114,7 @@ fn do_test_fail_backwards_unrevoked_remote_announce(deliver_last_raa: bool, anno } else { nodes[2].chain_monitor.block_connected_checked(&header, 1, &[&ds_prev_commitment_tx[0]], &[1; 1]); } + connect_blocks(&nodes[2].chain_monitor, HTLC_FAIL_ANTI_REORG_DELAY, 1, true, header.bitcoin_hash()); check_closed_broadcast!(nodes[2]); expect_pending_htlcs_forwardable!(nodes[2]); check_added_monitors!(nodes[2], 2); From 1ff9395dabef950fcea8482f0b2a0871a42c8082 Mon Sep 17 00:00:00 2001 From: Antoine Riard Date: Mon, 4 Feb 2019 21:21:11 -0500 Subject: [PATCH 2/6] Implement block_disconnect for pruning of waiting-conf HTLC updates Modify ChainListener API by adding height field to block_disconnect --- fuzz/fuzz_targets/full_stack_target.rs | 4 ++-- src/chain/chaininterface.rs | 10 +++++++--- src/ln/channelmanager.rs | 2 +- src/ln/channelmonitor.rs | 15 ++++++++++++++- src/ln/functional_tests.rs | 4 +++- 5 files changed, 27 insertions(+), 8 deletions(-) diff --git a/fuzz/fuzz_targets/full_stack_target.rs b/fuzz/fuzz_targets/full_stack_target.rs index 937c735064b..4a5bc315d6c 100644 --- a/fuzz/fuzz_targets/full_stack_target.rs +++ b/fuzz/fuzz_targets/full_stack_target.rs @@ -209,8 +209,8 @@ impl<'a> MoneyLossDetector<'a> { if self.height > 0 && (self.max_height < 6 || self.height >= self.max_height - 6) { self.height -= 1; let header = BlockHeader { version: 0x20000000, prev_blockhash: self.header_hashes[self.height], merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; - self.manager.block_disconnected(&header); - self.monitor.block_disconnected(&header); + self.manager.block_disconnected(&header, self.height as u32); + self.monitor.block_disconnected(&header, self.height as u32); let removal_height = self.height; self.txids_confirmed.retain(|_, height| { removal_height != *height diff --git a/src/chain/chaininterface.rs b/src/chain/chaininterface.rs index d1995b44221..3e77c0ce2b6 100644 --- a/src/chain/chaininterface.rs +++ b/src/chain/chaininterface.rs @@ -78,7 +78,11 @@ pub trait ChainListener: Sync + Send { fn block_connected(&self, header: &BlockHeader, height: u32, txn_matched: &[&Transaction], indexes_of_txn_matched: &[u32]); /// Notifies a listener that a block was disconnected. /// Unlike block_connected, this *must* never be called twice for the same disconnect event. - fn block_disconnected(&self, header: &BlockHeader); + /// + /// Provide listeners with filtered txn previously registered as watched because channels are + /// driven by onchain events (tx broadcast, height), a cancel of one of them may conduct to + /// rollback state (ChannelMonitor or Channel). + fn block_disconnected(&self, header: &BlockHeader, height: u32); } /// An enum that represents the speed at which we want a transaction to confirm used for feerate @@ -279,11 +283,11 @@ impl ChainWatchInterfaceUtil { } /// Notify listeners that a block was disconnected. - pub fn block_disconnected(&self, header: &BlockHeader) { + pub fn block_disconnected(&self, block: &Block, height: u32) { let listeners = self.listeners.lock().unwrap().clone(); for listener in listeners.iter() { match listener.upgrade() { - Some(arc) => arc.block_disconnected(header), + Some(arc) => arc.block_disconnected(&block.header, height), None => () } } diff --git a/src/ln/channelmanager.rs b/src/ln/channelmanager.rs index e3de3c09e43..398f719bae4 100644 --- a/src/ln/channelmanager.rs +++ b/src/ln/channelmanager.rs @@ -2474,7 +2474,7 @@ impl ChainListener for ChannelManager { } /// We force-close the channel without letting our counterparty participate in the shutdown - fn block_disconnected(&self, header: &BlockHeader) { + fn block_disconnected(&self, header: &BlockHeader, _: u32) { let _ = self.total_consistency_lock.read().unwrap(); let mut failed_channels = Vec::new(); { diff --git a/src/ln/channelmonitor.rs b/src/ln/channelmonitor.rs index 931718986d1..7483a8bf540 100644 --- a/src/ln/channelmonitor.rs +++ b/src/ln/channelmonitor.rs @@ -186,7 +186,13 @@ impl ChainListener for SimpleManyChannelMonit pending_events.append(&mut new_events); } - fn block_disconnected(&self, _: &BlockHeader) { } + fn block_disconnected(&self, header: &BlockHeader, height: u32) { + let block_hash = header.bitcoin_hash(); + let mut monitors = self.monitors.lock().unwrap(); + for monitor in monitors.values_mut() { + monitor.block_disconnected(height, &block_hash); + } + } } impl SimpleManyChannelMonitor { @@ -1806,6 +1812,13 @@ impl ChannelMonitor { (watch_outputs, spendable_outputs, htlc_updated) } + fn block_disconnected(&mut self, height: u32, block_hash: &Sha256dHash) { + if let Some(_) = self.htlc_updated_waiting_threshold_conf.remove(&(height + HTLC_FAIL_ANTI_REORG_DELAY - 1)) { + //We discard htlc update there as failure-trigger tx (revoked commitment tx, non-revoked commitment tx, HTLC-timeout tx) has been disconnected + } + self.last_block_hash = block_hash.clone(); + } + pub(super) fn would_broadcast_at_height(&self, height: u32) -> bool { // We need to consider all HTLCs which are: // * in any unrevoked remote commitment transaction, as they could broadcast said diff --git a/src/ln/functional_tests.rs b/src/ln/functional_tests.rs index dd3ab6ca3c9..ff10840a473 100644 --- a/src/ln/functional_tests.rs +++ b/src/ln/functional_tests.rs @@ -2674,8 +2674,10 @@ fn test_unconf_chan() { header = BlockHeader { version: 0x20000000, prev_blockhash: header.bitcoin_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; headers.push(header.clone()); } + let mut height = 99; while !headers.is_empty() { - nodes[0].node.block_disconnected(&headers.pop().unwrap()); + nodes[0].node.block_disconnected(&headers.pop().unwrap(), height); + height -= 1; } check_closed_broadcast!(nodes[0]); let channel_state = nodes[0].node.channel_state.lock().unwrap(); From 44bbd4cac452414c206b4a0417655d766cf9fdfa Mon Sep 17 00:00:00 2001 From: Antoine Riard Date: Wed, 6 Feb 2019 20:02:38 -0500 Subject: [PATCH 3/6] Delay failure of non-dust HTLC-outputs until solving timeout tx matures Fix tests broken by introduced change --- fuzz/fuzz_targets/full_stack_target.rs | 9 +++++++-- src/ln/channelmonitor.rs | 16 +++++++++++++--- src/ln/functional_tests.rs | 2 ++ 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/fuzz/fuzz_targets/full_stack_target.rs b/fuzz/fuzz_targets/full_stack_target.rs index 4a5bc315d6c..7022a739b1d 100644 --- a/fuzz/fuzz_targets/full_stack_target.rs +++ b/fuzz/fuzz_targets/full_stack_target.rs @@ -881,13 +881,18 @@ mod tests { // 02000000013f00000000000000000000000000000000000000000000000000000000000000000000000000000080020001000000000000220020e2000000000000000000000000000000000000000000000000000000000000006cc10000000000001600142e0000000000000000000000000000000000000005000020 - the commitment transaction for channel 3f00000000000000000000000000000000000000000000000000000000000000 // 00fd - A feerate request (returning min feerate, which our open_channel also uses) (gonna be ingested by FuzzEstimator) // 0c005e - connect a block with one transaction of len 94 - // 0200000001fb00000000000000000000000000000000000000000000000000000000000000000000000000000000014f00000000000000220020f60000000000000000000000000000000000000000000000000000000000000000000000 - the commitment transaction for channel 3d00000000000000000000000000000000000000000000000000000000000000 + // 0200000001fb00000000000000000000000000000000000000000000000000000000000000000000000000000000014f00000000000000220020f60000000000000000000000000000000000000000000000000000000000000000000000 - the funding transaction + // 0c0000 - connect a block with no transactions + // 0c0000 - connect a block with no transactions + // 0c0000 - connect a block with no transactions + // 0c0000 - connect a block with no transactions + // 0c0000 - connect a block with no transactions // // 07 - process the now-pending HTLC forward // - client now fails the HTLC backwards as it was unable to extract the payment preimage (CHECK 9 duplicate and CHECK 10) let logger = Arc::new(TrackingLogger { lines: Mutex::new(HashMap::new()) }); - super::do_test(&::hex::decode("00000000000000000000000000000000000000000000000000000000000000000000000001000300000000000000000000000000000000000000000000000000000000000000000300320003000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000030012000603000000000000000000000000000000030016001000000000030000000000000000000000000000000300120141030000000000000000000000000000000300fe00207500000000000000000000000000000000000000000000000000000000000000ff4f00f805273c1b203bb5ebf8436bfde57b3be8c2f5e95d9491dbb181909679000000000000c35000000000000000000000000000000222ffffffffffffffff00000000000002220000000000000000000000fd000601e3030000000000000000000000000000000000000000000000000000000000000001030000000000000000000000000000000000000000000000000000000000000002030000000000000000000000000000000000000000000000000000000000000003030000000000000000000000000000000000000000000000000000000000000004030053030000000000000000000000000000000000000000000000000000000000000005030000000000000000000000000000000000000000000000000000000000000000010300000000000000000000000000000000fd00fd00fd0300120084030000000000000000000000000000000300940022ff4f00f805273c1b203bb5ebf8436bfde57b3be8c2f5e95d9491dbb1819096793d0000000000000000000000000000000000000000000000000000000000000000005c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001030000000000000000000000000000000c005e020000000100000000000000000000000000000000000000000000000000000000000000000000000000ffffffff0150c3000000000000220020ae00000000000000000000000000000000000000000000000000000000000000000000000c00000c00000c00000c00000c00000c00000c00000c00000c00000c00000c00000c000003001200430300000000000000000000000000000003005300243d000000000000000000000000000000000000000000000000000000000000000301000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001030132000300000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000003014200030200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000300000000000000000000000000000003011200060100000000000000000000000000000003011600100000000001000000000000000000000000000000050103020000000000000000000000000000000000000000000000000000000000000000c3500003e800fd00fd00fd0301120110010000000000000000000000000000000301ff00210200000000000000020000000000000002000000000000000200000000000000000000000000001a00000000004c4b4000000000000003e800000000000003e80000000203f00005030000000000000000000000000000000000000000000000000000000000000100030000000000000000000000000000000000000000000000000000000000000200030000000000000000000000000000000000000000000000000000000000000300030000000000000000000000000000000000000000000000000000000000000400030000000000000000000000000000000000000000000000000000000000000500030000000000000000000000000000000301210000000000000000000000000000000000010000000000000000000000000000000a03011200620100000000000000000000000000000003017200233f00000000000000000000000000000000000000000000000000000000000000f6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100010000000000000000000000000000000b03011200430100000000000000000000000000000003015300243f000000000000000000000000000000000000000000000000000000000000000301000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000003001205ac030000000000000000000000000000000300ff00803d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003e80ff0000000000000000000000000000000000000000000000000000000000000000000121000300000000000000000000000000000000000000000000000000000000000005550000000e000001000000000000000003e8000000010000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300c1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffef000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000fd03001200640300000000000000000000000000000003007400843d000000000000000000000000000000000000000000000000000000000000004d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000300000000000000000000000000000003001200630300000000000000000000000000000003007300853d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000703011200640100000000000000000000000000000003017400843f00000000000000000000000000000000000000000000000000000000000000f700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000100000000000000000000000000000003011200630100000000000000000000000000000003017300853f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003020000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000030112004a0100000000000000000000000000000003015a00823f000000000000000000000000000000000000000000000000000000000000000000000000000000ff008888888888888888888888888888888888888888888888888888888888880100000000000000000000000000000003011200640100000000000000000000000000000003017400843f00000000000000000000000000000000000000000000000000000000000000fb00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000100000000000000000000000000000003011200630100000000000000000000000000000003017300853f0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000303000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000003001205ac030000000000000000000000000000000300ff00803d0000000000000000000000000000000000000000000000000000000000000000000000000000010000000000003e80ff0000000000000000000000000000000000000000000000000000000000000000000121000300000000000000000000000000000000000000000000000000000000000005550000000e000001000000000000000003e8000000010000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300c1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffef000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000fd03001200630300000000000000000000000000000003007300853d0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000303000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000003001200640300000000000000000000000000000003007400843d00000000000000000000000000000000000000000000000000000000000000be00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000300000000000000000000000000000003001200630300000000000000000000000000000003007300853d000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030400000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000703011200640100000000000000000000000000000003017400843f00000000000000000000000000000000000000000000000000000000000000fa00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000100000000000000000000000000000003011200630100000000000000000000000000000003017300853f00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003040000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000030112002c0100000000000000000000000000000003013c00833f00000000000000000000000000000000000000000000000000000000000000000000000000000100000100000000000000000000000000000003011200640100000000000000000000000000000003017400843f00000000000000000000000000000000000000000000000000000000000000fd00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000100000000000000000000000000000003011200630100000000000000000000000000000003017300853f000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000030500000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000703001200630300000000000000000000000000000003007300853d0000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000305000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000003001200640300000000000000000000000000000003007400843d000000000000000000000000000000000000000000000000000000000000004f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000300000000000000000000000000000003001205ac030000000000000000000000000000000300ff00803d00000000000000000000000000000000000000000000000000000000000000000000000000000200000000000b0838ff0000000000000000000000000000000000000000000000000000000000000000000121000300000000000000000000000000000000000000000000000000000000000005550000000e0000010000000000000003e800000000010000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300c1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffef000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000fd03001200a4030000000000000000000000000000000300b400843d00000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001c8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007f000000000000000300000000000000000000000000000003001200630300000000000000000000000000000003007300853d00000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000003060000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000070c007d02000000013f00000000000000000000000000000000000000000000000000000000000000000000000000000080020001000000000000220020e2000000000000000000000000000000000000000000000000000000000000006cc10000000000001600142e000000000000000000000000000000000000000500002000fd0c005e0200000001fb00000000000000000000000000000000000000000000000000000000000000000000000000000000014f00000000000000220020f6000000000000000000000000000000000000000000000000000000000000000000000007").unwrap(), &(Arc::clone(&logger) as Arc)); + super::do_test(&::hex::decode("00000000000000000000000000000000000000000000000000000000000000000000000001000300000000000000000000000000000000000000000000000000000000000000000300320003000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000030012000603000000000000000000000000000000030016001000000000030000000000000000000000000000000300120141030000000000000000000000000000000300fe00207500000000000000000000000000000000000000000000000000000000000000ff4f00f805273c1b203bb5ebf8436bfde57b3be8c2f5e95d9491dbb181909679000000000000c35000000000000000000000000000000222ffffffffffffffff00000000000002220000000000000000000000fd000601e3030000000000000000000000000000000000000000000000000000000000000001030000000000000000000000000000000000000000000000000000000000000002030000000000000000000000000000000000000000000000000000000000000003030000000000000000000000000000000000000000000000000000000000000004030053030000000000000000000000000000000000000000000000000000000000000005030000000000000000000000000000000000000000000000000000000000000000010300000000000000000000000000000000fd00fd00fd0300120084030000000000000000000000000000000300940022ff4f00f805273c1b203bb5ebf8436bfde57b3be8c2f5e95d9491dbb1819096793d0000000000000000000000000000000000000000000000000000000000000000005c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001030000000000000000000000000000000c005e020000000100000000000000000000000000000000000000000000000000000000000000000000000000ffffffff0150c3000000000000220020ae00000000000000000000000000000000000000000000000000000000000000000000000c00000c00000c00000c00000c00000c00000c00000c00000c00000c00000c00000c000003001200430300000000000000000000000000000003005300243d000000000000000000000000000000000000000000000000000000000000000301000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001030132000300000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000003014200030200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000300000000000000000000000000000003011200060100000000000000000000000000000003011600100000000001000000000000000000000000000000050103020000000000000000000000000000000000000000000000000000000000000000c3500003e800fd00fd00fd0301120110010000000000000000000000000000000301ff00210200000000000000020000000000000002000000000000000200000000000000000000000000001a00000000004c4b4000000000000003e800000000000003e80000000203f00005030000000000000000000000000000000000000000000000000000000000000100030000000000000000000000000000000000000000000000000000000000000200030000000000000000000000000000000000000000000000000000000000000300030000000000000000000000000000000000000000000000000000000000000400030000000000000000000000000000000000000000000000000000000000000500030000000000000000000000000000000301210000000000000000000000000000000000010000000000000000000000000000000a03011200620100000000000000000000000000000003017200233f00000000000000000000000000000000000000000000000000000000000000f6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100010000000000000000000000000000000b03011200430100000000000000000000000000000003015300243f000000000000000000000000000000000000000000000000000000000000000301000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000003001205ac030000000000000000000000000000000300ff00803d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003e80ff0000000000000000000000000000000000000000000000000000000000000000000121000300000000000000000000000000000000000000000000000000000000000005550000000e000001000000000000000003e8000000010000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300c1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffef000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000fd03001200640300000000000000000000000000000003007400843d000000000000000000000000000000000000000000000000000000000000004d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000300000000000000000000000000000003001200630300000000000000000000000000000003007300853d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000703011200640100000000000000000000000000000003017400843f00000000000000000000000000000000000000000000000000000000000000f700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000100000000000000000000000000000003011200630100000000000000000000000000000003017300853f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003020000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000030112004a0100000000000000000000000000000003015a00823f000000000000000000000000000000000000000000000000000000000000000000000000000000ff008888888888888888888888888888888888888888888888888888888888880100000000000000000000000000000003011200640100000000000000000000000000000003017400843f00000000000000000000000000000000000000000000000000000000000000fb00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000100000000000000000000000000000003011200630100000000000000000000000000000003017300853f0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000303000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000003001205ac030000000000000000000000000000000300ff00803d0000000000000000000000000000000000000000000000000000000000000000000000000000010000000000003e80ff0000000000000000000000000000000000000000000000000000000000000000000121000300000000000000000000000000000000000000000000000000000000000005550000000e000001000000000000000003e8000000010000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300c1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffef000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000fd03001200630300000000000000000000000000000003007300853d0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000303000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000003001200640300000000000000000000000000000003007400843d00000000000000000000000000000000000000000000000000000000000000be00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000300000000000000000000000000000003001200630300000000000000000000000000000003007300853d000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030400000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000703011200640100000000000000000000000000000003017400843f00000000000000000000000000000000000000000000000000000000000000fa00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000100000000000000000000000000000003011200630100000000000000000000000000000003017300853f00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003040000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000030112002c0100000000000000000000000000000003013c00833f00000000000000000000000000000000000000000000000000000000000000000000000000000100000100000000000000000000000000000003011200640100000000000000000000000000000003017400843f00000000000000000000000000000000000000000000000000000000000000fd00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000100000000000000000000000000000003011200630100000000000000000000000000000003017300853f000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000030500000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000703001200630300000000000000000000000000000003007300853d0000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000305000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000003001200640300000000000000000000000000000003007400843d000000000000000000000000000000000000000000000000000000000000004f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000300000000000000000000000000000003001205ac030000000000000000000000000000000300ff00803d00000000000000000000000000000000000000000000000000000000000000000000000000000200000000000b0838ff0000000000000000000000000000000000000000000000000000000000000000000121000300000000000000000000000000000000000000000000000000000000000005550000000e0000010000000000000003e800000000010000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300c1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffef000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000fd03001200a4030000000000000000000000000000000300b400843d00000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001c8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007f000000000000000300000000000000000000000000000003001200630300000000000000000000000000000003007300853d00000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000003060000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000070c007d02000000013f00000000000000000000000000000000000000000000000000000000000000000000000000000080020001000000000000220020e2000000000000000000000000000000000000000000000000000000000000006cc10000000000001600142e000000000000000000000000000000000000000500002000fd0c005e0200000001fb00000000000000000000000000000000000000000000000000000000000000000000000000000000014f00000000000000220020f600000000000000000000000000000000000000000000000000000000000000000000000c00000c00000c00000c00000c000007").unwrap(), &(Arc::clone(&logger) as Arc)); let log_entries = logger.lines.lock().unwrap(); assert_eq!(log_entries.get(&("lightning::ln::peer_handler".to_string(), "Handling SendAcceptChannel event in peer_handler for node 030000000000000000000000000000000000000000000000000000000000000000 for channel ff4f00f805273c1b203bb5ebf8436bfde57b3be8c2f5e95d9491dbb181909679".to_string())), Some(&1)); // 1 diff --git a/src/ln/channelmonitor.rs b/src/ln/channelmonitor.rs index 7483a8bf540..76b9c90ab2c 100644 --- a/src/ln/channelmonitor.rs +++ b/src/ln/channelmonitor.rs @@ -1770,7 +1770,7 @@ impl ChannelMonitor { // While all commitment/HTLC-Success/HTLC-Timeout transactions have one input, HTLCs // can also be resolved in a few other ways which can have more than one output. Thus, // we call is_resolving_htlc_output here outside of the tx.input.len() == 1 check. - let mut updated = self.is_resolving_htlc_output(tx); + let mut updated = self.is_resolving_htlc_output(tx, height); if updated.len() > 0 { htlc_updated.append(&mut updated); } @@ -1888,7 +1888,7 @@ impl ChannelMonitor { /// Check if any transaction broadcasted is resolving HTLC output by a success or timeout on a local /// or remote commitment tx, if so send back the source, preimage if found and payment_hash of resolved HTLC - fn is_resolving_htlc_output(&mut self, tx: &Transaction) -> Vec<(HTLCSource, Option, PaymentHash)> { + fn is_resolving_htlc_output(&mut self, tx: &Transaction, height: u32) -> Vec<(HTLCSource, Option, PaymentHash)> { let mut htlc_updated = Vec::new(); 'outer_loop: for input in &tx.input { @@ -1995,7 +1995,17 @@ impl ChannelMonitor { payment_preimage.0.copy_from_slice(&input.witness[1]); htlc_updated.push((source, Some(payment_preimage), payment_hash)); } else { - htlc_updated.push((source, None, payment_hash)); + log_trace!(self, "Failing HTLC with payment_hash {} timeout by a spend tx, waiting confirmation until {} height", log_bytes!(payment_hash.0), height + HTLC_FAIL_ANTI_REORG_DELAY - 1); + match self.htlc_updated_waiting_threshold_conf.entry(height + HTLC_FAIL_ANTI_REORG_DELAY - 1) { + hash_map::Entry::Occupied(mut entry) => { + let e = entry.get_mut(); + e.retain(|ref update| update.0 != source); + e.push((source, None, payment_hash.clone())); + } + hash_map::Entry::Vacant(entry) => { + entry.insert(vec![(source, None, payment_hash)]); + } + } } } } diff --git a/src/ln/functional_tests.rs b/src/ln/functional_tests.rs index ff10840a473..bf3aa740c19 100644 --- a/src/ln/functional_tests.rs +++ b/src/ln/functional_tests.rs @@ -2241,6 +2241,7 @@ fn test_htlc_on_chain_timeout() { } nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![timeout_tx]}, 1); + connect_blocks(&nodes[1].chain_monitor, HTLC_FAIL_ANTI_REORG_DELAY, 1, true, header.bitcoin_hash()); check_added_monitors!(nodes[1], 0); check_closed_broadcast!(nodes[1]); @@ -3898,6 +3899,7 @@ fn test_duplicate_payment_hash_one_failure_one_success() { check_spends!(htlc_success_txn[1], commitment_txn[0].clone()); nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![htlc_timeout_tx] }, 200); + connect_blocks(&nodes[1].chain_monitor, HTLC_FAIL_ANTI_REORG_DELAY, 200, true, header.bitcoin_hash()); expect_pending_htlcs_forwardable!(nodes[1]); let htlc_updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); assert!(htlc_updates.update_add_htlcs.is_empty()); From 1f2c3f5588d1272863766d9587c23154e3f01afc Mon Sep 17 00:00:00 2001 From: Antoine Riard Date: Wed, 6 Feb 2019 20:28:55 -0500 Subject: [PATCH 4/6] Fail back dust HTLC of local commitment tx after enough confirmations Add test_failure_delay_htlc_local_commitment Move some bits of check_spend_remote as we need to fail dust HTLCs which can be spread on both prev/lastest local commitment tx --- src/ln/channelmonitor.rs | 61 ++++++++++++++++++++------ src/ln/functional_tests.rs | 89 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 137 insertions(+), 13 deletions(-) diff --git a/src/ln/channelmonitor.rs b/src/ln/channelmonitor.rs index 76b9c90ab2c..cdba6451e8b 100644 --- a/src/ln/channelmonitor.rs +++ b/src/ln/channelmonitor.rs @@ -1632,42 +1632,77 @@ impl ChannelMonitor { /// Attempts to claim any claimable HTLCs in a commitment transaction which was not (yet) /// revoked using data in local_claimable_outpoints. /// Should not be used if check_spend_revoked_transaction succeeds. - fn check_spend_local_transaction(&self, tx: &Transaction, _height: u32) -> (Vec, Vec, (Sha256dHash, Vec)) { + fn check_spend_local_transaction(&mut self, tx: &Transaction, height: u32) -> (Vec, Vec, (Sha256dHash, Vec)) { let commitment_txid = tx.txid(); - // TODO: If we find a match here we need to fail back HTLCs that weren't included in the - // broadcast commitment transaction, either because they didn't meet dust or because they - // weren't yet included in our commitment transaction(s). + let mut local_txn = Vec::new(); + let mut spendable_outputs = Vec::new(); + let mut watch_outputs = Vec::new(); + + macro_rules! wait_threshold_conf { + ($height: expr, $source: expr, $update: expr, $commitment_tx: expr, $payment_hash: expr) => { + log_trace!(self, "Failing HTLC with payment_hash {} from {} local commitment tx due to broadcast of transaction, waiting confirmation until {} height", log_bytes!($payment_hash.0), $commitment_tx, height + HTLC_FAIL_ANTI_REORG_DELAY - 1); + match self.htlc_updated_waiting_threshold_conf.entry($height + HTLC_FAIL_ANTI_REORG_DELAY - 1) { + hash_map::Entry::Occupied(mut entry) => { + let e = entry.get_mut(); + e.retain(|ref update| update.0 != $source); + e.push(($source, $update, $payment_hash)); + } + hash_map::Entry::Vacant(entry) => { + entry.insert(vec![($source, $update, $payment_hash)]); + } + } + } + } + + macro_rules! append_onchain_update { + ($updates: expr) => { + local_txn.append(&mut $updates.0); + spendable_outputs.append(&mut $updates.1); + watch_outputs.append(&mut $updates.2); + } + } + if let &Some(ref local_tx) = &self.current_local_signed_commitment_tx { + for &(ref htlc, _, ref source) in &local_tx.htlc_outputs { + if htlc.transaction_output_index.is_none() { + if let &Some(ref source) = source { + wait_threshold_conf!(height, source.clone(), None, "lastest", htlc.payment_hash.clone()); + } + } + } if local_tx.txid == commitment_txid { log_trace!(self, "Got latest local commitment tx broadcast, searching for available HTLCs to claim"); match self.key_storage { Storage::Local { ref delayed_payment_base_key, ref latest_per_commitment_point, .. } => { - let (local_txn, spendable_outputs, watch_outputs) = self.broadcast_by_local_state(local_tx, latest_per_commitment_point, &Some(*delayed_payment_base_key)); - return (local_txn, spendable_outputs, (commitment_txid, watch_outputs)); + append_onchain_update!(self.broadcast_by_local_state(local_tx, latest_per_commitment_point, &Some(*delayed_payment_base_key))); }, Storage::Watchtower { .. } => { - let (local_txn, spendable_outputs, watch_outputs) = self.broadcast_by_local_state(local_tx, &None, &None); - return (local_txn, spendable_outputs, (commitment_txid, watch_outputs)); + append_onchain_update!(self.broadcast_by_local_state(local_tx, &None, &None)); } } } } if let &Some(ref local_tx) = &self.prev_local_signed_commitment_tx { + for &(ref htlc, _, ref source) in &local_tx.htlc_outputs { + if htlc.transaction_output_index.is_none() { + if let &Some(ref source) = source { + wait_threshold_conf!(height, source.clone(), None, "previous", htlc.payment_hash.clone()); + } + } + } if local_tx.txid == commitment_txid { log_trace!(self, "Got previous local commitment tx broadcast, searching for available HTLCs to claim"); match self.key_storage { Storage::Local { ref delayed_payment_base_key, ref prev_latest_per_commitment_point, .. } => { - let (local_txn, spendable_outputs, watch_outputs) = self.broadcast_by_local_state(local_tx, prev_latest_per_commitment_point, &Some(*delayed_payment_base_key)); - return (local_txn, spendable_outputs, (commitment_txid, watch_outputs)); + append_onchain_update!(self.broadcast_by_local_state(local_tx, prev_latest_per_commitment_point, &Some(*delayed_payment_base_key))); }, Storage::Watchtower { .. } => { - let (local_txn, spendable_outputs, watch_outputs) = self.broadcast_by_local_state(local_tx, &None, &None); - return (local_txn, spendable_outputs, (commitment_txid, watch_outputs)); + append_onchain_update!(self.broadcast_by_local_state(local_tx, &None, &None)); } } } } - (Vec::new(), Vec::new(), (commitment_txid, Vec::new())) + (local_txn, spendable_outputs, (commitment_txid, watch_outputs)) } /// Generate a spendable output event when closing_transaction get registered onchain. diff --git a/src/ln/functional_tests.rs b/src/ln/functional_tests.rs index bf3aa740c19..d595f07a226 100644 --- a/src/ln/functional_tests.rs +++ b/src/ln/functional_tests.rs @@ -5513,3 +5513,92 @@ fn test_update_fulfill_htlc_bolt2_after_malformed_htlc_message_must_forward_upda check_added_monitors!(nodes[1], 1); } + +fn do_test_failure_delay_dust_htlc_local_commitment(announce_latest: bool) { + // Dust-HTLC failure updates must be delayed until failure-trigger tx (in this case local commitment) reach HTLC_FAIL_ANTI_REORG_DELAY + // We can have at most two valid local commitment tx, so both cases must be covered, and both txs must be checked to get them all as + // HTLC could have been removed from lastest local commitment tx but still valid until we get remote RAA + + let nodes = create_network(2); + let chan =create_announced_chan_between_nodes(&nodes, 0, 1); + + let bs_dust_limit = nodes[1].node.channel_state.lock().unwrap().by_id.get(&chan.2).unwrap().our_dust_limit_satoshis; + + // We route 2 dust-HTLCs between A and B + let (_, payment_hash_1) = route_payment(&nodes[0], &[&nodes[1]], bs_dust_limit*1000); + let (_, payment_hash_2) = route_payment(&nodes[0], &[&nodes[1]], bs_dust_limit*1000); + route_payment(&nodes[0], &[&nodes[1]], 1000000); + + // Cache one local commitment tx as previous + let as_prev_commitment_tx = nodes[0].node.channel_state.lock().unwrap().by_id.get(&chan.2).unwrap().last_local_commitment_txn.clone(); + + // Fail one HTLC to prune it in the will-be-latest-local commitment tx + assert!(nodes[1].node.fail_htlc_backwards(&payment_hash_2)); + check_added_monitors!(nodes[1], 0); + expect_pending_htlcs_forwardable!(nodes[1]); + check_added_monitors!(nodes[1], 1); + + let remove = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); + nodes[0].node.handle_update_fail_htlc(&nodes[1].node.get_our_node_id(), &remove.update_fail_htlcs[0]).unwrap(); + nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), &remove.commitment_signed).unwrap(); + check_added_monitors!(nodes[0], 1); + + // Cache one local commitment tx as lastest + let as_last_commitment_tx = nodes[0].node.channel_state.lock().unwrap().by_id.get(&chan.2).unwrap().last_local_commitment_txn.clone(); + + let events = nodes[0].node.get_and_clear_pending_msg_events(); + match events[0] { + MessageSendEvent::SendRevokeAndACK { node_id, .. } => { + assert_eq!(node_id, nodes[1].node.get_our_node_id()); + }, + _ => panic!("Unexpected event"), + } + match events[1] { + MessageSendEvent::UpdateHTLCs { node_id, .. } => { + assert_eq!(node_id, nodes[1].node.get_our_node_id()); + }, + _ => panic!("Unexpected event"), + } + + assert_ne!(as_prev_commitment_tx, as_last_commitment_tx); + // Fail the 2 dust-HTLCs, move their failure in maturation buffer (htlc_updated_waiting_threshold_conf) + let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; + if announce_latest { + nodes[0].chain_monitor.block_connected_checked(&header, 1, &[&as_last_commitment_tx[0]], &[1; 1]); + } else { + nodes[0].chain_monitor.block_connected_checked(&header, 1, &[&as_prev_commitment_tx[0]], &[1; 1]); + } + + let events = nodes[0].node.get_and_clear_pending_msg_events(); + assert_eq!(events.len(), 1); + match events[0] { + MessageSendEvent::BroadcastChannelUpdate { .. } => {}, + _ => panic!("Unexpected event"), + } + + assert_eq!(nodes[0].node.get_and_clear_pending_events().len(), 0); + connect_blocks(&nodes[0].chain_monitor, HTLC_FAIL_ANTI_REORG_DELAY, 1, true, header.bitcoin_hash()); + let events = nodes[0].node.get_and_clear_pending_events(); + // Only 2 PaymentFailed events should show up, over-dust HTLC has to be failed by timeout tx + assert_eq!(events.len(), 2); + let mut first_failed = false; + for event in events { + match event { + Event::PaymentFailed { payment_hash, .. } => { + if payment_hash == payment_hash_1 { + assert!(!first_failed); + first_failed = true; + } else { + assert_eq!(payment_hash, payment_hash_2); + } + } + _ => panic!("Unexpected event"), + } + } +} + +#[test] +fn test_failure_delay_dust_htlc_local_commitment() { + do_test_failure_delay_dust_htlc_local_commitment(true); + do_test_failure_delay_dust_htlc_local_commitment(false); +} From d4f5c5924d4596a7c29ecc110972cfcd763ab7b1 Mon Sep 17 00:00:00 2001 From: Antoine Riard Date: Sat, 9 Feb 2019 21:37:54 -0500 Subject: [PATCH 5/6] Implement delay channel closing in ChannelManager until maturation Add pruning of waiting-conf channel closing at block_disconnect Fix tests broken by introduced change --- src/ln/channelmanager.rs | 90 +++++++++++--- src/ln/functional_tests.rs | 233 +++++++++++++++++++++---------------- 2 files changed, 206 insertions(+), 117 deletions(-) diff --git a/src/ln/channelmanager.rs b/src/ln/channelmanager.rs index 398f719bae4..4f5db7a3684 100644 --- a/src/ln/channelmanager.rs +++ b/src/ln/channelmanager.rs @@ -332,6 +332,8 @@ pub struct ChannelManager { channel_state: Mutex, our_network_key: SecretKey, + channel_closing_waiting_threshold_conf: Mutex>>, + pending_events: Mutex>, /// Used when we have to take a BIG lock to make sure everything is self-consistent. /// Essentially just when we're serializing ourselves out. @@ -556,6 +558,8 @@ impl ChannelManager { }), our_network_key: keys_manager.get_node_secret(), + channel_closing_waiting_threshold_conf: Mutex::new(HashMap::new()), + pending_events: Mutex::new(Vec::new()), total_consistency_lock: RwLock::new(()), @@ -2400,11 +2404,12 @@ impl ChainListener for ChannelManager { let _ = self.total_consistency_lock.read().unwrap(); let mut failed_channels = Vec::new(); { + let mut channel_closing_lock = self.channel_closing_waiting_threshold_conf.lock().unwrap(); let mut channel_lock = self.channel_state.lock().unwrap(); let channel_state = channel_lock.borrow_parts(); let short_to_id = channel_state.short_to_id; let pending_msg_events = channel_state.pending_msg_events; - channel_state.by_id.retain(|_, channel| { + channel_state.by_id.retain(|channel_id, channel| { let chan_res = channel.block_connected(header, height, txn_matched, indexes_of_txn_matched); if let Ok(Some(funding_locked)) = chan_res { pending_msg_events.push(events::MessageSendEvent::SendFundingLocked { @@ -2429,20 +2434,24 @@ impl ChainListener for ChannelManager { for tx in txn_matched { for inp in tx.input.iter() { if inp.previous_output == funding_txo.into_bitcoin_outpoint() { - log_trace!(self, "Detected channel-closing tx {} spending {}:{}, closing channel {}", tx.txid(), inp.previous_output.txid, inp.previous_output.vout, log_bytes!(channel.channel_id())); - if let Some(short_id) = channel.get_short_channel_id() { - short_to_id.remove(&short_id); - } - // It looks like our counterparty went on-chain. We go ahead and - // broadcast our latest local state as well here, just in case its - // some kind of SPV attack, though we expect these to be dropped. - failed_channels.push(channel.force_shutdown()); - if let Ok(update) = self.get_channel_update(&channel) { - pending_msg_events.push(events::MessageSendEvent::BroadcastChannelUpdate { - msg: update - }); + log_trace!(self, "Detected channel-closing tx {} spending {}:{}, waiting until {} to close channel {}", tx.txid(), inp.previous_output.txid, inp.previous_output.vout, height + HTLC_FAIL_ANTI_REORG_DELAY - 1, log_bytes!(channel_id[..])); + match channel_closing_lock.entry(height + HTLC_FAIL_ANTI_REORG_DELAY - 1) { + hash_map::Entry::Occupied(mut entry) => { + let mut duplicate = false; + for id in entry.get().iter() { + if *id == *channel_id { + duplicate = true; + break; + } + } + if !duplicate { + entry.get_mut().push(*channel_id); + } + } + hash_map::Entry::Vacant(entry) => { + entry.insert(vec![*channel_id]); + } } - return false; } } } @@ -2465,6 +2474,25 @@ impl ChainListener for ChannelManager { } true }); + if let Some(channel_closings) = channel_closing_lock.remove(&height) { + for channel_id in channel_closings { + log_trace!(self, "Enough confirmations for a broacast commitment tx, channel {} can be closed", log_bytes!(&channel_id[..])); + if let Some(mut channel) = channel_state.by_id.remove(&channel_id) { + if let Some(short_id) = channel.get_short_channel_id() { + short_to_id.remove(&short_id); + } + // It looks like our counterparty went on-chain. We go ahead and + // broadcast our latest local state as well here, just in case its + // some kind of SPV attack, though we expect these to be dropped. + failed_channels.push(channel.force_shutdown()); + if let Ok(update) = self.get_channel_update(&channel) { + pending_msg_events.push(events::MessageSendEvent::BroadcastChannelUpdate { + msg: update + }); + } + } + } + } } for failure in failed_channels.drain(..) { self.finish_force_close_channel(failure); @@ -2474,7 +2502,7 @@ impl ChainListener for ChannelManager { } /// We force-close the channel without letting our counterparty participate in the shutdown - fn block_disconnected(&self, header: &BlockHeader, _: u32) { + fn block_disconnected(&self, header: &BlockHeader, height: u32) { let _ = self.total_consistency_lock.read().unwrap(); let mut failed_channels = Vec::new(); { @@ -2499,6 +2527,12 @@ impl ChainListener for ChannelManager { } }); } + { + let mut channel_closing_lock = self.channel_closing_waiting_threshold_conf.lock().unwrap(); + if let Some(_) = channel_closing_lock.remove(&(height + HTLC_FAIL_ANTI_REORG_DELAY - 1)) { + // We discard channel_closing there as brooadcast commitment tx has been disconnected, (and may be replaced by a legit closing_signed) + } + } for failure in failed_channels.drain(..) { self.finish_force_close_channel(failure); } @@ -2936,6 +2970,15 @@ impl Writeable for ChannelManager { } } + let channel_closing_lock = self.channel_closing_waiting_threshold_conf.lock().unwrap(); + (channel_closing_lock.len() as u64).write(writer)?; + for (confirmation_height, channel_id) in channel_closing_lock.iter() { + confirmation_height.write(writer)?; + for id in channel_id { + id.write(writer)?; + } + } + Ok(()) } } @@ -3073,6 +3116,21 @@ impl<'a, R : ::std::io::Read> ReadableArgs> for (S claimable_htlcs.insert(payment_hash, previous_hops); } + let channel_closing_count: u64 = Readable::read(reader)?; + let mut channel_closing: HashMap> = HashMap::with_capacity(cmp::min(channel_closing_count as usize, 32)); + for _ in 0..channel_closing_count { + let confirmation_height: u32 = Readable::read(reader)?; + let channel_id: [u8; 32] = Readable::read(reader)?; + match channel_closing.entry(confirmation_height) { + hash_map::Entry::Occupied(mut entry) => { + entry.get_mut().push(channel_id); + } + hash_map::Entry::Vacant(entry) => { + entry.insert(vec![channel_id]); + } + } + } + let channel_manager = ChannelManager { genesis_hash, fee_estimator: args.fee_estimator, @@ -3094,6 +3152,8 @@ impl<'a, R : ::std::io::Read> ReadableArgs> for (S }), our_network_key: args.keys_manager.get_node_secret(), + channel_closing_waiting_threshold_conf: Mutex::new(channel_closing), + pending_events: Mutex::new(Vec::new()), total_consistency_lock: RwLock::new(()), keys_manager: args.keys_manager, diff --git a/src/ln/functional_tests.rs b/src/ln/functional_tests.rs index d595f07a226..3ad23d5748d 100644 --- a/src/ln/functional_tests.rs +++ b/src/ln/functional_tests.rs @@ -1621,6 +1621,7 @@ fn channel_monitor_network_test() { let mut node_txn = test_txn_broadcast(&nodes[1], &chan_1, None, HTLCType::NONE); let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; nodes[0].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![node_txn.drain(..).next().unwrap()] }, 1); + connect_blocks(&nodes[0].chain_monitor, HTLC_FAIL_ANTI_REORG_DELAY, 1, true, header.bitcoin_hash()); test_txn_broadcast(&nodes[0], &chan_1, None, HTLCType::NONE); } get_announce_close_broadcast_events(&nodes, 0, 1); @@ -1636,6 +1637,7 @@ fn channel_monitor_network_test() { let mut node_txn = test_txn_broadcast(&nodes[1], &chan_2, None, HTLCType::TIMEOUT); let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; nodes[2].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![node_txn.drain(..).next().unwrap()] }, 1); + connect_blocks(&nodes[2].chain_monitor, HTLC_FAIL_ANTI_REORG_DELAY, 1, true, header.bitcoin_hash()); test_txn_broadcast(&nodes[2], &chan_2, None, HTLCType::NONE); } get_announce_close_broadcast_events(&nodes, 1, 2); @@ -1673,6 +1675,7 @@ fn channel_monitor_network_test() { let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; nodes[3].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![node_txn[0].clone()] }, 1); + connect_blocks(&nodes[3].chain_monitor, HTLC_FAIL_ANTI_REORG_DELAY, 1, true, header.bitcoin_hash()); check_preimage_claim(&nodes[3], &node_txn); } @@ -1685,7 +1688,7 @@ fn channel_monitor_network_test() { nodes[4].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![] }, 1); } - assert_eq!(nodes[3].node.latest_block_height.load(Ordering::Acquire), 1); + assert_eq!(nodes[3].node.latest_block_height.load(Ordering::Acquire), 6); assert_eq!(nodes[4].node.latest_block_height.load(Ordering::Acquire), 1); // One pending HTLC to time out: let payment_preimage_2 = route_payment(&nodes[3], &vec!(&nodes[4])[..], 3000000).0; @@ -1694,8 +1697,8 @@ fn channel_monitor_network_test() { { let mut header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; - nodes[3].chain_monitor.block_connected_checked(&header, 2, &Vec::new()[..], &[0; 0]); - for i in 3..TEST_FINAL_CLTV + 2 + HTLC_FAIL_TIMEOUT_BLOCKS + 1 { + nodes[3].chain_monitor.block_connected_checked(&header, 7, &Vec::new()[..], &[0; 0]); + for i in 8..TEST_FINAL_CLTV + 2 + HTLC_FAIL_TIMEOUT_BLOCKS + 6 { header = BlockHeader { version: 0x20000000, prev_blockhash: header.bitcoin_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; nodes[3].chain_monitor.block_connected_checked(&header, i, &Vec::new()[..], &[0; 0]); } @@ -1707,7 +1710,7 @@ fn channel_monitor_network_test() { header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; nodes[4].chain_monitor.block_connected_checked(&header, 2, &Vec::new()[..], &[0; 0]); - for i in 3..TEST_FINAL_CLTV + 2 - CLTV_CLAIM_BUFFER + 1 { + for i in 3..TEST_FINAL_CLTV + 2 - CLTV_CLAIM_BUFFER + 6 { header = BlockHeader { version: 0x20000000, prev_blockhash: header.bitcoin_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; nodes[4].chain_monitor.block_connected_checked(&header, i, &Vec::new()[..], &[0; 0]); } @@ -1749,10 +1752,11 @@ fn test_justice_tx() { { let mut header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1); + connect_blocks(&nodes[1].chain_monitor, HTLC_FAIL_ANTI_REORG_DELAY, 1, true, header.bitcoin_hash()); { let mut node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap(); assert_eq!(node_txn.len(), 3); - assert_eq!(node_txn.pop().unwrap(), node_txn[0]); // An outpoint registration will result in a 2nd block_connected + assert_eq!(node_txn.remove(0), node_txn[0]); // An outpoint registration will result in a 2nd block_connected assert_eq!(node_txn[0].input.len(), 2); // We should claim the revoked output and the HTLC output check_spends!(node_txn[0], revoked_local_txn[0].clone()); @@ -1761,6 +1765,7 @@ fn test_justice_tx() { test_txn_broadcast(&nodes[1], &chan_5, None, HTLCType::NONE); nodes[0].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1); + connect_blocks(&nodes[0].chain_monitor, HTLC_FAIL_ANTI_REORG_DELAY, 1, true, header.bitcoin_hash()); let node_txn = test_txn_broadcast(&nodes[0], &chan_5, Some(revoked_local_txn[0].clone()), HTLCType::TIMEOUT); header = BlockHeader { version: 0x20000000, prev_blockhash: header.bitcoin_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![node_txn[1].clone()] }, 1); @@ -1788,10 +1793,11 @@ fn test_justice_tx() { { let mut header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; nodes[0].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1); + connect_blocks(&nodes[0].chain_monitor, HTLC_FAIL_ANTI_REORG_DELAY, 1, true, header.bitcoin_hash()); { let mut node_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap(); assert_eq!(node_txn.len(), 3); - assert_eq!(node_txn.pop().unwrap(), node_txn[0]); // An outpoint registration will result in a 2nd block_connected + assert_eq!(node_txn.remove(0), node_txn[0]); // An outpoint registration will result in a 2nd block_connected assert_eq!(node_txn[0].input.len(), 1); // We claim the received HTLC output check_spends!(node_txn[0], revoked_local_txn[0].clone()); @@ -1800,6 +1806,7 @@ fn test_justice_tx() { test_txn_broadcast(&nodes[0], &chan_6, None, HTLCType::NONE); nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1); + connect_blocks(&nodes[1].chain_monitor, HTLC_FAIL_ANTI_REORG_DELAY, 1, true, header.bitcoin_hash()); let node_txn = test_txn_broadcast(&nodes[1], &chan_6, Some(revoked_local_txn[0].clone()), HTLCType::SUCCESS); header = BlockHeader { version: 0x20000000, prev_blockhash: header.bitcoin_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; nodes[0].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![node_txn[1].clone()] }, 1); @@ -1827,16 +1834,18 @@ fn revoked_output_claim() { // Inform nodes[1] that nodes[0] broadcast a stale tx let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1); + connect_blocks(&nodes[1].chain_monitor, HTLC_FAIL_ANTI_REORG_DELAY, 1, true, header.bitcoin_hash()); let node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap(); assert_eq!(node_txn.len(), 3); // nodes[1] will broadcast justice tx twice, and its own local state once - assert_eq!(node_txn[0], node_txn[2]); + assert_eq!(node_txn[0], node_txn[1]); check_spends!(node_txn[0], revoked_local_txn[0].clone()); - check_spends!(node_txn[1], chan_1.3.clone()); + check_spends!(node_txn[2], chan_1.3.clone()); // Inform nodes[0] that a watchtower cheated on its behalf, so it will force-close the chan nodes[0].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1); + connect_blocks(&nodes[0].chain_monitor, HTLC_FAIL_ANTI_REORG_DELAY, 1, true, header.bitcoin_hash()); get_announce_close_broadcast_events(&nodes, 0, 1); } @@ -1871,6 +1880,7 @@ fn claim_htlc_outputs_shared_tx() { let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; nodes[0].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1); nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1); + connect_blocks(&nodes[0].chain_monitor, HTLC_FAIL_ANTI_REORG_DELAY, 1, true, header.bitcoin_hash()); connect_blocks(&nodes[1].chain_monitor, HTLC_FAIL_ANTI_REORG_DELAY, 1, true, header.bitcoin_hash()); let events = nodes[1].node.get_and_clear_pending_events(); @@ -1888,7 +1898,7 @@ fn claim_htlc_outputs_shared_tx() { assert_eq!(node_txn[0].input.len(), 3); // Claim the revoked output + both revoked HTLC outputs check_spends!(node_txn[0], revoked_local_txn[0].clone()); - assert_eq!(node_txn[0], node_txn[3]); // justice tx is duplicated due to block re-scanning + assert_eq!(node_txn[0], node_txn[1]); // justice tx is duplicated due to block re-scanning let mut witness_lens = BTreeSet::new(); witness_lens.insert(node_txn[0].input[0].witness.last().unwrap().len()); @@ -1900,15 +1910,15 @@ fn claim_htlc_outputs_shared_tx() { assert_eq!(*witness_lens.iter().skip(2).next().unwrap(), ACCEPTED_HTLC_SCRIPT_WEIGHT); // revoked received HTLC // Next nodes[1] broadcasts its current local tx state: - assert_eq!(node_txn[1].input.len(), 1); - assert_eq!(node_txn[1].input[0].previous_output.txid, chan_1.3.txid()); //Spending funding tx unique txouput, tx broadcasted by ChannelManager - assert_eq!(node_txn[2].input.len(), 1); - let witness_script = node_txn[2].clone().input[0].witness.pop().unwrap(); + assert_eq!(node_txn[2].input[0].previous_output.txid, chan_1.3.txid()); //Spending funding tx unique txouput, tx broadcasted by ChannelManager + + assert_eq!(node_txn[3].input.len(), 1); + let witness_script = node_txn[3].clone().input[0].witness.pop().unwrap(); assert_eq!(witness_script.len(), OFFERED_HTLC_SCRIPT_WEIGHT); //Spending an offered htlc output - assert_eq!(node_txn[2].input[0].previous_output.txid, node_txn[1].txid()); - assert_ne!(node_txn[2].input[0].previous_output.txid, node_txn[0].input[0].previous_output.txid); - assert_ne!(node_txn[2].input[0].previous_output.txid, node_txn[0].input[1].previous_output.txid); + assert_eq!(node_txn[3].input[0].previous_output.txid, node_txn[2].txid()); + assert_ne!(node_txn[3].input[0].previous_output.txid, node_txn[0].input[0].previous_output.txid); + assert_ne!(node_txn[3].input[0].previous_output.txid, node_txn[0].input[1].previous_output.txid); } get_announce_close_broadcast_events(&nodes, 0, 1); assert_eq!(nodes[0].node.list_channels().len(), 0); @@ -1938,6 +1948,7 @@ fn claim_htlc_outputs_single_tx() { { let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; nodes[0].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 200); + connect_blocks(&nodes[0].chain_monitor, HTLC_FAIL_ANTI_REORG_DELAY, 200, true, header.bitcoin_hash()); nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 200); connect_blocks(&nodes[1].chain_monitor, HTLC_FAIL_ANTI_REORG_DELAY, 200, true, header.bitcoin_hash()); @@ -1951,17 +1962,12 @@ fn claim_htlc_outputs_single_tx() { } let node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap(); - assert_eq!(node_txn.len(), 22); // ChannelManager : 2, ChannelMontitor: 8 (1 standard revoked output, 2 revocation htlc tx, 1 local commitment tx + 1 htlc timeout tx) * 2 (block-rescan) + 5 * (1 local commitment tx + 1 htlc timeout tx) - - assert_eq!(node_txn[0], node_txn[7]); - assert_eq!(node_txn[1], node_txn[8]); - assert_eq!(node_txn[2], node_txn[9]); - assert_eq!(node_txn[3], node_txn[10]); - assert_eq!(node_txn[4], node_txn[11]); - assert_eq!(node_txn[3], node_txn[5]); //local commitment tx + htlc timeout tx broadcasted by ChannelManger - assert_eq!(node_txn[4], node_txn[6]); + assert_eq!(node_txn.len(), 20); // ChannelManager : 2, ChannelMontitor: 8 (1 standard revoked output, 2 revocation htlc tx, 1 local commitment tx + 1 htlc timeout tx) * 2 (block-rescan) + 5 * (1 local commitment tx + 1 htlc timeout tx) - for i in 12..22 { + assert_eq!(node_txn[0], node_txn[5]); + assert_eq!(node_txn[1], node_txn[6]); + assert_eq!(node_txn[2], node_txn[7]); + for i in 8..20 { if i % 2 == 0 { assert_eq!(node_txn[3], node_txn[i]); } else { assert_eq!(node_txn[4], node_txn[i]); } } @@ -2044,12 +2050,13 @@ fn test_htlc_on_chain_success() { assert_eq!(updates.update_fulfill_htlcs.len(), 1); nodes[2].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![commitment_tx[0].clone()]}, 1); + connect_blocks(&nodes[2].chain_monitor, HTLC_FAIL_ANTI_REORG_DELAY, 1, true, header.bitcoin_hash()); check_closed_broadcast!(nodes[2]); let node_txn = nodes[2].tx_broadcaster.txn_broadcasted.lock().unwrap().clone(); // ChannelManager : 1 (commitment tx), ChannelMonitor : 4 (2*2 * HTLC-Success tx) assert_eq!(node_txn.len(), 5); - assert_eq!(node_txn[0], node_txn[3]); - assert_eq!(node_txn[1], node_txn[4]); - assert_eq!(node_txn[2], commitment_tx[0]); + assert_eq!(node_txn[0], node_txn[2]); + assert_eq!(node_txn[1], node_txn[3]); + assert_eq!(node_txn[4], commitment_tx[0]); check_spends!(node_txn[0], commitment_tx[0].clone()); check_spends!(node_txn[1], commitment_tx[0].clone()); assert_eq!(node_txn[0].input[0].witness.clone().last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT); @@ -2061,6 +2068,7 @@ fn test_htlc_on_chain_success() { // Verify that B's ChannelManager is able to extract preimage from HTLC Success tx and pass it backward nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: node_txn}, 1); + connect_blocks(&nodes[1].chain_monitor, HTLC_FAIL_ANTI_REORG_DELAY, 1, true, header.bitcoin_hash()); let events = nodes[1].node.get_and_clear_pending_msg_events(); { let mut added_monitors = nodes[1].chan_monitor.added_monitors.lock().unwrap(); @@ -2089,8 +2097,8 @@ fn test_htlc_on_chain_success() { // ChannelManager : 3 (commitment tx, 2*HTLC-Timeout tx), ChannelMonitor : 2 (timeout tx) * 2 (block-rescan) let mut node_txn = $node.tx_broadcaster.txn_broadcasted.lock().unwrap(); assert_eq!(node_txn.len(), 7); - assert_eq!(node_txn[0], node_txn[5]); - assert_eq!(node_txn[1], node_txn[6]); + assert_eq!(node_txn[0], node_txn[2]); + assert_eq!(node_txn[1], node_txn[3]); check_spends!(node_txn[0], $commitment_tx.clone()); check_spends!(node_txn[1], $commitment_tx.clone()); assert_ne!(node_txn[0].lock_time, 0); @@ -2106,16 +2114,16 @@ fn test_htlc_on_chain_success() { assert!(node_txn[0].output[0].script_pubkey.is_v0_p2wpkh()); // direct payment assert!(node_txn[1].output[0].script_pubkey.is_v0_p2wpkh()); // direct payment } - check_spends!(node_txn[2], $chan_tx.clone()); - check_spends!(node_txn[3], node_txn[2].clone()); - check_spends!(node_txn[4], node_txn[2].clone()); - assert_eq!(node_txn[2].input[0].witness.last().unwrap().len(), 71); - assert_eq!(node_txn[3].input[0].witness.last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT); - assert_eq!(node_txn[4].input[0].witness.last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT); - assert!(node_txn[3].output[0].script_pubkey.is_v0_p2wsh()); // revokeable output + check_spends!(node_txn[4], $chan_tx.clone()); + check_spends!(node_txn[5], node_txn[4].clone()); + check_spends!(node_txn[6], node_txn[4].clone()); + assert_eq!(node_txn[4].input[0].witness.last().unwrap().len(), 71); + assert_eq!(node_txn[5].input[0].witness.last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT); + assert_eq!(node_txn[6].input[0].witness.last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT); assert!(node_txn[4].output[0].script_pubkey.is_v0_p2wsh()); // revokeable output - assert_ne!(node_txn[3].lock_time, 0); + assert!(node_txn[5].output[0].script_pubkey.is_v0_p2wsh()); // revokeable output assert_ne!(node_txn[4].lock_time, 0); + assert_ne!(node_txn[5].lock_time, 0); node_txn.clear(); } } } @@ -2129,23 +2137,25 @@ fn test_htlc_on_chain_success() { let commitment_tx = nodes[0].node.channel_state.lock().unwrap().by_id.get(&chan_1.2).unwrap().last_local_commitment_txn.clone(); check_spends!(commitment_tx[0], chan_1.3.clone()); nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![commitment_tx[0].clone()]}, 1); + connect_blocks(&nodes[1].chain_monitor, HTLC_FAIL_ANTI_REORG_DELAY, 1, true, header.bitcoin_hash()); check_closed_broadcast!(nodes[1]); let node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap().clone(); // ChannelManager : 1 (commitment tx), ChannelMonitor : 1 (HTLC-Success) * 2 (block-rescan) assert_eq!(node_txn.len(), 3); - assert_eq!(node_txn[0], node_txn[2]); + assert_eq!(node_txn[0], node_txn[1]); check_spends!(node_txn[0], commitment_tx[0].clone()); assert_eq!(node_txn[0].input.len(), 2); assert_eq!(node_txn[0].input[0].witness.last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT); assert_eq!(node_txn[0].input[1].witness.last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT); assert_eq!(node_txn[0].lock_time, 0); assert!(node_txn[0].output[0].script_pubkey.is_v0_p2wpkh()); // direct payment - check_spends!(node_txn[1], chan_1.3.clone()); - assert_eq!(node_txn[1].input[0].witness.clone().last().unwrap().len(), 71); + check_spends!(node_txn[2], chan_1.3.clone()); + assert_eq!(node_txn[2].input[0].witness.clone().last().unwrap().len(), 71); // We don't bother to check that B can claim the HTLC output on its commitment tx here as // we already checked the same situation with A. // Verify that A's ChannelManager is able to extract preimage from preimage tx and generate PaymentSent nodes[0].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![commitment_tx[0].clone(), node_txn[0].clone()] }, 1); + connect_blocks(&nodes[0].chain_monitor, HTLC_FAIL_ANTI_REORG_DELAY, 1, true, header.bitcoin_hash()); check_closed_broadcast!(nodes[0]); let events = nodes[0].node.get_and_clear_pending_events(); assert_eq!(events.len(), 2); @@ -2210,6 +2220,7 @@ fn test_htlc_on_chain_timeout() { _ => panic!("Unexpected event"), }; nodes[2].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![commitment_tx[0].clone()]}, 1); + connect_blocks(&nodes[2].chain_monitor, HTLC_FAIL_ANTI_REORG_DELAY, 1, true, header.bitcoin_hash()); check_closed_broadcast!(nodes[2]); let node_txn = nodes[2].tx_broadcaster.txn_broadcasted.lock().unwrap().clone(); // ChannelManager : 1 (commitment tx) assert_eq!(node_txn.len(), 1); @@ -2219,23 +2230,24 @@ fn test_htlc_on_chain_timeout() { // Broadcast timeout transaction by B on received output from C's commitment tx on B's chain // Verify that B's ChannelManager is able to detect that HTLC is timeout by its own tx and react backward in consequence nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![commitment_tx[0].clone()]}, 200); + connect_blocks(&nodes[1].chain_monitor, HTLC_FAIL_ANTI_REORG_DELAY, 200, true, header.bitcoin_hash()); let timeout_tx; { let mut node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap(); - assert_eq!(node_txn.len(), 8); // ChannelManager : 2 (commitment tx, HTLC-Timeout tx), ChannelMonitor : 6 (HTLC-Timeout tx, commitment tx, timeout tx) * 2 (block-rescan) - assert_eq!(node_txn[0], node_txn[5]); - assert_eq!(node_txn[1], node_txn[6]); - assert_eq!(node_txn[2], node_txn[7]); + assert_eq!(node_txn.len(), 16); // ChannelManager : 2 (commitment tx, HTLC-Timeout tx), ChannelMonitor : 6 (HTLC-Timeout tx, commitment tx, timeout tx) * 2 (block-rescan) + assert_eq!(node_txn[0], node_txn[3]); + assert_eq!(node_txn[1], node_txn[4]); + assert_eq!(node_txn[2], node_txn[5]); check_spends!(node_txn[0], commitment_tx[0].clone()); assert_eq!(node_txn[0].clone().input[0].witness.last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT); check_spends!(node_txn[1], chan_2.3.clone()); check_spends!(node_txn[2], node_txn[1].clone()); assert_eq!(node_txn[1].clone().input[0].witness.last().unwrap().len(), 71); assert_eq!(node_txn[2].clone().input[0].witness.last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT); - check_spends!(node_txn[3], chan_2.3.clone()); - check_spends!(node_txn[4], node_txn[3].clone()); - assert_eq!(node_txn[3].input[0].witness.clone().last().unwrap().len(), 71); - assert_eq!(node_txn[4].input[0].witness.clone().last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT); + check_spends!(node_txn[6], chan_2.3.clone()); + check_spends!(node_txn[7], node_txn[6].clone()); + assert_eq!(node_txn[6].input[0].witness.clone().last().unwrap().len(), 71); + assert_eq!(node_txn[7].input[0].witness.clone().last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT); timeout_tx = node_txn[0].clone(); node_txn.clear(); } @@ -2267,16 +2279,17 @@ fn test_htlc_on_chain_timeout() { check_spends!(commitment_tx[0], chan_1.3.clone()); nodes[0].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![commitment_tx[0].clone()]}, 200); + connect_blocks(&nodes[0].chain_monitor, HTLC_FAIL_ANTI_REORG_DELAY, 200, true, header.bitcoin_hash()); check_closed_broadcast!(nodes[0]); let node_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().clone(); // ChannelManager : 2 (commitment tx, HTLC-Timeout tx), ChannelMonitor : 2 (timeout tx) * 2 block-rescan assert_eq!(node_txn.len(), 4); - assert_eq!(node_txn[0], node_txn[3]); + assert_eq!(node_txn[0], node_txn[1]); check_spends!(node_txn[0], commitment_tx[0].clone()); assert_eq!(node_txn[0].clone().input[0].witness.last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT); - check_spends!(node_txn[1], chan_1.3.clone()); - check_spends!(node_txn[2], node_txn[1].clone()); - assert_eq!(node_txn[1].clone().input[0].witness.last().unwrap().len(), 71); - assert_eq!(node_txn[2].clone().input[0].witness.last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT); + check_spends!(node_txn[2], chan_1.3.clone()); + check_spends!(node_txn[3], node_txn[2].clone()); + assert_eq!(node_txn[2].clone().input[0].witness.last().unwrap().len(), 71); + assert_eq!(node_txn[3].clone().input[0].witness.last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT); } #[test] @@ -2576,6 +2589,7 @@ fn test_htlc_ignore_latest_remote_commitment() { let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; nodes[1].chain_monitor.block_connected_checked(&header, 1, &[&node_txn[0], &node_txn[1]], &[1; 2]); + connect_blocks(&nodes[1].chain_monitor, HTLC_FAIL_ANTI_REORG_DELAY, 1, true, header.bitcoin_hash()); check_closed_broadcast!(nodes[1]); // Duplicate the block_connected call since this may happen due to other listeners @@ -2636,6 +2650,7 @@ fn test_force_close_fail_back() { let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; nodes[1].chain_monitor.block_connected_checked(&header, 1, &[&tx], &[1]); + connect_blocks(&nodes[1].chain_monitor, HTLC_FAIL_ANTI_REORG_DELAY, 1, true, header.bitcoin_hash()); // Note no UpdateHTLCs event here from nodes[1] to nodes[0]! check_closed_broadcast!(nodes[1]); @@ -3547,6 +3562,7 @@ fn test_claim_on_remote_sizeable_push_msat() { let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![node_txn[0].clone()] }, 0); + connect_blocks(&nodes[1].chain_monitor, HTLC_FAIL_ANTI_REORG_DELAY, 1, true, header.bitcoin_hash()); check_closed_broadcast!(nodes[1]); let spend_txn = check_spendable_outputs!(nodes[1], 1); assert_eq!(spend_txn.len(), 2); @@ -3570,6 +3586,7 @@ fn test_claim_on_remote_revoked_sizeable_push_msat() { claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage); let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1); + connect_blocks(&nodes[1].chain_monitor, HTLC_FAIL_ANTI_REORG_DELAY, 1, true, header.bitcoin_hash()); check_closed_broadcast!(nodes[1]); let node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap(); @@ -3599,6 +3616,7 @@ fn test_static_spendable_outputs_preimage_tx() { assert!(nodes[1].node.claim_funds(payment_preimage)); check_added_monitors!(nodes[1], 1); nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![commitment_tx[0].clone()] }, 1); + connect_blocks(&nodes[1].chain_monitor, HTLC_FAIL_ANTI_REORG_DELAY, 1, true, header.bitcoin_hash()); let events = nodes[1].node.get_and_clear_pending_msg_events(); match events[0] { MessageSendEvent::UpdateHTLCs { .. } => {}, @@ -3612,9 +3630,9 @@ fn test_static_spendable_outputs_preimage_tx() { // Check B's monitor was able to send back output descriptor event for preimage tx on A's commitment tx let node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap(); // ChannelManager : 1 (local commitment tx), ChannelMonitor: 2 (1 preimage tx) * 2 (block-rescan) check_spends!(node_txn[0], commitment_tx[0].clone()); - assert_eq!(node_txn[0], node_txn[2]); + assert_eq!(node_txn[0], node_txn[1]); assert_eq!(node_txn[0].input[0].witness.last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT); - check_spends!(node_txn[1], chan_1.3.clone()); + check_spends!(node_txn[2], chan_1.3.clone()); let spend_txn = check_spendable_outputs!(nodes[1], 1); // , 0, 0, 1, 1); assert_eq!(spend_txn.len(), 2); @@ -3638,11 +3656,12 @@ fn test_static_spendable_outputs_justice_tx_revoked_commitment_tx() { let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1); + connect_blocks(&nodes[1].chain_monitor, HTLC_FAIL_ANTI_REORG_DELAY, 1, true, header.bitcoin_hash()); check_closed_broadcast!(nodes[1]); - let mut node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap(); + let node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap(); assert_eq!(node_txn.len(), 3); - assert_eq!(node_txn.pop().unwrap(), node_txn[0]); + assert_eq!(node_txn[0], node_txn[1]); assert_eq!(node_txn[0].input.len(), 2); check_spends!(node_txn[0], revoked_local_txn[0].clone()); @@ -3669,31 +3688,33 @@ fn test_static_spendable_outputs_justice_tx_revoked_htlc_timeout_tx() { let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; // A will generate HTLC-Timeout from revoked commitment tx nodes[0].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1); + connect_blocks(&nodes[0].chain_monitor, HTLC_FAIL_ANTI_REORG_DELAY, 1, true, header.bitcoin_hash()); check_closed_broadcast!(nodes[0]); let revoked_htlc_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap(); assert_eq!(revoked_htlc_txn.len(), 3); - assert_eq!(revoked_htlc_txn[0], revoked_htlc_txn[2]); + assert_eq!(revoked_htlc_txn[0], revoked_htlc_txn[1]); assert_eq!(revoked_htlc_txn[0].input.len(), 1); assert_eq!(revoked_htlc_txn[0].input[0].witness.last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT); check_spends!(revoked_htlc_txn[0], revoked_local_txn[0].clone()); - check_spends!(revoked_htlc_txn[1], chan_1.3.clone()); + check_spends!(revoked_htlc_txn[2], chan_1.3.clone()); // B will generate justice tx from A's revoked commitment/HTLC tx nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone(), revoked_htlc_txn[0].clone()] }, 1); + connect_blocks(&nodes[1].chain_monitor, HTLC_FAIL_ANTI_REORG_DELAY, 1, true, header.bitcoin_hash()); check_closed_broadcast!(nodes[1]); let node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap(); assert_eq!(node_txn.len(), 4); - assert_eq!(node_txn[3].input.len(), 1); - check_spends!(node_txn[3], revoked_htlc_txn[0].clone()); + assert_eq!(node_txn[2].input.len(), 1); + check_spends!(node_txn[2], revoked_htlc_txn[0].clone()); // Check B's ChannelMonitor was able to generate the right spendable output descriptor let spend_txn = check_spendable_outputs!(nodes[1], 1); assert_eq!(spend_txn.len(), 3); assert_eq!(spend_txn[0], spend_txn[1]); check_spends!(spend_txn[0], node_txn[0].clone()); - check_spends!(spend_txn[2], node_txn[3].clone()); + check_spends!(spend_txn[2], node_txn[2].clone()); } #[test] @@ -3713,23 +3734,25 @@ fn test_static_spendable_outputs_justice_tx_revoked_htlc_success_tx() { let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; // B will generate HTLC-Success from revoked commitment tx nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1); + connect_blocks(&nodes[1].chain_monitor, HTLC_FAIL_ANTI_REORG_DELAY, 1, true, header.bitcoin_hash()); check_closed_broadcast!(nodes[1]); let revoked_htlc_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap(); assert_eq!(revoked_htlc_txn.len(), 3); - assert_eq!(revoked_htlc_txn[0], revoked_htlc_txn[2]); + assert_eq!(revoked_htlc_txn[0], revoked_htlc_txn[1]); assert_eq!(revoked_htlc_txn[0].input.len(), 1); assert_eq!(revoked_htlc_txn[0].input[0].witness.last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT); check_spends!(revoked_htlc_txn[0], revoked_local_txn[0].clone()); // A will generate justice tx from B's revoked commitment/HTLC tx nodes[0].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone(), revoked_htlc_txn[0].clone()] }, 1); + connect_blocks(&nodes[0].chain_monitor, HTLC_FAIL_ANTI_REORG_DELAY, 1, true, header.bitcoin_hash()); check_closed_broadcast!(nodes[0]); let node_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap(); assert_eq!(node_txn.len(), 4); - assert_eq!(node_txn[3].input.len(), 1); - check_spends!(node_txn[3], revoked_htlc_txn[0].clone()); + assert_eq!(node_txn[2].input.len(), 1); + check_spends!(node_txn[2], revoked_htlc_txn[0].clone()); // Check A's ChannelMonitor was able to generate the right spendable output descriptor let spend_txn = check_spendable_outputs!(nodes[0], 1); @@ -3737,8 +3760,8 @@ fn test_static_spendable_outputs_justice_tx_revoked_htlc_success_tx() { assert_eq!(spend_txn[0], spend_txn[2]); assert_eq!(spend_txn[1], spend_txn[3]); check_spends!(spend_txn[0], revoked_local_txn[0].clone()); // spending to_remote output from revoked local tx - check_spends!(spend_txn[1], node_txn[2].clone()); // spending justice tx output from revoked local tx htlc received output - check_spends!(spend_txn[4], node_txn[3].clone()); // spending justice tx output on htlc success tx + check_spends!(spend_txn[1], node_txn[1].clone()); // spending justice tx output from revoked local tx htlc received output + check_spends!(spend_txn[4], node_txn[2].clone()); // spending justice tx output on htlc success tx } #[test] @@ -3774,34 +3797,36 @@ fn test_onchain_to_onchain_claim() { assert!(updates.update_fail_malformed_htlcs.is_empty()); nodes[2].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![commitment_tx[0].clone()]}, 1); + connect_blocks(&nodes[2].chain_monitor, HTLC_FAIL_ANTI_REORG_DELAY, 1, true, header.bitcoin_hash()); check_closed_broadcast!(nodes[2]); let c_txn = nodes[2].tx_broadcaster.txn_broadcasted.lock().unwrap().clone(); // ChannelManager : 2 (commitment tx, HTLC-Success tx), ChannelMonitor : 1 (HTLC-Success tx) assert_eq!(c_txn.len(), 3); - assert_eq!(c_txn[0], c_txn[2]); - assert_eq!(commitment_tx[0], c_txn[1]); - check_spends!(c_txn[1], chan_2.3.clone()); - check_spends!(c_txn[2], c_txn[1].clone()); - assert_eq!(c_txn[1].input[0].witness.clone().last().unwrap().len(), 71); - assert_eq!(c_txn[2].input[0].witness.clone().last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT); + assert_eq!(c_txn[0], c_txn[1]); + assert_eq!(commitment_tx[0], c_txn[2]); + check_spends!(c_txn[2], chan_2.3.clone()); + check_spends!(c_txn[1], c_txn[2].clone()); + assert_eq!(c_txn[2].input[0].witness.clone().last().unwrap().len(), 71); + assert_eq!(c_txn[1].input[0].witness.clone().last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT); assert!(c_txn[0].output[0].script_pubkey.is_v0_p2wsh()); // revokeable output assert_eq!(c_txn[0].lock_time, 0); // Success tx // So we broadcast C's commitment tx and HTLC-Success on B's chain, we should successfully be able to extract preimage and update downstream monitor nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![c_txn[1].clone(), c_txn[2].clone()]}, 1); + connect_blocks(&nodes[1].chain_monitor, HTLC_FAIL_ANTI_REORG_DELAY, 1, true, header.bitcoin_hash()); { let mut b_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap(); assert_eq!(b_txn.len(), 4); - assert_eq!(b_txn[0], b_txn[3]); - check_spends!(b_txn[1], chan_2.3); // B local commitment tx, issued by ChannelManager - check_spends!(b_txn[2], b_txn[1].clone()); // HTLC-Timeout on B local commitment tx, issued by ChannelManager - assert_eq!(b_txn[2].input[0].witness.clone().last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT); - assert!(b_txn[2].output[0].script_pubkey.is_v0_p2wsh()); // revokeable output - assert_ne!(b_txn[2].lock_time, 0); // Timeout tx - check_spends!(b_txn[0], c_txn[1].clone()); // timeout tx on C remote commitment tx, issued by ChannelMonitor, * 2 due to block rescan + assert_eq!(b_txn[0], b_txn[1]); + check_spends!(b_txn[2], chan_2.3); // B local commitment tx, issued by ChannelManager + check_spends!(b_txn[3], b_txn[2].clone()); // HTLC-Timeout on B local commitment tx, issued by ChannelManager + assert_eq!(b_txn[3].input[0].witness.clone().last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT); + assert!(b_txn[3].output[0].script_pubkey.is_v0_p2wsh()); // revokeable output + assert_ne!(b_txn[3].lock_time, 0); // Timeout tx + check_spends!(b_txn[0], c_txn[2].clone()); // timeout tx on C remote commitment tx, issued by ChannelMonitor, * 2 due to block rescan assert_eq!(b_txn[0].input[0].witness.clone().last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT); assert!(b_txn[0].output[0].script_pubkey.is_v0_p2wpkh()); // direct payment - assert_ne!(b_txn[2].lock_time, 0); // Timeout tx + assert_ne!(b_txn[1].lock_time, 0); // Timeout tx b_txn.clear(); } let msg_events = nodes[1].node.get_and_clear_pending_msg_events(); @@ -3823,14 +3848,15 @@ fn test_onchain_to_onchain_claim() { // Broadcast A's commitment tx on B's chain to see if we are able to claim inbound HTLC with our HTLC-Success tx let commitment_tx = nodes[0].node.channel_state.lock().unwrap().by_id.get(&chan_1.2).unwrap().last_local_commitment_txn.clone(); nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![commitment_tx[0].clone()]}, 1); + connect_blocks(&nodes[1].chain_monitor, HTLC_FAIL_ANTI_REORG_DELAY, 1, true, header.bitcoin_hash()); let b_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap(); assert_eq!(b_txn.len(), 3); - check_spends!(b_txn[1], chan_1.3); // Local commitment tx, issued by ChannelManager - assert_eq!(b_txn[0], b_txn[2]); // HTLC-Success tx, issued by ChannelMonitor, * 2 due to block rescan + check_spends!(b_txn[2], chan_1.3); // Local commitment tx, issued by ChannelManager + assert_eq!(b_txn[0], b_txn[1]); // HTLC-Success tx, issued by ChannelMonitor, * 2 due to block rescan check_spends!(b_txn[0], commitment_tx[0].clone()); assert_eq!(b_txn[0].input[0].witness.clone().last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT); assert!(b_txn[0].output[0].script_pubkey.is_v0_p2wpkh()); // direct payment - assert_eq!(b_txn[2].lock_time, 0); // Success tx + assert_eq!(b_txn[1].lock_time, 0); // Success tx check_closed_broadcast!(nodes[1]); } @@ -3854,27 +3880,29 @@ fn test_duplicate_payment_hash_one_failure_one_success() { let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![commitment_txn[0].clone()] }, 1); + connect_blocks(&nodes[1].chain_monitor, HTLC_FAIL_ANTI_REORG_DELAY, 1, true, header.bitcoin_hash()); check_closed_broadcast!(nodes[1]); let htlc_timeout_tx; { // Extract one of the two HTLC-Timeout transaction let node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap(); assert_eq!(node_txn.len(), 7); - assert_eq!(node_txn[0], node_txn[5]); - assert_eq!(node_txn[1], node_txn[6]); + assert_eq!(node_txn[0], node_txn[2]); + assert_eq!(node_txn[1], node_txn[3]); check_spends!(node_txn[0], commitment_txn[0].clone()); assert_eq!(node_txn[0].input.len(), 1); check_spends!(node_txn[1], commitment_txn[0].clone()); assert_eq!(node_txn[1].input.len(), 1); assert_ne!(node_txn[0].input[0], node_txn[1].input[0]); - check_spends!(node_txn[2], chan_2.3.clone()); - check_spends!(node_txn[3], node_txn[2].clone()); - check_spends!(node_txn[4], node_txn[2].clone()); + check_spends!(node_txn[4], chan_2.3.clone()); + check_spends!(node_txn[5], node_txn[4].clone()); + check_spends!(node_txn[6], node_txn[4].clone()); htlc_timeout_tx = node_txn[1].clone(); } nodes[2].node.claim_funds(our_payment_preimage); nodes[2].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![commitment_txn[0].clone()] }, 1); + connect_blocks(&nodes[2].chain_monitor, HTLC_FAIL_ANTI_REORG_DELAY, 1, true, header.bitcoin_hash()); check_added_monitors!(nodes[2], 2); let events = nodes[2].node.get_and_clear_pending_msg_events(); match events[0] { @@ -3887,11 +3915,11 @@ fn test_duplicate_payment_hash_one_failure_one_success() { } let htlc_success_txn: Vec<_> = nodes[2].tx_broadcaster.txn_broadcasted.lock().unwrap().clone(); assert_eq!(htlc_success_txn.len(), 5); - check_spends!(htlc_success_txn[2], chan_2.3.clone()); - assert_eq!(htlc_success_txn[0], htlc_success_txn[3]); + check_spends!(htlc_success_txn[4], chan_2.3.clone()); + assert_eq!(htlc_success_txn[0], htlc_success_txn[2]); assert_eq!(htlc_success_txn[0].input.len(), 1); assert_eq!(htlc_success_txn[0].input[0].witness.last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT); - assert_eq!(htlc_success_txn[1], htlc_success_txn[4]); + assert_eq!(htlc_success_txn[1], htlc_success_txn[3]); assert_eq!(htlc_success_txn[1].input.len(), 1); assert_eq!(htlc_success_txn[1].input[0].witness.last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT); assert_ne!(htlc_success_txn[0].input[0], htlc_success_txn[1].input[0]); @@ -3968,6 +3996,7 @@ fn test_dynamic_spendable_outputs_local_htlc_success_tx() { check_added_monitors!(nodes[1], 1); let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![local_txn[0].clone()] }, 1); + connect_blocks(&nodes[1].chain_monitor, HTLC_FAIL_ANTI_REORG_DELAY, 1, true, header.bitcoin_hash()); let events = nodes[1].node.get_and_clear_pending_msg_events(); match events[0] { MessageSendEvent::UpdateHTLCs { .. } => {}, @@ -3986,7 +4015,7 @@ fn test_dynamic_spendable_outputs_local_htlc_success_tx() { let spend_txn = check_spendable_outputs!(nodes[1], 1); assert_eq!(spend_txn.len(), 2); check_spends!(spend_txn[0], node_txn[0].clone()); - check_spends!(spend_txn[1], node_txn[2].clone()); + check_spends!(spend_txn[1], node_txn[1].clone()); } fn do_test_fail_backwards_unrevoked_remote_announce(deliver_last_raa: bool, announce_latest: bool) { @@ -5569,13 +5598,6 @@ fn do_test_failure_delay_dust_htlc_local_commitment(announce_latest: bool) { nodes[0].chain_monitor.block_connected_checked(&header, 1, &[&as_prev_commitment_tx[0]], &[1; 1]); } - let events = nodes[0].node.get_and_clear_pending_msg_events(); - assert_eq!(events.len(), 1); - match events[0] { - MessageSendEvent::BroadcastChannelUpdate { .. } => {}, - _ => panic!("Unexpected event"), - } - assert_eq!(nodes[0].node.get_and_clear_pending_events().len(), 0); connect_blocks(&nodes[0].chain_monitor, HTLC_FAIL_ANTI_REORG_DELAY, 1, true, header.bitcoin_hash()); let events = nodes[0].node.get_and_clear_pending_events(); @@ -5595,6 +5617,13 @@ fn do_test_failure_delay_dust_htlc_local_commitment(announce_latest: bool) { _ => panic!("Unexpected event"), } } + + let events = nodes[0].node.get_and_clear_pending_msg_events(); + assert_eq!(events.len(), 1); + match events[0] { + MessageSendEvent::BroadcastChannelUpdate { .. } => {}, + _ => panic!("Unexpected event"), + } } #[test] From 669824f1ae48f676b20d2bf7cbbd714934659d19 Mon Sep 17 00:00:00 2001 From: Antoine Riard Date: Fri, 8 Feb 2019 21:43:56 -0500 Subject: [PATCH 6/6] Add block_disconnecting tests to cancel HTLC failure updates --- src/ln/functional_test_utils.rs | 16 +++++++- src/ln/functional_tests.rs | 68 +++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 1 deletion(-) diff --git a/src/ln/functional_test_utils.rs b/src/ln/functional_test_utils.rs index ef247ae921f..db229cdb980 100644 --- a/src/ln/functional_test_utils.rs +++ b/src/ln/functional_test_utils.rs @@ -15,7 +15,7 @@ use util::logger::Logger; use util::config::UserConfig; use bitcoin::util::hash::BitcoinHash; -use bitcoin::blockdata::block::BlockHeader; +use bitcoin::blockdata::block::{BlockHeader, Block}; use bitcoin::blockdata::transaction::{Transaction, TxOut}; use bitcoin::network::constants::Network; @@ -56,6 +56,20 @@ pub fn connect_blocks(chain: &chaininterface::ChainWatchInterfaceUtil, depth: u3 } } +pub fn disconnect_blocks(chain: &chaininterface::ChainWatchInterfaceUtil, depth: u32, height: u32, parent: bool, prev_blockhash: Sha256d) { + let mut header = BlockHeader { version: 0x2000000, prev_blockhash: if parent { prev_blockhash } else { Default::default() }, merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; + let mut blocks = Vec::new(); + for _ in 0..depth { + blocks.push(Block { header, txdata: Vec::new() }); + header = BlockHeader { version: 0x20000000, prev_blockhash: header.bitcoin_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; + } + let mut height = height; + for block in blocks.pop() { + chain.block_disconnected(&block, height); + height -= 1; + } +} + pub struct Node { pub chain_monitor: Arc, pub tx_broadcaster: Arc, diff --git a/src/ln/functional_tests.rs b/src/ln/functional_tests.rs index 3ad23d5748d..d2d2b244c12 100644 --- a/src/ln/functional_tests.rs +++ b/src/ln/functional_tests.rs @@ -5631,3 +5631,71 @@ fn test_failure_delay_dust_htlc_local_commitment() { do_test_failure_delay_dust_htlc_local_commitment(true); do_test_failure_delay_dust_htlc_local_commitment(false); } + +fn do_test_sweep_outbound_htlc_failure_update(revoked: bool, local: bool) { + // Outbound HTLC-failure updates must be cancelled if we get a reorg before we reach HTLC_FAIL_ANTI_REORG_DELAY. + // Broadcast of revoked remote commitment tx, trigger failure-update of dust/non-dust HTLCs + // Broadcast of remote commitment tx, trigger failure-update of dust-HTLCs + // Broadcast of timeout tx on remote commitment tx, trigger failure-udate of non-dust HTLCs + // Broadcast of local commitment tx, trigger failure-update of dust-HTLCs + // Broadcast of HTLC-timeout tx on local commitment tx, trigger failure-update of non-dust HTLCs + + let nodes = create_network(2); + let chan = create_announced_chan_between_nodes(&nodes, 0, 1); + + let bs_dust_limit = nodes[1].node.channel_state.lock().unwrap().by_id.get(&chan.2).unwrap().our_dust_limit_satoshis; + + let (payment_preimage_1, _) = route_payment(&nodes[0], &[&nodes[1]], bs_dust_limit*1000); + let (payment_preimage_2, _) = route_payment(&nodes[0], &[&nodes[1]], 1000000); + + let as_commitment_tx = nodes[0].node.channel_state.lock().unwrap().by_id.get(&chan.2).unwrap().last_local_commitment_txn.clone(); + let bs_commitment_tx = nodes[1].node.channel_state.lock().unwrap().by_id.get(&chan.2).unwrap().last_local_commitment_txn.clone(); + + // We revoked bs_commitment_tx + if revoked { + let (payment_preimage_3, _) = route_payment(&nodes[0], &[&nodes[1]], 1000000); + claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage_3); + } + + let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; + let header_2 = BlockHeader { version: 0x20000000, prev_blockhash: header.bitcoin_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; + let mut timeout_tx = Vec::new(); + if local { + // We fail dust-HTLC 1 by broadcast of local commitment tx + nodes[0].chain_monitor.block_connected_checked(&header, 1, &[&as_commitment_tx[0]], &[1; 1]); + timeout_tx.push(nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap()[0].clone()); + assert_eq!(timeout_tx[0].input[0].witness.last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT); + // We fail dust-HTLC 2 by broadcast of local HTLC-timeout tx on local commitment tx + nodes[0].chain_monitor.block_connected_checked(&header_2, 1, &[&timeout_tx[0]], &[1; 1]); + } else { + // We fail dust-HTLC 1 by broadcast of remote commitment tx. If revoked, fail also non-dust HTLC + nodes[0].chain_monitor.block_connected_checked(&header, 1, &[&bs_commitment_tx[0]], &[1; 1]); + if !revoked { + timeout_tx.push(nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap()[0].clone()); + assert_eq!(timeout_tx[0].input[0].witness.last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT); + // We fail non-dust-HTLC 2 by broadcast of local timeout tx on remote commitment tx + nodes[0].chain_monitor.block_connected_checked(&header_2, 1, &[&timeout_tx[0]], &[1; 1]); + } + } + + assert_eq!(nodes[0].node.get_and_clear_pending_events().len(), 0); + // We connect 3 blocks, not enough to reach HTLC_FAIL_ANTI_REORG_DELAY + connect_blocks(&nodes[0].chain_monitor, 3, 2, true, header.bitcoin_hash()); + assert_eq!(nodes[0].node.get_and_clear_pending_events().len(), 0); + + // We disconnect 5 blocks, updates should have been cancelled and HTLC still claimable + disconnect_blocks(&nodes[0].chain_monitor, 3, 5, true, header.bitcoin_hash()); + nodes[0].chain_monitor.block_disconnected(&Block { header: header_2, txdata: if !revoked { timeout_tx } else { vec![] } }, 2); + nodes[0].chain_monitor.block_disconnected(&Block { header, txdata: vec![if local { as_commitment_tx[0].clone() } else { bs_commitment_tx[0].clone() }] }, 1); + assert_eq!(nodes[0].node.get_and_clear_pending_events().len(), 0); + + claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage_1); + claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage_2); +} + +#[test] +fn test_sweep_outbound_htlc_failure_update() { + do_test_sweep_outbound_htlc_failure_update(false, true); + do_test_sweep_outbound_htlc_failure_update(false, false); + do_test_sweep_outbound_htlc_failure_update(true, false); +}