@@ -484,10 +484,30 @@ pub fn build_htlc_transaction(prev_hash: &Sha256dHash, feerate_per_kw: u64, to_s
484
484
/// to broadcast. Eventually this will require a signer which is possibly external, but for now we
485
485
/// just pass in the SecretKeys required.
486
486
pub struct LocalCommitmentTransaction {
487
- tx : Transaction ,
488
- pub ( crate ) local_keys : TxCreationKeys ,
489
- pub ( crate ) feerate_per_kw : u64 ,
490
- pub ( crate ) per_htlc : Vec < ( HTLCOutputInCommitment , Option < Signature > ) > ,
487
+ // TODO: We should migrate away from providing the transaction, instead providing enough to
488
+ // allow the ChannelKeys to construct it from scratch. Luckily we already have HTLC data here,
489
+ // so we're probably most of the way there.
490
+ /// The commitment transaction itself, in unsigned form.
491
+ pub unsigned_tx : Transaction ,
492
+ /// Our counterparty's signature for the transaction, above.
493
+ pub their_sig : Signature ,
494
+ // Which order the signatures should go in when constructing the final commitment tx witness.
495
+ // The user should be able to reconstruc this themselves, so we don't bother to expose it.
496
+ our_sig_first : bool ,
497
+ /// The key derivation parameters for this commitment transaction
498
+ pub local_keys : TxCreationKeys ,
499
+ /// The feerate paid per 1000-weight-unit in this commitment transaction. This value is
500
+ /// controlled by the channel initiator.
501
+ pub feerate_per_kw : u64 ,
502
+ /// The HTLCs and remote htlc signatures which were included in this commitment transaction.
503
+ ///
504
+ /// Note that this includes all HTLCs, including ones which were considered dust and not
505
+ /// acually included in the transaction as it appears on-chain, but who's value factor into fee
506
+ /// calculations.
507
+ ///
508
+ /// The remote HTLC signatures in the second element will always be set for non-dust HTLCs, ie
509
+ /// those for which transaction_output_index.is_some().
510
+ pub per_htlc : Vec < ( HTLCOutputInCommitment , Option < Signature > ) > ,
491
511
}
492
512
impl LocalCommitmentTransaction {
493
513
#[ cfg( test) ]
@@ -499,16 +519,19 @@ impl LocalCommitmentTransaction {
499
519
} ,
500
520
script_sig : Default :: default ( ) ,
501
521
sequence : 0 ,
502
- witness : vec ! [ vec! [ ] , vec! [ ] , vec! [ ] ]
522
+ witness : vec ! [ ]
503
523
} ;
504
524
let dummy_key = PublicKey :: from_secret_key ( & Secp256k1 :: new ( ) , & SecretKey :: from_slice ( & [ 42 ; 32 ] ) . unwrap ( ) ) ;
525
+ let dummy_sig = Secp256k1 :: new ( ) . sign ( & secp256k1:: Message :: from_slice ( & [ 42 ; 32 ] ) . unwrap ( ) , & SecretKey :: from_slice ( & [ 42 ; 32 ] ) . unwrap ( ) ) ;
505
526
Self {
506
- tx : Transaction {
527
+ unsigned_tx : Transaction {
507
528
version : 2 ,
508
529
input : vec ! [ dummy_input] ,
509
530
output : Vec :: new ( ) ,
510
531
lock_time : 0 ,
511
532
} ,
533
+ their_sig : dummy_sig,
534
+ our_sig_first : false ,
512
535
local_keys : TxCreationKeys {
513
536
per_commitment_point : dummy_key. clone ( ) ,
514
537
revocation_key : dummy_key. clone ( ) ,
@@ -524,23 +547,14 @@ impl LocalCommitmentTransaction {
524
547
525
548
/// Generate a new LocalCommitmentTransaction based on a raw commitment transaction,
526
549
/// remote signature and both parties keys
527
- pub ( crate ) fn new_missing_local_sig ( mut tx : Transaction , their_sig : & Signature , our_funding_key : & PublicKey , their_funding_key : & PublicKey , local_keys : TxCreationKeys , feerate_per_kw : u64 , htlc_data : Vec < ( HTLCOutputInCommitment , Option < Signature > ) > ) -> LocalCommitmentTransaction {
528
- if tx. input . len ( ) != 1 { panic ! ( "Tried to store a commitment transaction that had input count != 1!" ) ; }
529
- if tx. input [ 0 ] . witness . len ( ) != 0 { panic ! ( "Tried to store a signed commitment transaction?" ) ; }
530
-
531
- tx. input [ 0 ] . witness . push ( Vec :: new ( ) ) ; // First is the multisig dummy
550
+ pub ( crate ) fn new_missing_local_sig ( unsigned_tx : Transaction , their_sig : Signature , our_funding_key : & PublicKey , their_funding_key : & PublicKey , local_keys : TxCreationKeys , feerate_per_kw : u64 , htlc_data : Vec < ( HTLCOutputInCommitment , Option < Signature > ) > ) -> LocalCommitmentTransaction {
551
+ if unsigned_tx. input . len ( ) != 1 { panic ! ( "Tried to store a commitment transaction that had input count != 1!" ) ; }
552
+ if unsigned_tx. input [ 0 ] . witness . len ( ) != 0 { panic ! ( "Tried to store a signed commitment transaction?" ) ; }
532
553
533
- if our_funding_key. serialize ( ) [ ..] < their_funding_key. serialize ( ) [ ..] {
534
- tx. input [ 0 ] . witness . push ( Vec :: new ( ) ) ;
535
- tx. input [ 0 ] . witness . push ( their_sig. serialize_der ( ) . to_vec ( ) ) ;
536
- tx. input [ 0 ] . witness [ 2 ] . push ( SigHashType :: All as u8 ) ;
537
- } else {
538
- tx. input [ 0 ] . witness . push ( their_sig. serialize_der ( ) . to_vec ( ) ) ;
539
- tx. input [ 0 ] . witness [ 1 ] . push ( SigHashType :: All as u8 ) ;
540
- tx. input [ 0 ] . witness . push ( Vec :: new ( ) ) ;
541
- }
542
-
543
- Self { tx,
554
+ Self {
555
+ unsigned_tx,
556
+ their_sig,
557
+ our_sig_first : our_funding_key. serialize ( ) [ ..] < their_funding_key. serialize ( ) [ ..] ,
544
558
local_keys,
545
559
feerate_per_kw,
546
560
per_htlc : htlc_data,
@@ -550,22 +564,7 @@ impl LocalCommitmentTransaction {
550
564
/// Get the txid of the local commitment transaction contained in this
551
565
/// LocalCommitmentTransaction
552
566
pub fn txid ( & self ) -> Sha256dHash {
553
- self . tx . txid ( )
554
- }
555
-
556
- /// Check if LocalCommitmentTransaction has already been signed by us
557
- pub ( crate ) fn has_local_sig ( & self ) -> bool {
558
- if self . tx . input . len ( ) != 1 { panic ! ( "Commitment transactions must have input count == 1!" ) ; }
559
- if self . tx . input [ 0 ] . witness . len ( ) == 4 {
560
- assert ! ( !self . tx. input[ 0 ] . witness[ 1 ] . is_empty( ) ) ;
561
- assert ! ( !self . tx. input[ 0 ] . witness[ 2 ] . is_empty( ) ) ;
562
- true
563
- } else {
564
- assert_eq ! ( self . tx. input[ 0 ] . witness. len( ) , 3 ) ;
565
- assert ! ( self . tx. input[ 0 ] . witness[ 0 ] . is_empty( ) ) ;
566
- assert ! ( self . tx. input[ 0 ] . witness[ 1 ] . is_empty( ) || self . tx. input[ 0 ] . witness[ 2 ] . is_empty( ) ) ;
567
- false
568
- }
567
+ self . unsigned_tx . txid ( )
569
568
}
570
569
571
570
/// Gets our signature for the contained commitment transaction given our funding private key.
@@ -577,32 +576,27 @@ impl LocalCommitmentTransaction {
577
576
/// ChannelKeys::sign_local_commitment() calls directly.
578
577
/// Channel value is amount locked in funding_outpoint.
579
578
pub fn get_local_sig < T : secp256k1:: Signing > ( & self , funding_key : & SecretKey , funding_redeemscript : & Script , channel_value_satoshis : u64 , secp_ctx : & Secp256k1 < T > ) -> Signature {
580
- let sighash = hash_to_message ! ( & bip143:: SighashComponents :: new( & self . tx )
581
- . sighash_all( & self . tx . input[ 0 ] , funding_redeemscript, channel_value_satoshis) [ ..] ) ;
579
+ let sighash = hash_to_message ! ( & bip143:: SighashComponents :: new( & self . unsigned_tx )
580
+ . sighash_all( & self . unsigned_tx . input[ 0 ] , funding_redeemscript, channel_value_satoshis) [ ..] ) ;
582
581
secp_ctx. sign ( & sighash, funding_key)
583
582
}
584
583
584
+ pub ( crate ) fn add_local_sig ( & self , funding_redeemscript : & Script , our_sig : Signature ) -> Transaction {
585
+ let mut tx = self . unsigned_tx . clone ( ) ;
586
+ tx. input [ 0 ] . witness . push ( Vec :: new ( ) ) ; // First is the multisig dummy
585
587
586
- pub ( crate ) fn add_local_sig ( & mut self , funding_redeemscript : & Script , our_sig : Signature ) {
587
- if self . has_local_sig ( ) { return ; }
588
-
589
- if self . tx . input [ 0 ] . witness [ 1 ] . is_empty ( ) {
590
- self . tx . input [ 0 ] . witness [ 1 ] = our_sig. serialize_der ( ) . to_vec ( ) ;
591
- self . tx . input [ 0 ] . witness [ 1 ] . push ( SigHashType :: All as u8 ) ;
588
+ if self . our_sig_first {
589
+ tx. input [ 0 ] . witness . push ( our_sig. serialize_der ( ) . to_vec ( ) ) ;
590
+ tx. input [ 0 ] . witness . push ( self . their_sig . serialize_der ( ) . to_vec ( ) ) ;
592
591
} else {
593
- self . tx . input [ 0 ] . witness [ 2 ] = our_sig . serialize_der ( ) . to_vec ( ) ;
594
- self . tx . input [ 0 ] . witness [ 2 ] . push ( SigHashType :: All as u8 ) ;
592
+ tx. input [ 0 ] . witness . push ( self . their_sig . serialize_der ( ) . to_vec ( ) ) ;
593
+ tx. input [ 0 ] . witness . push ( our_sig . serialize_der ( ) . to_vec ( ) ) ;
595
594
}
595
+ tx. input [ 0 ] . witness [ 1 ] . push ( SigHashType :: All as u8 ) ;
596
+ tx. input [ 0 ] . witness [ 2 ] . push ( SigHashType :: All as u8 ) ;
596
597
597
- self . tx . input [ 0 ] . witness . push ( funding_redeemscript. as_bytes ( ) . to_vec ( ) ) ;
598
- }
599
-
600
- /// Get raw transaction without asserting if witness is complete
601
- pub ( crate ) fn without_valid_witness ( & self ) -> & Transaction { & self . tx }
602
- /// Get raw transaction with panics if witness is incomplete
603
- pub ( crate ) fn with_valid_witness ( & self ) -> & Transaction {
604
- assert ! ( self . has_local_sig( ) ) ;
605
- & self . tx
598
+ tx. input [ 0 ] . witness . push ( funding_redeemscript. as_bytes ( ) . to_vec ( ) ) ;
599
+ tx
606
600
}
607
601
608
602
/// Get a signature for each HTLC which was included in the commitment transaction (ie for
@@ -677,12 +671,14 @@ impl PartialEq for LocalCommitmentTransaction {
677
671
}
678
672
impl Writeable for LocalCommitmentTransaction {
679
673
fn write < W : Writer > ( & self , writer : & mut W ) -> Result < ( ) , :: std:: io:: Error > {
680
- if let Err ( e) = self . tx . consensus_encode ( & mut WriterWriteAdaptor ( writer) ) {
674
+ if let Err ( e) = self . unsigned_tx . consensus_encode ( & mut WriterWriteAdaptor ( writer) ) {
681
675
match e {
682
676
encode:: Error :: Io ( e) => return Err ( e) ,
683
677
_ => panic ! ( "local tx must have been well-formed!" ) ,
684
678
}
685
679
}
680
+ self . their_sig . write ( writer) ?;
681
+ self . our_sig_first . write ( writer) ?;
686
682
self . local_keys . write ( writer) ?;
687
683
self . feerate_per_kw . write ( writer) ?;
688
684
writer. write_all ( & byte_utils:: be64_to_array ( self . per_htlc . len ( ) as u64 ) ) ?;
@@ -695,13 +691,15 @@ impl Writeable for LocalCommitmentTransaction {
695
691
}
696
692
impl Readable for LocalCommitmentTransaction {
697
693
fn read < R : :: std:: io:: Read > ( reader : & mut R ) -> Result < Self , DecodeError > {
698
- let tx = match Transaction :: consensus_decode ( reader. by_ref ( ) ) {
694
+ let unsigned_tx = match Transaction :: consensus_decode ( reader. by_ref ( ) ) {
699
695
Ok ( tx) => tx,
700
696
Err ( e) => match e {
701
697
encode:: Error :: Io ( ioe) => return Err ( DecodeError :: Io ( ioe) ) ,
702
698
_ => return Err ( DecodeError :: InvalidValue ) ,
703
699
} ,
704
700
} ;
701
+ let their_sig = Readable :: read ( reader) ?;
702
+ let our_sig_first = Readable :: read ( reader) ?;
705
703
let local_keys = Readable :: read ( reader) ?;
706
704
let feerate_per_kw = Readable :: read ( reader) ?;
707
705
let htlcs_count: u64 = Readable :: read ( reader) ?;
@@ -712,12 +710,14 @@ impl Readable for LocalCommitmentTransaction {
712
710
per_htlc. push ( ( htlc, sigs) ) ;
713
711
}
714
712
715
- if tx . input . len ( ) != 1 {
713
+ if unsigned_tx . input . len ( ) != 1 {
716
714
// Ensure tx didn't hit the 0-input ambiguity case.
717
715
return Err ( DecodeError :: InvalidValue ) ;
718
716
}
719
717
Ok ( Self {
720
- tx,
718
+ unsigned_tx,
719
+ their_sig,
720
+ our_sig_first,
721
721
local_keys,
722
722
feerate_per_kw,
723
723
per_htlc,
0 commit comments