22
22
23
23
use bitcoin:: blockdata:: block:: BlockHeader ;
24
24
use bitcoin:: blockdata:: transaction:: { TxOut , Transaction } ;
25
- use bitcoin:: blockdata:: transaction:: OutPoint as BitcoinOutPoint ;
26
25
use bitcoin:: blockdata:: script:: { Script , Builder } ;
27
26
use bitcoin:: blockdata:: opcodes;
28
27
use bitcoin:: consensus:: encode;
@@ -40,7 +39,7 @@ use ln::chan_utils;
40
39
use ln:: chan_utils:: { CounterpartyCommitmentSecrets , HTLCOutputInCommitment , HolderCommitmentTransaction , HTLCType } ;
41
40
use ln:: channelmanager:: { HTLCSource , PaymentPreimage , PaymentHash } ;
42
41
use ln:: onchaintx:: OnchainTxHandler ;
43
- use ln:: onchain_utils:: InputDescriptors ;
42
+ use ln:: onchain_utils:: { InputDescriptors , PackageTemplate } ;
44
43
use chain:: chaininterface:: { ChainListener , ChainWatchInterface , BroadcasterInterface , FeeEstimator } ;
45
44
use chain:: transaction:: OutPoint ;
46
45
use chain:: keysinterface:: { SpendableOutputDescriptor , ChannelKeys } ;
@@ -459,129 +458,6 @@ impl Readable for CounterpartyCommitmentTransaction {
459
458
}
460
459
}
461
460
462
- /// When ChannelMonitor discovers an onchain outpoint being a step of a channel and that it needs
463
- /// to generate a tx to push channel state forward, we cache outpoint-solving tx material to build
464
- /// a new bumped one in case of lenghty confirmation delay
465
- #[ derive( Clone , PartialEq ) ]
466
- pub ( crate ) enum InputMaterial {
467
- Revoked {
468
- per_commitment_point : PublicKey ,
469
- counterparty_delayed_payment_base_key : PublicKey ,
470
- counterparty_htlc_base_key : PublicKey ,
471
- per_commitment_key : SecretKey ,
472
- input_descriptor : InputDescriptors ,
473
- amount : u64 ,
474
- htlc : Option < HTLCOutputInCommitment > ,
475
- on_counterparty_tx_csv : u16 ,
476
- } ,
477
- CounterpartyHTLC {
478
- per_commitment_point : PublicKey ,
479
- counterparty_delayed_payment_base_key : PublicKey ,
480
- counterparty_htlc_base_key : PublicKey ,
481
- preimage : Option < PaymentPreimage > ,
482
- htlc : HTLCOutputInCommitment
483
- } ,
484
- HolderHTLC {
485
- preimage : Option < PaymentPreimage > ,
486
- amount : u64 ,
487
- } ,
488
- Funding {
489
- funding_redeemscript : Script ,
490
- }
491
- }
492
-
493
- impl Writeable for InputMaterial {
494
- fn write < W : Writer > ( & self , writer : & mut W ) -> Result < ( ) , :: std:: io:: Error > {
495
- match self {
496
- & InputMaterial :: Revoked { ref per_commitment_point, ref counterparty_delayed_payment_base_key, ref counterparty_htlc_base_key, ref per_commitment_key, ref input_descriptor, ref amount, ref htlc, ref on_counterparty_tx_csv} => {
497
- writer. write_all ( & [ 0 ; 1 ] ) ?;
498
- per_commitment_point. write ( writer) ?;
499
- counterparty_delayed_payment_base_key. write ( writer) ?;
500
- counterparty_htlc_base_key. write ( writer) ?;
501
- writer. write_all ( & per_commitment_key[ ..] ) ?;
502
- input_descriptor. write ( writer) ?;
503
- writer. write_all ( & byte_utils:: be64_to_array ( * amount) ) ?;
504
- htlc. write ( writer) ?;
505
- on_counterparty_tx_csv. write ( writer) ?;
506
- } ,
507
- & InputMaterial :: CounterpartyHTLC { ref per_commitment_point, ref counterparty_delayed_payment_base_key, ref counterparty_htlc_base_key, ref preimage, ref htlc} => {
508
- writer. write_all ( & [ 1 ; 1 ] ) ?;
509
- per_commitment_point. write ( writer) ?;
510
- counterparty_delayed_payment_base_key. write ( writer) ?;
511
- counterparty_htlc_base_key. write ( writer) ?;
512
- preimage. write ( writer) ?;
513
- htlc. write ( writer) ?;
514
- } ,
515
- & InputMaterial :: HolderHTLC { ref preimage, ref amount } => {
516
- writer. write_all ( & [ 2 ; 1 ] ) ?;
517
- preimage. write ( writer) ?;
518
- writer. write_all ( & byte_utils:: be64_to_array ( * amount) ) ?;
519
- } ,
520
- & InputMaterial :: Funding { ref funding_redeemscript } => {
521
- writer. write_all ( & [ 3 ; 1 ] ) ?;
522
- funding_redeemscript. write ( writer) ?;
523
- }
524
- }
525
- Ok ( ( ) )
526
- }
527
- }
528
-
529
- impl Readable for InputMaterial {
530
- fn read < R : :: std:: io:: Read > ( reader : & mut R ) -> Result < Self , DecodeError > {
531
- let input_material = match <u8 as Readable >:: read ( reader) ? {
532
- 0 => {
533
- let per_commitment_point = Readable :: read ( reader) ?;
534
- let counterparty_delayed_payment_base_key = Readable :: read ( reader) ?;
535
- let counterparty_htlc_base_key = Readable :: read ( reader) ?;
536
- let per_commitment_key = Readable :: read ( reader) ?;
537
- let input_descriptor = Readable :: read ( reader) ?;
538
- let amount = Readable :: read ( reader) ?;
539
- let htlc = Readable :: read ( reader) ?;
540
- let on_counterparty_tx_csv = Readable :: read ( reader) ?;
541
- InputMaterial :: Revoked {
542
- per_commitment_point,
543
- counterparty_delayed_payment_base_key,
544
- counterparty_htlc_base_key,
545
- per_commitment_key,
546
- input_descriptor,
547
- amount,
548
- htlc,
549
- on_counterparty_tx_csv
550
- }
551
- } ,
552
- 1 => {
553
- let per_commitment_point = Readable :: read ( reader) ?;
554
- let counterparty_delayed_payment_base_key = Readable :: read ( reader) ?;
555
- let counterparty_htlc_base_key = Readable :: read ( reader) ?;
556
- let preimage = Readable :: read ( reader) ?;
557
- let htlc = Readable :: read ( reader) ?;
558
- InputMaterial :: CounterpartyHTLC {
559
- per_commitment_point,
560
- counterparty_delayed_payment_base_key,
561
- counterparty_htlc_base_key,
562
- preimage,
563
- htlc
564
- }
565
- } ,
566
- 2 => {
567
- let preimage = Readable :: read ( reader) ?;
568
- let amount = Readable :: read ( reader) ?;
569
- InputMaterial :: HolderHTLC {
570
- preimage,
571
- amount,
572
- }
573
- } ,
574
- 3 => {
575
- InputMaterial :: Funding {
576
- funding_redeemscript : Readable :: read ( reader) ?,
577
- }
578
- }
579
- _ => return Err ( DecodeError :: InvalidValue ) ,
580
- } ;
581
- Ok ( input_material)
582
- }
583
- }
584
-
585
461
/// ClaimRequest is a descriptor structure to communicate between detection
586
462
/// and reaction module. They are generated by ChannelMonitor while parsing
587
463
/// onchain txn leaked from a channel and handed over to OnchainTxHandler which
@@ -597,11 +473,9 @@ pub(crate) struct ClaimRequest {
597
473
// of a sooner-HTLC could be swallowed by the highest nLocktime of the HTLC set.
598
474
// Do simplify we mark them as non-aggregable.
599
475
pub ( crate ) aggregable : bool ,
600
- // Basic bitcoin outpoint (txid, vout)
601
- pub ( crate ) outpoint : BitcoinOutPoint ,
602
- // Following outpoint type, set of data needed to generate transaction digest
603
- // and satisfy witness program.
604
- pub ( crate ) witness_data : InputMaterial
476
+ // Template (list of outpoint and set of data needed to generate transaction digest
477
+ // and satisfy witness program).
478
+ pub ( crate ) package_template : PackageTemplate ,
605
479
}
606
480
607
481
/// Upon discovering of some classes of onchain tx by ChannelMonitor, we may have to take actions on it
@@ -1526,8 +1400,8 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
1526
1400
// First, process non-htlc outputs (to_holder & to_counterparty)
1527
1401
for ( idx, outp) in tx. output . iter ( ) . enumerate ( ) {
1528
1402
if outp. script_pubkey == revokeable_p2wsh {
1529
- let witness_data = InputMaterial :: Revoked { per_commitment_point, counterparty_delayed_payment_base_key : self . counterparty_tx_cache . counterparty_delayed_payment_base_key , counterparty_htlc_base_key : self . counterparty_tx_cache . counterparty_htlc_base_key , per_commitment_key , input_descriptor : InputDescriptors :: RevokedOutput , amount : outp. value , htlc : None , on_counterparty_tx_csv : self . counterparty_tx_cache . on_counterparty_tx_csv } ;
1530
- claimable_outpoints. push ( ClaimRequest { absolute_timelock : height + self . counterparty_tx_cache . on_counterparty_tx_csv as u32 , aggregable : true , outpoint : BitcoinOutPoint { txid : commitment_txid , vout : idx as u32 } , witness_data } ) ;
1403
+ let malleable_justice_tx = PackageTemplate :: build_malleable_justice_tx ( per_commitment_point, per_commitment_key , self . counterparty_tx_cache . counterparty_delayed_payment_base_key , self . counterparty_tx_cache . counterparty_htlc_base_key , InputDescriptors :: RevokedOutput , commitment_txid , idx as u32 , outp. value , None , self . counterparty_tx_cache . on_counterparty_tx_csv ) ;
1404
+ claimable_outpoints. push ( ClaimRequest { absolute_timelock : height + self . counterparty_tx_cache . on_counterparty_tx_csv as u32 , aggregable : true , package_template : malleable_justice_tx } ) ;
1531
1405
}
1532
1406
}
1533
1407
@@ -1539,8 +1413,8 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
1539
1413
tx. output [ transaction_output_index as usize ] . value != htlc. amount_msat / 1000 {
1540
1414
return ( claimable_outpoints, ( commitment_txid, watch_outputs) ) ; // Corrupted per_commitment_data, fuck this user
1541
1415
}
1542
- let witness_data = InputMaterial :: Revoked { per_commitment_point, counterparty_delayed_payment_base_key : self . counterparty_tx_cache . counterparty_delayed_payment_base_key , counterparty_htlc_base_key : self . counterparty_tx_cache . counterparty_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_counterparty_tx_csv : self . counterparty_tx_cache . on_counterparty_tx_csv } ;
1543
- claimable_outpoints. push ( ClaimRequest { absolute_timelock : htlc. cltv_expiry , aggregable : true , outpoint : BitcoinOutPoint { txid : commitment_txid , vout : transaction_output_index } , witness_data } ) ;
1416
+ let malleable_justice_tx = PackageTemplate :: build_malleable_justice_tx ( per_commitment_point, per_commitment_key , self . counterparty_tx_cache . counterparty_delayed_payment_base_key , self . counterparty_tx_cache . counterparty_htlc_base_key , if htlc. offered { InputDescriptors :: RevokedOfferedHTLC } else { InputDescriptors :: RevokedReceivedHTLC } , commitment_txid , transaction_output_index, htlc. amount_msat / 1000 , Some ( htlc. clone ( ) ) , self . counterparty_tx_cache . on_counterparty_tx_csv ) ;
1417
+ claimable_outpoints. push ( ClaimRequest { absolute_timelock : htlc. cltv_expiry , aggregable : true , package_template : malleable_justice_tx } ) ;
1544
1418
}
1545
1419
}
1546
1420
}
@@ -1674,8 +1548,8 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
1674
1548
let preimage = if htlc. offered { if let Some ( p) = self . payment_preimages . get ( & htlc. payment_hash ) { Some ( * p) } else { None } } else { None } ;
1675
1549
let aggregable = if !htlc. offered { false } else { true } ;
1676
1550
if preimage. is_some ( ) || !htlc. offered {
1677
- let witness_data = InputMaterial :: CounterpartyHTLC { per_commitment_point : * revocation_point, counterparty_delayed_payment_base_key : self . counterparty_tx_cache . counterparty_delayed_payment_base_key , counterparty_htlc_base_key : self . counterparty_tx_cache . counterparty_htlc_base_key , preimage, htlc : htlc . clone ( ) } ;
1678
- claimable_outpoints. push ( ClaimRequest { absolute_timelock : htlc. cltv_expiry , aggregable, outpoint : BitcoinOutPoint { txid : commitment_txid , vout : transaction_output_index } , witness_data } ) ;
1551
+ let counterparty_htlc_tx = PackageTemplate :: build_counterparty_htlc_tx ( * revocation_point, self . counterparty_tx_cache . counterparty_delayed_payment_base_key , self . counterparty_tx_cache . counterparty_htlc_base_key , preimage, htlc. clone ( ) , commitment_txid , transaction_output_index ) ;
1552
+ claimable_outpoints. push ( ClaimRequest { absolute_timelock : htlc. cltv_expiry , aggregable, package_template : counterparty_htlc_tx } ) ;
1679
1553
}
1680
1554
}
1681
1555
}
@@ -1705,9 +1579,9 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
1705
1579
let per_commitment_key = ignore_error ! ( SecretKey :: from_slice( & secret) ) ;
1706
1580
let per_commitment_point = PublicKey :: from_secret_key ( & self . secp_ctx , & per_commitment_key) ;
1707
1581
1708
- log_trace ! ( logger, "Counterparty HTLC broadcast {}:{}" , htlc_txid, 0 ) ;
1709
- let witness_data = InputMaterial :: Revoked { per_commitment_point, counterparty_delayed_payment_base_key : self . counterparty_tx_cache . counterparty_delayed_payment_base_key , counterparty_htlc_base_key : self . counterparty_tx_cache . counterparty_htlc_base_key , per_commitment_key , input_descriptor : InputDescriptors :: RevokedOutput , amount : tx. output [ 0 ] . value , htlc : None , on_counterparty_tx_csv : self . counterparty_tx_cache . on_counterparty_tx_csv } ;
1710
- let claimable_outpoints = vec ! ( ClaimRequest { absolute_timelock: height + self . counterparty_tx_cache. on_counterparty_tx_csv as u32 , aggregable: true , outpoint : BitcoinOutPoint { txid : htlc_txid , vout : 0 } , witness_data } ) ;
1582
+ log_trace ! ( logger, "Remote HTLC broadcast {}:{}" , htlc_txid, 0 ) ;
1583
+ let malleable_justice_tx = PackageTemplate :: build_malleable_justice_tx ( per_commitment_point, per_commitment_key , self . counterparty_tx_cache . counterparty_delayed_payment_base_key , self . counterparty_tx_cache . counterparty_htlc_base_key , InputDescriptors :: RevokedOutput , htlc_txid , 0 , tx. output [ 0 ] . value , None , self . counterparty_tx_cache . on_counterparty_tx_csv ) ;
1584
+ let claimable_outpoints = vec ! ( ClaimRequest { absolute_timelock: height + self . counterparty_tx_cache. on_counterparty_tx_csv as u32 , aggregable: true , package_template : malleable_justice_tx } ) ;
1711
1585
( claimable_outpoints, Some ( ( htlc_txid, tx. output . clone ( ) ) ) )
1712
1586
}
1713
1587
@@ -1720,18 +1594,15 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
1720
1594
1721
1595
for & ( ref htlc, _, _) in holder_tx. htlc_outputs . iter ( ) {
1722
1596
if let Some ( transaction_output_index) = htlc. transaction_output_index {
1723
- claim_requests. push ( ClaimRequest { absolute_timelock : :: std:: u32:: MAX , aggregable : false , outpoint : BitcoinOutPoint { txid : holder_tx. txid , vout : transaction_output_index as u32 } ,
1724
- witness_data : InputMaterial :: HolderHTLC {
1725
- preimage : if !htlc. offered {
1726
- if let Some ( preimage) = self . payment_preimages . get ( & htlc. payment_hash ) {
1727
- Some ( preimage. clone ( ) )
1728
- } else {
1729
- // We can't build an HTLC-Success transaction without the preimage
1730
- continue ;
1731
- }
1732
- } else { None } ,
1733
- amount : htlc. amount_msat ,
1734
- } } ) ;
1597
+ let holder_htlc_tx = PackageTemplate :: build_holder_htlc_tx ( if !htlc. offered {
1598
+ if let Some ( preimage) = self . payment_preimages . get ( & htlc. payment_hash ) {
1599
+ Some ( preimage. clone ( ) )
1600
+ } else {
1601
+ // We can't build an HTLC-Success transaction without the preimage
1602
+ continue ;
1603
+ }
1604
+ } else { None } , htlc. amount_msat , holder_tx. txid , transaction_output_index) ;
1605
+ claim_requests. push ( ClaimRequest { absolute_timelock : :: std:: u32:: MAX , aggregable : false , package_template : holder_htlc_tx } ) ;
1735
1606
watch_outputs. push ( commitment_tx. output [ transaction_output_index as usize ] . clone ( ) ) ;
1736
1607
}
1737
1608
}
@@ -1944,7 +1815,8 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
1944
1815
}
1945
1816
let should_broadcast = self . would_broadcast_at_height ( height, & logger) ;
1946
1817
if should_broadcast {
1947
- 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 ( ) } } ) ;
1818
+ let holder_commitment_tx = PackageTemplate :: build_holder_commitment_tx ( self . funding_redeemscript . clone ( ) , self . funding_info . 0 . txid . clone ( ) , self . funding_info . 0 . index as u32 ) ;
1819
+ claimable_outpoints. push ( ClaimRequest { absolute_timelock : height, aggregable : false , package_template : holder_commitment_tx } ) ;
1948
1820
}
1949
1821
if should_broadcast {
1950
1822
self . pending_monitor_events . push ( MonitorEvent :: CommitmentTxBroadcasted ( self . funding_info . 0 ) ) ;
0 commit comments