X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fchain%2Fkeysinterface.rs;h=ce865107abc3ee831b25263a7281b08921547155;hb=dde344a51d431ef013cb7ebb3df0c765dd9ef8be;hp=ec76262b15ad026d9d2d6a6a42d85b91554f82db;hpb=5b24d3e3275b8ca7f0ea064cc1626c8e1def2ccb;p=rust-lightning diff --git a/lightning/src/chain/keysinterface.rs b/lightning/src/chain/keysinterface.rs index ec76262b..ce865107 100644 --- a/lightning/src/chain/keysinterface.rs +++ b/lightning/src/chain/keysinterface.rs @@ -9,15 +9,15 @@ use bitcoin::network::constants::Network; use bitcoin::util::bip32::{ExtendedPrivKey, ExtendedPubKey, ChildNumber}; use bitcoin::util::bip143; -use bitcoin_hashes::{Hash, HashEngine}; -use bitcoin_hashes::sha256::HashEngine as Sha256State; -use bitcoin_hashes::sha256::Hash as Sha256; -use bitcoin_hashes::sha256d::Hash as Sha256dHash; -use bitcoin_hashes::hash160::Hash as Hash160; +use bitcoin::hashes::{Hash, HashEngine}; +use bitcoin::hashes::sha256::HashEngine as Sha256State; +use bitcoin::hashes::sha256::Hash as Sha256; +use bitcoin::hashes::sha256d::Hash as Sha256dHash; +use bitcoin::hash_types::WPubkeyHash; -use secp256k1::key::{SecretKey, PublicKey}; -use secp256k1::{Secp256k1, Signature, Signing}; -use secp256k1; +use bitcoin::secp256k1::key::{SecretKey, PublicKey}; +use bitcoin::secp256k1::{Secp256k1, Signature, Signing}; +use bitcoin::secp256k1; use util::byte_utils; use util::logger::Logger; @@ -25,7 +25,6 @@ use util::ser::{Writeable, Writer, Readable}; use ln::chan_utils; use ln::chan_utils::{TxCreationKeys, HTLCOutputInCommitment, make_funding_redeemscript, ChannelPublicKeys, LocalCommitmentTransaction}; -use ln::channelmanager::PaymentPreimage; use ln::msgs; use std::sync::Arc; @@ -185,11 +184,11 @@ pub trait KeysInterface: Send + Sync { /// Readable/Writable to serialize out a unique reference to this set of keys so /// that you can serialize the full ChannelManager object. /// -/// (TODO: We shouldn't require that, and should have an API to get them at deser time, due mostly -/// to the possibility of reentrancy issues by calling the user's code during our deserialization -/// routine). -/// TODO: We should remove Clone by instead requesting a new ChannelKeys copy when we create -/// ChannelMonitors instead of expecting to clone the one out of the Channel into the monitors. +// (TODO: We shouldn't require that, and should have an API to get them at deser time, due mostly +// to the possibility of reentrancy issues by calling the user's code during our deserialization +// routine). +// TODO: We should remove Clone by instead requesting a new ChannelKeys copy when we create +// ChannelMonitors instead of expecting to clone the one out of the Channel into the monitors. pub trait ChannelKeys : Send+Clone { /// Gets the private key for the anchor tx fn funding_key<'a>(&'a self) -> &'a SecretKey; @@ -210,32 +209,42 @@ pub trait ChannelKeys : Send+Clone { /// Create a signature for a remote commitment transaction and associated HTLC transactions. /// /// Note that if signing fails or is rejected, the channel will be force-closed. - /// - /// 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)! + // + // 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(&self, feerate_per_kw: u64, commitment_tx: &Transaction, keys: &TxCreationKeys, htlcs: &[&HTLCOutputInCommitment], to_self_delay: u16, secp_ctx: &Secp256k1) -> Result<(Signature, Vec), ()>; - /// Create a signature for a local commitment transaction - /// - /// 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 - /// TODO: Ensure test-only version doesn't enforce uniqueness of signature when it's enforced in this method - /// making the callee generate it via some util function we expose)! - fn sign_local_commitment(&self, local_commitment_tx: &mut LocalCommitmentTransaction, secp_ctx: &Secp256k1); + /// 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 + /// that it will not be called multiple times. + // + // 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 + fn sign_local_commitment(&self, local_commitment_tx: &LocalCommitmentTransaction, secp_ctx: &Secp256k1) -> Result; + + /// Same as sign_local_commitment, but exists only for tests to get access to local commitment + /// 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)] + fn unsafe_sign_local_commitment(&self, local_commitment_tx: &LocalCommitmentTransaction, secp_ctx: &Secp256k1) -> Result; - /// Create a signature for a local commitment transaction without enforcing one-time signing. + /// Create a signature for each HTLC transaction spending a local commitment transaction. /// - /// Testing revocation logic by our test framework needs to sign multiple local commitment - /// transactions. This unsafe test-only version doesn't enforce one-time signing security - /// requirement. - #[cfg(test)] - fn unsafe_sign_local_commitment(&self, local_commitment_tx: &mut LocalCommitmentTransaction, secp_ctx: &Secp256k1); + /// Unlike sign_local_commitment, this may be called multiple times with *different* + /// local_commitment_tx values. While this will never be called with a revoked + /// local_commitment_tx, it is possible that it is called with the second-latest + /// local_commitment_tx (only if we haven't yet revoked it) if some watchtower/secondary + /// ChannelMonitor decided to broadcast before it had been updated to the latest. + /// + /// Either an Err should be returned, or a Vec with one entry for each HTLC which exists in + /// local_commitment_tx. For those HTLCs which have transaction_output_index set to None + /// (implying they were considered dust at the time the commitment transaction was negotiated), + /// a corresponding None should be included in the return value. All other positions in the + /// return value must contain a signature. + fn sign_local_commitment_htlc_transactions(&self, local_commitment_tx: &LocalCommitmentTransaction, local_csv: u16, secp_ctx: &Secp256k1) -> Result>, ()>; - /// Signs a transaction created by build_htlc_transaction. If the transaction is an - /// HTLC-Success transaction, preimage must be set! - /// TODO: should be merged with sign_local_commitment as a slice of HTLC transactions to sign - fn sign_htlc_transaction(&self, local_commitment_tx: &mut LocalCommitmentTransaction, htlc_index: u32, preimage: Option, local_csv: u16, secp_ctx: &Secp256k1); /// Create a signature for a (proposed) closing transaction. /// /// Note that, due to rounding, there may be one "missing" satoshi, and either party may have @@ -363,25 +372,25 @@ impl ChannelKeys for InMemoryChannelKeys { Ok((commitment_sig, htlc_sigs)) } - fn sign_local_commitment(&self, local_commitment_tx: &mut LocalCommitmentTransaction, secp_ctx: &Secp256k1) { + fn sign_local_commitment(&self, local_commitment_tx: &LocalCommitmentTransaction, secp_ctx: &Secp256k1) -> Result { let funding_pubkey = PublicKey::from_secret_key(secp_ctx, &self.funding_key); let remote_channel_pubkeys = self.remote_channel_pubkeys.as_ref().expect("must set remote channel pubkeys before signing"); let channel_funding_redeemscript = make_funding_redeemscript(&funding_pubkey, &remote_channel_pubkeys.funding_pubkey); - local_commitment_tx.add_local_sig(&self.funding_key, &channel_funding_redeemscript, self.channel_value_satoshis, secp_ctx); + Ok(local_commitment_tx.get_local_sig(&self.funding_key, &channel_funding_redeemscript, self.channel_value_satoshis, secp_ctx)) } #[cfg(test)] - fn unsafe_sign_local_commitment(&self, local_commitment_tx: &mut LocalCommitmentTransaction, secp_ctx: &Secp256k1) { + fn unsafe_sign_local_commitment(&self, local_commitment_tx: &LocalCommitmentTransaction, secp_ctx: &Secp256k1) -> Result { let funding_pubkey = PublicKey::from_secret_key(secp_ctx, &self.funding_key); let remote_channel_pubkeys = self.remote_channel_pubkeys.as_ref().expect("must set remote channel pubkeys before signing"); let channel_funding_redeemscript = make_funding_redeemscript(&funding_pubkey, &remote_channel_pubkeys.funding_pubkey); - local_commitment_tx.add_local_sig(&self.funding_key, &channel_funding_redeemscript, self.channel_value_satoshis, secp_ctx); + Ok(local_commitment_tx.get_local_sig(&self.funding_key, &channel_funding_redeemscript, self.channel_value_satoshis, secp_ctx)) } - fn sign_htlc_transaction(&self, local_commitment_tx: &mut LocalCommitmentTransaction, htlc_index: u32, preimage: Option, local_csv: u16, secp_ctx: &Secp256k1) { - local_commitment_tx.add_htlc_sig(&self.htlc_base_key, htlc_index, preimage, local_csv, secp_ctx); + fn sign_local_commitment_htlc_transactions(&self, local_commitment_tx: &LocalCommitmentTransaction, local_csv: u16, secp_ctx: &Secp256k1) -> Result>, ()> { + local_commitment_tx.get_htlc_sigs(&self.htlc_base_key, local_csv, secp_ctx) } fn sign_closing_transaction(&self, closing_tx: &Transaction, secp_ctx: &Secp256k1) -> Result { @@ -504,9 +513,9 @@ impl KeysManager { let node_secret = master_key.ckd_priv(&secp_ctx, ChildNumber::from_hardened_idx(0).unwrap()).expect("Your RNG is busted").private_key.key; let destination_script = match master_key.ckd_priv(&secp_ctx, ChildNumber::from_hardened_idx(1).unwrap()) { Ok(destination_key) => { - let pubkey_hash160 = Hash160::hash(&ExtendedPubKey::from_private(&secp_ctx, &destination_key).public_key.key.serialize()[..]); + let wpubkey_hash = WPubkeyHash::hash(&ExtendedPubKey::from_private(&secp_ctx, &destination_key).public_key.to_bytes()); Builder::new().push_opcode(opcodes::all::OP_PUSHBYTES_0) - .push_slice(&pubkey_hash160.into_inner()) + .push_slice(&wpubkey_hash.into_inner()) .into_script() }, Err(_) => panic!("Your RNG is busted"),