Add annotations for things which we cannot (yet) expose
[rust-lightning] / lightning / src / chain / keysinterface.rs
index 26d1f07c7c43c38fc378d42431ffa2dde190ab92..3c115bc770bf24ab8fe12cd7947cfddc42edb8d0 100644 (file)
@@ -1,8 +1,17 @@
+// This file is Copyright its original authors, visible in version control
+// history.
+//
+// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
+// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
+// You may not use this file except in accordance with one or both of these
+// licenses.
+
 //! keysinterface provides keys into rust-lightning and defines some useful enums which describe
 //! spendable on-chain outputs which the user owns and is responsible for using just as any other
 //! on-chain output which is theirs.
 
-use bitcoin::blockdata::transaction::{Transaction, OutPoint, TxOut};
+use bitcoin::blockdata::transaction::{Transaction, TxOut, SigHashType};
 use bitcoin::blockdata::script::{Script, Builder};
 use bitcoin::blockdata::opcodes;
 use bitcoin::network::constants::Network;
@@ -22,9 +31,10 @@ use bitcoin::secp256k1;
 use util::byte_utils;
 use util::ser::{Writeable, Writer, Readable};
 
+use chain::transaction::OutPoint;
 use ln::chan_utils;
-use ln::chan_utils::{TxCreationKeys, HTLCOutputInCommitment, make_funding_redeemscript, ChannelPublicKeys, LocalCommitmentTransaction};
-use ln::msgs;
+use ln::chan_utils::{HTLCOutputInCommitment, make_funding_redeemscript, ChannelPublicKeys, LocalCommitmentTransaction, PreCalculatedTxCreationKeys};
+use ln::msgs::UnsignedChannelAnnouncement;
 
 use std::sync::atomic::{AtomicUsize, Ordering};
 use std::io::Error;
@@ -223,7 +233,7 @@ pub trait ChannelKeys : Send+Clone {
        // TODO: Document the things someone using this interface should enforce before signing.
        // TODO: Add more input vars to enable better checking (preferably removing commitment_tx and
        // making the callee generate it via some util function we expose)!
-       fn sign_remote_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, feerate_per_kw: u32, commitment_tx: &Transaction, keys: &TxCreationKeys, htlcs: &[&HTLCOutputInCommitment], secp_ctx: &Secp256k1<T>) -> Result<(Signature, Vec<Signature>), ()>;
+       fn sign_remote_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, feerate_per_kw: u32, commitment_tx: &Transaction, keys: &PreCalculatedTxCreationKeys, htlcs: &[&HTLCOutputInCommitment], secp_ctx: &Secp256k1<T>) -> Result<(Signature, Vec<Signature>), ()>;
 
        /// Create a signature for a local commitment transaction. This will only ever be called with
        /// the same local_commitment_tx (or a copy thereof), though there are currently no guarantees
@@ -238,7 +248,7 @@ pub trait ChannelKeys : Send+Clone {
        /// transactions which will be broadcasted later, after the channel has moved on to a newer
        /// state. Thus, needs its own method as sign_local_commitment may enforce that we only ever
        /// get called once.
-       #[cfg(test)]
+       #[cfg(any(test,feature = "unsafe_revoked_tx_signing"))]
        fn unsafe_sign_local_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, local_commitment_tx: &LocalCommitmentTransaction, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()>;
 
        /// Create a signature for each HTLC transaction spending a local commitment transaction.
@@ -307,7 +317,7 @@ pub trait ChannelKeys : Send+Clone {
        /// Note that if this fails or is rejected, the channel will not be publicly announced and
        /// our counterparty may (though likely will not) close the channel on us for violating the
        /// protocol.
-       fn sign_channel_announcement<T: secp256k1::Signing>(&self, msg: &msgs::UnsignedChannelAnnouncement, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()>;
+       fn sign_channel_announcement<T: secp256k1::Signing>(&self, msg: &UnsignedChannelAnnouncement, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()>;
 
        /// Set the remote channel basepoints and remote/local to_self_delay.
        /// This is done immediately on incoming channels and as soon as the channel is accepted on outgoing channels.
@@ -332,12 +342,10 @@ pub trait KeysInterface: Send + Sync {
        /// Get a new set of ChannelKeys for per-channel secrets. These MUST be unique even if you
        /// restarted with some stale data!
        fn get_channel_keys(&self, inbound: bool, channel_value_satoshis: u64) -> Self::ChanKeySigner;
-       /// Get a secret and PRNG seed for constructing an onion packet
-       fn get_onion_rand(&self) -> (SecretKey, [u8; 32]);
-       /// Get a unique temporary channel id. Channels will be referred to by this until the funding
-       /// transaction is created, at which point they will use the outpoint in the funding
-       /// transaction.
-       fn get_channel_id(&self) -> [u8; 32];
+       /// Gets a unique, cryptographically-secure, random 32 byte value. This is used for encrypting
+       /// onion packets and for temporary channel IDs. There is no requirement that these be
+       /// persisted anywhere, though they must be unique across restarts.
+       fn get_secure_random_bytes(&self) -> [u8; 32];
 }
 
 #[derive(Clone)]
@@ -461,14 +469,15 @@ impl ChannelKeys for InMemoryChannelKeys {
        fn pubkeys(&self) -> &ChannelPublicKeys { &self.local_channel_pubkeys }
        fn key_derivation_params(&self) -> (u64, u64) { self.key_derivation_params }
 
-       fn sign_remote_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, feerate_per_kw: u32, commitment_tx: &Transaction, keys: &TxCreationKeys, htlcs: &[&HTLCOutputInCommitment], secp_ctx: &Secp256k1<T>) -> Result<(Signature, Vec<Signature>), ()> {
+       fn sign_remote_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, feerate_per_kw: u32, commitment_tx: &Transaction, pre_keys: &PreCalculatedTxCreationKeys, htlcs: &[&HTLCOutputInCommitment], secp_ctx: &Secp256k1<T>) -> Result<(Signature, Vec<Signature>), ()> {
                if commitment_tx.input.len() != 1 { return Err(()); }
+               let keys = pre_keys.trust_key_derivation();
 
                let funding_pubkey = PublicKey::from_secret_key(secp_ctx, &self.funding_key);
                let accepted_data = self.accepted_channel_data.as_ref().expect("must accept before signing");
                let channel_funding_redeemscript = make_funding_redeemscript(&funding_pubkey, &accepted_data.remote_channel_pubkeys.funding_pubkey);
 
-               let commitment_sighash = hash_to_message!(&bip143::SighashComponents::new(&commitment_tx).sighash_all(&commitment_tx.input[0], &channel_funding_redeemscript, self.channel_value_satoshis)[..]);
+               let commitment_sighash = hash_to_message!(&bip143::SigHashCache::new(commitment_tx).signature_hash(0, &channel_funding_redeemscript, self.channel_value_satoshis, SigHashType::All)[..]);
                let commitment_sig = secp_ctx.sign(&commitment_sighash, &self.funding_key);
 
                let commitment_txid = commitment_tx.txid();
@@ -478,7 +487,7 @@ impl ChannelKeys for InMemoryChannelKeys {
                        if let Some(_) = htlc.transaction_output_index {
                                let htlc_tx = chan_utils::build_htlc_transaction(&commitment_txid, feerate_per_kw, accepted_data.local_to_self_delay, htlc, &keys.a_delayed_payment_key, &keys.revocation_key);
                                let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &keys);
-                               let htlc_sighash = hash_to_message!(&bip143::SighashComponents::new(&htlc_tx).sighash_all(&htlc_tx.input[0], &htlc_redeemscript, htlc.amount_msat / 1000)[..]);
+                               let htlc_sighash = hash_to_message!(&bip143::SigHashCache::new(&htlc_tx).signature_hash(0, &htlc_redeemscript, htlc.amount_msat / 1000, SigHashType::All)[..]);
                                let our_htlc_key = match chan_utils::derive_private_key(&secp_ctx, &keys.per_commitment_point, &self.htlc_base_key) {
                                        Ok(s) => s,
                                        Err(_) => return Err(()),
@@ -498,7 +507,7 @@ impl ChannelKeys for InMemoryChannelKeys {
                Ok(local_commitment_tx.get_local_sig(&self.funding_key, &channel_funding_redeemscript, self.channel_value_satoshis, secp_ctx))
        }
 
-       #[cfg(test)]
+       #[cfg(any(test,feature = "unsafe_revoked_tx_signing"))]
        fn unsafe_sign_local_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, local_commitment_tx: &LocalCommitmentTransaction, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()> {
                let funding_pubkey = PublicKey::from_secret_key(secp_ctx, &self.funding_key);
                let remote_channel_pubkeys = &self.accepted_channel_data.as_ref().expect("must accept before signing").remote_channel_pubkeys;
@@ -539,8 +548,8 @@ impl ChannelKeys for InMemoryChannelKeys {
                        };
                        chan_utils::get_revokeable_redeemscript(&revocation_pubkey, self.local_to_self_delay(), &remote_delayedpubkey)
                };
-               let sighash_parts = bip143::SighashComponents::new(&justice_tx);
-               let sighash = hash_to_message!(&sighash_parts.sighash_all(&justice_tx.input[input], &witness_script, amount)[..]);
+               let mut sighash_parts = bip143::SigHashCache::new(justice_tx);
+               let sighash = hash_to_message!(&sighash_parts.signature_hash(input, &witness_script, amount, SigHashType::All)[..]);
                return Ok(secp_ctx.sign(&sighash, &revocation_key))
        }
 
@@ -553,8 +562,8 @@ impl ChannelKeys for InMemoryChannelKeys {
                                        } else { return Err(()) }
                                } else { return Err(()) }
                        } else { return Err(()) };
-                       let sighash_parts = bip143::SighashComponents::new(&htlc_tx);
-                       let sighash = hash_to_message!(&sighash_parts.sighash_all(&htlc_tx.input[input], &witness_script, amount)[..]);
+                       let mut sighash_parts = bip143::SigHashCache::new(htlc_tx);
+                       let sighash = hash_to_message!(&sighash_parts.signature_hash(input, &witness_script, amount, SigHashType::All)[..]);
                        return Ok(secp_ctx.sign(&sighash, &htlc_key))
                }
                Err(())
@@ -569,12 +578,12 @@ impl ChannelKeys for InMemoryChannelKeys {
                let remote_channel_data = self.accepted_channel_data.as_ref().expect("must accept before signing");
                let channel_funding_redeemscript = make_funding_redeemscript(&funding_pubkey, &remote_channel_data.remote_channel_pubkeys.funding_pubkey);
 
-               let sighash = hash_to_message!(&bip143::SighashComponents::new(closing_tx)
-                       .sighash_all(&closing_tx.input[0], &channel_funding_redeemscript, self.channel_value_satoshis)[..]);
+               let sighash = hash_to_message!(&bip143::SigHashCache::new(closing_tx)
+                       .signature_hash(0, &channel_funding_redeemscript, self.channel_value_satoshis, SigHashType::All)[..]);
                Ok(secp_ctx.sign(&sighash, &self.funding_key))
        }
 
-       fn sign_channel_announcement<T: secp256k1::Signing>(&self, msg: &msgs::UnsignedChannelAnnouncement, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()> {
+       fn sign_channel_announcement<T: secp256k1::Signing>(&self, msg: &UnsignedChannelAnnouncement, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()> {
                let msghash = hash_to_message!(&Sha256dHash::hash(&msg.encode()[..])[..]);
                Ok(secp_ctx.sign(&msghash, &self.funding_key))
        }
@@ -656,10 +665,8 @@ pub struct KeysManager {
        shutdown_pubkey: PublicKey,
        channel_master_key: ExtendedPrivKey,
        channel_child_index: AtomicUsize,
-       session_master_key: ExtendedPrivKey,
-       session_child_index: AtomicUsize,
-       channel_id_master_key: ExtendedPrivKey,
-       channel_id_child_index: AtomicUsize,
+       rand_bytes_master_key: ExtendedPrivKey,
+       rand_bytes_child_index: AtomicUsize,
 
        seed: [u8; 32],
        starting_time_secs: u64,
@@ -668,7 +675,7 @@ pub struct KeysManager {
 
 impl KeysManager {
        /// Constructs a KeysManager from a 32-byte seed. If the seed is in some way biased (eg your
-       /// RNG is busted) this may panic (but more importantly, you will possibly lose funds).
+       /// CSRNG is busted) this may panic (but more importantly, you will possibly lose funds).
        /// starting_time isn't strictly required to actually be a time, but it must absolutely,
        /// without a doubt, be unique to this instance. ie if you start multiple times with the same
        /// seed, starting_time must be unique to each run. Thus, the easiest way to achieve this is to
@@ -705,8 +712,7 @@ impl KeysManager {
                                        Err(_) => panic!("Your RNG is busted"),
                                };
                                let channel_master_key = master_key.ckd_priv(&secp_ctx, ChildNumber::from_hardened_idx(3).unwrap()).expect("Your RNG is busted");
-                               let session_master_key = master_key.ckd_priv(&secp_ctx, ChildNumber::from_hardened_idx(4).unwrap()).expect("Your RNG is busted");
-                               let channel_id_master_key = master_key.ckd_priv(&secp_ctx, ChildNumber::from_hardened_idx(5).unwrap()).expect("Your RNG is busted");
+                               let rand_bytes_master_key = master_key.ckd_priv(&secp_ctx, ChildNumber::from_hardened_idx(4).unwrap()).expect("Your RNG is busted");
 
                                KeysManager {
                                        secp_ctx,
@@ -715,10 +721,8 @@ impl KeysManager {
                                        shutdown_pubkey,
                                        channel_master_key,
                                        channel_child_index: AtomicUsize::new(0),
-                                       session_master_key,
-                                       session_child_index: AtomicUsize::new(0),
-                                       channel_id_master_key,
-                                       channel_id_child_index: AtomicUsize::new(0),
+                                       rand_bytes_master_key,
+                                       rand_bytes_child_index: AtomicUsize::new(0),
 
                                        seed: *seed,
                                        starting_time_secs,
@@ -805,35 +809,20 @@ impl KeysInterface for KeysManager {
                self.shutdown_pubkey.clone()
        }
 
-       fn get_channel_keys(&self, _inbound: bool, channel_value_satoshis: u64) -> InMemoryChannelKeys {
+       fn get_channel_keys(&self, _inbound: bool, channel_value_satoshis: u64) -> Self::ChanKeySigner {
                let child_ix = self.channel_child_index.fetch_add(1, Ordering::AcqRel);
                let ix_and_nanos: u64 = (child_ix as u64) << 32 | (self.starting_time_nanos as u64);
                self.derive_channel_keys(channel_value_satoshis, ix_and_nanos, self.starting_time_secs)
        }
 
-       fn get_onion_rand(&self) -> (SecretKey, [u8; 32]) {
-               let mut sha = self.derive_unique_start();
-
-               let child_ix = self.session_child_index.fetch_add(1, Ordering::AcqRel);
-               let child_privkey = self.session_master_key.ckd_priv(&self.secp_ctx, ChildNumber::from_hardened_idx(child_ix as u32).expect("key space exhausted")).expect("Your RNG is busted");
-               sha.input(&child_privkey.private_key.key[..]);
-
-               let mut rng_seed = sha.clone();
-               // Not exactly the most ideal construction, but the second value will get fed into
-               // ChaCha so it is another step harder to break.
-               rng_seed.input(b"RNG Seed Salt");
-               sha.input(b"Session Key Salt");
-               (SecretKey::from_slice(&Sha256::from_engine(sha).into_inner()).expect("Your RNG is busted"),
-               Sha256::from_engine(rng_seed).into_inner())
-       }
-
-       fn get_channel_id(&self) -> [u8; 32] {
+       fn get_secure_random_bytes(&self) -> [u8; 32] {
                let mut sha = self.derive_unique_start();
 
-               let child_ix = self.channel_id_child_index.fetch_add(1, Ordering::AcqRel);
-               let child_privkey = self.channel_id_master_key.ckd_priv(&self.secp_ctx, ChildNumber::from_hardened_idx(child_ix as u32).expect("key space exhausted")).expect("Your RNG is busted");
+               let child_ix = self.rand_bytes_child_index.fetch_add(1, Ordering::AcqRel);
+               let child_privkey = self.rand_bytes_master_key.ckd_priv(&self.secp_ctx, ChildNumber::from_hardened_idx(child_ix as u32).expect("key space exhausted")).expect("Your RNG is busted");
                sha.input(&child_privkey.private_key.key[..]);
 
+               sha.input(b"Unique Secure Random Bytes Salt");
                Sha256::from_engine(sha).into_inner()
        }
 }