@@ -786,7 +786,7 @@ impl<ChannelSigner: EcdsaChannelSigner> OnchainTxHandler<ChannelSigner> {
786786 let mut preprocessed_requests = Vec :: with_capacity ( requests. len ( ) ) ;
787787 for req in requests {
788788 let package_locktime = req. package_locktime ( cur_height) ;
789- if package_locktime > cur_height + 1 {
789+ if package_locktime > cur_height {
790790 log_info ! ( logger, "Delaying claim of package until its timelock at {} (current height {}), the following outpoints are spent:" , package_locktime, cur_height) ;
791791 for outpoint in req. outpoints ( ) {
792792 log_info ! ( logger, " Outpoint {}" , outpoint) ;
@@ -1276,3 +1276,178 @@ impl<ChannelSigner: EcdsaChannelSigner> OnchainTxHandler<ChannelSigner> {
12761276 & self . channel_transaction_parameters . channel_type_features
12771277 }
12781278}
1279+
1280+ #[ cfg( test) ]
1281+ mod tests {
1282+ use bitcoin:: hash_types:: Txid ;
1283+ use bitcoin:: hashes:: sha256:: Hash as Sha256 ;
1284+ use bitcoin:: hashes:: Hash ;
1285+ use bitcoin:: Network ;
1286+ use bitcoin:: { key:: Secp256k1 , secp256k1:: PublicKey , secp256k1:: SecretKey , ScriptBuf } ;
1287+ use types:: features:: ChannelTypeFeatures ;
1288+
1289+ use crate :: chain:: chaininterface:: { ConfirmationTarget , LowerBoundedFeeEstimator } ;
1290+ use crate :: chain:: package:: { HolderHTLCOutput , PackageSolvingData , PackageTemplate } ;
1291+ use crate :: chain:: transaction:: OutPoint ;
1292+ use crate :: ln:: chan_utils:: {
1293+ ChannelPublicKeys , ChannelTransactionParameters , CounterpartyChannelTransactionParameters ,
1294+ HTLCOutputInCommitment , HolderCommitmentTransaction ,
1295+ } ;
1296+ use crate :: ln:: channel_keys:: { DelayedPaymentBasepoint , HtlcBasepoint , RevocationBasepoint } ;
1297+ use crate :: ln:: functional_test_utils:: create_dummy_block;
1298+ use crate :: sign:: InMemorySigner ;
1299+ use crate :: types:: payment:: { PaymentHash , PaymentPreimage } ;
1300+ use crate :: util:: test_utils:: { TestBroadcaster , TestFeeEstimator , TestLogger } ;
1301+
1302+ use super :: OnchainTxHandler ;
1303+
1304+ // Test that all claims with locktime equal to or less than the current height are broadcast
1305+ // immediately while claims with locktime greater than the current height are only broadcast
1306+ // once the locktime is reached.
1307+ #[ test]
1308+ fn test_broadcast_height ( ) {
1309+ let secp_ctx = Secp256k1 :: new ( ) ;
1310+ let signer = InMemorySigner :: new (
1311+ & secp_ctx,
1312+ SecretKey :: from_slice ( & [ 41 ; 32 ] ) . unwrap ( ) ,
1313+ SecretKey :: from_slice ( & [ 41 ; 32 ] ) . unwrap ( ) ,
1314+ SecretKey :: from_slice ( & [ 41 ; 32 ] ) . unwrap ( ) ,
1315+ SecretKey :: from_slice ( & [ 41 ; 32 ] ) . unwrap ( ) ,
1316+ SecretKey :: from_slice ( & [ 41 ; 32 ] ) . unwrap ( ) ,
1317+ [ 41 ; 32 ] ,
1318+ 0 ,
1319+ [ 0 ; 32 ] ,
1320+ [ 0 ; 32 ] ,
1321+ ) ;
1322+ let counterparty_pubkeys = ChannelPublicKeys {
1323+ funding_pubkey : PublicKey :: from_secret_key (
1324+ & secp_ctx,
1325+ & SecretKey :: from_slice ( & [ 44 ; 32 ] ) . unwrap ( ) ,
1326+ ) ,
1327+ revocation_basepoint : RevocationBasepoint :: from ( PublicKey :: from_secret_key (
1328+ & secp_ctx,
1329+ & SecretKey :: from_slice ( & [ 45 ; 32 ] ) . unwrap ( ) ,
1330+ ) ) ,
1331+ payment_point : PublicKey :: from_secret_key (
1332+ & secp_ctx,
1333+ & SecretKey :: from_slice ( & [ 46 ; 32 ] ) . unwrap ( ) ,
1334+ ) ,
1335+ delayed_payment_basepoint : DelayedPaymentBasepoint :: from ( PublicKey :: from_secret_key (
1336+ & secp_ctx,
1337+ & SecretKey :: from_slice ( & [ 47 ; 32 ] ) . unwrap ( ) ,
1338+ ) ) ,
1339+ htlc_basepoint : HtlcBasepoint :: from ( PublicKey :: from_secret_key (
1340+ & secp_ctx,
1341+ & SecretKey :: from_slice ( & [ 48 ; 32 ] ) . unwrap ( ) ,
1342+ ) ) ,
1343+ } ;
1344+ let funding_outpoint = OutPoint { txid : Txid :: all_zeros ( ) , index : u16:: MAX } ;
1345+
1346+ // Use non-anchor channels so that HTLC-Timeouts are broadcast immediately instead of sent
1347+ // to the user for external funding.
1348+ let chan_params = ChannelTransactionParameters {
1349+ holder_pubkeys : signer. holder_channel_pubkeys . clone ( ) ,
1350+ holder_selected_contest_delay : 66 ,
1351+ is_outbound_from_holder : true ,
1352+ counterparty_parameters : Some ( CounterpartyChannelTransactionParameters {
1353+ pubkeys : counterparty_pubkeys,
1354+ selected_contest_delay : 67 ,
1355+ } ) ,
1356+ funding_outpoint : Some ( funding_outpoint) ,
1357+ channel_type_features : ChannelTypeFeatures :: only_static_remote_key ( ) ,
1358+ } ;
1359+
1360+ // Create an OnchainTxHandler for a commitment containing HTLCs with CLTV expiries of 0, 1,
1361+ // and 2 blocks.
1362+ let mut htlcs = Vec :: new ( ) ;
1363+ for i in 0 ..3 {
1364+ let preimage = PaymentPreimage ( [ i; 32 ] ) ;
1365+ let hash = PaymentHash ( Sha256 :: hash ( & preimage. 0 [ ..] ) . to_byte_array ( ) ) ;
1366+ htlcs. push ( (
1367+ HTLCOutputInCommitment {
1368+ offered : true ,
1369+ amount_msat : 10000 ,
1370+ cltv_expiry : i as u32 ,
1371+ payment_hash : hash,
1372+ transaction_output_index : Some ( i as u32 ) ,
1373+ } ,
1374+ ( ) ,
1375+ ) ) ;
1376+ }
1377+ let holder_commit = HolderCommitmentTransaction :: dummy ( & mut htlcs) ;
1378+ let mut tx_handler = OnchainTxHandler :: new (
1379+ 1000000 ,
1380+ [ 0 ; 32 ] ,
1381+ ScriptBuf :: new ( ) ,
1382+ signer,
1383+ chan_params,
1384+ holder_commit,
1385+ secp_ctx,
1386+ ) ;
1387+
1388+ // Create a broadcaster with current block height 1.
1389+ let broadcaster = TestBroadcaster :: new ( Network :: Testnet ) ;
1390+ {
1391+ let mut blocks = broadcaster. blocks . lock ( ) . unwrap ( ) ;
1392+ let genesis_hash = blocks[ 0 ] . 0 . block_hash ( ) ;
1393+ blocks. push ( ( create_dummy_block ( genesis_hash, 0 , Vec :: new ( ) ) , 1 ) ) ;
1394+ }
1395+
1396+ let fee_estimator = TestFeeEstimator :: new ( 253 ) ;
1397+ let fee_estimator = LowerBoundedFeeEstimator :: new ( & fee_estimator) ;
1398+ let logger = TestLogger :: new ( ) ;
1399+
1400+ // Request claiming of each HTLC on the holder's commitment, with current block height 1.
1401+ let holder_commit_txid = tx_handler. get_unsigned_holder_commitment_tx ( ) . compute_txid ( ) ;
1402+ let mut requests = Vec :: new ( ) ;
1403+ for ( htlc, _) in htlcs {
1404+ requests. push ( PackageTemplate :: build_package (
1405+ holder_commit_txid,
1406+ htlc. transaction_output_index . unwrap ( ) ,
1407+ PackageSolvingData :: HolderHTLCOutput ( HolderHTLCOutput :: build_offered (
1408+ htlc. amount_msat ,
1409+ htlc. cltv_expiry ,
1410+ ChannelTypeFeatures :: only_static_remote_key ( ) ,
1411+ ) ) ,
1412+ 0 ,
1413+ ) ) ;
1414+ }
1415+ tx_handler. update_claims_view_from_requests (
1416+ requests,
1417+ 1 ,
1418+ 1 ,
1419+ & & broadcaster,
1420+ ConfirmationTarget :: UrgentOnChainSweep ,
1421+ & fee_estimator,
1422+ & logger,
1423+ ) ;
1424+
1425+ // HTLC-Timeouts should be broadcast for the HTLCs with expiries at heights 0 and 1. The
1426+ // HTLC with expiry at height 2 should not be claimed yet.
1427+ let txs_broadcasted = broadcaster. txn_broadcast ( ) ;
1428+ assert_eq ! ( txs_broadcasted. len( ) , 2 ) ;
1429+ assert ! ( txs_broadcasted[ 0 ] . lock_time. to_consensus_u32( ) <= 1 ) ;
1430+ assert ! ( txs_broadcasted[ 1 ] . lock_time. to_consensus_u32( ) <= 1 ) ;
1431+
1432+ // Advance to block height 2, and reprocess pending claims.
1433+ {
1434+ let mut blocks = broadcaster. blocks . lock ( ) . unwrap ( ) ;
1435+ let block1_hash = blocks[ 1 ] . 0 . block_hash ( ) ;
1436+ blocks. push ( ( create_dummy_block ( block1_hash, 0 , Vec :: new ( ) ) , 2 ) ) ;
1437+ }
1438+ tx_handler. update_claims_view_from_requests (
1439+ Vec :: new ( ) ,
1440+ 2 ,
1441+ 2 ,
1442+ & & broadcaster,
1443+ ConfirmationTarget :: UrgentOnChainSweep ,
1444+ & fee_estimator,
1445+ & logger,
1446+ ) ;
1447+
1448+ // The final HTLC-Timeout should now be broadcast.
1449+ let txs_broadcasted = broadcaster. txn_broadcast ( ) ;
1450+ assert_eq ! ( txs_broadcasted. len( ) , 1 ) ;
1451+ assert_eq ! ( txs_broadcasted[ 0 ] . lock_time. to_consensus_u32( ) , 2 ) ;
1452+ }
1453+ }
0 commit comments