Skip to content

Commit b5fbb0b

Browse files
committed
[wip] Port monitor_tests to P2A anchors
1 parent 7655dbf commit b5fbb0b

File tree

3 files changed

+73
-36
lines changed

3 files changed

+73
-36
lines changed

lightning/src/chain/channelmonitor.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5800,6 +5800,8 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
58005800
assert_eq!(&bitcoin::Address::p2wsh(&ScriptBuf::from(input.witness.last().unwrap().to_vec()), bitcoin::Network::Bitcoin).script_pubkey(), _script_pubkey);
58015801
} else if _script_pubkey.is_p2wpkh() {
58025802
assert_eq!(&bitcoin::Address::p2wpkh(&bitcoin::CompressedPublicKey(bitcoin::PublicKey::from_slice(&input.witness.last().unwrap()).unwrap().inner), bitcoin::Network::Bitcoin).script_pubkey(), _script_pubkey);
5803+
} else if _script_pubkey == &chan_utils::shared_anchor_script_pubkey() {
5804+
assert!(input.witness.is_empty());
58035805
} else { panic!(); }
58045806
}
58055807
return true;

lightning/src/ln/functional_test_utils.rs

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1941,11 +1941,15 @@ pub fn update_nodes_with_chan_announce<'a, 'b, 'c, 'd>(
19411941
pub fn do_check_spends<F: Fn(&bitcoin::transaction::OutPoint) -> Option<TxOut>>(
19421942
tx: &Transaction, get_output: F,
19431943
) {
1944+
let mut single_output_below_dust = false;
19441945
for outp in tx.output.iter() {
1945-
assert!(
1946-
outp.value >= outp.script_pubkey.minimal_non_dust(),
1947-
"Spending tx output didn't meet dust limit"
1948-
);
1946+
if outp.value < outp.script_pubkey.minimal_non_dust() {
1947+
if single_output_below_dust {
1948+
panic!("Spending tx output didn't meet dust limit");
1949+
} else {
1950+
single_output_below_dust = true;
1951+
}
1952+
};
19491953
}
19501954
let mut total_value_in = 0;
19511955
for input in tx.input.iter() {
@@ -1955,9 +1959,15 @@ pub fn do_check_spends<F: Fn(&bitcoin::transaction::OutPoint) -> Option<TxOut>>(
19551959
for output in tx.output.iter() {
19561960
total_value_out += output.value.to_sat();
19571961
}
1958-
let min_fee = (tx.weight().to_wu() as u64 + 3) / 4; // One sat per vbyte (ie per weight/4, rounded up)
1959-
// Input amount - output amount = fee, so check that out + min_fee is smaller than input
1960-
assert!(total_value_out + min_fee <= total_value_in);
1962+
if single_output_below_dust {
1963+
assert_eq!(
1964+
total_value_in, total_value_out,
1965+
"Spending tx has one output below dust, while not zero fee"
1966+
);
1967+
} else {
1968+
let min_fee = (tx.weight().to_wu() as u64 + 3) / 4; // One sat per vbyte (ie per weight/4, rounded up)
1969+
assert!(total_value_out + min_fee <= total_value_in);
1970+
}
19611971
tx.verify(get_output).unwrap();
19621972
}
19631973

@@ -1966,8 +1976,15 @@ macro_rules! check_spends {
19661976
($tx: expr, $($spends_txn: expr),*) => {
19671977
{
19681978
$(
1979+
let mut single_output_below_dust = false;
19691980
for outp in $spends_txn.output.iter() {
1970-
assert!(outp.value >= outp.script_pubkey.minimal_non_dust(), "Input tx output didn't meet dust limit");
1981+
if outp.value.lt(&outp.script_pubkey.minimal_non_dust()) {
1982+
if single_output_below_dust || outp.script_pubkey != crate::ln::chan_utils::shared_anchor_script_pubkey() {
1983+
panic!("Input tx output didn't meet dust limit");
1984+
} else {
1985+
single_output_below_dust = true;
1986+
}
1987+
}
19711988
}
19721989
)*
19731990
let get_output = |out_point: &bitcoin::transaction::OutPoint| {
@@ -1980,7 +1997,10 @@ macro_rules! check_spends {
19801997
};
19811998
$crate::ln::functional_test_utils::do_check_spends(&$tx, get_output);
19821999
}
1983-
}
2000+
};
2001+
($tx: expr, $($spends_txn: expr),*) => {
2002+
check_spends!($tx, $($spends_txn; false),*)
2003+
};
19842004
}
19852005

19862006
macro_rules! get_closing_signed_broadcast {

lightning/src/ln/monitor_tests.rs

Lines changed: 42 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -309,17 +309,20 @@ fn archive_fully_resolved_monitors() {
309309
}
310310
}
311311

312-
fn do_chanmon_claim_value_coop_close(anchors: bool) {
312+
fn do_chanmon_claim_value_coop_close(keyed_anchors: bool, p2a_anchor: bool) {
313313
// Tests `get_claimable_balances` returns the correct values across a simple cooperative claim.
314314
// Specifically, this tests that the channel non-HTLC balances show up in
315315
// `get_claimable_balances` until the cooperative claims have confirmed and generated a
316316
// `SpendableOutputs` event, and no longer.
317317
let chanmon_cfgs = create_chanmon_cfgs(2);
318318
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
319319
let mut user_config = test_default_channel_config();
320-
if anchors {
320+
if keyed_anchors {
321321
user_config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = true;
322322
user_config.manually_accept_inbound_channels = true;
323+
} else if p2a_anchor {
324+
user_config.channel_handshake_config.negotiate_anchor_zero_fee_commitments = true;
325+
user_config.manually_accept_inbound_channels = true;
323326
}
324327
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(user_config.clone()), Some(user_config)]);
325328
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
@@ -333,7 +336,7 @@ fn do_chanmon_claim_value_coop_close(anchors: bool) {
333336
let channel_type_features = get_channel_type_features!(nodes[0], nodes[1], chan_id);
334337

335338
let commitment_tx_fee = chan_feerate * chan_utils::commitment_tx_base_weight(&channel_type_features) / 1000;
336-
let anchor_outputs_value = if anchors { channel::ANCHOR_OUTPUT_VALUE_SATOSHI * 2 } else { 0 };
339+
let anchor_outputs_value = if keyed_anchors { channel::ANCHOR_OUTPUT_VALUE_SATOSHI * 2 } else { 0 };
337340
assert_eq!(vec![Balance::ClaimableOnChannelClose {
338341
balance_candidates: vec![HolderCommitmentTransactionBalance {
339342
amount_satoshis: 1_000_000 - 1_000 - commitment_tx_fee - anchor_outputs_value,
@@ -434,8 +437,9 @@ fn do_chanmon_claim_value_coop_close(anchors: bool) {
434437

435438
#[test]
436439
fn chanmon_claim_value_coop_close() {
437-
do_chanmon_claim_value_coop_close(false);
438-
do_chanmon_claim_value_coop_close(true);
440+
do_chanmon_claim_value_coop_close(false, false);
441+
do_chanmon_claim_value_coop_close(true, false);
442+
do_chanmon_claim_value_coop_close(false, true);
439443
}
440444

441445
fn sorted_vec<T: Ord>(mut v: Vec<T>) -> Vec<T> {
@@ -454,7 +458,7 @@ fn fuzzy_assert_eq<V: core::convert::TryInto<u64>>(a: V, b: V) {
454458
assert!(b_u64 >= a_u64 - 5);
455459
}
456460

457-
fn do_test_claim_value_force_close(anchors: bool, prev_commitment_tx: bool) {
461+
fn do_test_claim_value_force_close(keyed_anchors: bool, p2a_anchor: bool, prev_commitment_tx: bool) {
458462
// Tests `get_claimable_balances` with an HTLC across a force-close.
459463
// We build a channel with an HTLC pending, then force close the channel and check that the
460464
// `get_claimable_balances` return value is correct as transactions confirm on-chain.
@@ -468,9 +472,12 @@ fn do_test_claim_value_force_close(anchors: bool, prev_commitment_tx: bool) {
468472
}
469473
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
470474
let mut user_config = test_default_channel_config();
471-
if anchors {
475+
if keyed_anchors {
472476
user_config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = true;
473477
user_config.manually_accept_inbound_channels = true;
478+
} else if p2a_anchor {
479+
user_config.channel_handshake_config.negotiate_anchor_zero_fee_commitments = true;
480+
user_config.manually_accept_inbound_channels = true;
474481
}
475482
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(user_config.clone()), Some(user_config)]);
476483
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
@@ -535,13 +542,13 @@ fn do_test_claim_value_force_close(anchors: bool, prev_commitment_tx: bool) {
535542
// as claimable. A lists both its to-self balance and the (possibly-claimable) HTLCs.
536543
let commitment_tx_fee = chan_feerate as u64 *
537544
(chan_utils::commitment_tx_base_weight(&channel_type_features) + 2 * chan_utils::COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000;
538-
let anchor_outputs_value = if anchors { 2 * channel::ANCHOR_OUTPUT_VALUE_SATOSHI } else { 0 };
545+
let anchor_outputs_value = if keyed_anchors { 2 * channel::ANCHOR_OUTPUT_VALUE_SATOSHI } else { 0 };
539546
let amount_satoshis = 1_000_000 - 3_000 - 4_000 - 1_000 - 3 - commitment_tx_fee - anchor_outputs_value - 1; /* msat amount that is burned to fees */
540547
assert_eq!(sorted_vec(vec![Balance::ClaimableOnChannelClose {
541548
balance_candidates: vec![HolderCommitmentTransactionBalance {
542549
amount_satoshis,
543550
// In addition to `commitment_tx_fee`, this also includes the dust HTLC, and the total msat amount rounded down from non-dust HTLCs
544-
transaction_fee_satoshis: 1_000_000 - 4_000 - 3_000 - 1_000 - amount_satoshis - anchor_outputs_value,
551+
transaction_fee_satoshis: if p2a_anchor { 0 } else { 1_000_000 - 4_000 - 3_000 - 1_000 - amount_satoshis - anchor_outputs_value },
545552
}],
546553
confirmed_balance_candidate_index: 0,
547554
outbound_payment_htlc_rounded_msat: 3300,
@@ -611,7 +618,7 @@ fn do_test_claim_value_force_close(anchors: bool, prev_commitment_tx: bool) {
611618
balance_candidates: vec![HolderCommitmentTransactionBalance {
612619
amount_satoshis, // Channel funding value in satoshis
613620
// In addition to `commitment_tx_fee`, this also includes the dust HTLC, and the total msat amount rounded down from non-dust HTLCs
614-
transaction_fee_satoshis: 1_000_000 - 4_000 - 3_000 - 1_000 - amount_satoshis - anchor_outputs_value,
621+
transaction_fee_satoshis: if p2a_anchor { 0 } else { 1_000_000 - 4_000 - 3_000 - 1_000 - amount_satoshis - anchor_outputs_value },
615622
}],
616623
confirmed_balance_candidate_index: 0,
617624
outbound_payment_htlc_rounded_msat: 3000 + if prev_commitment_tx {
@@ -645,7 +652,7 @@ fn do_test_claim_value_force_close(anchors: bool, prev_commitment_tx: bool) {
645652
mine_transaction(&nodes[0], &remote_txn[0]);
646653
mine_transaction(&nodes[1], &remote_txn[0]);
647654

648-
if anchors {
655+
if keyed_anchors || p2a_anchor {
649656
let mut events = nodes[1].chain_monitor.chain_monitor.get_and_clear_pending_events();
650657
assert_eq!(events.len(), 1);
651658
match events.pop().unwrap() {
@@ -674,8 +681,8 @@ fn do_test_claim_value_force_close(anchors: bool, prev_commitment_tx: bool) {
674681
// b_broadcast_txn should spend the HTLCs output of the commitment tx for 3_000 and 4_000 sats
675682
check_spends!(b_broadcast_txn[0], remote_txn[0], coinbase_tx);
676683
check_spends!(b_broadcast_txn[1], remote_txn[0], coinbase_tx);
677-
assert_eq!(b_broadcast_txn[0].input.len(), if anchors { 2 } else { 1 });
678-
assert_eq!(b_broadcast_txn[1].input.len(), if anchors { 2 } else { 1 });
684+
assert_eq!(b_broadcast_txn[0].input.len(), if keyed_anchors || p2a_anchor { 2 } else { 1 });
685+
assert_eq!(b_broadcast_txn[1].input.len(), if keyed_anchors || p2a_anchor { 2 } else { 1 });
679686
assert_eq!(remote_txn[0].output[b_broadcast_txn[0].input[0].previous_output.vout as usize].value.to_sat(), 3_000);
680687
assert_eq!(remote_txn[0].output[b_broadcast_txn[1].input[0].previous_output.vout as usize].value.to_sat(), 4_000);
681688

@@ -807,7 +814,7 @@ fn do_test_claim_value_force_close(anchors: bool, prev_commitment_tx: bool) {
807814
// After reaching the commitment output CSV, we'll get a SpendableOutputs event for it and have
808815
// only the HTLCs claimable on node B.
809816
connect_blocks(&nodes[1], node_b_commitment_claimable - nodes[1].best_block_info().1);
810-
test_spendable_output(&nodes[1], &remote_txn[0], anchors);
817+
test_spendable_output(&nodes[1], &remote_txn[0], keyed_anchors || p2a_anchor);
811818

812819
assert_eq!(sorted_vec(vec![Balance::ClaimableAwaitingConfirmations {
813820
amount_satoshis: 3_000,
@@ -819,7 +826,7 @@ fn do_test_claim_value_force_close(anchors: bool, prev_commitment_tx: bool) {
819826
// After reaching the claimed HTLC output CSV, we'll get a SpendableOutptus event for it and
820827
// have only one HTLC output left spendable.
821828
connect_blocks(&nodes[1], node_b_htlc_claimable - nodes[1].best_block_info().1);
822-
test_spendable_output(&nodes[1], &b_broadcast_txn[0], anchors);
829+
test_spendable_output(&nodes[1], &b_broadcast_txn[0], keyed_anchors || p2a_anchor);
823830

824831
assert_eq!(vec![received_htlc_timeout_claiming_balance.clone()],
825832
nodes[1].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances());
@@ -847,10 +854,12 @@ fn do_test_claim_value_force_close(anchors: bool, prev_commitment_tx: bool) {
847854

848855
#[test]
849856
fn test_claim_value_force_close() {
850-
do_test_claim_value_force_close(false, true);
851-
do_test_claim_value_force_close(false, false);
852-
do_test_claim_value_force_close(true, true);
853-
do_test_claim_value_force_close(true, false);
857+
do_test_claim_value_force_close(false, false, true);
858+
do_test_claim_value_force_close(false, false, false);
859+
do_test_claim_value_force_close(true, false, true);
860+
do_test_claim_value_force_close(true, false, false);
861+
do_test_claim_value_force_close(false, true, true);
862+
do_test_claim_value_force_close(false, true, false);
854863
}
855864

856865
fn do_test_balances_on_local_commitment_htlcs(anchors: bool) {
@@ -2496,7 +2505,7 @@ fn test_monitor_timer_based_claim() {
24962505
do_test_monitor_rebroadcast_pending_claims(true);
24972506
}
24982507

2499-
fn do_test_yield_anchors_events(have_htlcs: bool) {
2508+
fn do_test_yield_anchors_events(have_htlcs: bool, p2a_anchor: bool) {
25002509
// Tests that two parties supporting anchor outputs can open a channel, route payments over
25012510
// it, and finalize its resolution uncooperatively. Once the HTLCs are locked in, one side will
25022511
// force close once the HTLCs expire. The force close should stem from an event emitted by LDK,
@@ -2508,6 +2517,7 @@ fn do_test_yield_anchors_events(have_htlcs: bool) {
25082517
let mut anchors_config = test_default_channel_config();
25092518
anchors_config.channel_handshake_config.announce_for_forwarding = true;
25102519
anchors_config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = true;
2520+
anchors_config.channel_handshake_config.negotiate_anchor_zero_fee_commitments = p2a_anchor;
25112521
anchors_config.manually_accept_inbound_channels = true;
25122522
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(anchors_config.clone()), Some(anchors_config)]);
25132523
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
@@ -2551,7 +2561,7 @@ fn do_test_yield_anchors_events(have_htlcs: bool) {
25512561
{
25522562
handle_bump_close_event(&nodes[1]);
25532563
let txn = nodes[1].tx_broadcaster.txn_broadcast();
2554-
assert_eq!(txn.len(), 1);
2564+
if p2a_anchor { assert_eq!(txn.len(), 2) } else { assert_eq!(txn.len(), 1) };
25552565
check_spends!(txn[0], funding_tx);
25562566
}
25572567

@@ -2601,7 +2611,10 @@ fn do_test_yield_anchors_events(have_htlcs: bool) {
26012611
};
26022612
check_spends!(commitment_tx, funding_tx);
26032613

2604-
if have_htlcs {
2614+
if have_htlcs && p2a_anchor {
2615+
assert_eq!(commitment_tx.output[1].value.to_sat(), 1_000); // HTLC A -> B
2616+
assert_eq!(commitment_tx.output[2].value.to_sat(), 2_000); // HTLC B -> A
2617+
} else if have_htlcs {
26052618
assert_eq!(commitment_tx.output[2].value.to_sat(), 1_000); // HTLC A -> B
26062619
assert_eq!(commitment_tx.output[3].value.to_sat(), 2_000); // HTLC B -> A
26072620
}
@@ -2626,12 +2639,12 @@ fn do_test_yield_anchors_events(have_htlcs: bool) {
26262639
assert_eq!(txn.len(), if nodes[1].connect_style.borrow().updates_best_block_first() { 3 } else { 1 });
26272640
if nodes[1].connect_style.borrow().updates_best_block_first() {
26282641
check_spends!(txn[1], funding_tx);
2629-
check_spends!(txn[2], txn[1]); // Anchor output spend.
2642+
check_spends!(txn[2], txn[1], coinbase_tx); // Anchor output spend.
26302643
}
26312644
let htlc_claim_tx = &txn[0];
26322645
assert_eq!(htlc_claim_tx.input.len(), 2);
2633-
assert_eq!(htlc_claim_tx.input[0].previous_output.vout, 2);
2634-
assert_eq!(htlc_claim_tx.input[1].previous_output.vout, 3);
2646+
assert_eq!(htlc_claim_tx.input[0].previous_output.vout, if p2a_anchor { 1 } else { 2 });
2647+
assert_eq!(htlc_claim_tx.input[1].previous_output.vout, if p2a_anchor { 2 } else { 3 });
26352648
check_spends!(htlc_claim_tx, commitment_tx);
26362649
}
26372650

@@ -2681,8 +2694,10 @@ fn do_test_yield_anchors_events(have_htlcs: bool) {
26812694

26822695
#[test]
26832696
fn test_yield_anchors_events() {
2684-
do_test_yield_anchors_events(true);
2685-
do_test_yield_anchors_events(false);
2697+
do_test_yield_anchors_events(true, false);
2698+
do_test_yield_anchors_events(false, false);
2699+
do_test_yield_anchors_events(true, true);
2700+
do_test_yield_anchors_events(false, true);
26862701
}
26872702

26882703
#[test]

0 commit comments

Comments
 (0)