Skip to content

Commit b8d0a7f

Browse files
committed
Do not test any block-contents-rescan cases
In anticipation for removing support for users calling block_connected multiple times for the same block to include all relevant transactions in the next PR, this commit stops testing such cases. Specifically, users who filter blocks for relevant transactions before calling block_connected will need to filter by including any transactions which spend a previously-matched transaction in the same block (and we now do so in our own filtering logic, which is also used in our testing).
1 parent dcb0659 commit b8d0a7f

File tree

2 files changed

+48
-34
lines changed

2 files changed

+48
-34
lines changed

lightning/src/chain/chaininterface.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -377,10 +377,19 @@ impl ChainWatchInterface for ChainWatchInterfaceUtil {
377377

378378
fn filter_block(&self, block: &Block) -> Vec<usize> {
379379
let mut matched_index = Vec::new();
380+
let mut match_set = HashSet::new();
380381
{
381382
let watched = self.watched.lock().unwrap();
382383
for (index, transaction) in block.txdata.iter().enumerate() {
383-
if self.does_match_tx_unguarded(transaction, &watched) {
384+
let mut matched = self.does_match_tx_unguarded(transaction, &watched);
385+
for input in transaction.input.iter() {
386+
if matched || match_set.contains(&input.previous_output.txid) {
387+
matched = true;
388+
break;
389+
}
390+
}
391+
if matched {
392+
match_set.insert(transaction.txid());
384393
matched_index.push(index);
385394
}
386395
}

lightning/src/ln/functional_tests.rs

Lines changed: 38 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -5037,33 +5037,32 @@ fn test_static_spendable_outputs_justice_tx_revoked_htlc_timeout_tx() {
50375037
check_added_monitors!(nodes[1], 1);
50385038

50395039
let node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap();
5040-
assert_eq!(node_txn.len(), 4); // ChannelMonitor: justice tx on revoked commitment, justice tx on revoked HTLC-timeout, adjusted justice tx, ChannelManager: local commitment tx
5040+
assert_eq!(node_txn.len(), 3); // ChannelMonitor: bogus justics tx, justice tx on revoked outputs, ChannelManager: local commitment tx
50415041
// The first transaction generated is bogus - it spends both outputs of revoked_local_txn[0]
50425042
// including the one already spent by revoked_htlc_txn[0]. That's OK, we'll spend with valid
50435043
// transactions next...
5044-
assert_eq!(node_txn[0].input.len(), 2);
5045-
check_spends!(node_txn[0], revoked_local_txn[0]);
5044+
assert_eq!(node_txn[0].input.len(), 3);
5045+
check_spends!(node_txn[0], revoked_local_txn[0], revoked_htlc_txn[0]);
50465046

5047-
check_spends!(node_txn[1], chan_1.3);
5047+
assert_eq!(node_txn[1].input.len(), 2);
5048+
check_spends!(node_txn[1], revoked_local_txn[0], revoked_htlc_txn[0]);
5049+
assert!((node_txn[1].input[1].previous_output.txid == revoked_htlc_txn[0].txid() &&
5050+
node_txn[1].input[0].previous_output != revoked_htlc_txn[0].input[0].previous_output) ||
5051+
(node_txn[1].input[0].previous_output.txid == revoked_htlc_txn[0].txid() &&
5052+
node_txn[1].input[1].previous_output != revoked_htlc_txn[0].input[0].previous_output));
50485053

50495054
assert_eq!(node_txn[2].input.len(), 1);
5050-
check_spends!(node_txn[2], revoked_htlc_txn[0]);
5051-
assert_eq!(node_txn[3].input.len(), 1);
5052-
check_spends!(node_txn[3], revoked_local_txn[0]);
5055+
check_spends!(node_txn[2], chan_1.3);
50535056

50545057
let header_1 = BlockHeader { version: 0x20000000, prev_blockhash: header.block_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
5055-
nodes[1].block_notifier.block_connected(&Block { header: header_1, txdata: vec![node_txn[2].clone(), node_txn[3].clone()] }, 1);
5058+
nodes[1].block_notifier.block_connected(&Block { header: header_1, txdata: vec![node_txn[1].clone()] }, 1);
50565059
connect_blocks(&nodes[1].block_notifier, ANTI_REORG_DELAY - 1, 1, true, header.block_hash());
50575060

5058-
// Note that nodes[1]'s tx_broadcaster is still locked, so if we get here the channelmonitor
5059-
// didn't try to generate any new transactions.
5060-
5061-
// Check B's ChannelMonitor was able to generate the right spendable output descriptor which
5062-
// allows the user to spend the newly-confirmed outputs.
5061+
// Check B's ChannelMonitor was able to generate the right spendable output descriptor
50635062
let spend_txn = check_spendable_outputs!(nodes[1], 1, node_cfgs[1].keys_manager, 100000);
5064-
assert_eq!(spend_txn.len(), 2);
5065-
check_spends!(spend_txn[0], node_txn[2]);
5066-
check_spends!(spend_txn[1], node_txn[3]);
5063+
assert_eq!(spend_txn.len(), 1);
5064+
assert_eq!(spend_txn[0].input.len(), 1);
5065+
check_spends!(spend_txn[0], node_txn[1]);
50675066
}
50685067

50695068
#[test]
@@ -5108,33 +5107,36 @@ fn test_static_spendable_outputs_justice_tx_revoked_htlc_success_tx() {
51085107
let node_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap();
51095108
assert_eq!(node_txn.len(), 3); // ChannelMonitor: justice tx on revoked commitment, justice tx on revoked HTLC-success, ChannelManager: local commitment tx
51105109

5111-
// The first transaction generated is just in case of a reorg - it double-spends
5112-
// revoked_htlc_txn[0], spending the HTLC output on revoked_local_txn[0] directly.
5113-
assert_eq!(node_txn[0].input.len(), 1);
5114-
check_spends!(node_txn[0], revoked_local_txn[0]);
5115-
assert_eq!(node_txn[0].input[0].previous_output, revoked_htlc_txn[0].input[0].previous_output);
5110+
// The first transaction generated is bogus - it spends both outputs of revoked_local_txn[0]
5111+
// including the one already spent by revoked_htlc_txn[0]. That's OK, we'll spend with valid
5112+
// transactions next...
5113+
assert_eq!(node_txn[0].input.len(), 2);
5114+
check_spends!(node_txn[0], revoked_local_txn[0], revoked_htlc_txn[0]);
5115+
assert!((node_txn[0].input[1].previous_output.txid == revoked_htlc_txn[0].txid() &&
5116+
node_txn[0].input[0].previous_output == revoked_htlc_txn[0].input[0].previous_output) ||
5117+
(node_txn[0].input[0].previous_output.txid == revoked_htlc_txn[0].txid() &&
5118+
node_txn[0].input[1].previous_output == revoked_htlc_txn[0].input[0].previous_output));
51165119

5117-
assert_eq!(node_txn[2].input.len(), 1);
5118-
check_spends!(node_txn[2], revoked_htlc_txn[0]);
5120+
assert_eq!(node_txn[1].input.len(), 1);
5121+
check_spends!(node_txn[1], revoked_htlc_txn[0]);
51195122

5120-
check_spends!(node_txn[1], chan_1.3);
5123+
check_spends!(node_txn[2], chan_1.3);
51215124

51225125
let header_1 = BlockHeader { version: 0x20000000, prev_blockhash: header.block_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
5123-
nodes[0].block_notifier.block_connected(&Block { header: header_1, txdata: vec![node_txn[2].clone()] }, 1);
5126+
nodes[0].block_notifier.block_connected(&Block { header: header_1, txdata: vec![node_txn[1].clone()] }, 1);
51245127
connect_blocks(&nodes[0].block_notifier, ANTI_REORG_DELAY - 1, 1, true, header.block_hash());
51255128

51265129
// Note that nodes[0]'s tx_broadcaster is still locked, so if we get here the channelmonitor
51275130
// didn't try to generate any new transactions.
51285131

51295132
// Check A's ChannelMonitor was able to generate the right spendable output descriptor
51305133
let spend_txn = check_spendable_outputs!(nodes[0], 1, node_cfgs[0].keys_manager, 100000);
5131-
assert_eq!(spend_txn.len(), 4); // Duplicated SpendableOutput due to block rescan after revoked htlc output tracking
5134+
assert_eq!(spend_txn.len(), 3); // Duplicated SpendableOutput due to block rescan after revoked htlc output tracking
51325135
assert_eq!(spend_txn[0], spend_txn[1]);
5133-
assert_eq!(spend_txn[0], spend_txn[2]);
51345136
assert_eq!(spend_txn[0].input.len(), 1);
51355137
check_spends!(spend_txn[0], revoked_local_txn[0]); // spending to_remote output from revoked local tx
51365138
assert_ne!(spend_txn[0].input[0].previous_output, revoked_htlc_txn[0].input[0].previous_output);
5137-
check_spends!(spend_txn[3], node_txn[2]); // spending justice tx output on the htlc success tx
5139+
check_spends!(spend_txn[2], node_txn[1]); // spending justice tx output on the htlc success tx
51385140
}
51395141

51405142
#[test]
@@ -7796,11 +7798,11 @@ fn test_bump_penalty_txn_on_revoked_htlcs() {
77967798
}
77977799

77987800
// Broadcast set of revoked txn on A
7799-
let header_128 = connect_blocks(&nodes[0].block_notifier, 128, 0, true, header.block_hash());
7801+
let header_128 = BlockHeader { version: 0x20000000, prev_blockhash: header.block_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
7802+
nodes[0].block_notifier.block_connected(&Block { header: header_128, txdata: vec![revoked_local_txn[0].clone()] }, 128);
78007803
expect_pending_htlcs_forwardable_ignore!(nodes[0]);
7801-
7802-
let header_129 = BlockHeader { version: 0x20000000, prev_blockhash: header_128, merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
7803-
nodes[0].block_notifier.block_connected(&Block { header: header_129, txdata: vec![revoked_local_txn[0].clone(), revoked_htlc_txn[0].clone(), revoked_htlc_txn[1].clone()] }, 129);
7804+
let header_129 = BlockHeader { version: 0x20000000, prev_blockhash: header_128.block_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
7805+
nodes[0].block_notifier.block_connected(&Block { header: header_129, txdata: vec![revoked_htlc_txn[0].clone(), revoked_htlc_txn[1].clone()] }, 129);
78047806
let first;
78057807
let feerate_1;
78067808
let penalty_txn;
@@ -7836,6 +7838,7 @@ fn test_bump_penalty_txn_on_revoked_htlcs() {
78367838
assert_eq!(node_txn[4].input.len(), 2);
78377839
assert_eq!(node_txn[4].output.len(), 1);
78387840
check_spends!(node_txn[4], revoked_htlc_txn[0], revoked_htlc_txn[1]);
7841+
78397842
first = node_txn[4].txid();
78407843
// Store both feerates for later comparison
78417844
let fee_1 = revoked_htlc_txn[0].output[0].value + revoked_htlc_txn[1].output[0].value - node_txn[4].output[0].value;
@@ -7847,6 +7850,8 @@ fn test_bump_penalty_txn_on_revoked_htlcs() {
78477850
// Connect one more block to see if bumped penalty are issued for HTLC txn
78487851
let header_130 = BlockHeader { version: 0x20000000, prev_blockhash: header_129.block_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
78497852
nodes[0].block_notifier.block_connected(&Block { header: header_130, txdata: penalty_txn }, 130);
7853+
let header_131 = BlockHeader { version: 0x20000000, prev_blockhash: header_130.block_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
7854+
nodes[0].block_notifier.block_connected(&Block { header: header_131, txdata: Vec::new() }, 131);
78507855
{
78517856
let mut node_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap();
78527857
assert_eq!(node_txn.len(), 2); // 2 bumped penalty txn on revoked commitment tx
@@ -7863,7 +7868,7 @@ fn test_bump_penalty_txn_on_revoked_htlcs() {
78637868
};
78647869

78657870
// Few more blocks to confirm penalty txn
7866-
let header_135 = connect_blocks(&nodes[0].block_notifier, 5, 130, true, header_130.block_hash());
7871+
let header_135 = connect_blocks(&nodes[0].block_notifier, 4, 131, true, header_131.block_hash());
78677872
assert!(nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().is_empty());
78687873
let header_144 = connect_blocks(&nodes[0].block_notifier, 9, 135, true, header_135);
78697874
let node_txn = {

0 commit comments

Comments
 (0)