Remove SecretKey from DynamicOuputP2WPKH descriptor
authorAntoine Riard <ariard@student.42.fr>
Tue, 24 Mar 2020 21:03:26 +0000 (17:03 -0400)
committerAntoine Riard <ariard@student.42.fr>
Thu, 28 May 2020 08:21:47 +0000 (04:21 -0400)
Add sign_payment_transaction in ChanSigner to be able to spend
SpendableOutputDescriptor in test framework

Extend ChannelKeys with remote_pubkeys to access remote revocation
basepoint for witnessScript construction.

lightning/src/chain/keysinterface.rs
lightning/src/ln/channelmonitor.rs
lightning/src/ln/functional_tests.rs

index 3a9c8168439852cfcfda719e2edfc2589701f158..ce92d1462ee3390837465c08bc5794721da36903 100644 (file)
@@ -7,6 +7,7 @@ use bitcoin::blockdata::script::{Script, Builder};
 use bitcoin::blockdata::opcodes;
 use bitcoin::network::constants::Network;
 use bitcoin::util::bip32::{ExtendedPrivKey, ExtendedPubKey, ChildNumber};
+use bitcoin::util::address::Address;
 use bitcoin::util::bip143;
 
 use bitcoin::hashes::{Hash, HashEngine};
@@ -88,16 +89,23 @@ pub enum SpendableOutputDescriptor {
        // this in favor of StaticOutput:
        /// An output to a P2WPKH, spendable exclusively by the given private key.
        /// The witness in the spending input, is, thus, simply:
-       /// <BIP 143 signature generated with the given key> <public key derived from the given key>
+       /// <BIP 143 signature> <payment key>
+       ///
        /// These are generally the result of our counterparty having broadcast the current state,
        /// allowing us to claim the non-HTLC-encumbered outputs immediately.
+       ///
+       /// To derive the payment key corresponding to the channel state, you must pass the
+       /// channel's payment_base_key and the provided per_commitment_point to
+       /// chan_utils::derive_private_key. The resulting key should be used to sign the spending
+       /// transaction.
        DynamicOutputP2WPKH {
                /// The outpoint which is spendable
                outpoint: OutPoint,
-               /// The secret key which must be used to sign the spending transaction
-               key: SecretKey,
                /// The output which is reference by the given outpoint
                output: TxOut,
+               /// The channel keys state used to proceed to derivation of signing key. Must
+               /// be pass to KeysInterface::derive_channel_keys.
+               key_derivation_params: (u64, u64),
        }
 }
 
@@ -119,11 +127,12 @@ impl Writeable for SpendableOutputDescriptor {
                                key_derivation_params.1.write(writer)?;
                                remote_revocation_pubkey.write(writer)?;
                        },
-                       &SpendableOutputDescriptor::DynamicOutputP2WPKH { ref outpoint, ref key, ref output } => {
+                       &SpendableOutputDescriptor::DynamicOutputP2WPKH { ref outpoint, ref output, ref key_derivation_params } => {
                                2u8.write(writer)?;
                                outpoint.write(writer)?;
-                               key.write(writer)?;
                                output.write(writer)?;
+                               key_derivation_params.0.write(writer)?;
+                               key_derivation_params.1.write(writer)?;
                        },
                }
                Ok(())
@@ -147,8 +156,8 @@ impl Readable for SpendableOutputDescriptor {
                        }),
                        2u8 => Ok(SpendableOutputDescriptor::DynamicOutputP2WPKH {
                                outpoint: Readable::read(reader)?,
-                               key: Readable::read(reader)?,
                                output: Readable::read(reader)?,
+                               key_derivation_params: (Readable::read(reader)?, Readable::read(reader)?),
                        }),
                        _ => Err(DecodeError::InvalidValue),
                }
@@ -396,6 +405,8 @@ impl InMemoryChannelKeys {
                        htlc_basepoint: from_secret(&htlc_base_key),
                }
        }
+
+       fn remote_pubkeys<'a>(&'a self) -> &'a ChannelPublicKeys { self.remote_channel_pubkeys.as_ref().unwrap() }
 }
 
 impl ChannelKeys for InMemoryChannelKeys {
index 526a36237e051de7bb84225a7ee22c891e403482..f90017bb8f0297fef362a6f0d289068616da8aa9 100644 (file)
@@ -2130,8 +2130,8 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
                        } else if self.remote_payment_script == outp.script_pubkey {
                                spendable_output = Some(SpendableOutputDescriptor::DynamicOutputP2WPKH {
                                        outpoint: BitcoinOutPoint { txid: tx.txid(), vout: i as u32 },
-                                       key: self.keys.payment_key().clone(),
                                        output: outp.clone(),
+                                       key_derivation_params: self.keys.key_derivation_params(),
                                });
                                break;
                        } else if outp.script_pubkey == self.shutdown_script {
index 1bc38faa28b7bc13e7e1a16aa021241bcc6d7937..3e4eaaa03837757f271672974ce5bc878fa6a1de 100644 (file)
@@ -4274,7 +4274,7 @@ macro_rules! check_spendable_outputs {
                                        Event::SpendableOutputs { ref outputs } => {
                                                for outp in outputs {
                                                        match *outp {
-                                                               SpendableOutputDescriptor::DynamicOutputP2WPKH { ref outpoint, ref key, ref output } => {
+                                                               SpendableOutputDescriptor::DynamicOutputP2WPKH { ref outpoint, ref output, ref key_derivation_params } => {
                                                                        let input = TxIn {
                                                                                previous_output: outpoint.clone(),
                                                                                script_sig: Script::new(),
@@ -4292,10 +4292,11 @@ macro_rules! check_spendable_outputs {
                                                                                output: vec![outp],
                                                                        };
                                                                        let secp_ctx = Secp256k1::new();
-                                                                       let remotepubkey = PublicKey::from_secret_key(&secp_ctx, &key);
+                                                                       let keys = $keysinterface.derive_channel_keys($chan_value, key_derivation_params.0, key_derivation_params.1);
+                                                                       let remotepubkey = PublicKey::from_secret_key(&secp_ctx, &keys.payment_key());
                                                                        let witness_script = Address::p2pkh(&::bitcoin::PublicKey{compressed: true, key: remotepubkey}, Network::Testnet).script_pubkey();
                                                                        let sighash = Message::from_slice(&bip143::SighashComponents::new(&spend_tx).sighash_all(&spend_tx.input[0], &witness_script, output.value)[..]).unwrap();
-                                                                       let remotesig = secp_ctx.sign(&sighash, key);
+                                                                       let remotesig = secp_ctx.sign(&sighash, &keys.payment_key());
                                                                        spend_tx.input[0].witness.push(remotesig.serialize_der().to_vec());
                                                                        spend_tx.input[0].witness[0].push(SigHashType::All as u8);
                                                                        spend_tx.input[0].witness.push(remotepubkey.serialize().to_vec());