Enforce signing counterparty commitment only after revocation
[rust-lightning] / lightning / src / chain / keysinterface.rs
index 114ceec211cd254fb22d14f64ac379960237f59b..d912740a019a8a6bb215081c94bd084dde380dc0 100644 (file)
@@ -36,10 +36,11 @@ use chain::transaction::OutPoint;
 use ln::chan_utils;
 use ln::chan_utils::{HTLCOutputInCommitment, make_funding_redeemscript, ChannelPublicKeys, HolderCommitmentTransaction, ChannelTransactionParameters, CommitmentTransaction};
 use ln::msgs::UnsignedChannelAnnouncement;
+use ln::script::ShutdownScript;
 
-use std::collections::HashSet;
+use prelude::*;
 use core::sync::atomic::{AtomicUsize, Ordering};
-use std::io::Error;
+use io::{self, Error};
 use ln::msgs::{DecodeError, MAX_VALUE_MSAT};
 
 /// Information about a spendable output to a P2WSH script. See
@@ -72,6 +73,16 @@ impl DelayedPaymentOutputDescriptor {
        pub const MAX_WITNESS_LENGTH: usize = 1 + 73 + 1 + chan_utils::REVOKEABLE_REDEEMSCRIPT_MAX_LENGTH + 1;
 }
 
+impl_writeable_tlv_based!(DelayedPaymentOutputDescriptor, {
+       (0, outpoint, required),
+       (2, per_commitment_point, required),
+       (4, to_self_delay, required),
+       (6, output, required),
+       (8, revocation_pubkey, required),
+       (10, channel_keys_id, required),
+       (12, channel_value_satoshis, required),
+});
+
 /// Information about a spendable output to our "payment key". See
 /// SpendableOutputDescriptor::StaticPaymentOutput for more details on how to spend this.
 #[derive(Clone, Debug, PartialEq)]
@@ -93,6 +104,12 @@ impl StaticPaymentOutputDescriptor {
        // redeemscript push length.
        pub const MAX_WITNESS_LENGTH: usize = 1 + 73 + 34;
 }
+impl_writeable_tlv_based!(StaticPaymentOutputDescriptor, {
+       (0, outpoint, required),
+       (2, output, required),
+       (4, channel_keys_id, required),
+       (6, channel_value_satoshis, required),
+});
 
 /// When on-chain outputs are created by rust-lightning (which our counterparty is not able to
 /// claim at any point in the future) an event is generated which you must track and be able to
@@ -102,8 +119,8 @@ impl StaticPaymentOutputDescriptor {
 #[derive(Clone, Debug, PartialEq)]
 pub enum SpendableOutputDescriptor {
        /// An output to a script which was provided via KeysInterface directly, either from
-       /// `get_destination_script()` or `get_shutdown_pubkey()`, thus you should already know how to
-       /// spend it. No secret keys are provided as rust-lightning was never given any key.
+       /// `get_destination_script()` or `get_shutdown_scriptpubkey()`, thus you should already know
+       /// how to spend it. No secret keys are provided as rust-lightning was never given any key.
        /// These may include outputs from a transaction punishing our counterparty or claiming an HTLC
        /// on-chain using the payment preimage or after it has timed out.
        StaticOutput {
@@ -151,62 +168,15 @@ pub enum SpendableOutputDescriptor {
        StaticPaymentOutput(StaticPaymentOutputDescriptor),
 }
 
-impl Writeable for SpendableOutputDescriptor {
-       fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
-               match self {
-                       &SpendableOutputDescriptor::StaticOutput { ref outpoint, ref output } => {
-                               0u8.write(writer)?;
-                               outpoint.write(writer)?;
-                               output.write(writer)?;
-                       },
-                       &SpendableOutputDescriptor::DelayedPaymentOutput(ref descriptor) => {
-                               1u8.write(writer)?;
-                               descriptor.outpoint.write(writer)?;
-                               descriptor.per_commitment_point.write(writer)?;
-                               descriptor.to_self_delay.write(writer)?;
-                               descriptor.output.write(writer)?;
-                               descriptor.revocation_pubkey.write(writer)?;
-                               descriptor.channel_keys_id.write(writer)?;
-                               descriptor.channel_value_satoshis.write(writer)?;
-                       },
-                       &SpendableOutputDescriptor::StaticPaymentOutput(ref descriptor) => {
-                               2u8.write(writer)?;
-                               descriptor.outpoint.write(writer)?;
-                               descriptor.output.write(writer)?;
-                               descriptor.channel_keys_id.write(writer)?;
-                               descriptor.channel_value_satoshis.write(writer)?;
-                       },
-               }
-               Ok(())
-       }
-}
-
-impl Readable for SpendableOutputDescriptor {
-       fn read<R: ::std::io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
-               match Readable::read(reader)? {
-                       0u8 => Ok(SpendableOutputDescriptor::StaticOutput {
-                               outpoint: Readable::read(reader)?,
-                               output: Readable::read(reader)?,
-                       }),
-                       1u8 => Ok(SpendableOutputDescriptor::DelayedPaymentOutput(DelayedPaymentOutputDescriptor {
-                               outpoint: Readable::read(reader)?,
-                               per_commitment_point: Readable::read(reader)?,
-                               to_self_delay: Readable::read(reader)?,
-                               output: Readable::read(reader)?,
-                               revocation_pubkey: Readable::read(reader)?,
-                               channel_keys_id: Readable::read(reader)?,
-                               channel_value_satoshis: Readable::read(reader)?,
-                       })),
-                       2u8 => Ok(SpendableOutputDescriptor::StaticPaymentOutput(StaticPaymentOutputDescriptor {
-                               outpoint: Readable::read(reader)?,
-                               output: Readable::read(reader)?,
-                               channel_keys_id: Readable::read(reader)?,
-                               channel_value_satoshis: Readable::read(reader)?,
-                       })),
-                       _ => Err(DecodeError::InvalidValue),
-               }
-       }
-}
+impl_writeable_tlv_based_enum!(SpendableOutputDescriptor,
+       (0, StaticOutput) => {
+               (0, outpoint, required),
+               (2, output, required),
+       },
+;
+       (1, DelayedPaymentOutput),
+       (2, StaticPaymentOutput),
+);
 
 /// A trait to sign lightning channel transactions as described in BOLT 3.
 ///
@@ -242,6 +212,11 @@ pub trait BaseSign {
        /// Note that the commitment number starts at (1 << 48) - 1 and counts backwards.
        // TODO: return a Result so we can signal a validation error
        fn release_commitment_secret(&self, idx: u64) -> [u8; 32];
+       /// Validate the counterparty's signatures on the holder commitment transaction and HTLCs.
+       ///
+       /// This is required in order for the signer to make sure that releasing a commitment
+       /// secret won't leave us without a broadcastable holder transaction.
+       fn validate_holder_commitment(&self, holder_tx: &HolderCommitmentTransaction);
        /// Gets the holder's channel public keys and basepoints
        fn pubkeys(&self) -> &ChannelPublicKeys;
        /// Gets an arbitrary identifier describing the set of keys which are provided back to you in
@@ -255,6 +230,11 @@ pub trait BaseSign {
        //
        // TODO: Document the things someone using this interface should enforce before signing.
        fn sign_counterparty_commitment(&self, commitment_tx: &CommitmentTransaction, secp_ctx: &Secp256k1<secp256k1::All>) -> Result<(Signature, Vec<Signature>), ()>;
+       /// Validate the counterparty's revocation.
+       ///
+       /// This is required in order for the signer to make sure that the state has moved
+       /// forward and it is safe to sign the next counterparty commitment.
+       fn validate_counterparty_revocation(&self, idx: u64, secret: &SecretKey);
 
        /// Create a signatures for a holder's commitment transaction and its claiming HTLC transactions.
        /// This will only ever be called with a non-revoked commitment_tx.  This will be called with the
@@ -382,12 +362,11 @@ pub trait KeysInterface {
        /// This method should return a different value each time it is called, to avoid linking
        /// on-chain funds across channels as controlled to the same user.
        fn get_destination_script(&self) -> Script;
-       /// Get a public key which we will send funds to (in the form of a P2WPKH output) when closing
-       /// a channel.
+       /// Get a script pubkey which we will send funds to when closing a channel.
        ///
        /// This method should return a different value each time it is called, to avoid linking
        /// on-chain funds across channels as controlled to the same user.
-       fn get_shutdown_pubkey(&self) -> PublicKey;
+       fn get_shutdown_scriptpubkey(&self) -> ShutdownScript;
        /// Get a new set of Sign for per-channel secrets. These MUST be unique even if you
        /// restarted with some stale data!
        ///
@@ -589,6 +568,9 @@ impl BaseSign for InMemorySigner {
                chan_utils::build_commitment_secret(&self.commitment_seed, idx)
        }
 
+       fn validate_holder_commitment(&self, _holder_tx: &HolderCommitmentTransaction) {
+       }
+
        fn pubkeys(&self) -> &ChannelPublicKeys { &self.holder_channel_pubkeys }
        fn channel_keys_id(&self) -> [u8; 32] { self.channel_keys_id }
 
@@ -615,6 +597,9 @@ impl BaseSign for InMemorySigner {
                Ok((commitment_sig, htlc_sigs))
        }
 
+       fn validate_counterparty_revocation(&self, _idx: u64, _secret: &SecretKey) {
+       }
+
        fn sign_holder_commitment_and_htlcs(&self, commitment_tx: &HolderCommitmentTransaction, secp_ctx: &Secp256k1<secp256k1::All>) -> Result<(Signature, Vec<Signature>), ()> {
                let funding_pubkey = PublicKey::from_secret_key(secp_ctx, &self.funding_key);
                let funding_redeemscript = make_funding_redeemscript(&funding_pubkey, &self.counterparty_pubkeys().funding_pubkey);
@@ -704,10 +689,15 @@ impl BaseSign for InMemorySigner {
        }
 }
 
+const SERIALIZATION_VERSION: u8 = 1;
+const MIN_SERIALIZATION_VERSION: u8 = 1;
+
 impl Sign for InMemorySigner {}
 
 impl Writeable for InMemorySigner {
        fn write<W: Writer>(&self, writer: &mut W) -> Result<(), Error> {
+               write_ver_prefix!(writer, SERIALIZATION_VERSION, MIN_SERIALIZATION_VERSION);
+
                self.funding_key.write(writer)?;
                self.revocation_base_key.write(writer)?;
                self.payment_key.write(writer)?;
@@ -718,12 +708,16 @@ impl Writeable for InMemorySigner {
                self.channel_value_satoshis.write(writer)?;
                self.channel_keys_id.write(writer)?;
 
+               write_tlv_fields!(writer, {});
+
                Ok(())
        }
 }
 
 impl Readable for InMemorySigner {
-       fn read<R: ::std::io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
+       fn read<R: io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
+               let _ver = read_ver_prefix!(reader, SERIALIZATION_VERSION);
+
                let funding_key = Readable::read(reader)?;
                let revocation_base_key = Readable::read(reader)?;
                let payment_key = Readable::read(reader)?;
@@ -739,6 +733,8 @@ impl Readable for InMemorySigner {
                                                             &htlc_base_key);
                let keys_id = Readable::read(reader)?;
 
+               read_tlv_fields!(reader, {});
+
                Ok(InMemorySigner {
                        funding_key,
                        revocation_base_key,
@@ -1033,8 +1029,8 @@ impl KeysInterface for KeysManager {
                self.destination_script.clone()
        }
 
-       fn get_shutdown_pubkey(&self) -> PublicKey {
-               self.shutdown_pubkey.clone()
+       fn get_shutdown_scriptpubkey(&self) -> ShutdownScript {
+               ShutdownScript::new_p2wpkh_from_pubkey(self.shutdown_pubkey.clone())
        }
 
        fn get_channel_signer(&self, _inbound: bool, channel_value_satoshis: u64) -> Self::Signer {
@@ -1059,7 +1055,7 @@ impl KeysInterface for KeysManager {
        }
 
        fn read_chan_signer(&self, reader: &[u8]) -> Result<Self::Signer, DecodeError> {
-               InMemorySigner::read(&mut std::io::Cursor::new(reader))
+               InMemorySigner::read(&mut io::Cursor::new(reader))
        }
 
        fn sign_invoice(&self, invoice_preimage: Vec<u8>) -> Result<RecoverableSignature, ()> {