From 2c07f8e794659d8be22437516a4185042256f7bf Mon Sep 17 00:00:00 2001 From: Antoine Riard Date: Tue, 24 Mar 2020 17:03:26 -0400 Subject: [PATCH] Remove SecretKey from DynamicOuputP2WPKH descriptor 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 | 23 +++++++++++++++++------ lightning/src/ln/channelmonitor.rs | 2 +- lightning/src/ln/functional_tests.rs | 7 ++++--- 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/lightning/src/chain/keysinterface.rs b/lightning/src/chain/keysinterface.rs index 3a9c8168..ce92d146 100644 --- a/lightning/src/chain/keysinterface.rs +++ b/lightning/src/chain/keysinterface.rs @@ -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: - /// + /// + /// /// 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 { diff --git a/lightning/src/ln/channelmonitor.rs b/lightning/src/ln/channelmonitor.rs index 526a3623..f90017bb 100644 --- a/lightning/src/ln/channelmonitor.rs +++ b/lightning/src/ln/channelmonitor.rs @@ -2130,8 +2130,8 @@ impl ChannelMonitor { } 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 { diff --git a/lightning/src/ln/functional_tests.rs b/lightning/src/ln/functional_tests.rs index 1bc38faa..3e4eaaa0 100644 --- a/lightning/src/ln/functional_tests.rs +++ b/lightning/src/ln/functional_tests.rs @@ -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()); -- 2.30.2