@@ -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
@@ -79,7 +80,7 @@ pub enum SpendableOutputDescriptor {
79
80
///
80
81
/// To derive the revocation_pubkey provided here (which is used in the witness
81
82
/// script generation), you must pass the counterparty revocation_basepoint (which appears in the
82
- /// call to ChannelKeys::on_accept ) and the provided per_commitment point
83
+ /// call to ChannelKeys::on_funding_created ) and the provided per_commitment point
83
84
/// to chan_utils::derive_public_revocation_key.
84
85
///
85
86
/// The witness script which is hashed and included in the output script_pubkey may be
@@ -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
@@ -319,13 +331,13 @@ pub trait ChannelKeys : Send+Clone {
319
331
/// protocol.
320
332
fn sign_channel_announcement < T : secp256k1:: Signing > ( & self , msg : & UnsignedChannelAnnouncement , secp_ctx : & Secp256k1 < T > ) -> Result < Signature , ( ) > ;
321
333
322
- /// Set the counterparty channel basepoints and counterparty_selected/holder_selected_contest_delay.
323
- /// This is done immediately on incoming channels and as soon as the channel is accepted on outgoing channels .
334
+ /// Set the counterparty channel basepoints, counterparty_selected/holder_selected_contest_delay and funding outpoint .
335
+ /// This is done as soon as the funding outpoint is known .
324
336
///
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_funding_created ( & mut self , channel_points : & ChannelPublicKeys , counterparty_selected_contest_delay : u16 , holder_selected_contest_delay : u16 , is_outbound : bool , funding_outpoint : & OutPoint ) ;
329
341
}
330
342
331
343
/// A trait to describe an object which can get user secrets and key material.
@@ -365,6 +377,8 @@ struct AcceptedChannelData {
365
377
/// by our counterparty, ie the amount of time that they have to wait to recover their funds
366
378
/// if they broadcast a transaction.
367
379
holder_selected_contest_delay : u16 ,
380
+ /// Whether the holder is the initiator of this channel
381
+ is_outbound : bool ,
368
382
}
369
383
370
384
#[ derive( Clone ) ]
@@ -386,6 +400,8 @@ pub struct InMemoryChannelKeys {
386
400
pub ( crate ) holder_channel_pubkeys : ChannelPublicKeys ,
387
401
/// Counterparty public keys and counterparty/holder selected_contest_delay, populated on channel acceptance
388
402
accepted_channel_data : Option < AcceptedChannelData > ,
403
+ /// Funding outpoint, populated on channel funding creation
404
+ funding_outpoint : Option < OutPoint > ,
389
405
/// The total value of this channel
390
406
channel_value_satoshis : u64 ,
391
407
/// Key derivation parameters
@@ -418,6 +434,7 @@ impl InMemoryChannelKeys {
418
434
channel_value_satoshis,
419
435
holder_channel_pubkeys,
420
436
accepted_channel_data : None ,
437
+ funding_outpoint : None ,
421
438
key_derivation_params,
422
439
}
423
440
}
@@ -439,21 +456,92 @@ impl InMemoryChannelKeys {
439
456
}
440
457
441
458
/// Counterparty pubkeys.
442
- /// Will panic if on_accept wasn't called.
459
+ /// Will panic if on_funding_created wasn't called.
443
460
pub fn counterparty_pubkeys ( & self ) -> & ChannelPublicKeys { & self . accepted_channel_data . as_ref ( ) . unwrap ( ) . counterparty_channel_pubkeys }
444
461
445
462
/// The contest_delay value specified by our counterparty and applied on holder-broadcastable
446
463
/// transactions, ie the amount of time that we have to wait to recover our funds if we
447
464
/// broadcast a transaction. You'll likely want to pass this to the
448
465
/// ln::chan_utils::build*_transaction functions when signing holder's transactions.
449
- /// Will panic if on_accept wasn't called.
466
+ /// Will panic if on_funding_created wasn't called.
450
467
pub fn counterparty_selected_contest_delay ( & self ) -> u16 { self . accepted_channel_data . as_ref ( ) . unwrap ( ) . counterparty_selected_contest_delay }
451
468
452
469
/// The contest_delay value specified by us and applied on transactions broadcastable
453
470
/// by our counterparty, ie the amount of time that they have to wait to recover their funds
454
471
/// if they broadcast a transaction.
455
- /// Will panic if on_accept wasn't called.
472
+ /// Will panic if on_funding_created wasn't called.
456
473
pub fn holder_selected_contest_delay ( & self ) -> u16 { self . accepted_channel_data . as_ref ( ) . unwrap ( ) . holder_selected_contest_delay }
474
+
475
+ /// Whether the holder is the initiator
476
+ pub fn is_outbound ( & self ) -> bool { self . accepted_channel_data . as_ref ( ) . unwrap ( ) . is_outbound }
477
+
478
+ /// Funding outpoint
479
+ /// Will panic if on_funding_created wasn't called.
480
+ pub fn funding_outpoint ( & self ) -> & OutPoint { self . funding_outpoint . as_ref ( ) . unwrap ( ) }
481
+
482
+ /// Prepare build information for a holder-broadcast commitment tx
483
+ pub fn build_holder_commitment_info < T : secp256k1:: Signing + secp256k1:: Verification > (
484
+ & self ,
485
+ per_commitment_point : & PublicKey ,
486
+ to_holder_value_sat : u64 ,
487
+ to_counterparty_value_sat : u64 ,
488
+ htlcs : & Vec < HTLCOutputInCommitment > ,
489
+ secp_ctx : & Secp256k1 < T > ,
490
+ ) -> Result < CommitmentInfo , ( ) > {
491
+ let counterparty_points = self . counterparty_pubkeys ( ) ;
492
+
493
+ let to_holder_delayed_pubkey = derive_public_key (
494
+ & secp_ctx,
495
+ & per_commitment_point,
496
+ & self . pubkeys ( ) . delayed_payment_basepoint ,
497
+ ) . map_err ( |_| ( ) ) ?;
498
+
499
+ let revocation_pubkey = derive_public_revocation_key (
500
+ & secp_ctx,
501
+ & per_commitment_point,
502
+ & counterparty_points. revocation_basepoint ,
503
+ ) . map_err ( |_| ( ) ) ?;
504
+
505
+ Ok ( CommitmentInfo {
506
+ is_counterparty_broadcaster : false ,
507
+ to_countersigner_pubkey : counterparty_points. payment_point ,
508
+ to_countersigner_value_sat : to_counterparty_value_sat,
509
+ revocation_pubkey,
510
+ to_broadcaster_delayed_pubkey : to_holder_delayed_pubkey,
511
+ to_broadcaster_value_sat : to_holder_value_sat,
512
+ to_self_delay : self . counterparty_selected_contest_delay ( ) ,
513
+ htlcs : htlcs. clone ( ) ,
514
+ } )
515
+ }
516
+
517
+ fn get_commitment_transaction_number_obscure_factor ( & self ) -> u64 {
518
+ get_commitment_transaction_number_obscure_factor (
519
+ & self . pubkeys ( ) . payment_point ,
520
+ & self . counterparty_pubkeys ( ) . payment_point ,
521
+ self . is_outbound ( ) ,
522
+ )
523
+ }
524
+
525
+ /// Build a commitment tx
526
+ pub fn build_commitment_tx < T : secp256k1:: Signing + secp256k1:: Verification > ( & self , per_commitment_point : & PublicKey ,
527
+ commitment_number : u64 , info : & CommitmentInfo ,
528
+ secp_ctx : & Secp256k1 < T > ) -> Result < ( bitcoin:: Transaction , Vec < HTLCOutputInCommitment > , TxCreationKeys , Vec < Script > ) , ( ) > {
529
+ let keys = if !info. is_counterparty_broadcaster {
530
+ TxCreationKeys :: make_tx_keys ( per_commitment_point, self . pubkeys ( ) , self . counterparty_pubkeys ( ) , secp_ctx)
531
+ } else {
532
+ TxCreationKeys :: make_tx_keys ( per_commitment_point, self . counterparty_pubkeys ( ) , self . pubkeys ( ) , secp_ctx)
533
+ } . unwrap ( ) ;
534
+
535
+ let obscured_commitment_transaction_number =
536
+ self . get_commitment_transaction_number_obscure_factor ( ) ^ commitment_number;
537
+ let ( tx, htlcs, scripts) = build_commitment_tx (
538
+ & keys,
539
+ info,
540
+ obscured_commitment_transaction_number,
541
+ self . funding_outpoint ( ) . into_bitcoin_outpoint ( ) ,
542
+ ) ;
543
+ Ok ( ( tx, htlcs, keys, scripts) )
544
+ }
457
545
}
458
546
459
547
impl ChannelKeys for InMemoryChannelKeys {
@@ -507,6 +595,47 @@ impl ChannelKeys for InMemoryChannelKeys {
507
595
Ok ( holder_commitment_tx. get_holder_sig ( & self . funding_key , & channel_funding_redeemscript, self . channel_value_satoshis , secp_ctx) )
508
596
}
509
597
598
+ 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 > ) , ( ) > {
599
+ let per_commitment_point = self . get_per_commitment_point ( commitment_number, secp_ctx) ;
600
+ let info = self . build_holder_commitment_info (
601
+ & per_commitment_point,
602
+ to_holder_value_sat,
603
+ to_counterparty_value_sat,
604
+ htlcs,
605
+ secp_ctx,
606
+ ) ?;
607
+ let ( tx, htlcs, keys, _) =
608
+ self . build_commitment_tx ( & per_commitment_point, commitment_number, & info, secp_ctx) ?;
609
+
610
+ let funding_pubkey = PublicKey :: from_secret_key ( secp_ctx, & self . funding_key ) ;
611
+ let funding_redeemscript = make_funding_redeemscript ( & funding_pubkey, & self . counterparty_pubkeys ( ) . funding_pubkey ) ;
612
+ let sighash = hash_to_message ! ( & bip143:: SigHashCache :: new( & tx)
613
+ . signature_hash( 0 , & funding_redeemscript, self . channel_value_satoshis, SigHashType :: All ) [ ..] ) ;
614
+ let sig = secp_ctx. sign ( & sighash, & self . funding_key ) ;
615
+
616
+ // We provide a dummy signature for the remote, since we don't require that sig
617
+ // to be passed in to this call. It would have been better if HolderCommitmentTransaction
618
+ // didn't require the remote sig.
619
+ let dummy_sig = Secp256k1 :: new ( ) . sign (
620
+ & secp256k1:: Message :: from_slice ( & [ 42 ; 32 ] ) . unwrap ( ) ,
621
+ & SecretKey :: from_slice ( & [ 42 ; 32 ] ) . unwrap ( ) ,
622
+ ) ;
623
+ let htlcs_with_sig = htlcs. iter ( ) . map ( |h| ( h. clone ( ) , Some ( dummy_sig. clone ( ) ) ) ) . collect ( ) ;
624
+ let commitment_tx = HolderCommitmentTransaction :: new_missing_holder_sig (
625
+ tx,
626
+ dummy_sig,
627
+ & self . pubkeys ( ) . funding_pubkey ,
628
+ & self . counterparty_pubkeys ( ) . funding_pubkey ,
629
+ keys,
630
+ feerate_per_kw,
631
+ htlcs_with_sig,
632
+ ) ;
633
+ let htlc_sigs_o = self . sign_holder_commitment_htlc_transactions ( & commitment_tx, secp_ctx) ?;
634
+ let htlc_sigs = htlc_sigs_o. iter ( ) . map ( |o| o. unwrap ( ) ) . collect ( ) ;
635
+
636
+ Ok ( ( sig, htlc_sigs) )
637
+ }
638
+
510
639
#[ cfg( any( test, feature = "unsafe_revoked_tx_signing" ) ) ]
511
640
fn unsafe_sign_holder_commitment < T : secp256k1:: Signing + secp256k1:: Verification > ( & self , holder_commitment_tx : & HolderCommitmentTransaction , secp_ctx : & Secp256k1 < T > ) -> Result < Signature , ( ) > {
512
641
let funding_pubkey = PublicKey :: from_secret_key ( secp_ctx, & self . funding_key ) ;
@@ -588,18 +717,21 @@ impl ChannelKeys for InMemoryChannelKeys {
588
717
Ok ( secp_ctx. sign ( & msghash, & self . funding_key ) )
589
718
}
590
719
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 " ) ;
720
+ fn on_funding_created ( & mut self , channel_pubkeys : & ChannelPublicKeys , counterparty_selected_contest_delay : u16 , holder_selected_contest_delay : u16 , is_outbound : bool , funding_outpoint : & OutPoint ) {
721
+ assert ! ( self . accepted_channel_data. is_none( ) , "Acceptance already noted " ) ;
593
722
self . accepted_channel_data = Some ( AcceptedChannelData {
594
723
counterparty_channel_pubkeys : channel_pubkeys. clone ( ) ,
595
724
counterparty_selected_contest_delay,
596
725
holder_selected_contest_delay,
726
+ is_outbound,
597
727
} ) ;
728
+ assert ! ( self . funding_outpoint. is_none( ) , "Funding creation already noted" ) ;
729
+ self . funding_outpoint = Some ( funding_outpoint. clone ( ) ) ;
598
730
}
599
731
}
600
732
601
733
impl_writeable ! ( AcceptedChannelData , 0 ,
602
- { counterparty_channel_pubkeys, counterparty_selected_contest_delay, holder_selected_contest_delay } ) ;
734
+ { counterparty_channel_pubkeys, counterparty_selected_contest_delay, holder_selected_contest_delay, is_outbound } ) ;
603
735
604
736
impl Writeable for InMemoryChannelKeys {
605
737
fn write < W : Writer > ( & self , writer : & mut W ) -> Result < ( ) , Error > {
@@ -610,6 +742,7 @@ impl Writeable for InMemoryChannelKeys {
610
742
self . htlc_base_key . write ( writer) ?;
611
743
self . commitment_seed . write ( writer) ?;
612
744
self . accepted_channel_data . write ( writer) ?;
745
+ self . funding_outpoint . write ( writer) ?;
613
746
self . channel_value_satoshis . write ( writer) ?;
614
747
self . key_derivation_params . 0 . write ( writer) ?;
615
748
self . key_derivation_params . 1 . write ( writer) ?;
@@ -627,6 +760,7 @@ impl Readable for InMemoryChannelKeys {
627
760
let htlc_base_key = Readable :: read ( reader) ?;
628
761
let commitment_seed = Readable :: read ( reader) ?;
629
762
let counterparty_channel_data = Readable :: read ( reader) ?;
763
+ let funding_outpoint = Readable :: read ( reader) ?;
630
764
let channel_value_satoshis = Readable :: read ( reader) ?;
631
765
let secp_ctx = Secp256k1 :: signing_only ( ) ;
632
766
let holder_channel_pubkeys =
@@ -646,6 +780,7 @@ impl Readable for InMemoryChannelKeys {
646
780
channel_value_satoshis,
647
781
holder_channel_pubkeys,
648
782
accepted_channel_data : counterparty_channel_data,
783
+ funding_outpoint,
649
784
key_derivation_params : ( params_1, params_2) ,
650
785
} )
651
786
}
0 commit comments