@@ -1672,8 +1672,7 @@ fn test_revoked_counterparty_htlc_tx_balances() {
16721672 do_test_revoked_counterparty_htlc_tx_balances ( true ) ;
16731673}
16741674
1675- #[ test]
1676- fn test_revoked_counterparty_aggregated_claims ( ) {
1675+ fn do_test_revoked_counterparty_aggregated_claims ( anchors : bool ) {
16771676 // Tests `get_claimable_balances` for revoked counterparty commitment transactions when
16781677 // claiming with an aggregated claim transaction.
16791678 let mut chanmon_cfgs = create_chanmon_cfgs ( 2 ) ;
@@ -1683,9 +1682,25 @@ fn test_revoked_counterparty_aggregated_claims() {
16831682 // transaction which, from the point of view of our keys_manager, is revoked.
16841683 chanmon_cfgs[ 1 ] . keys_manager . disable_revocation_policy_check = true ;
16851684 let node_cfgs = create_node_cfgs ( 2 , & chanmon_cfgs) ;
1686- let node_chanmgrs = create_node_chanmgrs ( 2 , & node_cfgs, & [ None , None ] ) ;
1685+ let mut user_config = test_default_channel_config ( ) ;
1686+ if anchors {
1687+ user_config. channel_handshake_config . negotiate_anchors_zero_fee_htlc_tx = true ;
1688+ user_config. manually_accept_inbound_channels = true ;
1689+ }
1690+ let node_chanmgrs = create_node_chanmgrs ( 2 , & node_cfgs, & [ Some ( user_config) , Some ( user_config) ] ) ;
16871691 let nodes = create_network ( 2 , & node_cfgs, & node_chanmgrs) ;
16881692
1693+ let coinbase_tx = Transaction {
1694+ version : 2 ,
1695+ lock_time : PackedLockTime :: ZERO ,
1696+ input : vec ! [ TxIn { ..Default :: default ( ) } ] ,
1697+ output : vec ! [ TxOut {
1698+ value: Amount :: ONE_BTC . to_sat( ) ,
1699+ script_pubkey: nodes[ 0 ] . wallet_source. get_change_script( ) . unwrap( ) ,
1700+ } ] ,
1701+ } ;
1702+ nodes[ 0 ] . wallet_source . add_utxo ( bitcoin:: OutPoint { txid : coinbase_tx. txid ( ) , vout : 0 } , coinbase_tx. output [ 0 ] . value ) ;
1703+
16891704 let ( _, _, chan_id, funding_tx) =
16901705 create_announced_chan_between_nodes_with_value ( & nodes, 0 , 1 , 1_000_000 , 100_000_000 ) ;
16911706 let funding_outpoint = OutPoint { txid : funding_tx. txid ( ) , index : 0 } ;
@@ -1708,9 +1723,11 @@ fn test_revoked_counterparty_aggregated_claims() {
17081723 // Now get the latest commitment transaction from A and then update the fee to revoke it
17091724 let as_revoked_txn = get_local_commitment_txn ! ( nodes[ 0 ] , chan_id) ;
17101725
1711- assert_eq ! ( as_revoked_txn. len( ) , 2 ) ;
1726+ assert_eq ! ( as_revoked_txn. len( ) , if anchors { 1 } else { 2 } ) ;
17121727 check_spends ! ( as_revoked_txn[ 0 ] , funding_tx) ;
1713- check_spends ! ( as_revoked_txn[ 1 ] , as_revoked_txn[ 0 ] ) ; // The HTLC-Claim transaction
1728+ if !anchors {
1729+ check_spends ! ( as_revoked_txn[ 1 ] , as_revoked_txn[ 0 ] ) ; // The HTLC-Claim transaction
1730+ }
17141731
17151732 let channel_type_features = get_channel_type_features ! ( nodes[ 0 ] , nodes[ 1 ] , chan_id) ;
17161733 let chan_feerate = get_feerate ! ( nodes[ 0 ] , nodes[ 1 ] , chan_id) as u64 ;
@@ -1749,51 +1766,93 @@ fn test_revoked_counterparty_aggregated_claims() {
17491766 check_closed_event ! ( nodes[ 1 ] , 1 , ClosureReason :: CommitmentTxConfirmed , [ nodes[ 0 ] . node. get_our_node_id( ) ] , 1000000 ) ;
17501767 check_added_monitors ! ( nodes[ 1 ] , 1 ) ;
17511768
1752- let mut claim_txn: Vec < _ > = nodes[ 1 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) . drain ( ..) . filter ( |tx| tx. input . iter ( ) . any ( |inp| inp. previous_output . txid == as_revoked_txn[ 0 ] . txid ( ) ) ) . collect ( ) ;
1753- // Currently the revoked commitment outputs are all claimed in one aggregated transaction
1754- assert_eq ! ( claim_txn. len( ) , 1 ) ;
1755- assert_eq ! ( claim_txn[ 0 ] . input. len( ) , 3 ) ;
1756- check_spends ! ( claim_txn[ 0 ] , as_revoked_txn[ 0 ] ) ;
1769+ let mut claim_txn = nodes[ 1 ] . tx_broadcaster . txn_broadcast ( ) ;
1770+ assert_eq ! ( claim_txn. len( ) , if anchors { 2 } else { 1 } ) ;
1771+ let revoked_to_self_claim = if anchors {
1772+ assert_eq ! ( claim_txn[ 0 ] . input. len( ) , 1 ) ;
1773+ assert_eq ! ( claim_txn[ 0 ] . input[ 0 ] . previous_output. vout, 5 ) ; // Separate to_remote claim
1774+ check_spends ! ( claim_txn[ 0 ] , as_revoked_txn[ 0 ] ) ;
1775+ assert_eq ! ( claim_txn[ 1 ] . input. len( ) , 2 ) ;
1776+ assert_eq ! ( claim_txn[ 1 ] . input[ 0 ] . previous_output. vout, 2 ) ;
1777+ assert_eq ! ( claim_txn[ 1 ] . input[ 1 ] . previous_output. vout, 3 ) ;
1778+ check_spends ! ( claim_txn[ 1 ] , as_revoked_txn[ 0 ] ) ;
1779+ Some ( claim_txn. remove ( 0 ) )
1780+ } else {
1781+ assert_eq ! ( claim_txn[ 0 ] . input. len( ) , 3 ) ;
1782+ assert_eq ! ( claim_txn[ 0 ] . input[ 0 ] . previous_output. vout, 3 ) ;
1783+ assert_eq ! ( claim_txn[ 0 ] . input[ 1 ] . previous_output. vout, 0 ) ;
1784+ assert_eq ! ( claim_txn[ 0 ] . input[ 2 ] . previous_output. vout, 1 ) ;
1785+ check_spends ! ( claim_txn[ 0 ] , as_revoked_txn[ 0 ] ) ;
1786+ None
1787+ } ;
17571788
17581789 let to_remote_maturity = nodes[ 1 ] . best_block_info ( ) . 1 + ANTI_REORG_DELAY - 1 ;
17591790
1791+ let commitment_tx_fee = chan_feerate *
1792+ ( channel:: commitment_tx_base_weight ( & channel_type_features) + 2 * channel:: COMMITMENT_TX_WEIGHT_PER_HTLC ) / 1000 ;
1793+ let anchor_outputs_value = if anchors { channel:: ANCHOR_OUTPUT_VALUE_SATOSHI * 2 } else { 0 } ;
17601794 assert_eq ! ( sorted_vec( vec![ Balance :: ClaimableAwaitingConfirmations {
17611795 // to_remote output in A's revoked commitment
17621796 amount_satoshis: 100_000 - 4_000 - 3_000 ,
17631797 confirmation_height: to_remote_maturity,
17641798 } , Balance :: CounterpartyRevokedOutputClaimable {
17651799 // to_self output in A's revoked commitment
1766- amount_satoshis: 1_000_000 - 100_000 - chan_feerate *
1767- ( channel:: commitment_tx_base_weight( & channel_type_features) + 2 * channel:: COMMITMENT_TX_WEIGHT_PER_HTLC ) / 1000 ,
1800+ amount_satoshis: 1_000_000 - 100_000 - commitment_tx_fee - anchor_outputs_value,
17681801 } , Balance :: CounterpartyRevokedOutputClaimable { // HTLC 1
17691802 amount_satoshis: 4_000 ,
17701803 } , Balance :: CounterpartyRevokedOutputClaimable { // HTLC 2
17711804 amount_satoshis: 3_000 ,
17721805 } ] ) ,
17731806 sorted_vec( nodes[ 1 ] . chain_monitor. chain_monitor. get_monitor( funding_outpoint) . unwrap( ) . get_claimable_balances( ) ) ) ;
17741807
1775- // Confirm A's HTLC-Success tranasction which presumably raced B's claim, causing B to create a
1808+ // Confirm A's HTLC-Success transaction which presumably raced B's claim, causing B to create a
17761809 // new claim.
1777- mine_transaction ( & nodes[ 1 ] , & as_revoked_txn[ 1 ] ) ;
1810+ if anchors {
1811+ mine_transaction ( & nodes[ 0 ] , & as_revoked_txn[ 0 ] ) ;
1812+ check_closed_broadcast ( & nodes[ 0 ] , 1 , true ) ;
1813+ check_added_monitors ( & nodes[ 0 ] , 1 ) ;
1814+ check_closed_event ! ( & nodes[ 0 ] , 1 , ClosureReason :: CommitmentTxConfirmed , false , [ nodes[ 1 ] . node. get_our_node_id( ) ] , 1_000_000 ) ;
1815+ handle_bump_htlc_event ( & nodes[ 0 ] , 1 ) ;
1816+ }
1817+ let htlc_success_claim = if anchors {
1818+ let mut txn = nodes[ 0 ] . tx_broadcaster . txn_broadcast ( ) ;
1819+ assert_eq ! ( txn. len( ) , 1 ) ;
1820+ check_spends ! ( txn[ 0 ] , as_revoked_txn[ 0 ] , coinbase_tx) ;
1821+ txn. pop ( ) . unwrap ( )
1822+ } else {
1823+ as_revoked_txn[ 1 ] . clone ( )
1824+ } ;
1825+ mine_transaction ( & nodes[ 1 ] , & htlc_success_claim) ;
17781826 expect_payment_sent ( & nodes[ 1 ] , claimed_payment_preimage, None , true , false ) ;
1779- let mut claim_txn_2 : Vec < _ > = nodes [ 1 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) . clone ( ) ;
1780- claim_txn_2 . sort_unstable_by_key ( |tx| if tx . input . iter ( ) . any ( |inp| inp . previous_output . txid == as_revoked_txn [ 0 ] . txid ( ) ) { 0 } else { 1 } ) ;
1827+
1828+ let mut claim_txn_2 = nodes [ 1 ] . tx_broadcaster . txn_broadcast ( ) ;
17811829 // Once B sees the HTLC-Success transaction it splits its claim transaction into two, though in
17821830 // theory it could re-aggregate the claims as well.
17831831 assert_eq ! ( claim_txn_2. len( ) , 2 ) ;
1784- assert_eq ! ( claim_txn_2[ 0 ] . input. len( ) , 2 ) ;
1785- check_spends ! ( claim_txn_2[ 0 ] , as_revoked_txn[ 0 ] ) ;
1786- assert_eq ! ( claim_txn_2[ 1 ] . input. len( ) , 1 ) ;
1787- check_spends ! ( claim_txn_2[ 1 ] , as_revoked_txn[ 1 ] ) ;
1832+ if anchors {
1833+ assert_eq ! ( claim_txn_2[ 0 ] . input. len( ) , 1 ) ;
1834+ assert_eq ! ( claim_txn_2[ 0 ] . input[ 0 ] . previous_output. vout, 0 ) ;
1835+ check_spends ! ( claim_txn_2[ 0 ] , & htlc_success_claim) ;
1836+ assert_eq ! ( claim_txn_2[ 1 ] . input. len( ) , 1 ) ;
1837+ assert_eq ! ( claim_txn_2[ 1 ] . input[ 0 ] . previous_output. vout, 3 ) ;
1838+ check_spends ! ( claim_txn_2[ 1 ] , as_revoked_txn[ 0 ] ) ;
1839+ } else {
1840+ assert_eq ! ( claim_txn_2[ 0 ] . input. len( ) , 1 ) ;
1841+ assert_eq ! ( claim_txn_2[ 0 ] . input[ 0 ] . previous_output. vout, 0 ) ;
1842+ check_spends ! ( claim_txn_2[ 0 ] , as_revoked_txn[ 1 ] ) ;
1843+ assert_eq ! ( claim_txn_2[ 1 ] . input. len( ) , 2 ) ;
1844+ assert_eq ! ( claim_txn_2[ 1 ] . input[ 0 ] . previous_output. vout, 3 ) ;
1845+ assert_eq ! ( claim_txn_2[ 1 ] . input[ 1 ] . previous_output. vout, 1 ) ;
1846+ check_spends ! ( claim_txn_2[ 1 ] , as_revoked_txn[ 0 ] ) ;
1847+ }
17881848
17891849 assert_eq ! ( sorted_vec( vec![ Balance :: ClaimableAwaitingConfirmations {
17901850 // to_remote output in A's revoked commitment
17911851 amount_satoshis: 100_000 - 4_000 - 3_000 ,
17921852 confirmation_height: to_remote_maturity,
17931853 } , Balance :: CounterpartyRevokedOutputClaimable {
17941854 // to_self output in A's revoked commitment
1795- amount_satoshis: 1_000_000 - 100_000 - chan_feerate *
1796- ( channel:: commitment_tx_base_weight( & channel_type_features) + 2 * channel:: COMMITMENT_TX_WEIGHT_PER_HTLC ) / 1000 ,
1855+ amount_satoshis: 1_000_000 - 100_000 - commitment_tx_fee - anchor_outputs_value,
17971856 } , Balance :: CounterpartyRevokedOutputClaimable { // HTLC 1
17981857 amount_satoshis: 4_000 ,
17991858 } , Balance :: CounterpartyRevokedOutputClaimable { // HTLC 2
@@ -1809,8 +1868,7 @@ fn test_revoked_counterparty_aggregated_claims() {
18091868
18101869 assert_eq ! ( sorted_vec( vec![ Balance :: CounterpartyRevokedOutputClaimable {
18111870 // to_self output in A's revoked commitment
1812- amount_satoshis: 1_000_000 - 100_000 - chan_feerate *
1813- ( channel:: commitment_tx_base_weight( & channel_type_features) + 2 * channel:: COMMITMENT_TX_WEIGHT_PER_HTLC ) / 1000 ,
1871+ amount_satoshis: 1_000_000 - 100_000 - commitment_tx_fee - anchor_outputs_value,
18141872 } , Balance :: CounterpartyRevokedOutputClaimable { // HTLC 1
18151873 amount_satoshis: 4_000 ,
18161874 } , Balance :: CounterpartyRevokedOutputClaimable { // HTLC 2
@@ -1821,47 +1879,75 @@ fn test_revoked_counterparty_aggregated_claims() {
18211879 } ] ) ,
18221880 sorted_vec( nodes[ 1 ] . chain_monitor. chain_monitor. get_monitor( funding_outpoint) . unwrap( ) . get_claimable_balances( ) ) ) ;
18231881
1824- mine_transaction ( & nodes[ 1 ] , & claim_txn_2[ 1 ] ) ;
1882+ mine_transaction ( & nodes[ 1 ] , & claim_txn_2[ 0 ] ) ;
18251883 let htlc_2_claim_maturity = nodes[ 1 ] . best_block_info ( ) . 1 + ANTI_REORG_DELAY - 1 ;
18261884
18271885 assert_eq ! ( sorted_vec( vec![ Balance :: CounterpartyRevokedOutputClaimable {
18281886 // to_self output in A's revoked commitment
1829- amount_satoshis: 1_000_000 - 100_000 - chan_feerate *
1830- ( channel:: commitment_tx_base_weight( & channel_type_features) + 2 * channel:: COMMITMENT_TX_WEIGHT_PER_HTLC ) / 1000 ,
1887+ amount_satoshis: 1_000_000 - 100_000 - commitment_tx_fee - anchor_outputs_value,
18311888 } , Balance :: CounterpartyRevokedOutputClaimable { // HTLC 1
18321889 amount_satoshis: 4_000 ,
18331890 } , Balance :: ClaimableAwaitingConfirmations { // HTLC 2
1834- amount_satoshis: claim_txn_2[ 1 ] . output[ 0 ] . value,
1891+ amount_satoshis: claim_txn_2[ 0 ] . output[ 0 ] . value,
18351892 confirmation_height: htlc_2_claim_maturity,
18361893 } ] ) ,
18371894 sorted_vec( nodes[ 1 ] . chain_monitor. chain_monitor. get_monitor( funding_outpoint) . unwrap( ) . get_claimable_balances( ) ) ) ;
18381895
18391896 connect_blocks ( & nodes[ 1 ] , 5 ) ;
1840- test_spendable_output ( & nodes[ 1 ] , & claim_txn_2[ 1 ] , false ) ;
1897+ test_spendable_output ( & nodes[ 1 ] , & claim_txn_2[ 0 ] , false ) ;
18411898
18421899 assert_eq ! ( sorted_vec( vec![ Balance :: CounterpartyRevokedOutputClaimable {
18431900 // to_self output in A's revoked commitment
1844- amount_satoshis: 1_000_000 - 100_000 - chan_feerate *
1845- ( channel:: commitment_tx_base_weight( & channel_type_features) + 2 * channel:: COMMITMENT_TX_WEIGHT_PER_HTLC ) / 1000 ,
1901+ amount_satoshis: 1_000_000 - 100_000 - commitment_tx_fee - anchor_outputs_value,
18461902 } , Balance :: CounterpartyRevokedOutputClaimable { // HTLC 1
18471903 amount_satoshis: 4_000 ,
18481904 } ] ) ,
18491905 sorted_vec( nodes[ 1 ] . chain_monitor. chain_monitor. get_monitor( funding_outpoint) . unwrap( ) . get_claimable_balances( ) ) ) ;
18501906
1851- mine_transaction ( & nodes[ 1 ] , & claim_txn_2[ 0 ] ) ;
1907+ if anchors {
1908+ mine_transactions ( & nodes[ 1 ] , & [ & claim_txn_2[ 1 ] , revoked_to_self_claim. as_ref ( ) . unwrap ( ) ] ) ;
1909+ } else {
1910+ mine_transaction ( & nodes[ 1 ] , & claim_txn_2[ 1 ] ) ;
1911+ }
18521912 let rest_claim_maturity = nodes[ 1 ] . best_block_info ( ) . 1 + ANTI_REORG_DELAY - 1 ;
18531913
1854- assert_eq ! ( vec![ Balance :: ClaimableAwaitingConfirmations {
1855- amount_satoshis: claim_txn_2[ 0 ] . output[ 0 ] . value,
1856- confirmation_height: rest_claim_maturity,
1857- } ] ,
1858- nodes[ 1 ] . chain_monitor. chain_monitor. get_monitor( funding_outpoint) . unwrap( ) . get_claimable_balances( ) ) ;
1914+ if anchors {
1915+ assert_eq ! ( vec![ Balance :: ClaimableAwaitingConfirmations {
1916+ amount_satoshis: claim_txn_2[ 1 ] . output[ 0 ] . value,
1917+ confirmation_height: rest_claim_maturity,
1918+ } , Balance :: ClaimableAwaitingConfirmations {
1919+ amount_satoshis: revoked_to_self_claim. as_ref( ) . unwrap( ) . output[ 0 ] . value,
1920+ confirmation_height: rest_claim_maturity,
1921+ } ] ,
1922+ nodes[ 1 ] . chain_monitor. chain_monitor. get_monitor( funding_outpoint) . unwrap( ) . get_claimable_balances( ) ) ;
1923+ } else {
1924+ assert_eq ! ( vec![ Balance :: ClaimableAwaitingConfirmations {
1925+ amount_satoshis: claim_txn_2[ 1 ] . output[ 0 ] . value,
1926+ confirmation_height: rest_claim_maturity,
1927+ } ] ,
1928+ nodes[ 1 ] . chain_monitor. chain_monitor. get_monitor( funding_outpoint) . unwrap( ) . get_claimable_balances( ) ) ;
1929+ }
18591930
18601931 assert ! ( nodes[ 1 ] . node. get_and_clear_pending_events( ) . is_empty( ) ) ; // We shouldn't fail the payment until we spend the output
18611932
18621933 connect_blocks ( & nodes[ 1 ] , 5 ) ;
18631934 expect_payment_failed ! ( nodes[ 1 ] , revoked_payment_hash, false ) ;
1864- test_spendable_output ( & nodes[ 1 ] , & claim_txn_2[ 0 ] , false ) ;
1935+ if anchors {
1936+ let events = nodes[ 1 ] . chain_monitor . chain_monitor . get_and_clear_pending_events ( ) ;
1937+ assert_eq ! ( events. len( ) , 2 ) ;
1938+ for ( i, event) in events. into_iter ( ) . enumerate ( ) {
1939+ if let Event :: SpendableOutputs { outputs, .. } = event {
1940+ assert_eq ! ( outputs. len( ) , 1 ) ;
1941+ let spend_tx = nodes[ 1 ] . keys_manager . backing . spend_spendable_outputs (
1942+ & [ & outputs[ 0 ] ] , Vec :: new ( ) , Builder :: new ( ) . push_opcode ( opcodes:: all:: OP_RETURN ) . into_script ( ) ,
1943+ 253 , None , & Secp256k1 :: new ( )
1944+ ) . unwrap ( ) ;
1945+ check_spends ! ( spend_tx, if i == 0 { & claim_txn_2[ 1 ] } else { revoked_to_self_claim. as_ref( ) . unwrap( ) } ) ;
1946+ } else { panic ! ( ) ; }
1947+ }
1948+ } else {
1949+ test_spendable_output ( & nodes[ 1 ] , & claim_txn_2[ 1 ] , false ) ;
1950+ }
18651951 assert ! ( nodes[ 1 ] . chain_monitor. chain_monitor. get_monitor( funding_outpoint) . unwrap( ) . get_claimable_balances( ) . is_empty( ) ) ;
18661952
18671953 // Ensure that even if we connect more blocks, potentially replaying the entire chain if we're
@@ -1873,6 +1959,12 @@ fn test_revoked_counterparty_aggregated_claims() {
18731959 assert ! ( nodes[ 1 ] . chain_monitor. chain_monitor. get_monitor( funding_outpoint) . unwrap( ) . get_claimable_balances( ) . is_empty( ) ) ;
18741960}
18751961
1962+ #[ test]
1963+ fn test_revoked_counterparty_aggregated_claims ( ) {
1964+ do_test_revoked_counterparty_aggregated_claims ( false ) ;
1965+ do_test_revoked_counterparty_aggregated_claims ( true ) ;
1966+ }
1967+
18761968fn do_test_restored_packages_retry ( check_old_monitor_retries_after_upgrade : bool ) {
18771969 // Tests that we'll retry packages that were previously timelocked after we've restored them.
18781970 let chanmon_cfgs = create_chanmon_cfgs ( 2 ) ;
0 commit comments