Skip to content

Commit 8640173

Browse files
authored
Merge pull request #715 from TheBlueMatt/2020-09-no-rescan-tests
Do not test any block-contents-rescan cases
2 parents 640ae63 + 38dacf1 commit 8640173

File tree

4 files changed

+116
-27
lines changed

4 files changed

+116
-27
lines changed

lightning/src/chain/chaininterface.rs

+13-1
Original file line numberDiff line numberDiff line change
@@ -377,10 +377,22 @@ impl ChainWatchInterface for ChainWatchInterfaceUtil {
377377

378378
fn filter_block(&self, block: &Block) -> Vec<usize> {
379379
let mut matched_index = Vec::new();
380+
let mut matched_txids = 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+
// A tx matches the filter if it either matches the filter directly (via
385+
// does_match_tx_unguarded) or if it is a descendant of another matched
386+
// transaction within the same block, which we check for in the loop.
387+
let mut matched = self.does_match_tx_unguarded(transaction, &watched);
388+
for input in transaction.input.iter() {
389+
if matched || matched_txids.contains(&input.previous_output.txid) {
390+
matched = true;
391+
break;
392+
}
393+
}
394+
if matched {
395+
matched_txids.insert(transaction.txid());
384396
matched_index.push(index);
385397
}
386398
}

lightning/src/chain/keysinterface.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ use ln::msgs::DecodeError;
4545
/// spend on-chain. The information needed to do this is provided in this enum, including the
4646
/// outpoint describing which txid and output index is available, the full output which exists at
4747
/// that txid/index, and any keys or other information required to sign.
48-
#[derive(Clone, PartialEq)]
48+
#[derive(Clone, Debug, PartialEq)]
4949
pub enum SpendableOutputDescriptor {
5050
/// An output to a script which was provided via KeysInterface, thus you should already know
5151
/// how to spend it. No keys are provided as rust-lightning was never given any keys - only the

lightning/src/ln/functional_tests.rs

+101-25
Original file line numberDiff line numberDiff line change
@@ -5037,24 +5037,34 @@ 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
5041-
assert_eq!(node_txn[0].input.len(), 2);
5042-
check_spends!(node_txn[0], revoked_local_txn[0]);
5043-
check_spends!(node_txn[1], chan_1.3);
5040+
assert_eq!(node_txn.len(), 3); // ChannelMonitor: bogus justice tx, justice tx on revoked outputs, ChannelManager: local commitment tx
5041+
// The first transaction generated is bogus - it spends both outputs of revoked_local_txn[0]
5042+
// including the one already spent by revoked_htlc_txn[0]. That's OK, we'll spend with valid
5043+
// transactions next...
5044+
assert_eq!(node_txn[0].input.len(), 3);
5045+
check_spends!(node_txn[0], revoked_local_txn[0], revoked_htlc_txn[0]);
5046+
5047+
assert_eq!(node_txn[1].input.len(), 2);
5048+
check_spends!(node_txn[1], revoked_local_txn[0], revoked_htlc_txn[0]);
5049+
if node_txn[1].input[1].previous_output.txid == revoked_htlc_txn[0].txid() {
5050+
assert_ne!(node_txn[1].input[0].previous_output, revoked_htlc_txn[0].input[0].previous_output);
5051+
} else {
5052+
assert_eq!(node_txn[1].input[0].previous_output.txid, revoked_htlc_txn[0].txid());
5053+
assert_ne!(node_txn[1].input[1].previous_output, revoked_htlc_txn[0].input[0].previous_output);
5054+
}
5055+
50445056
assert_eq!(node_txn[2].input.len(), 1);
5045-
check_spends!(node_txn[2], revoked_htlc_txn[0]);
5046-
assert_eq!(node_txn[3].input.len(), 1);
5047-
check_spends!(node_txn[3], revoked_local_txn[0]);
5057+
check_spends!(node_txn[2], chan_1.3);
50485058

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

50535063
// Check B's ChannelMonitor was able to generate the right spendable output descriptor
50545064
let spend_txn = check_spendable_outputs!(nodes[1], 1, node_cfgs[1].keys_manager, 100000);
5055-
assert_eq!(spend_txn.len(), 2);
5056-
check_spends!(spend_txn[0], node_txn[0]);
5057-
check_spends!(spend_txn[1], node_txn[2]);
5065+
assert_eq!(spend_txn.len(), 1);
5066+
assert_eq!(spend_txn[0].input.len(), 1);
5067+
check_spends!(spend_txn[0], node_txn[1]);
50585068
}
50595069

50605070
#[test]
@@ -5072,6 +5082,9 @@ fn test_static_spendable_outputs_justice_tx_revoked_htlc_success_tx() {
50725082
assert_eq!(revoked_local_txn[0].input.len(), 1);
50735083
assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan_1.3.txid());
50745084

5085+
// The to-be-revoked commitment tx should have one HTLC and one to_remote output
5086+
assert_eq!(revoked_local_txn[0].output.len(), 2);
5087+
50755088
claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage, 3_000_000);
50765089

50775090
let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
@@ -5086,28 +5099,50 @@ fn test_static_spendable_outputs_justice_tx_revoked_htlc_success_tx() {
50865099
assert_eq!(revoked_htlc_txn[0].input[0].witness.last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT);
50875100
check_spends!(revoked_htlc_txn[0], revoked_local_txn[0]);
50885101

5102+
// Check that the unspent (of two) outputs on revoked_local_txn[0] is a P2WPKH:
5103+
let unspent_local_txn_output = revoked_htlc_txn[0].input[0].previous_output.vout as usize ^ 1;
5104+
assert_eq!(revoked_local_txn[0].output[unspent_local_txn_output].script_pubkey.len(), 2 + 20); // P2WPKH
5105+
50895106
// A will generate justice tx from B's revoked commitment/HTLC tx
50905107
nodes[0].block_notifier.block_connected(&Block { header, txdata: vec![revoked_local_txn[0].clone(), revoked_htlc_txn[0].clone()] }, 1);
50915108
check_closed_broadcast!(nodes[0], false);
50925109
check_added_monitors!(nodes[0], 1);
50935110

50945111
let node_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap();
50955112
assert_eq!(node_txn.len(), 3); // ChannelMonitor: justice tx on revoked commitment, justice tx on revoked HTLC-success, ChannelManager: local commitment tx
5096-
assert_eq!(node_txn[2].input.len(), 1);
5097-
check_spends!(node_txn[2], revoked_htlc_txn[0]);
5113+
5114+
// The first transaction generated is bogus - it spends both outputs of revoked_local_txn[0]
5115+
// including the one already spent by revoked_htlc_txn[0]. That's OK, we'll spend with valid
5116+
// transactions next...
5117+
assert_eq!(node_txn[0].input.len(), 2);
5118+
check_spends!(node_txn[0], revoked_local_txn[0], revoked_htlc_txn[0]);
5119+
if node_txn[0].input[1].previous_output.txid == revoked_htlc_txn[0].txid() {
5120+
assert_eq!(node_txn[0].input[0].previous_output, revoked_htlc_txn[0].input[0].previous_output);
5121+
} else {
5122+
assert_eq!(node_txn[0].input[0].previous_output.txid, revoked_htlc_txn[0].txid());
5123+
assert_eq!(node_txn[0].input[1].previous_output, revoked_htlc_txn[0].input[0].previous_output);
5124+
}
5125+
5126+
assert_eq!(node_txn[1].input.len(), 1);
5127+
check_spends!(node_txn[1], revoked_htlc_txn[0]);
5128+
5129+
check_spends!(node_txn[2], chan_1.3);
50985130

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

5135+
// Note that nodes[0]'s tx_broadcaster is still locked, so if we get here the channelmonitor
5136+
// didn't try to generate any new transactions.
5137+
51035138
// Check A's ChannelMonitor was able to generate the right spendable output descriptor
51045139
let spend_txn = check_spendable_outputs!(nodes[0], 1, node_cfgs[0].keys_manager, 100000);
5105-
assert_eq!(spend_txn.len(), 5); // Duplicated SpendableOutput due to block rescan after revoked htlc output tracking
5140+
assert_eq!(spend_txn.len(), 3); // Duplicated SpendableOutput due to block rescan after revoked htlc output tracking
51065141
assert_eq!(spend_txn[0], spend_txn[1]);
5107-
assert_eq!(spend_txn[0], spend_txn[2]);
5142+
assert_eq!(spend_txn[0].input.len(), 1);
51085143
check_spends!(spend_txn[0], revoked_local_txn[0]); // spending to_remote output from revoked local tx
5109-
check_spends!(spend_txn[3], node_txn[0]); // spending justice tx output from revoked local tx htlc received output
5110-
check_spends!(spend_txn[4], node_txn[2]); // spending justice tx output on htlc success tx
5144+
assert_ne!(spend_txn[0].input[0].previous_output, revoked_htlc_txn[0].input[0].previous_output);
5145+
check_spends!(spend_txn[2], node_txn[1]); // spending justice tx output on the htlc success tx
51115146
}
51125147

51135148
#[test]
@@ -7757,54 +7792,95 @@ fn test_bump_penalty_txn_on_revoked_htlcs() {
77577792
check_spends!(revoked_htlc_txn[0], revoked_local_txn[0]);
77587793
assert_eq!(revoked_htlc_txn[1].input.len(), 1);
77597794
assert_eq!(revoked_htlc_txn[1].input[0].witness.last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT);
7795+
assert_eq!(revoked_htlc_txn[1].output.len(), 1);
77607796
check_spends!(revoked_htlc_txn[1], revoked_local_txn[0]);
77617797
} else if revoked_htlc_txn[1].input[0].witness.last().unwrap().len() == ACCEPTED_HTLC_SCRIPT_WEIGHT {
77627798
assert_eq!(revoked_htlc_txn[1].input.len(), 1);
77637799
check_spends!(revoked_htlc_txn[1], revoked_local_txn[0]);
77647800
assert_eq!(revoked_htlc_txn[0].input.len(), 1);
77657801
assert_eq!(revoked_htlc_txn[0].input[0].witness.last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT);
7802+
assert_eq!(revoked_htlc_txn[0].output.len(), 1);
77667803
check_spends!(revoked_htlc_txn[0], revoked_local_txn[0]);
77677804
}
77687805

77697806
// Broadcast set of revoked txn on A
7770-
let header_128 = connect_blocks(&nodes[0].block_notifier, 128, 0, true, header.block_hash());
7807+
let header_128 = BlockHeader { version: 0x20000000, prev_blockhash: header.block_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
7808+
nodes[0].block_notifier.block_connected(&Block { header: header_128, txdata: vec![revoked_local_txn[0].clone()] }, 128);
77717809
expect_pending_htlcs_forwardable_ignore!(nodes[0]);
7772-
7773-
let header_129 = BlockHeader { version: 0x20000000, prev_blockhash: header_128, merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
7774-
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);
7810+
let header_129 = BlockHeader { version: 0x20000000, prev_blockhash: header_128.block_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
7811+
nodes[0].block_notifier.block_connected(&Block { header: header_129, txdata: vec![revoked_htlc_txn[0].clone(), revoked_htlc_txn[1].clone()] }, 129);
77757812
let first;
77767813
let feerate_1;
77777814
let penalty_txn;
77787815
{
77797816
let mut node_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap();
77807817
assert_eq!(node_txn.len(), 5); // 3 penalty txn on revoked commitment tx + A commitment tx + 1 penalty tnx on revoked HTLC txn
77817818
// Verify claim tx are spending revoked HTLC txn
7819+
7820+
// node_txn 0-2 each spend a separate revoked output from revoked_local_txn[0]
7821+
// Note that node_txn[0] and node_txn[1] are bogus - they double spend the revoked_htlc_txn
7822+
// which are included in the same block (they are broadcasted because we scan the
7823+
// transactions linearly and generate claims as we go, they likely should be removed in the
7824+
// future).
7825+
assert_eq!(node_txn[0].input.len(), 1);
7826+
check_spends!(node_txn[0], revoked_local_txn[0]);
7827+
assert_eq!(node_txn[1].input.len(), 1);
7828+
check_spends!(node_txn[1], revoked_local_txn[0]);
7829+
assert_eq!(node_txn[2].input.len(), 1);
7830+
check_spends!(node_txn[2], revoked_local_txn[0]);
7831+
7832+
// Each of the three justice transactions claim a separate (single) output of the three
7833+
// available, which we check here:
7834+
assert_ne!(node_txn[0].input[0].previous_output, node_txn[1].input[0].previous_output);
7835+
assert_ne!(node_txn[0].input[0].previous_output, node_txn[2].input[0].previous_output);
7836+
assert_ne!(node_txn[1].input[0].previous_output, node_txn[2].input[0].previous_output);
7837+
7838+
assert_eq!(node_txn[0].input[0].previous_output, revoked_htlc_txn[0].input[0].previous_output);
7839+
assert_eq!(node_txn[1].input[0].previous_output, revoked_htlc_txn[1].input[0].previous_output);
7840+
7841+
// node_txn[3] is the local commitment tx broadcast just because (and somewhat in case of
7842+
// reorgs, though its not clear its ever worth broadcasting conflicting txn like this when
7843+
// a remote commitment tx has already been confirmed).
7844+
check_spends!(node_txn[3], chan.3);
7845+
7846+
// node_txn[4] spends the revoked outputs from the revoked_htlc_txn (which only have one
7847+
// output, checked above).
77827848
assert_eq!(node_txn[4].input.len(), 2);
77837849
assert_eq!(node_txn[4].output.len(), 1);
77847850
check_spends!(node_txn[4], revoked_htlc_txn[0], revoked_htlc_txn[1]);
7851+
77857852
first = node_txn[4].txid();
77867853
// Store both feerates for later comparison
77877854
let fee_1 = revoked_htlc_txn[0].output[0].value + revoked_htlc_txn[1].output[0].value - node_txn[4].output[0].value;
77887855
feerate_1 = fee_1 * 1000 / node_txn[4].get_weight() as u64;
7789-
penalty_txn = vec![node_txn[0].clone(), node_txn[1].clone(), node_txn[2].clone()];
7856+
penalty_txn = vec![node_txn[2].clone()];
77907857
node_txn.clear();
77917858
}
77927859

7793-
// Connect three more block to see if bumped penalty are issued for HTLC txn
7860+
// Connect one more block to see if bumped penalty are issued for HTLC txn
77947861
let header_130 = BlockHeader { version: 0x20000000, prev_blockhash: header_129.block_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
77957862
nodes[0].block_notifier.block_connected(&Block { header: header_130, txdata: penalty_txn }, 130);
7863+
let header_131 = BlockHeader { version: 0x20000000, prev_blockhash: header_130.block_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
7864+
nodes[0].block_notifier.block_connected(&Block { header: header_131, txdata: Vec::new() }, 131);
77967865
{
77977866
let mut node_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap();
77987867
assert_eq!(node_txn.len(), 2); // 2 bumped penalty txn on revoked commitment tx
77997868

78007869
check_spends!(node_txn[0], revoked_local_txn[0]);
78017870
check_spends!(node_txn[1], revoked_local_txn[0]);
7871+
// Note that these are both bogus - they spend outputs already claimed in block 129:
7872+
if node_txn[0].input[0].previous_output == revoked_htlc_txn[0].input[0].previous_output {
7873+
assert_eq!(node_txn[1].input[0].previous_output, revoked_htlc_txn[1].input[0].previous_output);
7874+
} else {
7875+
assert_eq!(node_txn[0].input[0].previous_output, revoked_htlc_txn[1].input[0].previous_output);
7876+
assert_eq!(node_txn[1].input[0].previous_output, revoked_htlc_txn[0].input[0].previous_output);
7877+
}
78027878

78037879
node_txn.clear();
78047880
};
78057881

78067882
// Few more blocks to confirm penalty txn
7807-
let header_135 = connect_blocks(&nodes[0].block_notifier, 5, 130, true, header_130.block_hash());
7883+
let header_135 = connect_blocks(&nodes[0].block_notifier, 4, 131, true, header_131.block_hash());
78087884
assert!(nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().is_empty());
78097885
let header_144 = connect_blocks(&nodes[0].block_notifier, 9, 135, true, header_135);
78107886
let node_txn = {

lightning/src/util/events.rs

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ use std::time::Duration;
3131
/// Note that while Writeable and Readable are implemented for Event, you probably shouldn't use
3232
/// them directly as they don't round-trip exactly (for example FundingGenerationReady is never
3333
/// written as it makes no sense to respond to it after reconnecting to peers).
34+
#[derive(Debug)]
3435
pub enum Event {
3536
/// Used to indicate that the client should generate a funding transaction with the given
3637
/// parameters and then call ChannelManager::funding_transaction_generated.

0 commit comments

Comments
 (0)