@@ -1339,15 +1339,39 @@ fn test_revoked_counterparty_commitment_balances() {
13391339	do_test_revoked_counterparty_commitment_balances ( true ,  false ) ; 
13401340} 
13411341
1342- #[ test]  
1343- fn  test_revoked_counterparty_htlc_tx_balances ( )  { 
1342+ fn  do_test_revoked_counterparty_htlc_tx_balances ( anchors :  bool )  { 
13441343	// Tests `get_claimable_balances` for revocation spends of HTLC transactions. 
13451344	let  mut  chanmon_cfgs = create_chanmon_cfgs ( 2 ) ; 
13461345	chanmon_cfgs[ 1 ] . keys_manager . disable_revocation_policy_check  = true ; 
13471346	let  node_cfgs = create_node_cfgs ( 2 ,  & chanmon_cfgs) ; 
1348- 	let  node_chanmgrs = create_node_chanmgrs ( 2 ,  & node_cfgs,  & [ None ,  None ] ) ; 
1347+ 	let  mut  user_config = test_default_channel_config ( ) ; 
1348+ 	if  anchors { 
1349+ 		user_config. channel_handshake_config . negotiate_anchors_zero_fee_htlc_tx  = true ; 
1350+ 		user_config. manually_accept_inbound_channels  = true ; 
1351+ 	} 
1352+ 	let  node_chanmgrs = create_node_chanmgrs ( 2 ,  & node_cfgs,  & [ Some ( user_config) ,  Some ( user_config) ] ) ; 
13491353	let  nodes = create_network ( 2 ,  & node_cfgs,  & node_chanmgrs) ; 
13501354
1355+ 	let  coinbase_tx = Transaction  { 
1356+ 		version :  2 , 
1357+ 		lock_time :  PackedLockTime :: ZERO , 
1358+ 		input :  vec ! [ TxIn  {  ..Default :: default ( )  } ] , 
1359+ 		output :  vec ! [ 
1360+ 			TxOut  { 
1361+ 				value:  Amount :: ONE_BTC . to_sat( ) , 
1362+ 				script_pubkey:  nodes[ 0 ] . wallet_source. get_change_script( ) . unwrap( ) , 
1363+ 			} , 
1364+ 			TxOut  { 
1365+ 				value:  Amount :: ONE_BTC . to_sat( ) , 
1366+ 				script_pubkey:  nodes[ 1 ] . wallet_source. get_change_script( ) . unwrap( ) , 
1367+ 			} , 
1368+ 		] , 
1369+ 	} ; 
1370+ 	if  anchors { 
1371+ 		nodes[ 0 ] . wallet_source . add_utxo ( bitcoin:: OutPoint  {  txid :  coinbase_tx. txid ( ) ,  vout :  0  } ,  coinbase_tx. output [ 0 ] . value ) ; 
1372+ 		nodes[ 1 ] . wallet_source . add_utxo ( bitcoin:: OutPoint  {  txid :  coinbase_tx. txid ( ) ,  vout :  1  } ,  coinbase_tx. output [ 1 ] . value ) ; 
1373+ 	} 
1374+ 
13511375	// Create some initial channels 
13521376	let  ( _,  _,  chan_id,  funding_tx)  =
13531377		create_announced_chan_between_nodes_with_value ( & nodes,  0 ,  1 ,  1_000_000 ,  11_000_000 ) ; 
@@ -1359,9 +1383,15 @@ fn test_revoked_counterparty_htlc_tx_balances() {
13591383	let  revoked_local_txn = get_local_commitment_txn ! ( nodes[ 1 ] ,  chan_id) ; 
13601384	assert_eq ! ( revoked_local_txn[ 0 ] . input. len( ) ,  1 ) ; 
13611385	assert_eq ! ( revoked_local_txn[ 0 ] . input[ 0 ] . previous_output. txid,  funding_tx. txid( ) ) ; 
1386+ 	if  anchors { 
1387+ 		assert_eq ! ( revoked_local_txn[ 0 ] . output[ 4 ] . value,  10000 ) ;  // to_self output 
1388+ 	}  else  { 
1389+ 		assert_eq ! ( revoked_local_txn[ 0 ] . output[ 2 ] . value,  10000 ) ;  // to_self output 
1390+ 	} 
13621391
1363- 	// The to-be-revoked commitment tx should have two HTLCs and an output for both sides 
1364- 	assert_eq ! ( revoked_local_txn[ 0 ] . output. len( ) ,  4 ) ; 
1392+ 	// The to-be-revoked commitment tx should have two HTLCs, an output for each side, and an 
1393+ 	// anchor output for each side if enabled. 
1394+ 	assert_eq ! ( revoked_local_txn[ 0 ] . output. len( ) ,  if  anchors {  6  }  else {  4  } ) ; 
13651395
13661396	claim_payment ( & nodes[ 0 ] ,  & [ & nodes[ 1 ] ] ,  payment_preimage) ; 
13671397
@@ -1373,16 +1403,25 @@ fn test_revoked_counterparty_htlc_tx_balances() {
13731403	check_closed_broadcast ! ( nodes[ 1 ] ,  true ) ; 
13741404	check_added_monitors ! ( nodes[ 1 ] ,  1 ) ; 
13751405	check_closed_event ! ( nodes[ 1 ] ,  1 ,  ClosureReason :: CommitmentTxConfirmed ,  [ nodes[ 0 ] . node. get_our_node_id( ) ] ,  1000000 ) ; 
1406+ 	if  anchors { 
1407+ 		handle_bump_htlc_event ( & nodes[ 1 ] ,  1 ) ; 
1408+ 	} 
13761409	let  revoked_htlc_success = { 
13771410		let  mut  txn = nodes[ 1 ] . tx_broadcaster . txn_broadcast ( ) ; 
13781411		assert_eq ! ( txn. len( ) ,  1 ) ; 
1379- 		assert_eq ! ( txn[ 0 ] . input. len( ) ,  1 ) ; 
1380- 		assert_eq ! ( txn[ 0 ] . input[ 0 ] . witness. last( ) . unwrap( ) . len( ) ,  ACCEPTED_HTLC_SCRIPT_WEIGHT ) ; 
1381- 		check_spends ! ( txn[ 0 ] ,  revoked_local_txn[ 0 ] ) ; 
1412+ 		assert_eq ! ( txn[ 0 ] . input. len( ) ,  if  anchors {  2  }  else {  1  } ) ; 
1413+ 		assert_eq ! ( txn[ 0 ] . input[ 0 ] . previous_output. vout,  if  anchors {  3  }  else {  1  } ) ; 
1414+ 		assert_eq ! ( txn[ 0 ] . input[ 0 ] . witness. last( ) . unwrap( ) . len( ) , 
1415+ 			if  anchors {  ACCEPTED_HTLC_SCRIPT_WEIGHT_ANCHORS  }  else {  ACCEPTED_HTLC_SCRIPT_WEIGHT  } ) ; 
1416+ 		check_spends ! ( txn[ 0 ] ,  revoked_local_txn[ 0 ] ,  coinbase_tx) ; 
13821417		txn. pop ( ) . unwrap ( ) 
13831418	} ; 
1419+ 	let  revoked_htlc_success_fee = chan_feerate *  revoked_htlc_success. weight ( )  as  u64  / 1000 ; 
13841420
13851421	connect_blocks ( & nodes[ 1 ] ,  TEST_FINAL_CLTV ) ; 
1422+ 	if  anchors { 
1423+ 		handle_bump_htlc_event ( & nodes[ 1 ] ,  2 ) ; 
1424+ 	} 
13861425	let  revoked_htlc_timeout = { 
13871426		let  mut  txn = nodes[ 1 ] . tx_broadcaster . unique_txn_broadcast ( ) ; 
13881427		assert_eq ! ( txn. len( ) ,  2 ) ; 
@@ -1392,7 +1431,7 @@ fn test_revoked_counterparty_htlc_tx_balances() {
13921431			txn. remove ( 0 ) 
13931432		} 
13941433	} ; 
1395- 	check_spends ! ( revoked_htlc_timeout,  revoked_local_txn[ 0 ] ) ; 
1434+ 	check_spends ! ( revoked_htlc_timeout,  revoked_local_txn[ 0 ] ,  coinbase_tx ) ; 
13961435	assert_ne ! ( revoked_htlc_success. input[ 0 ] . previous_output,  revoked_htlc_timeout. input[ 0 ] . previous_output) ; 
13971436	assert_eq ! ( revoked_htlc_success. lock_time. 0 ,  0 ) ; 
13981437	assert_ne ! ( revoked_htlc_timeout. lock_time. 0 ,  0 ) ; 
@@ -1404,17 +1443,37 @@ fn test_revoked_counterparty_htlc_tx_balances() {
14041443	check_closed_event ! ( nodes[ 0 ] ,  1 ,  ClosureReason :: CommitmentTxConfirmed ,  [ nodes[ 1 ] . node. get_our_node_id( ) ] ,  1000000 ) ; 
14051444	let  to_remote_conf_height = nodes[ 0 ] . best_block_info ( ) . 1  + ANTI_REORG_DELAY  - 1 ; 
14061445
1407- 	let  as_commitment_claim_txn = nodes[ 0 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) . split_off ( 0 ) ; 
1408- 	assert_eq ! ( as_commitment_claim_txn. len( ) ,  1 ) ; 
1409- 	check_spends ! ( as_commitment_claim_txn[ 0 ] ,  revoked_local_txn[ 0 ] ) ; 
1446+ 	let  revoked_to_self_claim = { 
1447+ 		let  mut  as_commitment_claim_txn = nodes[ 0 ] . tx_broadcaster . txn_broadcast ( ) ; 
1448+ 		assert_eq ! ( as_commitment_claim_txn. len( ) ,  if  anchors {  2  }  else {  1  } ) ; 
1449+ 		if  anchors { 
1450+ 			assert_eq ! ( as_commitment_claim_txn[ 0 ] . input. len( ) ,  1 ) ; 
1451+ 			assert_eq ! ( as_commitment_claim_txn[ 0 ] . input[ 0 ] . previous_output. vout,  4 ) ;  // Separate to_remote claim 
1452+ 			check_spends ! ( as_commitment_claim_txn[ 0 ] ,  revoked_local_txn[ 0 ] ) ; 
1453+ 			assert_eq ! ( as_commitment_claim_txn[ 1 ] . input. len( ) ,  2 ) ; 
1454+ 			assert_eq ! ( as_commitment_claim_txn[ 1 ] . input[ 0 ] . previous_output. vout,  2 ) ; 
1455+ 			assert_eq ! ( as_commitment_claim_txn[ 1 ] . input[ 1 ] . previous_output. vout,  3 ) ; 
1456+ 			check_spends ! ( as_commitment_claim_txn[ 1 ] ,  revoked_local_txn[ 0 ] ) ; 
1457+ 			Some ( as_commitment_claim_txn. remove ( 0 ) ) 
1458+ 		}  else  { 
1459+ 			assert_eq ! ( as_commitment_claim_txn[ 0 ] . input. len( ) ,  3 ) ; 
1460+ 			assert_eq ! ( as_commitment_claim_txn[ 0 ] . input[ 0 ] . previous_output. vout,  2 ) ; 
1461+ 			assert_eq ! ( as_commitment_claim_txn[ 0 ] . input[ 1 ] . previous_output. vout,  0 ) ; 
1462+ 			assert_eq ! ( as_commitment_claim_txn[ 0 ] . input[ 2 ] . previous_output. vout,  1 ) ; 
1463+ 			check_spends ! ( as_commitment_claim_txn[ 0 ] ,  revoked_local_txn[ 0 ] ) ; 
1464+ 			None 
1465+ 		} 
1466+ 	} ; 
14101467
14111468	// The next two checks have the same balance set for A - even though we confirm a revoked HTLC 
14121469	// transaction our balance tracking doesn't use the on-chain value so the 
14131470	// `CounterpartyRevokedOutputClaimable` entry doesn't change. 
1471+ 	let  commitment_tx_fee = chan_feerate * 
1472+ 		( channel:: commitment_tx_base_weight ( & channel_type_features)  + 2  *  channel:: COMMITMENT_TX_WEIGHT_PER_HTLC )  / 1000 ; 
1473+ 	let  anchor_outputs_value = if  anchors {  channel:: ANCHOR_OUTPUT_VALUE_SATOSHI  *  2  }  else  {  0  } ; 
14141474	let  as_balances = sorted_vec ( vec ! [ Balance :: ClaimableAwaitingConfirmations  { 
14151475			// to_remote output in B's revoked commitment 
1416- 			amount_satoshis:  1_000_000  - 11_000  - 3_000  - chan_feerate * 
1417- 				( channel:: commitment_tx_base_weight( & channel_type_features)  + 2  *  channel:: COMMITMENT_TX_WEIGHT_PER_HTLC )  / 1000 , 
1476+ 			amount_satoshis:  1_000_000  - 11_000  - 3_000  - commitment_tx_fee - anchor_outputs_value, 
14181477			confirmation_height:  to_remote_conf_height, 
14191478		} ,  Balance :: CounterpartyRevokedOutputClaimable  { 
14201479			// to_self output in B's revoked commitment 
@@ -1430,22 +1489,36 @@ fn test_revoked_counterparty_htlc_tx_balances() {
14301489	mine_transaction ( & nodes[ 0 ] ,  & revoked_htlc_success) ; 
14311490	let  as_htlc_claim_tx = nodes[ 0 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) . split_off ( 0 ) ; 
14321491	assert_eq ! ( as_htlc_claim_tx. len( ) ,  2 ) ; 
1492+ 	assert_eq ! ( as_htlc_claim_tx[ 0 ] . input. len( ) ,  1 ) ; 
14331493	check_spends ! ( as_htlc_claim_tx[ 0 ] ,  revoked_htlc_success) ; 
1434- 	check_spends ! ( as_htlc_claim_tx[ 1 ] ,  revoked_local_txn[ 0 ] ) ;  // A has to generate a new claim for the remaining revoked 
1435- 	                                                          // outputs (which no longer includes the spent HTLC output) 
1494+ 	// A has to generate a new claim for the remaining revoked outputs (which no longer includes the 
1495+ 	// spent HTLC output) 
1496+ 	assert_eq ! ( as_htlc_claim_tx[ 1 ] . input. len( ) ,  if  anchors {  1  }  else {  2  } ) ; 
1497+ 	assert_eq ! ( as_htlc_claim_tx[ 1 ] . input[ 0 ] . previous_output. vout,  2 ) ; 
1498+ 	if  !anchors { 
1499+ 		assert_eq ! ( as_htlc_claim_tx[ 1 ] . input[ 1 ] . previous_output. vout,  0 ) ; 
1500+ 	} 
1501+ 	check_spends ! ( as_htlc_claim_tx[ 1 ] ,  revoked_local_txn[ 0 ] ) ; 
14361502
14371503	assert_eq ! ( as_balances, 
14381504		sorted_vec( nodes[ 0 ] . chain_monitor. chain_monitor. get_monitor( funding_outpoint) . unwrap( ) . get_claimable_balances( ) ) ) ; 
14391505
14401506	assert_eq ! ( as_htlc_claim_tx[ 0 ] . output. len( ) ,  1 ) ; 
1441- 	fuzzy_assert_eq ( as_htlc_claim_tx[ 0 ] . output [ 0 ] . value , 
1442- 		3_000  - chan_feerate *  ( revoked_htlc_success. weight ( )  + as_htlc_claim_tx[ 0 ] . weight ( ) )  as  u64  / 1000 ) ; 
1507+ 	let  as_revoked_htlc_success_claim_fee = chan_feerate *  as_htlc_claim_tx[ 0 ] . weight ( )  as  u64  / 1000 ; 
1508+ 	if  anchors { 
1509+ 		// With anchors, B can pay for revoked_htlc_success's fee with additional inputs, rather 
1510+ 		// than with the HTLC itself. 
1511+ 		fuzzy_assert_eq ( as_htlc_claim_tx[ 0 ] . output [ 0 ] . value , 
1512+ 			3_000  - as_revoked_htlc_success_claim_fee) ; 
1513+ 	}  else  { 
1514+ 		fuzzy_assert_eq ( as_htlc_claim_tx[ 0 ] . output [ 0 ] . value , 
1515+ 			3_000  - revoked_htlc_success_fee - as_revoked_htlc_success_claim_fee) ; 
1516+ 	} 
14431517
14441518	mine_transaction ( & nodes[ 0 ] ,  & as_htlc_claim_tx[ 0 ] ) ; 
14451519	assert_eq ! ( sorted_vec( vec![ Balance :: ClaimableAwaitingConfirmations  { 
14461520			// to_remote output in B's revoked commitment 
1447- 			amount_satoshis:  1_000_000  - 11_000  - 3_000  - chan_feerate * 
1448- 				( channel:: commitment_tx_base_weight( & channel_type_features)  + 2  *  channel:: COMMITMENT_TX_WEIGHT_PER_HTLC )  / 1000 , 
1521+ 			amount_satoshis:  1_000_000  - 11_000  - 3_000  - commitment_tx_fee - anchor_outputs_value, 
14491522			confirmation_height:  to_remote_conf_height, 
14501523		} ,  Balance :: CounterpartyRevokedOutputClaimable  { 
14511524			// to_self output in B's revoked commitment 
@@ -1499,11 +1572,24 @@ fn test_revoked_counterparty_htlc_tx_balances() {
14991572	} 
15001573
15011574	mine_transaction ( & nodes[ 0 ] ,  & revoked_htlc_timeout) ; 
1502- 	let  as_second_htlc_claim_tx = nodes[ 0 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) . split_off ( 0 ) ; 
1503- 	assert_eq ! ( as_second_htlc_claim_tx. len( ) ,  2 ) ; 
1504- 
1505- 	check_spends ! ( as_second_htlc_claim_tx[ 0 ] ,  revoked_htlc_timeout) ; 
1506- 	check_spends ! ( as_second_htlc_claim_tx[ 1 ] ,  revoked_local_txn[ 0 ] ) ; 
1575+ 	let  ( revoked_htlc_timeout_claim,  revoked_to_self_claim)  = { 
1576+ 		let  mut  as_second_htlc_claim_tx = nodes[ 0 ] . tx_broadcaster . txn_broadcast ( ) ; 
1577+ 		assert_eq ! ( as_second_htlc_claim_tx. len( ) ,  if  anchors {  1  }  else {  2  } ) ; 
1578+ 		if  anchors { 
1579+ 			assert_eq ! ( as_second_htlc_claim_tx[ 0 ] . input. len( ) ,  1 ) ; 
1580+ 			assert_eq ! ( as_second_htlc_claim_tx[ 0 ] . input[ 0 ] . previous_output. vout,  0 ) ; 
1581+ 			check_spends ! ( as_second_htlc_claim_tx[ 0 ] ,  revoked_htlc_timeout) ; 
1582+ 			( as_second_htlc_claim_tx. remove ( 0 ) ,  revoked_to_self_claim. unwrap ( ) ) 
1583+ 		}  else  { 
1584+ 			assert_eq ! ( as_second_htlc_claim_tx[ 0 ] . input. len( ) ,  1 ) ; 
1585+ 			assert_eq ! ( as_second_htlc_claim_tx[ 0 ] . input[ 0 ] . previous_output. vout,  0 ) ; 
1586+ 			check_spends ! ( as_second_htlc_claim_tx[ 0 ] ,  revoked_htlc_timeout) ; 
1587+ 			assert_eq ! ( as_second_htlc_claim_tx[ 1 ] . input. len( ) ,  1 ) ; 
1588+ 			assert_eq ! ( as_second_htlc_claim_tx[ 1 ] . input[ 0 ] . previous_output. vout,  2 ) ; 
1589+ 			check_spends ! ( as_second_htlc_claim_tx[ 1 ] ,  revoked_local_txn[ 0 ] ) ; 
1590+ 			( as_second_htlc_claim_tx. remove ( 0 ) ,  as_second_htlc_claim_tx. remove ( 0 ) ) 
1591+ 		} 
1592+ 	} ; 
15071593
15081594	// Connect blocks to finalize the HTLC resolution with the HTLC-Timeout transaction. In a 
15091595	// previous iteration of the revoked balance handling this would result in us "forgetting" that 
@@ -1517,31 +1603,31 @@ fn test_revoked_counterparty_htlc_tx_balances() {
15171603		} ] ) , 
15181604		sorted_vec( nodes[ 0 ] . chain_monitor. chain_monitor. get_monitor( funding_outpoint) . unwrap( ) . get_claimable_balances( ) ) ) ; 
15191605
1520- 	mine_transaction ( & nodes[ 0 ] ,  & as_second_htlc_claim_tx [ 0 ] ) ; 
1606+ 	mine_transaction ( & nodes[ 0 ] ,  & revoked_htlc_timeout_claim ) ; 
15211607	assert_eq ! ( sorted_vec( vec![ Balance :: CounterpartyRevokedOutputClaimable  { 
15221608			// to_self output in B's revoked commitment 
15231609			amount_satoshis:  10_000 , 
15241610		} ,  Balance :: ClaimableAwaitingConfirmations  { 
1525- 			amount_satoshis:  as_second_htlc_claim_tx [ 0 ] . output[ 0 ] . value, 
1611+ 			amount_satoshis:  revoked_htlc_timeout_claim . output[ 0 ] . value, 
15261612			confirmation_height:  nodes[ 0 ] . best_block_info( ) . 1  + ANTI_REORG_DELAY  - 1 , 
15271613		} ] ) , 
15281614		sorted_vec( nodes[ 0 ] . chain_monitor. chain_monitor. get_monitor( funding_outpoint) . unwrap( ) . get_claimable_balances( ) ) ) ; 
15291615
1530- 	mine_transaction ( & nodes[ 0 ] ,  & as_second_htlc_claim_tx [ 1 ] ) ; 
1616+ 	mine_transaction ( & nodes[ 0 ] ,  & revoked_to_self_claim ) ; 
15311617	assert_eq ! ( sorted_vec( vec![ Balance :: ClaimableAwaitingConfirmations  { 
15321618			// to_self output in B's revoked commitment 
1533- 			amount_satoshis:  as_second_htlc_claim_tx [ 1 ] . output[ 0 ] . value, 
1619+ 			amount_satoshis:  revoked_to_self_claim . output[ 0 ] . value, 
15341620			confirmation_height:  nodes[ 0 ] . best_block_info( ) . 1  + ANTI_REORG_DELAY  - 1 , 
15351621		} ,  Balance :: ClaimableAwaitingConfirmations  { 
1536- 			amount_satoshis:  as_second_htlc_claim_tx [ 0 ] . output[ 0 ] . value, 
1622+ 			amount_satoshis:  revoked_htlc_timeout_claim . output[ 0 ] . value, 
15371623			confirmation_height:  nodes[ 0 ] . best_block_info( ) . 1  + ANTI_REORG_DELAY  - 2 , 
15381624		} ] ) , 
15391625		sorted_vec( nodes[ 0 ] . chain_monitor. chain_monitor. get_monitor( funding_outpoint) . unwrap( ) . get_claimable_balances( ) ) ) ; 
15401626
15411627	connect_blocks ( & nodes[ 0 ] ,  ANTI_REORG_DELAY  - 2 ) ; 
1542- 	test_spendable_output ( & nodes[ 0 ] ,  & as_second_htlc_claim_tx [ 0 ] ,  false ) ; 
1628+ 	test_spendable_output ( & nodes[ 0 ] ,  & revoked_htlc_timeout_claim ,  false ) ; 
15431629	connect_blocks ( & nodes[ 0 ] ,  1 ) ; 
1544- 	test_spendable_output ( & nodes[ 0 ] ,  & as_second_htlc_claim_tx [ 1 ] ,  false ) ; 
1630+ 	test_spendable_output ( & nodes[ 0 ] ,  & revoked_to_self_claim ,  false ) ; 
15451631
15461632	assert_eq ! ( nodes[ 0 ] . chain_monitor. chain_monitor. get_monitor( funding_outpoint) . unwrap( ) . get_claimable_balances( ) ,  Vec :: new( ) ) ; 
15471633
@@ -1555,7 +1641,11 @@ fn test_revoked_counterparty_htlc_tx_balances() {
15551641} 
15561642
15571643#[ test]  
1558- fn  test_revoked_counterparty_aggregated_claims ( )  { 
1644+ fn  test_revoked_counterparty_htlc_tx_balances ( )  { 
1645+ 	do_test_revoked_counterparty_htlc_tx_balances ( false ) ; 
1646+ 	do_test_revoked_counterparty_htlc_tx_balances ( true ) ; 
1647+ } 
1648+ 
15591649	// Tests `get_claimable_balances` for revoked counterparty commitment transactions when 
15601650	// claiming with an aggregated claim transaction. 
15611651	let  mut  chanmon_cfgs = create_chanmon_cfgs ( 2 ) ; 
0 commit comments