@@ -14,7 +14,7 @@ use bitcoin_hashes::ripemd160::Hash as Ripemd160;
14
14
use bitcoin_hashes:: hash160:: Hash as Hash160 ;
15
15
use bitcoin_hashes:: sha256d:: Hash as Sha256dHash ;
16
16
17
- use ln:: channelmanager:: PaymentHash ;
17
+ use ln:: channelmanager:: { PaymentHash , PaymentPreimage } ;
18
18
use ln:: msgs:: DecodeError ;
19
19
use util:: ser:: { Readable , Writeable , Writer , WriterWriteAdaptor } ;
20
20
use util:: byte_utils;
@@ -23,6 +23,11 @@ use secp256k1::key::{SecretKey, PublicKey};
23
23
use secp256k1:: { Secp256k1 , Signature } ;
24
24
use secp256k1;
25
25
26
+ use std:: collections:: HashMap ;
27
+ use std:: cmp;
28
+
29
+ const MAX_ALLOC_SIZE : usize = 64 * 1024 ;
30
+
26
31
pub ( super ) const HTLC_SUCCESS_TX_WEIGHT : u64 = 703 ;
27
32
pub ( super ) const HTLC_TIMEOUT_TX_WEIGHT : u64 = 663 ;
28
33
@@ -480,7 +485,11 @@ pub fn build_htlc_transaction(prev_hash: &Sha256dHash, feerate_per_kw: u64, to_s
480
485
/// to broadcast. Eventually this will require a signer which is possibly external, but for now we
481
486
/// just pass in the SecretKeys required.
482
487
pub struct LocalCommitmentTransaction {
483
- tx : Transaction
488
+ tx : Transaction ,
489
+ //TODO: modify Channel methods to integrate HTLC material at LocalCommitmentTransaction generation to drop Option here
490
+ local_keys : Option < TxCreationKeys > ,
491
+ feerate_per_kw : Option < u64 > ,
492
+ per_htlc : HashMap < u32 , ( HTLCOutputInCommitment , Option < Signature > , Option < Transaction > ) >
484
493
}
485
494
impl LocalCommitmentTransaction {
486
495
#[ cfg( test) ]
@@ -495,7 +504,11 @@ impl LocalCommitmentTransaction {
495
504
input : vec ! [ dummy_input] ,
496
505
output : Vec :: new ( ) ,
497
506
lock_time : 0 ,
498
- } }
507
+ } ,
508
+ local_keys : None ,
509
+ feerate_per_kw : None ,
510
+ per_htlc : HashMap :: new ( )
511
+ }
499
512
}
500
513
501
514
/// Generate a new LocalCommitmentTransaction based on a raw commitment transaction, remote signature and both parties keys
@@ -515,7 +528,11 @@ impl LocalCommitmentTransaction {
515
528
tx. input [ 0 ] . witness . push ( Vec :: new ( ) ) ;
516
529
}
517
530
518
- Self { tx }
531
+ Self { tx,
532
+ local_keys : None ,
533
+ feerate_per_kw : None ,
534
+ per_htlc : HashMap :: new ( )
535
+ }
519
536
}
520
537
521
538
/// Get the txid of the local commitment transaction contained in this LocalCommitmentTransaction
@@ -567,6 +584,63 @@ impl LocalCommitmentTransaction {
567
584
assert ! ( self . has_local_sig( ) ) ;
568
585
& self . tx
569
586
}
587
+
588
+ /// Set HTLC cache to generate any local HTLC transaction spending one of htlc ouput
589
+ /// from this local commitment transaction
590
+ pub fn set_htlc_cache ( & mut self , local_keys : TxCreationKeys , feerate_per_kw : u64 , htlc_outputs : HashMap < u32 , ( HTLCOutputInCommitment , Option < Signature > , Option < Transaction > ) > ) {
591
+ self . local_keys = Some ( local_keys) ;
592
+ self . feerate_per_kw = Some ( feerate_per_kw) ;
593
+ self . per_htlc = htlc_outputs;
594
+ }
595
+
596
+ /// Add local signature for a htlc transaction, do nothing if a cached signed transaction is
597
+ /// already present
598
+ pub fn add_htlc_sig < T : secp256k1:: Signing > ( & mut self , htlc_base_key : & SecretKey , htlc_index : u32 , preimage : Option < PaymentPreimage > , local_csv : u16 , secp_ctx : & Secp256k1 < T > ) {
599
+ if self . local_keys . is_none ( ) || self . feerate_per_kw . is_none ( ) { return ; }
600
+ let local_keys = self . local_keys . as_ref ( ) . unwrap ( ) ;
601
+ let txid = self . txid ( ) ;
602
+ if let Some ( ref mut this_htlc) = self . per_htlc . get_mut ( & htlc_index) {
603
+ if this_htlc. 2 . is_some ( ) { return ; } // we already have a cached htlc transaction at provided index
604
+ let mut htlc_tx = build_htlc_transaction ( & txid, self . feerate_per_kw . unwrap ( ) , local_csv, & this_htlc. 0 , & local_keys. a_delayed_payment_key , & local_keys. revocation_key ) ;
605
+ if !this_htlc. 0 . offered && preimage. is_none ( ) { return ; } // if we don't have preimage for HTLC-Success, don't try to generate
606
+ let htlc_secret = if !this_htlc. 0 . offered { preimage } else { None } ; // if we have a preimage for HTLC-Timeout, don't use it that's likely a duplicate HTLC hash
607
+ if this_htlc. 1 . is_none ( ) { return ; } // we don't have any remote signature for this htlc
608
+ if htlc_tx. input . len ( ) != 1 { return ; }
609
+ if htlc_tx. input [ 0 ] . witness . len ( ) != 0 { return ; }
610
+
611
+ let htlc_redeemscript = get_htlc_redeemscript_with_explicit_keys ( & this_htlc. 0 , & local_keys. a_htlc_key , & local_keys. b_htlc_key , & local_keys. revocation_key ) ;
612
+
613
+ if let Ok ( our_htlc_key) = derive_private_key ( secp_ctx, & local_keys. per_commitment_point , htlc_base_key) {
614
+ let sighash = hash_to_message ! ( & bip143:: SighashComponents :: new( & htlc_tx) . sighash_all( & htlc_tx. input[ 0 ] , & htlc_redeemscript, this_htlc. 0 . amount_msat / 1000 ) [ ..] ) ;
615
+ let our_sig = secp_ctx. sign ( & sighash, & our_htlc_key) ;
616
+
617
+ htlc_tx. input [ 0 ] . witness . push ( Vec :: new ( ) ) ; // First is the multisig dummy
618
+
619
+ htlc_tx. input [ 0 ] . witness . push ( this_htlc. 1 . unwrap ( ) . serialize_der ( ) . to_vec ( ) ) ;
620
+ htlc_tx. input [ 0 ] . witness . push ( our_sig. serialize_der ( ) . to_vec ( ) ) ;
621
+ htlc_tx. input [ 0 ] . witness [ 1 ] . push ( SigHashType :: All as u8 ) ;
622
+ htlc_tx. input [ 0 ] . witness [ 2 ] . push ( SigHashType :: All as u8 ) ;
623
+
624
+ if this_htlc. 0 . offered {
625
+ htlc_tx. input [ 0 ] . witness . push ( Vec :: new ( ) ) ;
626
+ assert ! ( htlc_secret. is_none( ) ) ;
627
+ } else {
628
+ htlc_tx. input [ 0 ] . witness . push ( htlc_secret. unwrap ( ) . 0 . to_vec ( ) ) ;
629
+ }
630
+
631
+ htlc_tx. input [ 0 ] . witness . push ( htlc_redeemscript. as_bytes ( ) . to_vec ( ) ) ;
632
+
633
+ this_htlc. 2 = Some ( htlc_tx) ;
634
+ } else { return ; }
635
+ }
636
+ }
637
+ /// Expose raw htlc transaction, guarante witness is complete if non-empty
638
+ pub fn htlc_with_valid_witness ( & self , htlc_index : u32 ) -> & Option < Transaction > {
639
+ if let Some ( ref this_htlc) = self . per_htlc . get ( & htlc_index) {
640
+ return & this_htlc. 2 ;
641
+ }
642
+ & None
643
+ }
570
644
}
571
645
impl PartialEq for LocalCommitmentTransaction {
572
646
// We dont care whether we are signed in equality comparison
@@ -582,6 +656,14 @@ impl Writeable for LocalCommitmentTransaction {
582
656
_ => panic ! ( "local tx must have been well-formed!" ) ,
583
657
}
584
658
}
659
+ self . local_keys . write ( writer) ?;
660
+ self . feerate_per_kw . write ( writer) ?;
661
+ writer. write_all ( & byte_utils:: be64_to_array ( self . per_htlc . len ( ) as u64 ) ) ?;
662
+ for ( ref _index, & ( ref htlc, ref sig, ref htlc_tx) ) in self . per_htlc . iter ( ) {
663
+ htlc. write ( writer) ?;
664
+ sig. write ( writer) ?;
665
+ htlc_tx. write ( writer) ?;
666
+ }
585
667
Ok ( ( ) )
586
668
}
587
669
}
@@ -594,12 +676,27 @@ impl Readable for LocalCommitmentTransaction {
594
676
_ => return Err ( DecodeError :: InvalidValue ) ,
595
677
} ,
596
678
} ;
679
+ let local_keys = Readable :: read ( reader) ?;
680
+ let feerate_per_kw = Readable :: read ( reader) ?;
681
+ let htlcs_count: u64 = Readable :: read ( reader) ?;
682
+ let mut per_htlc = HashMap :: with_capacity ( cmp:: min ( htlcs_count as usize , MAX_ALLOC_SIZE / 32 ) ) ;
683
+ for _ in 0 ..htlcs_count {
684
+ let htlc: HTLCOutputInCommitment = Readable :: read ( reader) ?;
685
+ let sigs = Readable :: read ( reader) ?;
686
+ let htlc_tx = Readable :: read ( reader) ?;
687
+ per_htlc. insert ( htlc. transaction_output_index . unwrap ( ) , ( htlc, sigs, htlc_tx) ) ;
688
+ }
597
689
598
690
if tx. input . len ( ) != 1 {
599
691
// Ensure tx didn't hit the 0-input ambiguity case.
600
692
return Err ( DecodeError :: InvalidValue ) ;
601
693
}
602
- Ok ( Self { tx } )
694
+ Ok ( Self {
695
+ tx,
696
+ local_keys,
697
+ feerate_per_kw,
698
+ per_htlc,
699
+ } )
603
700
}
604
701
}
605
702
0 commit comments