@@ -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::ready_channel ) 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,15 @@ 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 static channel data, including basepoints,
335
+ /// counterparty_selected/holder_selected_contest_delay and funding outpoint.
336
+ /// This is done as soon as the funding outpoint is known. Since these are static channel data,
337
+ /// they MUST NOT be allowed to change to different values once set.
324
338
///
325
339
/// We bind holder_selected_contest_delay late here for API convenience.
326
340
///
327
341
/// 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 ) ;
342
+ fn ready_channel ( & mut self , channel_points : & ChannelPublicKeys , counterparty_selected_contest_delay : u16 , holder_selected_contest_delay : u16 , is_outbound : bool , funding_outpoint : & OutPoint ) ;
329
343
}
330
344
331
345
/// A trait to describe an object which can get user secrets and key material.
@@ -349,11 +363,11 @@ pub trait KeysInterface: Send + Sync {
349
363
}
350
364
351
365
#[ derive( Clone ) ]
352
- /// Holds late-bound channel data.
353
- /// This data is available after the channel is known to be accepted , either
354
- /// when receiving an open_channel for an inbound channel or when
355
- /// receiving accept_channel for an outbound channel.
356
- struct AcceptedChannelData {
366
+ /// Holds late-bound static channel data.
367
+ /// This data is available after the channel is readied , either
368
+ /// when receiving an funding_created for an inbound channel or when
369
+ /// creating a funding transaction for an outbound channel.
370
+ struct StaticChannelData {
357
371
/// Counterparty public keys and base points
358
372
counterparty_channel_pubkeys : ChannelPublicKeys ,
359
373
/// The contest_delay value specified by our counterparty and applied on holder-broadcastable
@@ -365,6 +379,8 @@ struct AcceptedChannelData {
365
379
/// by our counterparty, ie the amount of time that they have to wait to recover their funds
366
380
/// if they broadcast a transaction.
367
381
holder_selected_contest_delay : u16 ,
382
+ /// Whether the holder is the initiator of this channel
383
+ is_outbound : bool ,
368
384
}
369
385
370
386
#[ derive( Clone ) ]
@@ -385,7 +401,9 @@ pub struct InMemoryChannelKeys {
385
401
/// Holder public keys and basepoints
386
402
pub ( crate ) holder_channel_pubkeys : ChannelPublicKeys ,
387
403
/// Counterparty public keys and counterparty/holder selected_contest_delay, populated on channel acceptance
388
- accepted_channel_data : Option < AcceptedChannelData > ,
404
+ accepted_channel_data : Option < StaticChannelData > ,
405
+ /// Funding outpoint, populated on channel funding creation
406
+ funding_outpoint : Option < OutPoint > ,
389
407
/// The total value of this channel
390
408
channel_value_satoshis : u64 ,
391
409
/// Key derivation parameters
@@ -418,6 +436,7 @@ impl InMemoryChannelKeys {
418
436
channel_value_satoshis,
419
437
holder_channel_pubkeys,
420
438
accepted_channel_data : None ,
439
+ funding_outpoint : None ,
421
440
key_derivation_params,
422
441
}
423
442
}
@@ -439,21 +458,84 @@ impl InMemoryChannelKeys {
439
458
}
440
459
441
460
/// Counterparty pubkeys.
442
- /// Will panic if on_accept wasn't called.
461
+ /// Will panic if ready_channel wasn't called.
443
462
pub fn counterparty_pubkeys ( & self ) -> & ChannelPublicKeys { & self . accepted_channel_data . as_ref ( ) . unwrap ( ) . counterparty_channel_pubkeys }
444
463
445
464
/// The contest_delay value specified by our counterparty and applied on holder-broadcastable
446
465
/// transactions, ie the amount of time that we have to wait to recover our funds if we
447
466
/// broadcast a transaction. You'll likely want to pass this to the
448
467
/// ln::chan_utils::build*_transaction functions when signing holder's transactions.
449
- /// Will panic if on_accept wasn't called.
468
+ /// Will panic if ready_channel wasn't called.
450
469
pub fn counterparty_selected_contest_delay ( & self ) -> u16 { self . accepted_channel_data . as_ref ( ) . unwrap ( ) . counterparty_selected_contest_delay }
451
470
452
471
/// The contest_delay value specified by us and applied on transactions broadcastable
453
472
/// by our counterparty, ie the amount of time that they have to wait to recover their funds
454
473
/// if they broadcast a transaction.
455
- /// Will panic if on_accept wasn't called.
474
+ /// Will panic if ready_channel wasn't called.
456
475
pub fn holder_selected_contest_delay ( & self ) -> u16 { self . accepted_channel_data . as_ref ( ) . unwrap ( ) . holder_selected_contest_delay }
476
+
477
+ /// Whether the holder is the initiator
478
+ pub fn is_outbound ( & self ) -> bool { self . accepted_channel_data . as_ref ( ) . unwrap ( ) . is_outbound }
479
+
480
+ /// Funding outpoint
481
+ /// Will panic if ready_channel wasn't called.
482
+ pub fn funding_outpoint ( & self ) -> & OutPoint { self . funding_outpoint . as_ref ( ) . unwrap ( ) }
483
+
484
+ /// Prepare build information for a commitment tx that the holder can broadcast
485
+ pub fn build_holder_commitment_tx < T : secp256k1:: Signing + secp256k1:: Verification > (
486
+ & self ,
487
+ commitment_number : u64 ,
488
+ per_commitment_point : & PublicKey ,
489
+ to_holder_value_sat : u64 ,
490
+ to_counterparty_value_sat : u64 ,
491
+ htlcs : & Vec < HTLCOutputInCommitment > ,
492
+ secp_ctx : & Secp256k1 < T > ,
493
+ ) -> Result < ( bitcoin:: Transaction , Vec < HTLCOutputInCommitment > , TxCreationKeys , Vec < Script > ) , ( ) > {
494
+ let counterparty_points = self . counterparty_pubkeys ( ) ;
495
+
496
+ let to_holder_delayed_pubkey = derive_public_key (
497
+ & secp_ctx,
498
+ & per_commitment_point,
499
+ & self . pubkeys ( ) . delayed_payment_basepoint ,
500
+ ) . map_err ( |_| ( ) ) ?;
501
+
502
+ let revocation_pubkey = derive_public_revocation_key (
503
+ & secp_ctx,
504
+ & per_commitment_point,
505
+ & counterparty_points. revocation_basepoint ,
506
+ ) . map_err ( |_| ( ) ) ?;
507
+
508
+ let keys = TxCreationKeys :: make_tx_keys ( per_commitment_point, self . pubkeys ( ) , self . counterparty_pubkeys ( ) , secp_ctx) . unwrap ( ) ;
509
+
510
+ let info = 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
+ let obscured_commitment_transaction_number =
522
+ self . get_commitment_transaction_number_obscure_factor ( ) ^ commitment_number;
523
+ let ( tx, htlcs, scripts) = build_commitment_tx (
524
+ & keys,
525
+ & info,
526
+ obscured_commitment_transaction_number,
527
+ self . funding_outpoint ( ) . into_bitcoin_outpoint ( ) ,
528
+ ) ;
529
+ Ok ( ( tx, htlcs, keys, scripts) )
530
+ }
531
+
532
+ fn get_commitment_transaction_number_obscure_factor ( & self ) -> u64 {
533
+ get_commitment_transaction_number_obscure_factor (
534
+ & self . pubkeys ( ) . payment_point ,
535
+ & self . counterparty_pubkeys ( ) . payment_point ,
536
+ self . is_outbound ( ) ,
537
+ )
538
+ }
457
539
}
458
540
459
541
impl ChannelKeys for InMemoryChannelKeys {
@@ -507,6 +589,46 @@ impl ChannelKeys for InMemoryChannelKeys {
507
589
Ok ( holder_commitment_tx. get_holder_sig ( & self . funding_key , & channel_funding_redeemscript, self . channel_value_satoshis , secp_ctx) )
508
590
}
509
591
592
+ 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 > ) , ( ) > {
593
+ let per_commitment_point = self . get_per_commitment_point ( commitment_number, secp_ctx) ;
594
+ let ( tx, htlcs, keys, _) = self . build_holder_commitment_tx (
595
+ commitment_number,
596
+ & per_commitment_point,
597
+ to_holder_value_sat,
598
+ to_counterparty_value_sat,
599
+ htlcs,
600
+ secp_ctx,
601
+ ) ?;
602
+
603
+ let funding_pubkey = PublicKey :: from_secret_key ( secp_ctx, & self . funding_key ) ;
604
+ let funding_redeemscript = make_funding_redeemscript ( & funding_pubkey, & self . counterparty_pubkeys ( ) . funding_pubkey ) ;
605
+ let sighash = hash_to_message ! ( & bip143:: SigHashCache :: new( & tx)
606
+ . signature_hash( 0 , & funding_redeemscript, self . channel_value_satoshis, SigHashType :: All ) [ ..] ) ;
607
+ let sig = secp_ctx. sign ( & sighash, & self . funding_key ) ;
608
+
609
+ // We provide a dummy signature for the remote, since we don't require that sig
610
+ // to be passed in to this call. It would have been better if HolderCommitmentTransaction
611
+ // didn't require the remote sig.
612
+ let dummy_sig = Secp256k1 :: new ( ) . sign (
613
+ & secp256k1:: Message :: from_slice ( & [ 42 ; 32 ] ) . unwrap ( ) ,
614
+ & SecretKey :: from_slice ( & [ 42 ; 32 ] ) . unwrap ( ) ,
615
+ ) ;
616
+ let htlcs_with_sig = htlcs. iter ( ) . map ( |h| ( h. clone ( ) , Some ( dummy_sig. clone ( ) ) ) ) . collect ( ) ;
617
+ let commitment_tx = HolderCommitmentTransaction :: new_missing_holder_sig (
618
+ tx,
619
+ dummy_sig,
620
+ & self . pubkeys ( ) . funding_pubkey ,
621
+ & self . counterparty_pubkeys ( ) . funding_pubkey ,
622
+ keys,
623
+ feerate_per_kw,
624
+ htlcs_with_sig,
625
+ ) ;
626
+ let htlc_sigs_o = self . sign_holder_commitment_htlc_transactions ( & commitment_tx, secp_ctx) ?;
627
+ let htlc_sigs = htlc_sigs_o. iter ( ) . map ( |o| o. unwrap ( ) ) . collect ( ) ;
628
+
629
+ Ok ( ( sig, htlc_sigs) )
630
+ }
631
+
510
632
#[ cfg( any( test, feature = "unsafe_revoked_tx_signing" ) ) ]
511
633
fn unsafe_sign_holder_commitment < T : secp256k1:: Signing + secp256k1:: Verification > ( & self , holder_commitment_tx : & HolderCommitmentTransaction , secp_ctx : & Secp256k1 < T > ) -> Result < Signature , ( ) > {
512
634
let funding_pubkey = PublicKey :: from_secret_key ( secp_ctx, & self . funding_key ) ;
@@ -588,18 +710,21 @@ impl ChannelKeys for InMemoryChannelKeys {
588
710
Ok ( secp_ctx. sign ( & msghash, & self . funding_key ) )
589
711
}
590
712
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 " ) ;
593
- self . accepted_channel_data = Some ( AcceptedChannelData {
713
+ fn ready_channel ( & mut self , channel_pubkeys : & ChannelPublicKeys , counterparty_selected_contest_delay : u16 , holder_selected_contest_delay : u16 , is_outbound : bool , funding_outpoint : & OutPoint ) {
714
+ assert ! ( self . accepted_channel_data. is_none( ) , "Acceptance already noted " ) ;
715
+ self . accepted_channel_data = Some ( StaticChannelData {
594
716
counterparty_channel_pubkeys : channel_pubkeys. clone ( ) ,
595
717
counterparty_selected_contest_delay,
596
718
holder_selected_contest_delay,
719
+ is_outbound,
597
720
} ) ;
721
+ assert ! ( self . funding_outpoint. is_none( ) , "Funding creation already noted" ) ;
722
+ self . funding_outpoint = Some ( funding_outpoint. clone ( ) ) ;
598
723
}
599
724
}
600
725
601
- impl_writeable ! ( AcceptedChannelData , 0 ,
602
- { counterparty_channel_pubkeys, counterparty_selected_contest_delay, holder_selected_contest_delay } ) ;
726
+ impl_writeable ! ( StaticChannelData , 0 ,
727
+ { counterparty_channel_pubkeys, counterparty_selected_contest_delay, holder_selected_contest_delay, is_outbound } ) ;
603
728
604
729
impl Writeable for InMemoryChannelKeys {
605
730
fn write < W : Writer > ( & self , writer : & mut W ) -> Result < ( ) , Error > {
@@ -610,6 +735,7 @@ impl Writeable for InMemoryChannelKeys {
610
735
self . htlc_base_key . write ( writer) ?;
611
736
self . commitment_seed . write ( writer) ?;
612
737
self . accepted_channel_data . write ( writer) ?;
738
+ self . funding_outpoint . write ( writer) ?;
613
739
self . channel_value_satoshis . write ( writer) ?;
614
740
self . key_derivation_params . 0 . write ( writer) ?;
615
741
self . key_derivation_params . 1 . write ( writer) ?;
@@ -627,6 +753,7 @@ impl Readable for InMemoryChannelKeys {
627
753
let htlc_base_key = Readable :: read ( reader) ?;
628
754
let commitment_seed = Readable :: read ( reader) ?;
629
755
let counterparty_channel_data = Readable :: read ( reader) ?;
756
+ let funding_outpoint = Readable :: read ( reader) ?;
630
757
let channel_value_satoshis = Readable :: read ( reader) ?;
631
758
let secp_ctx = Secp256k1 :: signing_only ( ) ;
632
759
let holder_channel_pubkeys =
@@ -646,6 +773,7 @@ impl Readable for InMemoryChannelKeys {
646
773
channel_value_satoshis,
647
774
holder_channel_pubkeys,
648
775
accepted_channel_data : counterparty_channel_data,
776
+ funding_outpoint,
649
777
key_derivation_params : ( params_1, params_2) ,
650
778
} )
651
779
}
0 commit comments