@@ -32,7 +32,8 @@ use ln::chan_utils;
32
32
use ln:: chan_utils:: { CounterpartyCommitmentSecrets , HTLCOutputInCommitment , LocalCommitmentTransaction , HTLCType } ;
33
33
use ln:: channelmanager:: { HTLCSource , PaymentPreimage , PaymentHash } ;
34
34
use ln:: onchaintx:: OnchainTxHandler ;
35
- use ln:: onchain_utils:: InputDescriptors ;
35
+ use ln:: onchain_utils;
36
+ use ln:: onchain_utils:: { InputDescriptors , PackageTemplate , LocalFundingOutput , LocalHTLCOutput , RemoteHTLCOutput , RevokedOutput } ;
36
37
use chain:: chaininterface:: { ChainListener , ChainWatchInterface , BroadcasterInterface , FeeEstimator } ;
37
38
use chain:: transaction:: OutPoint ;
38
39
use chain:: keysinterface:: { SpendableOutputDescriptor , ChannelKeys } ;
@@ -428,129 +429,6 @@ impl Readable for RemoteCommitmentTransaction {
428
429
}
429
430
}
430
431
431
- /// When ChannelMonitor discovers an onchain outpoint being a step of a channel and that it needs
432
- /// to generate a tx to push channel state forward, we cache outpoint-solving tx material to build
433
- /// a new bumped one in case of lenghty confirmation delay
434
- #[ derive( Clone , PartialEq ) ]
435
- pub ( crate ) enum InputMaterial {
436
- Revoked {
437
- per_commitment_point : PublicKey ,
438
- remote_delayed_payment_base_key : PublicKey ,
439
- remote_htlc_base_key : PublicKey ,
440
- per_commitment_key : SecretKey ,
441
- input_descriptor : InputDescriptors ,
442
- amount : u64 ,
443
- htlc : Option < HTLCOutputInCommitment > ,
444
- on_remote_tx_csv : u16 ,
445
- } ,
446
- RemoteHTLC {
447
- per_commitment_point : PublicKey ,
448
- remote_delayed_payment_base_key : PublicKey ,
449
- remote_htlc_base_key : PublicKey ,
450
- preimage : Option < PaymentPreimage > ,
451
- htlc : HTLCOutputInCommitment
452
- } ,
453
- LocalHTLC {
454
- preimage : Option < PaymentPreimage > ,
455
- amount : u64 ,
456
- } ,
457
- Funding {
458
- funding_redeemscript : Script ,
459
- }
460
- }
461
-
462
- impl Writeable for InputMaterial {
463
- fn write < W : Writer > ( & self , writer : & mut W ) -> Result < ( ) , :: std:: io:: Error > {
464
- match self {
465
- & InputMaterial :: Revoked { ref per_commitment_point, ref remote_delayed_payment_base_key, ref remote_htlc_base_key, ref per_commitment_key, ref input_descriptor, ref amount, ref htlc, ref on_remote_tx_csv} => {
466
- writer. write_all ( & [ 0 ; 1 ] ) ?;
467
- per_commitment_point. write ( writer) ?;
468
- remote_delayed_payment_base_key. write ( writer) ?;
469
- remote_htlc_base_key. write ( writer) ?;
470
- writer. write_all ( & per_commitment_key[ ..] ) ?;
471
- input_descriptor. write ( writer) ?;
472
- writer. write_all ( & byte_utils:: be64_to_array ( * amount) ) ?;
473
- htlc. write ( writer) ?;
474
- on_remote_tx_csv. write ( writer) ?;
475
- } ,
476
- & InputMaterial :: RemoteHTLC { ref per_commitment_point, ref remote_delayed_payment_base_key, ref remote_htlc_base_key, ref preimage, ref htlc} => {
477
- writer. write_all ( & [ 1 ; 1 ] ) ?;
478
- per_commitment_point. write ( writer) ?;
479
- remote_delayed_payment_base_key. write ( writer) ?;
480
- remote_htlc_base_key. write ( writer) ?;
481
- preimage. write ( writer) ?;
482
- htlc. write ( writer) ?;
483
- } ,
484
- & InputMaterial :: LocalHTLC { ref preimage, ref amount } => {
485
- writer. write_all ( & [ 2 ; 1 ] ) ?;
486
- preimage. write ( writer) ?;
487
- writer. write_all ( & byte_utils:: be64_to_array ( * amount) ) ?;
488
- } ,
489
- & InputMaterial :: Funding { ref funding_redeemscript } => {
490
- writer. write_all ( & [ 3 ; 1 ] ) ?;
491
- funding_redeemscript. write ( writer) ?;
492
- }
493
- }
494
- Ok ( ( ) )
495
- }
496
- }
497
-
498
- impl Readable for InputMaterial {
499
- fn read < R : :: std:: io:: Read > ( reader : & mut R ) -> Result < Self , DecodeError > {
500
- let input_material = match <u8 as Readable >:: read ( reader) ? {
501
- 0 => {
502
- let per_commitment_point = Readable :: read ( reader) ?;
503
- let remote_delayed_payment_base_key = Readable :: read ( reader) ?;
504
- let remote_htlc_base_key = Readable :: read ( reader) ?;
505
- let per_commitment_key = Readable :: read ( reader) ?;
506
- let input_descriptor = Readable :: read ( reader) ?;
507
- let amount = Readable :: read ( reader) ?;
508
- let htlc = Readable :: read ( reader) ?;
509
- let on_remote_tx_csv = Readable :: read ( reader) ?;
510
- InputMaterial :: Revoked {
511
- per_commitment_point,
512
- remote_delayed_payment_base_key,
513
- remote_htlc_base_key,
514
- per_commitment_key,
515
- input_descriptor,
516
- amount,
517
- htlc,
518
- on_remote_tx_csv
519
- }
520
- } ,
521
- 1 => {
522
- let per_commitment_point = Readable :: read ( reader) ?;
523
- let remote_delayed_payment_base_key = Readable :: read ( reader) ?;
524
- let remote_htlc_base_key = Readable :: read ( reader) ?;
525
- let preimage = Readable :: read ( reader) ?;
526
- let htlc = Readable :: read ( reader) ?;
527
- InputMaterial :: RemoteHTLC {
528
- per_commitment_point,
529
- remote_delayed_payment_base_key,
530
- remote_htlc_base_key,
531
- preimage,
532
- htlc
533
- }
534
- } ,
535
- 2 => {
536
- let preimage = Readable :: read ( reader) ?;
537
- let amount = Readable :: read ( reader) ?;
538
- InputMaterial :: LocalHTLC {
539
- preimage,
540
- amount,
541
- }
542
- } ,
543
- 3 => {
544
- InputMaterial :: Funding {
545
- funding_redeemscript : Readable :: read ( reader) ?,
546
- }
547
- }
548
- _ => return Err ( DecodeError :: InvalidValue ) ,
549
- } ;
550
- Ok ( input_material)
551
- }
552
- }
553
-
554
432
/// ClaimRequest is a descriptor structure to communicate between detection
555
433
/// and reaction module. They are generated by ChannelMonitor while parsing
556
434
/// onchain txn leaked from a channel and handed over to OnchainTxHandler which
@@ -566,11 +444,9 @@ pub(crate) struct ClaimRequest {
566
444
// of a sooner-HTLC could be swallowed by the highest nLocktime of the HTLC set.
567
445
// Do simplify we mark them as non-aggregable.
568
446
pub ( crate ) aggregable : bool ,
569
- // Basic bitcoin outpoint (txid, vout)
570
- pub ( crate ) outpoint : BitcoinOutPoint ,
571
- // Following outpoint type, set of data needed to generate transaction digest
572
- // and satisfy witness program.
573
- pub ( crate ) witness_data : InputMaterial
447
+ // Template (list of outpoint and set of data needed to generate transaction digest
448
+ // and satisfy witness program).
449
+ pub ( crate ) package_template : PackageTemplate ,
574
450
}
575
451
576
452
/// Upon discovering of some classes of onchain tx by ChannelMonitor, we may have to take actions on it
@@ -1508,8 +1384,8 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
1508
1384
// First, process non-htlc outputs (to_local & to_remote)
1509
1385
for ( idx, outp) in tx. output . iter ( ) . enumerate ( ) {
1510
1386
if outp. script_pubkey == revokeable_p2wsh {
1511
- let witness_data = InputMaterial :: Revoked { per_commitment_point, remote_delayed_payment_base_key : self . remote_tx_cache . remote_delayed_payment_base_key , remote_htlc_base_key : self . remote_tx_cache . remote_htlc_base_key , per_commitment_key , input_descriptor : InputDescriptors :: RevokedOutput , amount : outp. value , htlc : None , on_remote_tx_csv : self . remote_tx_cache . on_remote_tx_csv } ;
1512
- claimable_outpoints. push ( ClaimRequest { absolute_timelock : height + self . remote_tx_cache . on_remote_tx_csv as u32 , aggregable : true , outpoint : BitcoinOutPoint { txid : commitment_txid , vout : idx as u32 } , witness_data } ) ;
1387
+ let malleable_justice_tx = PackageTemplate :: build_malleable_justice_tx ( per_commitment_point, per_commitment_key , self . remote_tx_cache . remote_delayed_payment_base_key , self . remote_tx_cache . remote_htlc_base_key , InputDescriptors :: RevokedOutput , commitment_txid , idx as u32 , outp. value , None , self . remote_tx_cache . on_remote_tx_csv ) ;
1388
+ claimable_outpoints. push ( ClaimRequest { absolute_timelock : height + self . remote_tx_cache . on_remote_tx_csv as u32 , aggregable : true , package_template : malleable_justice_tx } ) ;
1513
1389
}
1514
1390
}
1515
1391
@@ -1521,8 +1397,8 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
1521
1397
tx. output [ transaction_output_index as usize ] . value != htlc. amount_msat / 1000 {
1522
1398
return ( claimable_outpoints, ( commitment_txid, watch_outputs) ) ; // Corrupted per_commitment_data, fuck this user
1523
1399
}
1524
- let witness_data = InputMaterial :: Revoked { per_commitment_point, remote_delayed_payment_base_key : self . remote_tx_cache . remote_delayed_payment_base_key , remote_htlc_base_key : self . remote_tx_cache . remote_htlc_base_key , per_commitment_key , input_descriptor : if htlc. offered { InputDescriptors :: RevokedOfferedHTLC } else { InputDescriptors :: RevokedReceivedHTLC } , amount : tx . output [ transaction_output_index as usize ] . value , htlc : Some ( htlc. clone ( ) ) , on_remote_tx_csv : self . remote_tx_cache . on_remote_tx_csv } ;
1525
- claimable_outpoints. push ( ClaimRequest { absolute_timelock : htlc. cltv_expiry , aggregable : true , outpoint : BitcoinOutPoint { txid : commitment_txid , vout : transaction_output_index } , witness_data } ) ;
1400
+ let malleable_justice_tx = PackageTemplate :: build_malleable_justice_tx ( per_commitment_point, per_commitment_key , self . remote_tx_cache . remote_delayed_payment_base_key , self . remote_tx_cache . remote_htlc_base_key , if htlc. offered { InputDescriptors :: RevokedOfferedHTLC } else { InputDescriptors :: RevokedReceivedHTLC } , commitment_txid , transaction_output_index, htlc. amount_msat / 1000 , Some ( htlc. clone ( ) ) , self . remote_tx_cache . on_remote_tx_csv ) ;
1401
+ claimable_outpoints. push ( ClaimRequest { absolute_timelock : htlc. cltv_expiry , aggregable : true , package_template : malleable_justice_tx } ) ;
1526
1402
}
1527
1403
}
1528
1404
}
@@ -1656,8 +1532,8 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
1656
1532
let preimage = if htlc. offered { if let Some ( p) = self . payment_preimages . get ( & htlc. payment_hash ) { Some ( * p) } else { None } } else { None } ;
1657
1533
let aggregable = if !htlc. offered { false } else { true } ;
1658
1534
if preimage. is_some ( ) || !htlc. offered {
1659
- let witness_data = InputMaterial :: RemoteHTLC { per_commitment_point : * revocation_point, remote_delayed_payment_base_key : self . remote_tx_cache . remote_delayed_payment_base_key , remote_htlc_base_key : self . remote_tx_cache . remote_htlc_base_key , preimage, htlc : htlc . clone ( ) } ;
1660
- claimable_outpoints. push ( ClaimRequest { absolute_timelock : htlc. cltv_expiry , aggregable, outpoint : BitcoinOutPoint { txid : commitment_txid , vout : transaction_output_index } , witness_data } ) ;
1535
+ let remote_htlc_tx = PackageTemplate :: build_remote_htlc_tx ( * revocation_point, self . remote_tx_cache . remote_delayed_payment_base_key , self . remote_tx_cache . remote_htlc_base_key , preimage, htlc. clone ( ) , commitment_txid , transaction_output_index ) ;
1536
+ claimable_outpoints. push ( ClaimRequest { absolute_timelock : htlc. cltv_expiry , aggregable, package_template : remote_htlc_tx } ) ;
1661
1537
}
1662
1538
}
1663
1539
}
@@ -1688,8 +1564,8 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
1688
1564
let per_commitment_point = PublicKey :: from_secret_key ( & self . secp_ctx , & per_commitment_key) ;
1689
1565
1690
1566
log_trace ! ( logger, "Remote HTLC broadcast {}:{}" , htlc_txid, 0 ) ;
1691
- let witness_data = InputMaterial :: Revoked { per_commitment_point, remote_delayed_payment_base_key : self . remote_tx_cache . remote_delayed_payment_base_key , remote_htlc_base_key : self . remote_tx_cache . remote_htlc_base_key , per_commitment_key , input_descriptor : InputDescriptors :: RevokedOutput , amount : tx. output [ 0 ] . value , htlc : None , on_remote_tx_csv : self . remote_tx_cache . on_remote_tx_csv } ;
1692
- let claimable_outpoints = vec ! ( ClaimRequest { absolute_timelock: height + self . remote_tx_cache. on_remote_tx_csv as u32 , aggregable: true , outpoint : BitcoinOutPoint { txid : htlc_txid , vout : 0 } , witness_data } ) ;
1567
+ let malleable_justice_tx = PackageTemplate :: build_malleable_justice_tx ( per_commitment_point, per_commitment_key , self . remote_tx_cache . remote_delayed_payment_base_key , self . remote_tx_cache . remote_htlc_base_key , InputDescriptors :: RevokedOutput , htlc_txid , 0 , tx. output [ 0 ] . value , None , self . remote_tx_cache . on_remote_tx_csv ) ;
1568
+ let claimable_outpoints = vec ! ( ClaimRequest { absolute_timelock: height + self . remote_tx_cache. on_remote_tx_csv as u32 , aggregable: true , package_template : malleable_justice_tx } ) ;
1693
1569
( claimable_outpoints, Some ( ( htlc_txid, tx. output . clone ( ) ) ) )
1694
1570
}
1695
1571
@@ -1702,18 +1578,15 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
1702
1578
1703
1579
for & ( ref htlc, _, _) in local_tx. htlc_outputs . iter ( ) {
1704
1580
if let Some ( transaction_output_index) = htlc. transaction_output_index {
1705
- claim_requests. push ( ClaimRequest { absolute_timelock : :: std:: u32:: MAX , aggregable : false , outpoint : BitcoinOutPoint { txid : local_tx. txid , vout : transaction_output_index as u32 } ,
1706
- witness_data : InputMaterial :: LocalHTLC {
1707
- preimage : if !htlc. offered {
1708
- if let Some ( preimage) = self . payment_preimages . get ( & htlc. payment_hash ) {
1709
- Some ( preimage. clone ( ) )
1710
- } else {
1711
- // We can't build an HTLC-Success transaction without the preimage
1712
- continue ;
1713
- }
1714
- } else { None } ,
1715
- amount : htlc. amount_msat ,
1716
- } } ) ;
1581
+ let local_htlc_tx = PackageTemplate :: build_local_htlc_tx ( if !htlc. offered {
1582
+ if let Some ( preimage) = self . payment_preimages . get ( & htlc. payment_hash ) {
1583
+ Some ( preimage. clone ( ) )
1584
+ } else {
1585
+ // We can't build an HTLC-Success transaction without the preimage
1586
+ continue ;
1587
+ }
1588
+ } else { None } , htlc. amount_msat , local_tx. txid , transaction_output_index) ;
1589
+ claim_requests. push ( ClaimRequest { absolute_timelock : :: std:: u32:: MAX , aggregable : false , package_template : local_htlc_tx } ) ;
1717
1590
watch_outputs. push ( commitment_tx. output [ transaction_output_index as usize ] . clone ( ) ) ;
1718
1591
}
1719
1592
}
@@ -1926,7 +1799,8 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
1926
1799
}
1927
1800
let should_broadcast = self . would_broadcast_at_height ( height, & logger) ;
1928
1801
if should_broadcast {
1929
- claimable_outpoints. push ( ClaimRequest { absolute_timelock : height, aggregable : false , outpoint : BitcoinOutPoint { txid : self . funding_info . 0 . txid . clone ( ) , vout : self . funding_info . 0 . index as u32 } , witness_data : InputMaterial :: Funding { funding_redeemscript : self . funding_redeemscript . clone ( ) } } ) ;
1802
+ let local_commitment_tx = PackageTemplate :: build_local_commitment_tx ( self . funding_redeemscript . clone ( ) , self . funding_info . 0 . txid . clone ( ) , self . funding_info . 0 . index as u32 ) ;
1803
+ claimable_outpoints. push ( ClaimRequest { absolute_timelock : height, aggregable : false , package_template : local_commitment_tx } ) ;
1930
1804
}
1931
1805
if should_broadcast {
1932
1806
if let Some ( commitment_tx) = self . onchain_tx_handler . get_fully_signed_local_tx ( & self . funding_redeemscript ) {
0 commit comments