@@ -33,12 +33,13 @@ use util::ser::{Writeable, Writer, Readable};
33
33
34
34
use chain:: transaction:: OutPoint ;
35
35
use ln:: chan_utils;
36
- use ln:: chan_utils:: { HTLCOutputInCommitment , make_funding_redeemscript, ChannelPublicKeys , HolderCommitmentTransaction , PreCalculatedTxCreationKeys } ;
36
+ use ln:: chan_utils:: { HTLCOutputInCommitment , make_funding_redeemscript, ChannelPublicKeys , HolderCommitmentTransaction , PreCalculatedTxCreationKeys , derive_public_key , derive_public_revocation_key , TxCreationKeys } ;
37
37
use ln:: msgs:: UnsignedChannelAnnouncement ;
38
38
39
39
use std:: sync:: atomic:: { AtomicUsize , Ordering } ;
40
40
use std:: io:: Error ;
41
41
use ln:: msgs:: DecodeError ;
42
+ use ln:: transaction:: { CommitmentInfo , build_commitment_tx, get_commitment_transaction_number_obscure_factor} ;
42
43
43
44
/// When on-chain outputs are created by rust-lightning (which our counterparty is not able to
44
45
/// claim at any point in the future) an event is generated which you must track and be able to
@@ -244,6 +245,17 @@ pub trait ChannelKeys : Send+Clone {
244
245
// TODO: Add more input vars to enable better checking (preferably removing commitment_tx and
245
246
fn sign_holder_commitment < T : secp256k1:: Signing + secp256k1:: Verification > ( & self , holder_commitment_tx : & HolderCommitmentTransaction , secp_ctx : & Secp256k1 < T > ) -> Result < Signature , ( ) > ;
246
247
248
+ /// Create a signature for a holder's commitment transaction and attached HTLC transactions.
249
+ fn sign_holder_commitment_phase2 < T : secp256k1:: Signing + secp256k1:: Verification > (
250
+ & self ,
251
+ commitment_number : u64 ,
252
+ feerate_per_kw : u32 ,
253
+ to_holder_value_sat : u64 ,
254
+ to_counterparty_value_sat : u64 ,
255
+ htlcs : & Vec < HTLCOutputInCommitment > ,
256
+ secp_ctx : & Secp256k1 < T > ,
257
+ ) -> Result < ( Signature , Vec < Signature > ) , ( ) > ;
258
+
247
259
/// Same as sign_holder_commitment, but exists only for tests to get access to holder commitment
248
260
/// transactions which will be broadcasted later, after the channel has moved on to a newer
249
261
/// state. Thus, needs its own method as sign_holder_commitment may enforce that we only ever
@@ -325,7 +337,12 @@ pub trait ChannelKeys : Send+Clone {
325
337
/// We bind holder_selected_contest_delay late here for API convenience.
326
338
///
327
339
/// Will be called before any signatures are applied.
328
- fn on_accept ( & mut self , channel_points : & ChannelPublicKeys , counterparty_selected_contest_delay : u16 , holder_selected_contest_delay : u16 ) ;
340
+ fn on_accept ( & mut self , channel_points : & ChannelPublicKeys , counterparty_selected_contest_delay : u16 , holder_selected_contest_delay : u16 , is_outbound : bool ) ;
341
+
342
+ /// Set the funding outpoint.
343
+ ///
344
+ /// Used for re-constructing transactions as part of signing.
345
+ fn on_funding_created ( & mut self , funding_outpoint : & OutPoint ) ;
329
346
}
330
347
331
348
/// A trait to describe an object which can get user secrets and key material.
@@ -365,6 +382,8 @@ struct AcceptedChannelData {
365
382
/// by our counterparty, ie the amount of time that they have to wait to recover their funds
366
383
/// if they broadcast a transaction.
367
384
holder_selected_contest_delay : u16 ,
385
+ /// Whether the holder is the initiator of this channel
386
+ is_outbound : bool ,
368
387
}
369
388
370
389
#[ derive( Clone ) ]
@@ -386,6 +405,8 @@ pub struct InMemoryChannelKeys {
386
405
pub ( crate ) holder_channel_pubkeys : ChannelPublicKeys ,
387
406
/// Counterparty public keys and counterparty/holder selected_contest_delay, populated on channel acceptance
388
407
accepted_channel_data : Option < AcceptedChannelData > ,
408
+ /// Funding outpoint, populated on channel funding creation
409
+ funding_outpoint : Option < OutPoint > ,
389
410
/// The total value of this channel
390
411
channel_value_satoshis : u64 ,
391
412
/// Key derivation parameters
@@ -418,6 +439,7 @@ impl InMemoryChannelKeys {
418
439
channel_value_satoshis,
419
440
holder_channel_pubkeys,
420
441
accepted_channel_data : None ,
442
+ funding_outpoint : None ,
421
443
key_derivation_params,
422
444
}
423
445
}
@@ -454,6 +476,77 @@ impl InMemoryChannelKeys {
454
476
/// if they broadcast a transaction.
455
477
/// Will panic if on_accept wasn't called.
456
478
pub fn holder_selected_contest_delay ( & self ) -> u16 { self . accepted_channel_data . as_ref ( ) . unwrap ( ) . holder_selected_contest_delay }
479
+
480
+ /// Whether the holder is the initiator
481
+ pub fn is_outbound ( & self ) -> bool { self . accepted_channel_data . as_ref ( ) . unwrap ( ) . is_outbound }
482
+
483
+ /// Funding outpoint
484
+ /// Will panic if on_funding_created wasn't called.
485
+ pub fn funding_outpoint ( & self ) -> & OutPoint { self . funding_outpoint . as_ref ( ) . unwrap ( ) }
486
+
487
+ /// Prepare build information for a holder-broadcast commitment tx
488
+ pub fn build_holder_commitment_info < T : secp256k1:: Signing + secp256k1:: Verification > (
489
+ & self ,
490
+ per_commitment_point : & PublicKey ,
491
+ to_holder_value_sat : u64 ,
492
+ to_counterparty_value_sat : u64 ,
493
+ htlcs : & Vec < HTLCOutputInCommitment > ,
494
+ secp_ctx : & Secp256k1 < T > ,
495
+ ) -> Result < CommitmentInfo , ( ) > {
496
+ let counterparty_points = self . counterparty_pubkeys ( ) ;
497
+
498
+ let to_holder_delayed_pubkey = derive_public_key (
499
+ & secp_ctx,
500
+ & per_commitment_point,
501
+ & self . pubkeys ( ) . delayed_payment_basepoint ,
502
+ ) . map_err ( |_| ( ) ) ?;
503
+
504
+ let revocation_pubkey = derive_public_revocation_key (
505
+ & secp_ctx,
506
+ & per_commitment_point,
507
+ & counterparty_points. revocation_basepoint ,
508
+ ) . map_err ( |_| ( ) ) ?;
509
+
510
+ Ok ( CommitmentInfo {
511
+ is_counterparty_broadcaster : false ,
512
+ to_countersigner_pubkey : counterparty_points. payment_point ,
513
+ to_countersigner_value_sat : to_counterparty_value_sat,
514
+ revocation_pubkey,
515
+ to_broadcaster_delayed_pubkey : to_holder_delayed_pubkey,
516
+ to_broadcaster_value_sat : to_holder_value_sat,
517
+ to_self_delay : self . counterparty_selected_contest_delay ( ) ,
518
+ htlcs : htlcs. clone ( ) ,
519
+ } )
520
+ }
521
+
522
+ fn get_commitment_transaction_number_obscure_factor ( & self ) -> u64 {
523
+ get_commitment_transaction_number_obscure_factor (
524
+ & self . pubkeys ( ) . payment_point ,
525
+ & self . counterparty_pubkeys ( ) . payment_point ,
526
+ self . is_outbound ( ) ,
527
+ )
528
+ }
529
+
530
+ /// Build a commitment tx
531
+ pub fn build_commitment_tx < T : secp256k1:: Signing + secp256k1:: Verification > ( & self , per_commitment_point : & PublicKey ,
532
+ commitment_number : u64 , info : & CommitmentInfo ,
533
+ secp_ctx : & Secp256k1 < T > ) -> Result < ( bitcoin:: Transaction , Vec < HTLCOutputInCommitment > , TxCreationKeys , Vec < Script > ) , ( ) > {
534
+ let keys = if !info. is_counterparty_broadcaster {
535
+ TxCreationKeys :: make_tx_keys ( per_commitment_point, self . pubkeys ( ) , self . counterparty_pubkeys ( ) , secp_ctx)
536
+ } else {
537
+ TxCreationKeys :: make_tx_keys ( per_commitment_point, self . counterparty_pubkeys ( ) , self . pubkeys ( ) , secp_ctx)
538
+ } . unwrap ( ) ;
539
+
540
+ let obscured_commitment_transaction_number =
541
+ self . get_commitment_transaction_number_obscure_factor ( ) ^ commitment_number;
542
+ let ( tx, htlcs, scripts) = build_commitment_tx (
543
+ & keys,
544
+ info,
545
+ obscured_commitment_transaction_number,
546
+ self . funding_outpoint ( ) . into_bitcoin_outpoint ( ) ,
547
+ ) ;
548
+ Ok ( ( tx, htlcs, keys, scripts) )
549
+ }
457
550
}
458
551
459
552
impl ChannelKeys for InMemoryChannelKeys {
@@ -507,6 +600,47 @@ impl ChannelKeys for InMemoryChannelKeys {
507
600
Ok ( holder_commitment_tx. get_holder_sig ( & self . funding_key , & channel_funding_redeemscript, self . channel_value_satoshis , secp_ctx) )
508
601
}
509
602
603
+ fn sign_holder_commitment_phase2 < T : secp256k1:: Signing + secp256k1:: Verification > ( & self , commitment_number : u64 , feerate_per_kw : u32 , to_holder_value_sat : u64 , to_counterparty_value_sat : u64 , htlcs : & Vec < HTLCOutputInCommitment > , secp_ctx : & Secp256k1 < T > ) -> Result < ( Signature , Vec < Signature > ) , ( ) > {
604
+ let per_commitment_point = self . get_per_commitment_point ( commitment_number, secp_ctx) ;
605
+ let info = self . build_holder_commitment_info (
606
+ & per_commitment_point,
607
+ to_holder_value_sat,
608
+ to_counterparty_value_sat,
609
+ htlcs,
610
+ secp_ctx,
611
+ ) ?;
612
+ let ( tx, htlcs, keys, _) =
613
+ self . build_commitment_tx ( & per_commitment_point, commitment_number, & info, secp_ctx) ?;
614
+
615
+ let funding_pubkey = PublicKey :: from_secret_key ( secp_ctx, & self . funding_key ) ;
616
+ let funding_redeemscript = make_funding_redeemscript ( & funding_pubkey, & self . counterparty_pubkeys ( ) . funding_pubkey ) ;
617
+ let sighash = hash_to_message ! ( & bip143:: SigHashCache :: new( & tx)
618
+ . signature_hash( 0 , & funding_redeemscript, self . channel_value_satoshis, SigHashType :: All ) [ ..] ) ;
619
+ let sig = secp_ctx. sign ( & sighash, & self . funding_key ) ;
620
+
621
+ // We provide a dummy signature for the remote, since we don't require that sig
622
+ // to be passed in to this call. It would have been better if HolderCommitmentTransaction
623
+ // didn't require the remote sig.
624
+ let dummy_sig = Secp256k1 :: new ( ) . sign (
625
+ & secp256k1:: Message :: from_slice ( & [ 42 ; 32 ] ) . unwrap ( ) ,
626
+ & SecretKey :: from_slice ( & [ 42 ; 32 ] ) . unwrap ( ) ,
627
+ ) ;
628
+ let htlcs_with_sig = htlcs. iter ( ) . map ( |h| ( h. clone ( ) , Some ( dummy_sig. clone ( ) ) ) ) . collect ( ) ;
629
+ let commitment_tx = HolderCommitmentTransaction :: new_missing_holder_sig (
630
+ tx,
631
+ dummy_sig,
632
+ & self . pubkeys ( ) . funding_pubkey ,
633
+ & self . counterparty_pubkeys ( ) . funding_pubkey ,
634
+ keys,
635
+ feerate_per_kw,
636
+ htlcs_with_sig,
637
+ ) ;
638
+ let htlc_sigs_o = self . sign_holder_commitment_htlc_transactions ( & commitment_tx, secp_ctx) ?;
639
+ let htlc_sigs = htlc_sigs_o. iter ( ) . map ( |o| o. unwrap ( ) ) . collect ( ) ;
640
+
641
+ Ok ( ( sig, htlc_sigs) )
642
+ }
643
+
510
644
#[ cfg( any( test, feature = "unsafe_revoked_tx_signing" ) ) ]
511
645
fn unsafe_sign_holder_commitment < T : secp256k1:: Signing + secp256k1:: Verification > ( & self , holder_commitment_tx : & HolderCommitmentTransaction , secp_ctx : & Secp256k1 < T > ) -> Result < Signature , ( ) > {
512
646
let funding_pubkey = PublicKey :: from_secret_key ( secp_ctx, & self . funding_key ) ;
@@ -588,18 +722,24 @@ impl ChannelKeys for InMemoryChannelKeys {
588
722
Ok ( secp_ctx. sign ( & msghash, & self . funding_key ) )
589
723
}
590
724
591
- fn on_accept ( & mut self , channel_pubkeys : & ChannelPublicKeys , counterparty_selected_contest_delay : u16 , holder_selected_contest_delay : u16 ) {
592
- assert ! ( self . accepted_channel_data. is_none( ) , "Already accepted " ) ;
725
+ fn on_accept ( & mut self , channel_pubkeys : & ChannelPublicKeys , counterparty_selected_contest_delay : u16 , holder_selected_contest_delay : u16 , is_outbound : bool ) {
726
+ assert ! ( self . accepted_channel_data. is_none( ) , "Acceptance already noted " ) ;
593
727
self . accepted_channel_data = Some ( AcceptedChannelData {
594
728
counterparty_channel_pubkeys : channel_pubkeys. clone ( ) ,
595
729
counterparty_selected_contest_delay,
596
730
holder_selected_contest_delay,
731
+ is_outbound,
597
732
} ) ;
598
733
}
734
+
735
+ fn on_funding_created ( & mut self , funding_outpoint : & OutPoint ) {
736
+ assert ! ( self . funding_outpoint. is_none( ) , "Funding creation already noted" ) ;
737
+ self . funding_outpoint = Some ( funding_outpoint. clone ( ) ) ;
738
+ }
599
739
}
600
740
601
741
impl_writeable ! ( AcceptedChannelData , 0 ,
602
- { counterparty_channel_pubkeys, counterparty_selected_contest_delay, holder_selected_contest_delay } ) ;
742
+ { counterparty_channel_pubkeys, counterparty_selected_contest_delay, holder_selected_contest_delay, is_outbound } ) ;
603
743
604
744
impl Writeable for InMemoryChannelKeys {
605
745
fn write < W : Writer > ( & self , writer : & mut W ) -> Result < ( ) , Error > {
@@ -627,6 +767,7 @@ impl Readable for InMemoryChannelKeys {
627
767
let htlc_base_key = Readable :: read ( reader) ?;
628
768
let commitment_seed = Readable :: read ( reader) ?;
629
769
let counterparty_channel_data = Readable :: read ( reader) ?;
770
+ let funding_outpoint = Readable :: read ( reader) ?;
630
771
let channel_value_satoshis = Readable :: read ( reader) ?;
631
772
let secp_ctx = Secp256k1 :: signing_only ( ) ;
632
773
let holder_channel_pubkeys =
@@ -646,6 +787,7 @@ impl Readable for InMemoryChannelKeys {
646
787
channel_value_satoshis,
647
788
holder_channel_pubkeys,
648
789
accepted_channel_data : counterparty_channel_data,
790
+ funding_outpoint,
649
791
key_derivation_params : ( params_1, params_2) ,
650
792
} )
651
793
}
0 commit comments