@@ -35,7 +35,7 @@ use crate::util::transaction_utils;
3535
3636use bitcoin:: locktime:: absolute:: LockTime ;
3737use bitcoin:: ecdsa:: Signature as BitcoinSignature ;
38- use bitcoin:: secp256k1:: { SecretKey , PublicKey , Scalar } ;
38+ use bitcoin:: secp256k1:: { SecretKey , PublicKey , Scalar , Verification } ;
3939use bitcoin:: secp256k1:: { Secp256k1 , ecdsa:: Signature , Message } ;
4040use bitcoin:: { secp256k1, Sequence , Witness } ;
4141
@@ -430,6 +430,24 @@ pub fn derive_private_revocation_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1
430430 . expect ( "Addition only fails if the tweak is the inverse of the key. This is not possible when the tweak commits to the key." )
431431}
432432
433+ /// Computes the tweak to apply to the base funding key of a channel.
434+ ///
435+ /// The tweak is computed similar to existing tweaks used in
436+ /// [BOLT-3](https://github.com/lightning/bolts/blob/master/03-transactions.md#key-derivation), but
437+ /// rather than using the `per_commitment_point`, as we cannot guarantee that it will change across
438+ /// multiple splice attempts, we use the txid of the funding transaction the splice transaction is
439+ /// spending, henceforth known as the splice's parent funding txid.
440+ ///
441+ /// tweak = base_funding_key + SHA256(splice_parent_funding_txid || base_funding_pubkey)
442+ //
443+ // TODO: Expose a helper on `FundingScope` that calls this.
444+ pub fn compute_funding_key_tweak ( base_funding_pubkey : & PublicKey , splice_parent_funding_txid : & Txid ) -> Scalar {
445+ let mut sha = Sha256 :: engine ( ) ;
446+ sha. input ( splice_parent_funding_txid. as_byte_array ( ) ) ;
447+ sha. input ( & base_funding_pubkey. serialize ( ) ) ;
448+ Scalar :: from_be_bytes ( Sha256 :: from_engine ( sha) . to_byte_array ( ) ) . unwrap ( )
449+ }
450+
433451/// The set of public keys which are used in the creation of one commitment transaction.
434452/// These are derived from the channel base keys and per-commitment data.
435453///
@@ -470,7 +488,14 @@ impl_writeable_tlv_based!(TxCreationKeys, {
470488pub struct ChannelPublicKeys {
471489 /// The public key which is used to sign all commitment transactions, as it appears in the
472490 /// on-chain channel lock-in 2-of-2 multisig output.
473- pub funding_pubkey : PublicKey ,
491+ funding_pubkey : PublicKey ,
492+ /// A scalar tweak applied to the base funding key to obtain the channel's funding key used in
493+ /// the 2-of-2 multisig. This is used to derive additional keys from the same secret backing the
494+ /// base `funding_pubkey`, as we have to rotate keys for each successful splice attempt.
495+ ///
496+ /// The tweak is computed as described in [`compute_funding_key_tweak`], and it must only be set
497+ /// for holder public keys, never for counterparty ones.
498+ funding_key_tweak : Option < Scalar > ,
474499 /// The base point which is used (with [`RevocationKey::from_basepoint`]) to derive per-commitment
475500 /// revocation keys. This is combined with the per-commitment-secret generated by the
476501 /// counterparty to create a secret which the counterparty can reveal to revoke previous
@@ -489,12 +514,43 @@ pub struct ChannelPublicKeys {
489514 pub htlc_basepoint : HtlcBasepoint ,
490515}
491516
517+ impl ChannelPublicKeys {
518+ /// Constructs a new instance of [`ChannelPublicKeys`].
519+ pub fn new (
520+ funding_pubkey : PublicKey , funding_key_tweak : Option < Scalar > ,
521+ revocation_basepoint : RevocationBasepoint , payment_point : PublicKey ,
522+ delayed_payment_basepoint : DelayedPaymentBasepoint , htlc_basepoint : HtlcBasepoint ,
523+ ) -> Self {
524+ Self {
525+ funding_pubkey, funding_key_tweak, revocation_basepoint, payment_point,
526+ delayed_payment_basepoint, htlc_basepoint,
527+ }
528+ }
529+
530+ /// Returns the funding public key with the required tweak applied if one exists.
531+ pub fn funding_pubkey < C : secp256k1:: Verification > ( & self , secp : & Secp256k1 < C > ) -> PublicKey {
532+ self . funding_key_tweak
533+ . map ( |tweak| {
534+ self . funding_pubkey . add_exp_tweak ( secp, & tweak) . expect (
535+ "Addition only fails if the tweak is the inverse of the key"
536+ )
537+ } )
538+ . unwrap_or ( self . funding_pubkey )
539+ }
540+
541+ /// Returns the tweak, if one exists, to apply to the funding key.
542+ pub fn funding_key_tweak ( & self ) -> Option < Scalar > {
543+ self . funding_key_tweak
544+ }
545+ }
546+
492547impl_writeable_tlv_based ! ( ChannelPublicKeys , {
493548 ( 0 , funding_pubkey, required) ,
494549 ( 2 , revocation_basepoint, required) ,
495550 ( 4 , payment_point, required) ,
496551 ( 6 , delayed_payment_basepoint, required) ,
497552 ( 8 , htlc_basepoint, required) ,
553+ ( 10 , funding_key_tweak, option) ,
498554} ) ;
499555
500556impl TxCreationKeys {
@@ -931,10 +987,10 @@ impl ChannelTransactionParameters {
931987 }
932988 }
933989
934- pub ( crate ) fn make_funding_redeemscript ( & self ) -> ScriptBuf {
990+ pub ( crate ) fn make_funding_redeemscript < C : Verification > ( & self , secp : & Secp256k1 < C > ) -> ScriptBuf {
935991 make_funding_redeemscript (
936- & self . holder_pubkeys . funding_pubkey ,
937- & self . counterparty_parameters . as_ref ( ) . unwrap ( ) . pubkeys . funding_pubkey
992+ & self . holder_pubkeys . funding_pubkey ( secp ) ,
993+ & self . counterparty_parameters . as_ref ( ) . unwrap ( ) . pubkeys . funding_pubkey ( & secp )
938994 )
939995 }
940996
@@ -945,13 +1001,13 @@ impl ChannelTransactionParameters {
9451001
9461002 #[ cfg( test) ]
9471003 pub fn test_dummy ( channel_value_satoshis : u64 ) -> Self {
948- let dummy_keys = ChannelPublicKeys {
949- funding_pubkey : PublicKey :: from_slice ( & [ 2 ; 33 ] ) . unwrap ( ) ,
950- revocation_basepoint : PublicKey :: from_slice ( & [ 2 ; 33 ] ) . unwrap ( ) . into ( ) ,
951- payment_point : PublicKey :: from_slice ( & [ 2 ; 33 ] ) . unwrap ( ) ,
952- delayed_payment_basepoint : PublicKey :: from_slice ( & [ 2 ; 33 ] ) . unwrap ( ) . into ( ) ,
953- htlc_basepoint : PublicKey :: from_slice ( & [ 2 ; 33 ] ) . unwrap ( ) . into ( ) ,
954- } ;
1004+ let dummy_keys = ChannelPublicKeys :: new (
1005+ PublicKey :: from_slice ( & [ 2 ; 33 ] ) . unwrap ( ) , None ,
1006+ PublicKey :: from_slice ( & [ 2 ; 33 ] ) . unwrap ( ) . into ( ) ,
1007+ PublicKey :: from_slice ( & [ 2 ; 33 ] ) . unwrap ( ) ,
1008+ PublicKey :: from_slice ( & [ 2 ; 33 ] ) . unwrap ( ) . into ( ) ,
1009+ PublicKey :: from_slice ( & [ 2 ; 33 ] ) . unwrap ( ) . into ( ) ,
1010+ ) ;
9551011 Self {
9561012 holder_pubkeys : dummy_keys. clone ( ) ,
9571013 holder_selected_contest_delay : 42 ,
@@ -1136,13 +1192,10 @@ impl HolderCommitmentTransaction {
11361192 countersignatory_htlc_key : HtlcKey :: from_basepoint ( & secp_ctx, & HtlcBasepoint :: from ( dummy_key) , & dummy_key) ,
11371193 broadcaster_delayed_payment_key : DelayedPaymentKey :: from_basepoint ( & secp_ctx, & DelayedPaymentBasepoint :: from ( dummy_key) , & dummy_key) ,
11381194 } ;
1139- let channel_pubkeys = ChannelPublicKeys {
1140- funding_pubkey : dummy_key. clone ( ) ,
1141- revocation_basepoint : RevocationBasepoint :: from ( dummy_key) ,
1142- payment_point : dummy_key. clone ( ) ,
1143- delayed_payment_basepoint : DelayedPaymentBasepoint :: from ( dummy_key. clone ( ) ) ,
1144- htlc_basepoint : HtlcBasepoint :: from ( dummy_key. clone ( ) )
1145- } ;
1195+ let channel_pubkeys = ChannelPublicKeys :: new (
1196+ dummy_key. clone ( ) , None , RevocationBasepoint :: from ( dummy_key) , dummy_key. clone ( ) ,
1197+ DelayedPaymentBasepoint :: from ( dummy_key. clone ( ) ) , HtlcBasepoint :: from ( dummy_key. clone ( ) )
1198+ ) ;
11461199 let channel_parameters = ChannelTransactionParameters {
11471200 holder_pubkeys : channel_pubkeys. clone ( ) ,
11481201 holder_selected_contest_delay : 0 ,
0 commit comments