Skip to content

Commit 336d815

Browse files
authored
Merge pull request #2606 from wpaulino/anchors-counterparty-htlc-claim-sequence
Use correct input sequence for HTLC claims from counterparty commitments
2 parents 7b4fb9d + 3c83783 commit 336d815

File tree

2 files changed

+82
-23
lines changed

2 files changed

+82
-23
lines changed

lightning/src/chain/package.rs

+28-7
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,32 @@ impl PackageSolvingData {
551551
_ => { mem::discriminant(self) == mem::discriminant(&input) }
552552
}
553553
}
554+
fn as_tx_input(&self, previous_output: BitcoinOutPoint) -> TxIn {
555+
let sequence = match self {
556+
PackageSolvingData::RevokedOutput(_) => Sequence::ENABLE_RBF_NO_LOCKTIME,
557+
PackageSolvingData::RevokedHTLCOutput(_) => Sequence::ENABLE_RBF_NO_LOCKTIME,
558+
PackageSolvingData::CounterpartyOfferedHTLCOutput(outp) => if outp.channel_type_features.supports_anchors_zero_fee_htlc_tx() {
559+
Sequence::from_consensus(1)
560+
} else {
561+
Sequence::ENABLE_RBF_NO_LOCKTIME
562+
},
563+
PackageSolvingData::CounterpartyReceivedHTLCOutput(outp) => if outp.channel_type_features.supports_anchors_zero_fee_htlc_tx() {
564+
Sequence::from_consensus(1)
565+
} else {
566+
Sequence::ENABLE_RBF_NO_LOCKTIME
567+
},
568+
_ => {
569+
debug_assert!(false, "This should not be reachable by 'untractable' or 'malleable with external funding' packages");
570+
Sequence::ENABLE_RBF_NO_LOCKTIME
571+
},
572+
};
573+
TxIn {
574+
previous_output,
575+
script_sig: Script::new(),
576+
sequence,
577+
witness: Witness::new(),
578+
}
579+
}
554580
fn finalize_input<Signer: WriteableEcdsaChannelSigner>(&self, bumped_tx: &mut Transaction, i: usize, onchain_handler: &mut OnchainTxHandler<Signer>) -> bool {
555581
match self {
556582
PackageSolvingData::RevokedOutput(ref outp) => {
@@ -895,13 +921,8 @@ impl PackageTemplate {
895921
value,
896922
}],
897923
};
898-
for (outpoint, _) in self.inputs.iter() {
899-
bumped_tx.input.push(TxIn {
900-
previous_output: *outpoint,
901-
script_sig: Script::new(),
902-
sequence: Sequence::ENABLE_RBF_NO_LOCKTIME,
903-
witness: Witness::new(),
904-
});
924+
for (outpoint, outp) in self.inputs.iter() {
925+
bumped_tx.input.push(outp.as_tx_input(*outpoint));
905926
}
906927
for (i, (outpoint, out)) in self.inputs.iter().enumerate() {
907928
log_debug!(logger, "Adding claiming input for outpoint {}:{}", outpoint.txid, outpoint.vout);

lightning/src/ln/monitor_tests.rs

+54-16
Original file line numberDiff line numberDiff line change
@@ -1867,23 +1867,35 @@ fn test_yield_anchors_events() {
18671867
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(anchors_config), Some(anchors_config)]);
18681868
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
18691869

1870-
let chan_id = create_announced_chan_between_nodes_with_value(
1870+
let (_, _, chan_id, funding_tx) = create_announced_chan_between_nodes_with_value(
18711871
&nodes, 0, 1, 1_000_000, 500_000_000
1872-
).2;
1873-
route_payment(&nodes[0], &[&nodes[1]], 1_000_000);
1874-
let (payment_preimage, payment_hash, ..) = route_payment(&nodes[1], &[&nodes[0]], 1_000_000);
1872+
);
1873+
let (payment_preimage_1, payment_hash_1, ..) = route_payment(&nodes[0], &[&nodes[1]], 1_000_000);
1874+
let (payment_preimage_2, payment_hash_2, ..) = route_payment(&nodes[1], &[&nodes[0]], 2_000_000);
18751875

18761876
assert!(nodes[0].node.get_and_clear_pending_events().is_empty());
1877+
assert!(nodes[1].node.get_and_clear_pending_events().is_empty());
18771878

18781879
*nodes[0].fee_estimator.sat_per_kw.lock().unwrap() *= 2;
1880+
18791881
connect_blocks(&nodes[0], TEST_FINAL_CLTV + LATENCY_GRACE_PERIOD_BLOCKS + 1);
1880-
check_closed_broadcast!(&nodes[0], true);
1881-
assert!(nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().is_empty());
1882+
assert!(nodes[0].tx_broadcaster.txn_broadcast().is_empty());
1883+
1884+
connect_blocks(&nodes[1], TEST_FINAL_CLTV + LATENCY_GRACE_PERIOD_BLOCKS + 1);
1885+
{
1886+
let txn = nodes[1].tx_broadcaster.txn_broadcast();
1887+
assert_eq!(txn.len(), 1);
1888+
check_spends!(txn[0], funding_tx);
1889+
}
18821890

18831891
get_monitor!(nodes[0], chan_id).provide_payment_preimage(
1884-
&payment_hash, &payment_preimage, &node_cfgs[0].tx_broadcaster,
1892+
&payment_hash_2, &payment_preimage_2, &node_cfgs[0].tx_broadcaster,
18851893
&LowerBoundedFeeEstimator::new(node_cfgs[0].fee_estimator), &nodes[0].logger
18861894
);
1895+
get_monitor!(nodes[1], chan_id).provide_payment_preimage(
1896+
&payment_hash_1, &payment_preimage_1, &node_cfgs[0].tx_broadcaster,
1897+
&LowerBoundedFeeEstimator::new(node_cfgs[1].fee_estimator), &nodes[1].logger
1898+
);
18871899

18881900
let mut holder_events = nodes[0].chain_monitor.chain_monitor.get_and_clear_pending_events();
18891901
assert_eq!(holder_events.len(), 1);
@@ -1904,27 +1916,50 @@ fn test_yield_anchors_events() {
19041916
assert_eq!(txn.len(), 2);
19051917
let anchor_tx = txn.pop().unwrap();
19061918
let commitment_tx = txn.pop().unwrap();
1919+
check_spends!(commitment_tx, funding_tx);
19071920
check_spends!(anchor_tx, coinbase_tx, commitment_tx);
19081921
(commitment_tx, anchor_tx)
19091922
},
19101923
_ => panic!("Unexpected event"),
19111924
};
19121925

1926+
assert_eq!(commitment_tx.output[2].value, 1_000); // HTLC A -> B
1927+
assert_eq!(commitment_tx.output[3].value, 2_000); // HTLC B -> A
1928+
19131929
mine_transactions(&nodes[0], &[&commitment_tx, &anchor_tx]);
19141930
check_added_monitors!(nodes[0], 1);
1931+
mine_transactions(&nodes[1], &[&commitment_tx, &anchor_tx]);
1932+
check_added_monitors!(nodes[1], 1);
1933+
1934+
{
1935+
let mut txn = nodes[1].tx_broadcaster.unique_txn_broadcast();
1936+
assert_eq!(txn.len(), if nodes[1].connect_style.borrow().updates_best_block_first() { 3 } else { 2 });
1937+
1938+
let htlc_preimage_tx = txn.pop().unwrap();
1939+
assert_eq!(htlc_preimage_tx.input.len(), 1);
1940+
assert_eq!(htlc_preimage_tx.input[0].previous_output.vout, 3);
1941+
check_spends!(htlc_preimage_tx, commitment_tx);
1942+
1943+
let htlc_timeout_tx = txn.pop().unwrap();
1944+
assert_eq!(htlc_timeout_tx.input.len(), 1);
1945+
assert_eq!(htlc_timeout_tx.input[0].previous_output.vout, 2);
1946+
check_spends!(htlc_timeout_tx, commitment_tx);
1947+
1948+
if let Some(commitment_tx) = txn.pop() {
1949+
check_spends!(commitment_tx, funding_tx);
1950+
}
1951+
}
19151952

19161953
let mut holder_events = nodes[0].chain_monitor.chain_monitor.get_and_clear_pending_events();
19171954
// Certain block `ConnectStyle`s cause an extra `ChannelClose` event to be emitted since the
19181955
// best block is updated before the confirmed transactions are notified.
1919-
match *nodes[0].connect_style.borrow() {
1920-
ConnectStyle::BestBlockFirst|ConnectStyle::BestBlockFirstReorgsOnlyTip|ConnectStyle::BestBlockFirstSkippingBlocks => {
1921-
assert_eq!(holder_events.len(), 3);
1922-
if let Event::BumpTransaction(BumpTransactionEvent::ChannelClose { .. }) = holder_events.remove(0) {}
1923-
else { panic!("unexpected event"); }
1924-
1925-
},
1926-
_ => assert_eq!(holder_events.len(), 2),
1927-
};
1956+
if nodes[0].connect_style.borrow().updates_best_block_first() {
1957+
assert_eq!(holder_events.len(), 3);
1958+
if let Event::BumpTransaction(BumpTransactionEvent::ChannelClose { .. }) = holder_events.remove(0) {}
1959+
else { panic!("unexpected event"); }
1960+
} else {
1961+
assert_eq!(holder_events.len(), 2);
1962+
}
19281963
let mut htlc_txs = Vec::with_capacity(2);
19291964
for event in holder_events {
19301965
match event {
@@ -1958,6 +1993,9 @@ fn test_yield_anchors_events() {
19581993

19591994
// Clear the remaining events as they're not relevant to what we're testing.
19601995
nodes[0].node.get_and_clear_pending_events();
1996+
nodes[1].node.get_and_clear_pending_events();
1997+
nodes[0].node.get_and_clear_pending_msg_events();
1998+
nodes[1].node.get_and_clear_pending_msg_events();
19611999
}
19622000

19632001
#[test]

0 commit comments

Comments
 (0)