@@ -28,12 +28,16 @@ use ln::msgs::DecodeError;
28
28
use util:: ser:: { Readable , Writeable , Writer , WriterWriteAdaptor } ;
29
29
use util:: byte_utils;
30
30
31
+ use bitcoin:: hash_types:: WPubkeyHash ;
31
32
use bitcoin:: secp256k1:: key:: { SecretKey , PublicKey } ;
32
- use bitcoin:: secp256k1:: { Secp256k1 , Signature } ;
33
+ use bitcoin:: secp256k1:: { Secp256k1 , Signature , Message } ;
33
34
use bitcoin:: secp256k1:: Error as SecpError ;
34
35
use bitcoin:: secp256k1;
35
36
36
37
use std:: { cmp, mem} ;
38
+ use ln:: chan_utils;
39
+ use util:: transaction_utils:: sort_outputs;
40
+ use ln:: channel:: INITIAL_COMMITMENT_NUMBER ;
37
41
38
42
const MAX_ALLOC_SIZE : usize = 64 * 1024 ;
39
43
@@ -550,6 +554,260 @@ pub fn build_htlc_transaction(prev_hash: &Txid, feerate_per_kw: u32, contest_del
550
554
}
551
555
}
552
556
557
+ #[ derive( Clone ) ]
558
+ /// We use this class to track the information needed to build a commitment transaction and to actually
559
+ /// build and sign. It is used for holder transactions that we sign only when needed
560
+ /// and for transactions we sign for the counterparty.
561
+ ///
562
+ /// This class can be used inside a signer implementation to generate a signature given the relevant
563
+ /// secret key.
564
+ pub struct CommitmentTransactionInfo {
565
+ /// The backwards-counting commitment number
566
+ pub commitment_number : u64 ,
567
+ /// The value to be sent to the broadcaster
568
+ pub to_broadcaster_value_sat : u64 ,
569
+ /// The value to be sent to the counterparty
570
+ pub to_countersignatory_value_sat : u64 ,
571
+ /// The feerate paid per 1000-weight-unit in this commitment transaction.
572
+ pub feerate_per_kw : u32 ,
573
+ /// The HTLCs which were included in this commitment transaction in output order.
574
+ pub htlcs : Vec < HTLCOutputInCommitment > ,
575
+ pub ( crate ) keys : TxCreationKeys ,
576
+ }
577
+
578
+ impl CommitmentTransactionInfo {
579
+ /// Construct an object of the class while assigning transaction output indices to HTLCs.
580
+ ///
581
+ /// Also keeps track of associated HTLC data and returns it along with the mutated HTLCs.
582
+ pub fn new_with_auxiliary_htlc_data < T : Copy > (
583
+ commitment_number : u64 ,
584
+ to_broadcaster_value_sat : u64 ,
585
+ to_countersignatory_value_sat : u64 ,
586
+ keys : TxCreationKeys ,
587
+ feerate_per_kw : u32 ,
588
+ htlcs_with_aux : Vec < ( HTLCOutputInCommitment , T ) > ,
589
+ broadcaster_pubkeys : & ChannelPublicKeys ,
590
+ countersignatory_pubkeys : & ChannelPublicKeys ,
591
+ contest_delay : u16 ,
592
+ secp_ctx : & Secp256k1 < secp256k1:: All >
593
+ ) -> ( CommitmentTransactionInfo , Vec < ( HTLCOutputInCommitment , T ) > ) {
594
+ // Populate output indices while keeping track of the auxiliary data
595
+ let mut txouts = Self :: do_build_outputs ( & keys, to_broadcaster_value_sat, to_countersignatory_value_sat, & htlcs_with_aux, broadcaster_pubkeys, countersignatory_pubkeys, contest_delay, & secp_ctx) . unwrap ( ) ;
596
+ let mut result_htlcs_with_aux = Vec :: new ( ) ;
597
+ let mut htlcs = Vec :: new ( ) ;
598
+ for ( idx, mut out) in txouts. drain ( ..) . enumerate ( ) {
599
+ if let Some ( mut htlc) = ( out. 1 ) . 1 . take ( ) {
600
+ htlc. 0 . transaction_output_index = Some ( idx as u32 ) ;
601
+ result_htlcs_with_aux. push ( ( htlc. 0 . clone ( ) , htlc. 1 ) ) ;
602
+ htlcs. push ( htlc. 0 ) ;
603
+ }
604
+ }
605
+
606
+ let info = CommitmentTransactionInfo {
607
+ commitment_number,
608
+ to_broadcaster_value_sat,
609
+ to_countersignatory_value_sat,
610
+ feerate_per_kw,
611
+ htlcs,
612
+ keys,
613
+ } ;
614
+ ( info, result_htlcs_with_aux)
615
+ }
616
+
617
+ /// Build the Bitcoin transaction.
618
+ ///
619
+ /// Required channel-static fields are provided by the caller.
620
+ ///
621
+ /// is_outbound is true if the channel is outbound from the point of view of the broadcaster
622
+ pub fn build < T : secp256k1:: Signing + secp256k1:: Verification > (
623
+ & self ,
624
+ broadcaster_pubkeys : & ChannelPublicKeys ,
625
+ countersignatory_pubkeys : & ChannelPublicKeys ,
626
+ funding_outpoint : & OutPoint ,
627
+ contest_delay : u16 ,
628
+ is_outbound : bool ,
629
+ secp_ctx : & Secp256k1 < T > ,
630
+ ) -> Result < ( bitcoin:: Transaction , Vec < HTLCOutputInCommitment > , Vec < Script > ) , ( ) > {
631
+ let ( obscured_commitment_transaction_number, txins) = self . build_inputs ( broadcaster_pubkeys, countersignatory_pubkeys, funding_outpoint, is_outbound) ;
632
+
633
+ let mut txouts = self . build_outputs ( broadcaster_pubkeys, countersignatory_pubkeys, contest_delay, secp_ctx) ?;
634
+
635
+ let mut outputs = Vec :: with_capacity ( txouts. len ( ) ) ;
636
+ let mut scripts = Vec :: with_capacity ( txouts. len ( ) ) ;
637
+ let mut htlcs = Vec :: new ( ) ;
638
+ for ( idx, mut out) in txouts. drain ( ..) . enumerate ( ) {
639
+ outputs. push ( out. 0 ) ;
640
+ scripts. push ( ( out. 1 ) . 0 . clone ( ) ) ;
641
+ if let Some ( mut htlc) = ( out. 1 ) . 1 . take ( ) {
642
+ htlc. transaction_output_index = Some ( idx as u32 ) ;
643
+ htlcs. push ( htlc) ;
644
+ }
645
+ }
646
+
647
+ Ok ( (
648
+ Transaction {
649
+ version : 2 ,
650
+ lock_time : ( ( 0x20 as u32 ) << 8 * 3 ) | ( ( obscured_commitment_transaction_number & 0xffffffu64 ) as u32 ) ,
651
+ input : txins,
652
+ output : outputs,
653
+ } ,
654
+ htlcs,
655
+ scripts,
656
+ ) )
657
+ }
658
+
659
+ fn build_outputs < T : secp256k1:: Signing + secp256k1:: Verification > ( & self , broadcaster_pubkeys : & ChannelPublicKeys , countersignatory_pubkeys : & ChannelPublicKeys , contest_delay : u16 , secp_ctx : & Secp256k1 < T > ) -> Result < Vec < ( TxOut , ( Script , Option < HTLCOutputInCommitment > ) ) > , ( ) > {
660
+ let htlcs = self . htlcs . iter ( ) . map ( |h| ( h. clone ( ) , ( ) ) ) . collect ( ) ;
661
+ let mut txouts = Self :: do_build_outputs ( & self . keys , self . to_broadcaster_value_sat , self . to_countersignatory_value_sat , & htlcs, broadcaster_pubkeys, countersignatory_pubkeys, contest_delay, secp_ctx) ?;
662
+ let outs = txouts. drain ( ..) . map ( |( out, ( s, extra) ) | ( out, ( s, extra. map ( |( p, _) | p) ) ) ) . collect ( ) ;
663
+ Ok ( outs)
664
+ }
665
+
666
+ fn do_build_outputs < T : Copy , S : secp256k1:: Signing + secp256k1:: Verification > (
667
+ keys : & TxCreationKeys ,
668
+ to_broadcaster_value_sat : u64 ,
669
+ to_countersignatory_value_sat : u64 ,
670
+ htlcs : & Vec < ( HTLCOutputInCommitment , T ) > ,
671
+ broadcaster_pubkeys : & ChannelPublicKeys , countersignatory_pubkeys : & ChannelPublicKeys , contest_delay : u16 , secp_ctx : & Secp256k1 < S > ) -> Result < Vec < ( TxOut , ( Script , Option < ( HTLCOutputInCommitment , T ) > ) ) > , ( ) > {
672
+ let per_commitment_point = & keys. per_commitment_point ;
673
+ let to_broadcaster_delayed_pubkey = derive_public_key (
674
+ & secp_ctx,
675
+ & per_commitment_point,
676
+ & broadcaster_pubkeys. delayed_payment_basepoint ,
677
+ ) . map_err ( |_| ( ) ) ?;
678
+
679
+ let revocation_pubkey = derive_public_revocation_key (
680
+ & secp_ctx,
681
+ per_commitment_point,
682
+ & countersignatory_pubkeys. revocation_basepoint ,
683
+ ) . map_err ( |_| ( ) ) ?;
684
+
685
+ let mut txouts: Vec < ( TxOut , ( Script , Option < ( HTLCOutputInCommitment , T ) > ) ) > = Vec :: new ( ) ;
686
+
687
+ if to_countersignatory_value_sat > 0 {
688
+ let script = script_for_p2wpkh ( & countersignatory_pubkeys. payment_point ) ;
689
+ txouts. push ( (
690
+ TxOut {
691
+ script_pubkey : script. clone ( ) ,
692
+ value : to_countersignatory_value_sat,
693
+ } ,
694
+ ( script, None ) ,
695
+ ) )
696
+ }
697
+
698
+ if to_broadcaster_value_sat > 0 {
699
+ let redeem_script = get_revokeable_redeemscript (
700
+ & revocation_pubkey,
701
+ contest_delay,
702
+ & to_broadcaster_delayed_pubkey,
703
+ ) ;
704
+ txouts. push ( (
705
+ TxOut {
706
+ script_pubkey : redeem_script. to_v0_p2wsh ( ) ,
707
+ value : to_broadcaster_value_sat,
708
+ } ,
709
+ ( redeem_script, None ) ,
710
+ ) ) ;
711
+ }
712
+
713
+ for ( htlc, t) in htlcs {
714
+ let script = chan_utils:: get_htlc_redeemscript ( & htlc, & keys) ;
715
+ let txout = TxOut {
716
+ script_pubkey : script. to_v0_p2wsh ( ) ,
717
+ value : htlc. amount_msat / 1000 ,
718
+ } ;
719
+ txouts. push ( ( txout, ( script, Some ( ( htlc. clone ( ) , * t) ) ) ) ) ;
720
+ }
721
+
722
+ sort_outputs ( & mut txouts, |a, b| {
723
+ if let & ( _, Some ( ref a_htlcout) ) = a {
724
+ if let & ( _, Some ( ref b_htlcout) ) = b {
725
+ a_htlcout. 0 . cltv_expiry . cmp ( & b_htlcout. 0 . cltv_expiry )
726
+ } else {
727
+ cmp:: Ordering :: Equal
728
+ }
729
+ } else {
730
+ cmp:: Ordering :: Equal
731
+ }
732
+ } ) ;
733
+ Ok ( txouts)
734
+ }
735
+
736
+ fn build_inputs ( & self , broadcaster_pubkeys : & ChannelPublicKeys , countersignatory_pubkeys : & ChannelPublicKeys , funding_outpoint : & OutPoint , is_outbound : bool ) -> ( u64 , Vec < TxIn > ) {
737
+ let commitment_transaction_number_obscure_factor = get_commitment_transaction_number_obscure_factor (
738
+ & broadcaster_pubkeys. payment_point ,
739
+ & countersignatory_pubkeys. payment_point ,
740
+ is_outbound,
741
+ ) ;
742
+
743
+ let obscured_commitment_transaction_number =
744
+ commitment_transaction_number_obscure_factor ^ ( INITIAL_COMMITMENT_NUMBER - self . commitment_number ) ;
745
+
746
+ let txins = {
747
+ let mut ins: Vec < TxIn > = Vec :: new ( ) ;
748
+ ins. push ( TxIn {
749
+ previous_output : funding_outpoint. clone ( ) ,
750
+ script_sig : Script :: new ( ) ,
751
+ sequence : ( ( 0x80 as u32 ) << 8 * 3 )
752
+ | ( ( obscured_commitment_transaction_number >> 3 * 8 ) as u32 ) ,
753
+ witness : Vec :: new ( ) ,
754
+ } ) ;
755
+ ins
756
+ } ;
757
+ ( obscured_commitment_transaction_number, txins)
758
+ }
759
+
760
+ /// Sign a transaction, either because we are counter-signing the counterparty's transaction or
761
+ /// because we are about to broadcast a holder transaction.
762
+ ///
763
+ /// is_outbound is true if the channel is outbound from the point of view of the broadcaster
764
+ pub fn get_signature < T : secp256k1:: Signing + secp256k1:: Verification > ( & self , broadcaster_pubkeys : & ChannelPublicKeys , countersignatory_pubkeys : & ChannelPublicKeys , funding_outpoint : & OutPoint , contest_delay : u16 , is_outbound : bool , funding_key : & SecretKey , funding_redeemscript : & Script , channel_value_satoshis : u64 , secp_ctx : & Secp256k1 < T > ) -> Signature {
765
+ let sighash = self . get_sighash ( broadcaster_pubkeys, countersignatory_pubkeys, funding_outpoint, contest_delay, is_outbound, funding_redeemscript, channel_value_satoshis, secp_ctx) . 0 ;
766
+ secp_ctx. sign ( & sighash, funding_key)
767
+ }
768
+
769
+ /// Get the sighash and the transaction.
770
+ ///
771
+ /// Builds the transaction and computes the sighash. This can be used to verify a signature.
772
+ pub fn get_sighash < T : secp256k1:: Signing + secp256k1:: Verification > ( & self , broadcaster_pubkeys : & ChannelPublicKeys , countersignatory_pubkeys : & ChannelPublicKeys , funding_outpoint : & OutPoint , contest_delay : u16 , is_outbound : bool , funding_redeemscript : & Script , channel_value_satoshis : u64 , secp_ctx : & Secp256k1 < T > ) -> ( Message , Transaction ) {
773
+ let ( unsigned_tx, _, _) = self . build ( broadcaster_pubkeys, countersignatory_pubkeys, funding_outpoint, contest_delay, is_outbound, secp_ctx) . unwrap ( ) ;
774
+ let sighash = hash_to_message ! ( & bip143:: SigHashCache :: new( & unsigned_tx)
775
+ . signature_hash( 0 , funding_redeemscript, channel_value_satoshis, SigHashType :: All ) [ ..] ) ;
776
+ ( sighash, unsigned_tx)
777
+ }
778
+ }
779
+
780
+ /// Get the transaction number obscure factor
781
+ pub fn get_commitment_transaction_number_obscure_factor (
782
+ broadcaster_payment_basepoint : & PublicKey ,
783
+ countersignatory_payment_basepoint : & PublicKey ,
784
+ outbound : bool ,
785
+ ) -> u64 {
786
+ let mut sha = Sha256 :: engine ( ) ;
787
+
788
+ if outbound {
789
+ sha. input ( & broadcaster_payment_basepoint. serialize ( ) ) ;
790
+ sha. input ( & countersignatory_payment_basepoint. serialize ( ) ) ;
791
+ } else {
792
+ sha. input ( & countersignatory_payment_basepoint. serialize ( ) ) ;
793
+ sha. input ( & broadcaster_payment_basepoint. serialize ( ) ) ;
794
+ }
795
+ let res = Sha256 :: from_engine ( sha) . into_inner ( ) ;
796
+
797
+ ( ( res[ 26 ] as u64 ) << 5 * 8 )
798
+ | ( ( res[ 27 ] as u64 ) << 4 * 8 )
799
+ | ( ( res[ 28 ] as u64 ) << 3 * 8 )
800
+ | ( ( res[ 29 ] as u64 ) << 2 * 8 )
801
+ | ( ( res[ 30 ] as u64 ) << 1 * 8 )
802
+ | ( ( res[ 31 ] as u64 ) << 0 * 8 )
803
+ }
804
+
805
+ fn script_for_p2wpkh ( key : & PublicKey ) -> Script {
806
+ Builder :: new ( ) . push_opcode ( opcodes:: all:: OP_PUSHBYTES_0 )
807
+ . push_slice ( & WPubkeyHash :: hash ( & key. serialize ( ) ) [ ..] )
808
+ . into_script ( )
809
+ }
810
+
553
811
#[ derive( Clone ) ]
554
812
/// We use this to track holder commitment transactions and put off signing them until we are ready
555
813
/// to broadcast. This class can be used inside a signer implementation to generate a signature
0 commit comments