X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fchannel.rs;h=02b1ae4ed2f58b413e8e4375716d490b6e0552e3;hb=9a0211543762ae15ce4a0b7cb5aa3cf295a4b61f;hp=269aef215f8b82e60a7180a10b18ef72d9085049;hpb=9f30b305e6ee9c411f1f14aaded665b5001d994f;p=rust-lightning diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index 269aef21..02b1ae4e 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -4,7 +4,7 @@ use bitcoin::blockdata::transaction::{TxIn, TxOut, Transaction, SigHashType}; use bitcoin::blockdata::opcodes; use bitcoin::util::hash::BitcoinHash; use bitcoin::util::bip143; -use bitcoin::consensus::encode::{self, Encodable, Decodable}; +use bitcoin::consensus::encode; use bitcoin_hashes::{Hash, HashEngine}; use bitcoin_hashes::sha256::Hash as Sha256; @@ -15,17 +15,18 @@ use secp256k1::key::{PublicKey,SecretKey}; use secp256k1::{Secp256k1,Signature}; use secp256k1; +use ln::features::{ChannelFeatures, InitFeatures}; use ln::msgs; -use ln::msgs::{DecodeError, OptionalField, LocalFeatures, DataLossProtect}; +use ln::msgs::{DecodeError, OptionalField, DataLossProtect}; use ln::channelmonitor::ChannelMonitor; use ln::channelmanager::{PendingHTLCStatus, HTLCSource, HTLCFailReason, HTLCFailureMsg, PendingForwardHTLCInfo, RAACommitmentOrder, PaymentPreimage, PaymentHash, BREAKDOWN_TIMEOUT, MAX_LOCAL_BREAKDOWN_TIMEOUT}; -use ln::chan_utils::{TxCreationKeys,HTLCOutputInCommitment,HTLC_SUCCESS_TX_WEIGHT,HTLC_TIMEOUT_TX_WEIGHT}; +use ln::chan_utils::{LocalCommitmentTransaction, TxCreationKeys, HTLCOutputInCommitment, HTLC_SUCCESS_TX_WEIGHT, HTLC_TIMEOUT_TX_WEIGHT, make_funding_redeemscript, ChannelPublicKeys}; use ln::chan_utils; use chain::chaininterface::{FeeEstimator,ConfirmationTarget}; use chain::transaction::OutPoint; use chain::keysinterface::{ChannelKeys, KeysInterface}; use util::transaction_utils; -use util::ser::{Readable, ReadableArgs, Writeable, Writer, WriterWriteAdaptor}; +use util::ser::{Readable, ReadableArgs, Writeable, Writer}; use util::logger::{Logger, LogHolder}; use util::errors::APIError; use util::config::{UserConfig,ChannelConfig}; @@ -228,7 +229,7 @@ enum UpdateStatus { // has been completed, and then turn into a Channel to get compiler-time enforcement of things like // calling channel_id() before we're set up or things like get_outbound_funding_signed on an // inbound channel. -pub(super) struct Channel { +pub(super) struct Channel { config: ChannelConfig, user_id: u64, @@ -239,7 +240,7 @@ pub(super) struct Channel { secp_ctx: Secp256k1, channel_value_satoshis: u64, - local_keys: ChannelKeys, + local_keys: ChanSigner, shutdown_pubkey: PublicKey, // Our commitment numbers start at 2^48-1 and count down, whereas the ones used in transaction @@ -297,13 +298,7 @@ pub(super) struct Channel { /// Max to_local and to_remote outputs in a remote-generated commitment transaction max_commitment_tx_output_remote: ::std::sync::Mutex<(u64, u64)>, - #[cfg(test)] - // Used in ChannelManager's tests to send a revoked transaction - pub last_local_commitment_txn: Vec, - #[cfg(not(test))] - last_local_commitment_txn: Vec, - - last_sent_closing_fee: Option<(u64, u64)>, // (feerate, fee) + last_sent_closing_fee: Option<(u64, u64, Signature)>, // (feerate, fee, our_sig) /// The hash of the block in which the funding transaction reached our CONF_TARGET. We use this /// to detect unconfirmation after a serialize-unserialize roundtrip where we may not see a full @@ -340,11 +335,8 @@ pub(super) struct Channel { //implied by OUR_MAX_HTLCS: our_max_accepted_htlcs: u16, minimum_depth: u32, - their_funding_pubkey: Option, - their_revocation_basepoint: Option, - their_payment_basepoint: Option, - their_delayed_payment_basepoint: Option, - their_htlc_basepoint: Option, + their_pubkeys: Option, + their_cur_commitment_point: Option, their_prev_commitment_point: Option, @@ -373,12 +365,6 @@ const B_OUTPUT_PLUS_SPENDING_INPUT_WEIGHT: u64 = 104; // prevout: 40, nSequence: /// it's 2^24. pub const MAX_FUNDING_SATOSHIS: u64 = (1 << 24); -#[cfg(test)] -pub const ACCEPTED_HTLC_SCRIPT_WEIGHT: usize = 138; //Here we have a diff due to HTLC CLTV expiry being < 2^15 in test -#[cfg(not(test))] -pub const ACCEPTED_HTLC_SCRIPT_WEIGHT: usize = 139; -pub const OFFERED_HTLC_SCRIPT_WEIGHT: usize = 133; - /// Used to return a simple Error back to ChannelManager. Will get converted to a /// msgs::ErrorAction::SendErrorMessage or msgs::ErrorAction::IgnoreError as appropriate with our /// channel_id in ChannelManager. @@ -410,7 +396,7 @@ macro_rules! secp_check { }; } -impl Channel { +impl Channel { // Convert constants + channel value to limits: fn get_our_max_htlc_value_in_flight_msat(channel_value_satoshis: u64) -> u64 { channel_value_satoshis * 1000 / 10 //TODO @@ -433,7 +419,7 @@ impl Channel { } // Constructors: - pub fn new_outbound(fee_estimator: &FeeEstimator, keys_provider: &Arc, their_node_id: PublicKey, channel_value_satoshis: u64, push_msat: u64, user_id: u64, logger: Arc, config: &UserConfig) -> Result { + pub fn new_outbound(fee_estimator: &FeeEstimator, keys_provider: &Arc>, their_node_id: PublicKey, channel_value_satoshis: u64, push_msat: u64, user_id: u64, logger: Arc, config: &UserConfig) -> Result, APIError> { let chan_keys = keys_provider.get_channel_keys(false); if channel_value_satoshis >= MAX_FUNDING_SATOSHIS { @@ -449,15 +435,15 @@ impl Channel { let background_feerate = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Background); - if Channel::get_our_channel_reserve_satoshis(channel_value_satoshis) < Channel::derive_our_dust_limit_satoshis(background_feerate) { + if Channel::::get_our_channel_reserve_satoshis(channel_value_satoshis) < Channel::::derive_our_dust_limit_satoshis(background_feerate) { return Err(APIError::FeeRateTooHigh{err: format!("Not enough reserve above dust limit can be found at current fee rate({})", background_feerate), feerate: background_feerate}); } let feerate = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Normal); let secp_ctx = Secp256k1::new(); - let channel_monitor = ChannelMonitor::new(&chan_keys.revocation_base_key, &chan_keys.delayed_payment_base_key, - &chan_keys.htlc_base_key, &chan_keys.payment_base_key, &keys_provider.get_shutdown_pubkey(), config.own_channel_config.our_to_self_delay, + let channel_monitor = ChannelMonitor::new(chan_keys.funding_key(), chan_keys.revocation_base_key(), chan_keys.delayed_payment_base_key(), + chan_keys.htlc_base_key(), chan_keys.payment_base_key(), &keys_provider.get_shutdown_pubkey(), config.own_channel_config.our_to_self_delay, keys_provider.get_destination_script(), logger.clone()); Ok(Channel { @@ -498,8 +484,6 @@ impl Channel { #[cfg(debug_assertions)] max_commitment_tx_output_remote: ::std::sync::Mutex::new((channel_value_satoshis * 1000 - push_msat, push_msat)), - last_local_commitment_txn: Vec::new(), - last_sent_closing_fee: None, funding_tx_confirmed_in: None, @@ -509,21 +493,17 @@ impl Channel { feerate_per_kw: feerate, their_dust_limit_satoshis: 0, - our_dust_limit_satoshis: Channel::derive_our_dust_limit_satoshis(background_feerate), + our_dust_limit_satoshis: Channel::::derive_our_dust_limit_satoshis(background_feerate), their_max_htlc_value_in_flight_msat: 0, their_channel_reserve_satoshis: 0, their_htlc_minimum_msat: 0, - our_htlc_minimum_msat: Channel::derive_our_htlc_minimum_msat(feerate), + our_htlc_minimum_msat: Channel::::derive_our_htlc_minimum_msat(feerate), their_to_self_delay: 0, our_to_self_delay: config.own_channel_config.our_to_self_delay, their_max_accepted_htlcs: 0, minimum_depth: 0, // Filled in in accept_channel - their_funding_pubkey: None, - their_revocation_basepoint: None, - their_payment_basepoint: None, - their_delayed_payment_basepoint: None, - their_htlc_basepoint: None, + their_pubkeys: None, their_cur_commitment_point: None, their_prev_commitment_point: None, @@ -551,8 +531,16 @@ impl Channel { /// Creates a new channel from a remote sides' request for one. /// Assumes chain_hash has already been checked and corresponds with what we expect! - pub fn new_from_req(fee_estimator: &FeeEstimator, keys_provider: &Arc, their_node_id: PublicKey, their_local_features: LocalFeatures, msg: &msgs::OpenChannel, user_id: u64, logger: Arc, config: &UserConfig) -> Result { - let chan_keys = keys_provider.get_channel_keys(true); + pub fn new_from_req(fee_estimator: &FeeEstimator, keys_provider: &Arc>, their_node_id: PublicKey, their_features: InitFeatures, msg: &msgs::OpenChannel, user_id: u64, logger: Arc, config: &UserConfig) -> Result, ChannelError> { + let mut chan_keys = keys_provider.get_channel_keys(true); + let their_pubkeys = ChannelPublicKeys { + funding_pubkey: msg.funding_pubkey, + revocation_basepoint: msg.revocation_basepoint, + payment_basepoint: msg.payment_basepoint, + delayed_payment_basepoint: msg.delayed_payment_basepoint, + htlc_basepoint: msg.htlc_basepoint + }; + chan_keys.set_remote_channel_pubkeys(&their_pubkeys); let mut local_config = (*config).channel_options.clone(); if config.own_channel_config.our_to_self_delay < BREAKDOWN_TIMEOUT { @@ -578,7 +566,7 @@ impl Channel { if msg.htlc_minimum_msat >= (msg.funding_satoshis - msg.channel_reserve_satoshis) * 1000 { return Err(ChannelError::Close("Minimum htlc value is full channel value")); } - Channel::check_remote_fee(fee_estimator, msg.feerate_per_kw)?; + Channel::::check_remote_fee(fee_estimator, msg.feerate_per_kw)?; if msg.to_self_delay > config.peer_channel_config_limits.their_to_self_delay || msg.to_self_delay > MAX_LOCAL_BREAKDOWN_TIMEOUT { return Err(ChannelError::Close("They wanted our payments to be delayed by a needlessly long period")); @@ -626,8 +614,8 @@ impl Channel { let background_feerate = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Background); - let our_dust_limit_satoshis = Channel::derive_our_dust_limit_satoshis(background_feerate); - let our_channel_reserve_satoshis = Channel::get_our_channel_reserve_satoshis(msg.funding_satoshis); + let our_dust_limit_satoshis = Channel::::derive_our_dust_limit_satoshis(background_feerate); + let our_channel_reserve_satoshis = Channel::::get_our_channel_reserve_satoshis(msg.funding_satoshis); if our_channel_reserve_satoshis < our_dust_limit_satoshis { return Err(ChannelError::Close("Suitable channel reserve not found. aborting")); } @@ -652,13 +640,11 @@ impl Channel { } let secp_ctx = Secp256k1::new(); - let mut channel_monitor = ChannelMonitor::new(&chan_keys.revocation_base_key, &chan_keys.delayed_payment_base_key, - &chan_keys.htlc_base_key, &chan_keys.payment_base_key, &keys_provider.get_shutdown_pubkey(), config.own_channel_config.our_to_self_delay, - keys_provider.get_destination_script(), logger.clone()); - channel_monitor.set_their_base_keys(&msg.htlc_basepoint, &msg.delayed_payment_basepoint); - channel_monitor.set_their_to_self_delay(msg.to_self_delay); + let channel_monitor = ChannelMonitor::new(chan_keys.funding_key(), chan_keys.revocation_base_key(), chan_keys.delayed_payment_base_key(), + chan_keys.htlc_base_key(), chan_keys.payment_base_key(), &keys_provider.get_shutdown_pubkey(), config.own_channel_config.our_to_self_delay, + keys_provider.get_destination_script(), logger.clone()); - let their_shutdown_scriptpubkey = if their_local_features.supports_upfront_shutdown_script() { + let their_shutdown_scriptpubkey = if their_features.supports_upfront_shutdown_script() { match &msg.shutdown_scriptpubkey { &OptionalField::Present(ref script) => { // Peer is signaling upfront_shutdown and has provided a non-accepted scriptpubkey format. We enforce it while receiving shutdown msg @@ -716,8 +702,6 @@ impl Channel { #[cfg(debug_assertions)] max_commitment_tx_output_remote: ::std::sync::Mutex::new((msg.push_msat, msg.funding_satoshis * 1000 - msg.push_msat)), - last_local_commitment_txn: Vec::new(), - last_sent_closing_fee: None, funding_tx_confirmed_in: None, @@ -732,17 +716,13 @@ impl Channel { their_max_htlc_value_in_flight_msat: cmp::min(msg.max_htlc_value_in_flight_msat, msg.funding_satoshis * 1000), their_channel_reserve_satoshis: msg.channel_reserve_satoshis, their_htlc_minimum_msat: msg.htlc_minimum_msat, - our_htlc_minimum_msat: Channel::derive_our_htlc_minimum_msat(msg.feerate_per_kw as u64), + our_htlc_minimum_msat: Channel::::derive_our_htlc_minimum_msat(msg.feerate_per_kw as u64), their_to_self_delay: msg.to_self_delay, our_to_self_delay: config.own_channel_config.our_to_self_delay, their_max_accepted_htlcs: msg.max_accepted_htlcs, minimum_depth: config.own_channel_config.minimum_depth, - their_funding_pubkey: Some(msg.funding_pubkey), - their_revocation_basepoint: Some(msg.revocation_basepoint), - their_payment_basepoint: Some(msg.payment_basepoint), - their_delayed_payment_basepoint: Some(msg.delayed_payment_basepoint), - their_htlc_basepoint: Some(msg.htlc_basepoint), + their_pubkeys: Some(their_pubkeys), their_cur_commitment_point: Some(msg.first_per_commitment_point), their_prev_commitment_point: None, @@ -758,7 +738,8 @@ impl Channel { }; let obscure_factor = chan.get_commitment_transaction_number_obscure_factor(); - chan.channel_monitor.set_commitment_obscure_factor(obscure_factor); + let funding_redeemscript = chan.get_funding_redeemscript(); + chan.channel_monitor.set_basic_channel_info(&msg.htlc_basepoint, &msg.delayed_payment_basepoint, msg.to_self_delay, funding_redeemscript, msg.funding_satoshis, obscure_factor); Ok(chan) } @@ -766,7 +747,7 @@ impl Channel { // Utilities to derive keys: fn build_local_commitment_secret(&self, idx: u64) -> SecretKey { - let res = chan_utils::build_commitment_secret(self.local_keys.commitment_seed, idx); + let res = chan_utils::build_commitment_secret(self.local_keys.commitment_seed(), idx); SecretKey::from_slice(&res).unwrap() } @@ -774,13 +755,14 @@ impl Channel { fn get_commitment_transaction_number_obscure_factor(&self) -> u64 { let mut sha = Sha256::engine(); - let our_payment_basepoint = PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.payment_base_key); + let our_payment_basepoint = PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.payment_base_key()); + let their_payment_basepoint = &self.their_pubkeys.as_ref().unwrap().payment_basepoint.serialize(); if self.channel_outbound { sha.input(&our_payment_basepoint.serialize()); - sha.input(&self.their_payment_basepoint.unwrap().serialize()); + sha.input(their_payment_basepoint); } else { - sha.input(&self.their_payment_basepoint.unwrap().serialize()); + sha.input(their_payment_basepoint); sha.input(&our_payment_basepoint.serialize()); } let res = Sha256::from_engine(sha).into_inner(); @@ -833,7 +815,7 @@ impl Channel { let mut local_htlc_total_msat = 0; let mut value_to_self_msat_offset = 0; - log_trace!(self, "Building commitment transaction number {} for {}, generated by {} with fee {}...", commitment_number, if local { "us" } else { "remote" }, if generated_by_local { "us" } else { "remote" }, feerate_per_kw); + log_trace!(self, "Building commitment transaction number {} (really {} xor {}) for {}, generated by {} with fee {}...", commitment_number, (INITIAL_COMMITMENT_NUMBER - commitment_number), self.get_commitment_transaction_number_obscure_factor(), if local { "us" } else { "remote" }, if generated_by_local { "us" } else { "remote" }, feerate_per_kw); macro_rules! get_htlc_in_commitment { ($htlc: expr, $offered: expr) => { @@ -952,7 +934,7 @@ impl Channel { }; debug_assert!(max_commitment_tx_output.0 <= value_to_self_msat as u64 || value_to_self_msat / 1000 >= self.their_channel_reserve_satoshis as i64); max_commitment_tx_output.0 = cmp::max(max_commitment_tx_output.0, value_to_self_msat as u64); - debug_assert!(max_commitment_tx_output.1 <= value_to_remote_msat as u64 || value_to_remote_msat / 1000 >= Channel::get_our_channel_reserve_satoshis(self.channel_value_satoshis) as i64); + debug_assert!(max_commitment_tx_output.1 <= value_to_remote_msat as u64 || value_to_remote_msat / 1000 >= Channel::::get_our_channel_reserve_satoshis(self.channel_value_satoshis) as i64); max_commitment_tx_output.1 = cmp::max(max_commitment_tx_output.1, value_to_remote_msat as u64); } @@ -1097,10 +1079,11 @@ impl Channel { /// TODO Some magic rust shit to compile-time check this? fn build_local_transaction_keys(&self, commitment_number: u64) -> Result { let per_commitment_point = PublicKey::from_secret_key(&self.secp_ctx, &self.build_local_commitment_secret(commitment_number)); - let delayed_payment_base = PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.delayed_payment_base_key); - let htlc_basepoint = PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.htlc_base_key); + let delayed_payment_base = PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.delayed_payment_base_key()); + let htlc_basepoint = PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.htlc_base_key()); + let their_pubkeys = self.their_pubkeys.as_ref().unwrap(); - Ok(secp_check!(TxCreationKeys::new(&self.secp_ctx, &per_commitment_point, &delayed_payment_base, &htlc_basepoint, &self.their_revocation_basepoint.unwrap(), &self.their_payment_basepoint.unwrap(), &self.their_htlc_basepoint.unwrap()), "Local tx keys generation got bogus keys")) + Ok(secp_check!(TxCreationKeys::new(&self.secp_ctx, &per_commitment_point, &delayed_payment_base, &htlc_basepoint, &their_pubkeys.revocation_basepoint, &their_pubkeys.payment_basepoint, &their_pubkeys.htlc_basepoint), "Local tx keys generation got bogus keys")) } #[inline] @@ -1110,59 +1093,20 @@ impl Channel { fn build_remote_transaction_keys(&self) -> Result { //TODO: Ensure that the payment_key derived here ends up in the library users' wallet as we //may see payments to it! - let payment_basepoint = PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.payment_base_key); - let revocation_basepoint = PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.revocation_base_key); - let htlc_basepoint = PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.htlc_base_key); + let payment_basepoint = PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.payment_base_key()); + let revocation_basepoint = PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.revocation_base_key()); + let htlc_basepoint = PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.htlc_base_key()); + let their_pubkeys = self.their_pubkeys.as_ref().unwrap(); - Ok(secp_check!(TxCreationKeys::new(&self.secp_ctx, &self.their_cur_commitment_point.unwrap(), &self.their_delayed_payment_basepoint.unwrap(), &self.their_htlc_basepoint.unwrap(), &revocation_basepoint, &payment_basepoint, &htlc_basepoint), "Remote tx keys generation got bogus keys")) + Ok(secp_check!(TxCreationKeys::new(&self.secp_ctx, &self.their_cur_commitment_point.unwrap(), &their_pubkeys.delayed_payment_basepoint, &their_pubkeys.htlc_basepoint, &revocation_basepoint, &payment_basepoint, &htlc_basepoint), "Remote tx keys generation got bogus keys")) } /// Gets the redeemscript for the funding transaction output (ie the funding transaction output /// pays to get_funding_redeemscript().to_v0_p2wsh()). /// Panics if called before accept_channel/new_from_req pub fn get_funding_redeemscript(&self) -> Script { - let builder = Builder::new().push_opcode(opcodes::all::OP_PUSHNUM_2); - let our_funding_key = PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.funding_key).serialize(); - let their_funding_key = self.their_funding_pubkey.expect("get_funding_redeemscript only allowed after accept_channel").serialize(); - if our_funding_key[..] < their_funding_key[..] { - builder.push_slice(&our_funding_key) - .push_slice(&their_funding_key) - } else { - builder.push_slice(&their_funding_key) - .push_slice(&our_funding_key) - }.push_opcode(opcodes::all::OP_PUSHNUM_2).push_opcode(opcodes::all::OP_CHECKMULTISIG).into_script() - } - - fn sign_commitment_transaction(&self, tx: &mut Transaction, their_sig: &Signature) -> Signature { - if tx.input.len() != 1 { - panic!("Tried to sign commitment transaction that had input count != 1!"); - } - if tx.input[0].witness.len() != 0 { - panic!("Tried to re-sign commitment transaction"); - } - - let funding_redeemscript = self.get_funding_redeemscript(); - - let sighash = hash_to_message!(&bip143::SighashComponents::new(&tx).sighash_all(&tx.input[0], &funding_redeemscript, self.channel_value_satoshis)[..]); - let our_sig = self.secp_ctx.sign(&sighash, &self.local_keys.funding_key); - - tx.input[0].witness.push(Vec::new()); // First is the multisig dummy - - let our_funding_key = PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.funding_key).serialize(); - let their_funding_key = self.their_funding_pubkey.unwrap().serialize(); - if our_funding_key[..] < their_funding_key[..] { - tx.input[0].witness.push(our_sig.serialize_der().to_vec()); - tx.input[0].witness.push(their_sig.serialize_der().to_vec()); - } else { - tx.input[0].witness.push(their_sig.serialize_der().to_vec()); - tx.input[0].witness.push(our_sig.serialize_der().to_vec()); - } - tx.input[0].witness[1].push(SigHashType::All as u8); - tx.input[0].witness[2].push(SigHashType::All as u8); - - tx.input[0].witness.push(funding_redeemscript.into_bytes()); - - our_sig + let our_funding_key = PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.funding_key()); + make_funding_redeemscript(&our_funding_key, self.their_funding_pubkey()) } /// Builds the htlc-success or htlc-timeout transaction which spends a given HTLC output @@ -1172,54 +1116,6 @@ impl Channel { chan_utils::build_htlc_transaction(prev_hash, feerate_per_kw, if local { self.their_to_self_delay } else { self.our_to_self_delay }, htlc, &keys.a_delayed_payment_key, &keys.revocation_key) } - fn create_htlc_tx_signature(&self, tx: &Transaction, htlc: &HTLCOutputInCommitment, keys: &TxCreationKeys) -> Result<(Script, Signature, bool), ChannelError> { - if tx.input.len() != 1 { - panic!("Tried to sign HTLC transaction that had input count != 1!"); - } - - let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &keys); - - let our_htlc_key = secp_check!(chan_utils::derive_private_key(&self.secp_ctx, &keys.per_commitment_point, &self.local_keys.htlc_base_key), "Derived invalid key, peer is maliciously selecting parameters"); - let sighash = hash_to_message!(&bip143::SighashComponents::new(&tx).sighash_all(&tx.input[0], &htlc_redeemscript, htlc.amount_msat / 1000)[..]); - let is_local_tx = PublicKey::from_secret_key(&self.secp_ctx, &our_htlc_key) == keys.a_htlc_key; - Ok((htlc_redeemscript, self.secp_ctx.sign(&sighash, &our_htlc_key), is_local_tx)) - } - - /// Signs a transaction created by build_htlc_transaction. If the transaction is an - /// HTLC-Success transaction (ie htlc.offered is false), preimage must be set! - fn sign_htlc_transaction(&self, tx: &mut Transaction, their_sig: &Signature, preimage: &Option, htlc: &HTLCOutputInCommitment, keys: &TxCreationKeys) -> Result { - if tx.input.len() != 1 { - panic!("Tried to sign HTLC transaction that had input count != 1!"); - } - if tx.input[0].witness.len() != 0 { - panic!("Tried to re-sign HTLC transaction"); - } - - let (htlc_redeemscript, our_sig, local_tx) = self.create_htlc_tx_signature(tx, htlc, keys)?; - - tx.input[0].witness.push(Vec::new()); // First is the multisig dummy - - if local_tx { // b, then a - tx.input[0].witness.push(their_sig.serialize_der().to_vec()); - tx.input[0].witness.push(our_sig.serialize_der().to_vec()); - } else { - tx.input[0].witness.push(our_sig.serialize_der().to_vec()); - tx.input[0].witness.push(their_sig.serialize_der().to_vec()); - } - tx.input[0].witness[1].push(SigHashType::All as u8); - tx.input[0].witness[2].push(SigHashType::All as u8); - - if htlc.offered { - tx.input[0].witness.push(Vec::new()); - } else { - tx.input[0].witness.push(preimage.unwrap().0.to_vec()); - } - - tx.input[0].witness.push(htlc_redeemscript.into_bytes()); - - Ok(our_sig) - } - /// Per HTLC, only one get_update_fail_htlc or get_update_fulfill_htlc call may be made. /// In such cases we debug_assert!(false) and return an IgnoreError. Thus, will always return /// Ok(_) if debug assertions are turned on and preconditions are met. @@ -1397,7 +1293,7 @@ impl Channel { // Message handlers: - pub fn accept_channel(&mut self, msg: &msgs::AcceptChannel, config: &UserConfig, their_local_features: LocalFeatures) -> Result<(), ChannelError> { + pub fn accept_channel(&mut self, msg: &msgs::AcceptChannel, config: &UserConfig, their_features: InitFeatures) -> Result<(), ChannelError> { // Check sanity of message fields: if !self.channel_outbound { return Err(ChannelError::Close("Got an accept_channel message from an inbound peer")); @@ -1417,7 +1313,7 @@ impl Channel { if msg.channel_reserve_satoshis < self.our_dust_limit_satoshis { return Err(ChannelError::Close("Peer never wants payout outputs?")); } - if msg.dust_limit_satoshis > Channel::get_our_channel_reserve_satoshis(self.channel_value_satoshis) { + if msg.dust_limit_satoshis > Channel::::get_our_channel_reserve_satoshis(self.channel_value_satoshis) { return Err(ChannelError::Close("Dust limit is bigger than our channel reverse")); } if msg.htlc_minimum_msat >= (self.channel_value_satoshis - msg.channel_reserve_satoshis) * 1000 { @@ -1456,7 +1352,7 @@ impl Channel { return Err(ChannelError::Close("We consider the minimum depth to be unreasonably large")); } - let their_shutdown_scriptpubkey = if their_local_features.supports_upfront_shutdown_script() { + let their_shutdown_scriptpubkey = if their_features.supports_upfront_shutdown_script() { match &msg.shutdown_scriptpubkey { &OptionalField::Present(ref script) => { // Peer is signaling upfront_shutdown and has provided a non-accepted scriptpubkey format. We enforce it while receiving shutdown msg @@ -1477,8 +1373,6 @@ impl Channel { } } else { None }; - self.channel_monitor.set_their_base_keys(&msg.htlc_basepoint, &msg.delayed_payment_basepoint); - self.their_dust_limit_satoshis = msg.dust_limit_satoshis; self.their_max_htlc_value_in_flight_msat = cmp::min(msg.max_htlc_value_in_flight_msat, self.channel_value_satoshis * 1000); self.their_channel_reserve_satoshis = msg.channel_reserve_satoshis; @@ -1486,42 +1380,53 @@ impl Channel { self.their_to_self_delay = msg.to_self_delay; self.their_max_accepted_htlcs = msg.max_accepted_htlcs; self.minimum_depth = msg.minimum_depth; - self.their_funding_pubkey = Some(msg.funding_pubkey); - self.their_revocation_basepoint = Some(msg.revocation_basepoint); - self.their_payment_basepoint = Some(msg.payment_basepoint); - self.their_delayed_payment_basepoint = Some(msg.delayed_payment_basepoint); - self.their_htlc_basepoint = Some(msg.htlc_basepoint); + + let their_pubkeys = ChannelPublicKeys { + funding_pubkey: msg.funding_pubkey, + revocation_basepoint: msg.revocation_basepoint, + payment_basepoint: msg.payment_basepoint, + delayed_payment_basepoint: msg.delayed_payment_basepoint, + htlc_basepoint: msg.htlc_basepoint + }; + + self.local_keys.set_remote_channel_pubkeys(&their_pubkeys); + self.their_pubkeys = Some(their_pubkeys); + self.their_cur_commitment_point = Some(msg.first_per_commitment_point); self.their_shutdown_scriptpubkey = their_shutdown_scriptpubkey; let obscure_factor = self.get_commitment_transaction_number_obscure_factor(); - self.channel_monitor.set_commitment_obscure_factor(obscure_factor); - self.channel_monitor.set_their_to_self_delay(msg.to_self_delay); + let funding_redeemscript = self.get_funding_redeemscript(); + self.channel_monitor.set_basic_channel_info(&msg.htlc_basepoint, &msg.delayed_payment_basepoint, msg.to_self_delay, funding_redeemscript, self.channel_value_satoshis, obscure_factor); self.channel_state = ChannelState::OurInitSent as u32 | ChannelState::TheirInitSent as u32; Ok(()) } - fn funding_created_signature(&mut self, sig: &Signature) -> Result<(Transaction, Transaction, Signature, TxCreationKeys), ChannelError> { + fn funding_created_signature(&mut self, sig: &Signature) -> Result<(Transaction, LocalCommitmentTransaction, Signature, TxCreationKeys), ChannelError> { let funding_script = self.get_funding_redeemscript(); let local_keys = self.build_local_transaction_keys(self.cur_local_commitment_transaction_number)?; - let mut local_initial_commitment_tx = self.build_commitment_transaction(self.cur_local_commitment_transaction_number, &local_keys, true, false, self.feerate_per_kw).0; + let local_initial_commitment_tx = self.build_commitment_transaction(self.cur_local_commitment_transaction_number, &local_keys, true, false, self.feerate_per_kw).0; let local_sighash = hash_to_message!(&bip143::SighashComponents::new(&local_initial_commitment_tx).sighash_all(&local_initial_commitment_tx.input[0], &funding_script, self.channel_value_satoshis)[..]); // They sign the "local" commitment transaction... - secp_check!(self.secp_ctx.verify(&local_sighash, &sig, &self.their_funding_pubkey.unwrap()), "Invalid funding_created signature from peer"); + secp_check!(self.secp_ctx.verify(&local_sighash, &sig, self.their_funding_pubkey()), "Invalid funding_created signature from peer"); - // ...and we sign it, allowing us to broadcast the tx if we wish - self.sign_commitment_transaction(&mut local_initial_commitment_tx, sig); + let localtx = LocalCommitmentTransaction::new_missing_local_sig(local_initial_commitment_tx, sig, &PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.funding_key()), self.their_funding_pubkey()); let remote_keys = self.build_remote_transaction_keys()?; let remote_initial_commitment_tx = self.build_commitment_transaction(self.cur_remote_commitment_transaction_number, &remote_keys, false, false, self.feerate_per_kw).0; - let remote_sighash = hash_to_message!(&bip143::SighashComponents::new(&remote_initial_commitment_tx).sighash_all(&remote_initial_commitment_tx.input[0], &funding_script, self.channel_value_satoshis)[..]); + let remote_signature = self.local_keys.sign_remote_commitment(self.channel_value_satoshis, self.feerate_per_kw, &remote_initial_commitment_tx, &remote_keys, &Vec::new(), self.our_to_self_delay, &self.secp_ctx) + .map_err(|_| ChannelError::Close("Failed to get signatures for new commitment_signed"))?.0; // We sign the "remote" commitment transaction, allowing them to broadcast the tx if they wish. - Ok((remote_initial_commitment_tx, local_initial_commitment_tx, self.secp_ctx.sign(&remote_sighash, &self.local_keys.funding_key), local_keys)) + Ok((remote_initial_commitment_tx, localtx, remote_signature, local_keys)) + } + + fn their_funding_pubkey(&self) -> &PublicKey { + &self.their_pubkeys.as_ref().expect("their_funding_pubkey() only allowed after accept_channel").funding_pubkey } pub fn funding_created(&mut self, msg: &msgs::FundingCreated) -> Result<(msgs::FundingSigned, ChannelMonitor), ChannelError> { @@ -1555,7 +1460,6 @@ impl Channel { // Now that we're past error-generating stuff, update our local state: self.channel_monitor.provide_latest_remote_commitment_tx_info(&remote_initial_commitment_tx, Vec::new(), self.cur_remote_commitment_transaction_number, self.their_cur_commitment_point.unwrap()); - self.last_local_commitment_txn = vec![local_initial_commitment_tx.clone()]; self.channel_monitor.provide_latest_local_commitment_tx_info(local_initial_commitment_tx, local_keys, self.feerate_per_kw, Vec::new()); self.channel_state = ChannelState::FundingSent as u32; self.channel_id = funding_txo.to_channel_id(); @@ -1586,15 +1490,17 @@ impl Channel { let funding_script = self.get_funding_redeemscript(); let local_keys = self.build_local_transaction_keys(self.cur_local_commitment_transaction_number)?; - let mut local_initial_commitment_tx = self.build_commitment_transaction(self.cur_local_commitment_transaction_number, &local_keys, true, false, self.feerate_per_kw).0; + let local_initial_commitment_tx = self.build_commitment_transaction(self.cur_local_commitment_transaction_number, &local_keys, true, false, self.feerate_per_kw).0; let local_sighash = hash_to_message!(&bip143::SighashComponents::new(&local_initial_commitment_tx).sighash_all(&local_initial_commitment_tx.input[0], &funding_script, self.channel_value_satoshis)[..]); + let their_funding_pubkey = &self.their_pubkeys.as_ref().unwrap().funding_pubkey; + // They sign the "local" commitment transaction, allowing us to broadcast the tx if we wish. - secp_check!(self.secp_ctx.verify(&local_sighash, &msg.signature, &self.their_funding_pubkey.unwrap()), "Invalid funding_signed signature from peer"); + secp_check!(self.secp_ctx.verify(&local_sighash, &msg.signature, their_funding_pubkey), "Invalid funding_signed signature from peer"); - self.sign_commitment_transaction(&mut local_initial_commitment_tx, &msg.signature); - self.channel_monitor.provide_latest_local_commitment_tx_info(local_initial_commitment_tx.clone(), local_keys, self.feerate_per_kw, Vec::new()); - self.last_local_commitment_txn = vec![local_initial_commitment_tx]; + self.channel_monitor.provide_latest_local_commitment_tx_info( + LocalCommitmentTransaction::new_missing_local_sig(local_initial_commitment_tx, &msg.signature, &PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.funding_key()), their_funding_pubkey), + local_keys, self.feerate_per_kw, Vec::new()); self.channel_state = ChannelState::FundingSent as u32 | (self.channel_state & (ChannelState::MonitorUpdateFailed as u32)); self.cur_local_commitment_transaction_number -= 1; @@ -1695,7 +1601,7 @@ impl Channel { return Err(ChannelError::Close("Remote tried to push more than our max accepted HTLCs")); } // Check our_max_htlc_value_in_flight_msat - if htlc_inbound_value_msat + msg.amount_msat > Channel::get_our_max_htlc_value_in_flight_msat(self.channel_value_satoshis) { + if htlc_inbound_value_msat + msg.amount_msat > Channel::::get_our_max_htlc_value_in_flight_msat(self.channel_value_satoshis) { return Err(ChannelError::Close("Remote HTLC add would put them over our max HTLC value")); } // Check our_channel_reserve_satoshis (we're getting paid, so they have to at least meet @@ -1718,7 +1624,7 @@ impl Channel { removed_outbound_total_msat += htlc.amount_msat; } } - if htlc_inbound_value_msat + msg.amount_msat + self.value_to_self_msat > (self.channel_value_satoshis - Channel::get_our_channel_reserve_satoshis(self.channel_value_satoshis)) * 1000 + removed_outbound_total_msat { + if htlc_inbound_value_msat + msg.amount_msat + self.value_to_self_msat > (self.channel_value_satoshis - Channel::::get_our_channel_reserve_satoshis(self.channel_value_satoshis)) * 1000 + removed_outbound_total_msat { return Err(ChannelError::Close("Remote HTLC add would put them over their reserve value")); } if self.next_remote_htlc_id != msg.htlc_id { @@ -1841,8 +1747,8 @@ impl Channel { }; let local_commitment_txid = local_commitment_tx.0.txid(); let local_sighash = hash_to_message!(&bip143::SighashComponents::new(&local_commitment_tx.0).sighash_all(&local_commitment_tx.0.input[0], &funding_script, self.channel_value_satoshis)[..]); - log_trace!(self, "Checking commitment tx signature {} by key {} against tx {} with redeemscript {}", log_bytes!(msg.signature.serialize_compact()[..]), log_bytes!(self.their_funding_pubkey.unwrap().serialize()), encode::serialize_hex(&local_commitment_tx.0), encode::serialize_hex(&funding_script)); - secp_check!(self.secp_ctx.verify(&local_sighash, &msg.signature, &self.their_funding_pubkey.unwrap()), "Invalid commitment tx signature from peer"); + log_trace!(self, "Checking commitment tx signature {} by key {} against tx {} with redeemscript {}", log_bytes!(msg.signature.serialize_compact()[..]), log_bytes!(self.their_funding_pubkey().serialize()), encode::serialize_hex(&local_commitment_tx.0), encode::serialize_hex(&funding_script)); + secp_check!(self.secp_ctx.verify(&local_sighash, &msg.signature, &self.their_funding_pubkey()), "Invalid commitment tx signature from peer"); //If channel fee was updated by funder confirm funder can afford the new fee rate when applied to the current local commitment transaction if update_fee { @@ -1858,33 +1764,22 @@ impl Channel { return Err(ChannelError::Close("Got wrong number of HTLC signatures from remote")); } - let mut new_local_commitment_txn = Vec::with_capacity(local_commitment_tx.1 + 1); - self.sign_commitment_transaction(&mut local_commitment_tx.0, &msg.signature); - new_local_commitment_txn.push(local_commitment_tx.0.clone()); - let mut htlcs_and_sigs = Vec::with_capacity(local_commitment_tx.2.len()); for (idx, (htlc, source)) in local_commitment_tx.2.drain(..).enumerate() { if let Some(_) = htlc.transaction_output_index { - let mut htlc_tx = self.build_htlc_transaction(&local_commitment_txid, &htlc, true, &local_keys, feerate_per_kw); + let htlc_tx = self.build_htlc_transaction(&local_commitment_txid, &htlc, true, &local_keys, feerate_per_kw); let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &local_keys); log_trace!(self, "Checking HTLC tx signature {} by key {} against tx {} with redeemscript {}", log_bytes!(msg.htlc_signatures[idx].serialize_compact()[..]), log_bytes!(local_keys.b_htlc_key.serialize()), encode::serialize_hex(&htlc_tx), encode::serialize_hex(&htlc_redeemscript)); let htlc_sighash = hash_to_message!(&bip143::SighashComponents::new(&htlc_tx).sighash_all(&htlc_tx.input[0], &htlc_redeemscript, htlc.amount_msat / 1000)[..]); secp_check!(self.secp_ctx.verify(&htlc_sighash, &msg.htlc_signatures[idx], &local_keys.b_htlc_key), "Invalid HTLC tx signature from peer"); - let htlc_sig = if htlc.offered { - let htlc_sig = self.sign_htlc_transaction(&mut htlc_tx, &msg.htlc_signatures[idx], &None, &htlc, &local_keys)?; - new_local_commitment_txn.push(htlc_tx); - htlc_sig - } else { - self.create_htlc_tx_signature(&htlc_tx, &htlc, &local_keys)?.1 - }; - htlcs_and_sigs.push((htlc, Some((msg.htlc_signatures[idx], htlc_sig)), source)); + htlcs_and_sigs.push((htlc, Some(msg.htlc_signatures[idx]), source)); } else { htlcs_and_sigs.push((htlc, None, source)); } } let next_per_commitment_point = PublicKey::from_secret_key(&self.secp_ctx, &self.build_local_commitment_secret(self.cur_local_commitment_transaction_number - 1)); - let per_commitment_secret = chan_utils::build_commitment_secret(self.local_keys.commitment_seed, self.cur_local_commitment_transaction_number + 1); + let per_commitment_secret = chan_utils::build_commitment_secret(self.local_keys.commitment_seed(), self.cur_local_commitment_transaction_number + 1); // Update state now that we've passed all the can-fail calls... let mut need_our_commitment = false; @@ -1901,7 +1796,11 @@ impl Channel { } } - self.channel_monitor.provide_latest_local_commitment_tx_info(local_commitment_tx.0, local_keys, self.feerate_per_kw, htlcs_and_sigs); + let their_funding_pubkey = self.their_pubkeys.as_ref().unwrap().funding_pubkey; + + self.channel_monitor.provide_latest_local_commitment_tx_info( + LocalCommitmentTransaction::new_missing_local_sig(local_commitment_tx.0, &msg.signature, &PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.funding_key()), &their_funding_pubkey), + local_keys, self.feerate_per_kw, htlcs_and_sigs); for htlc in self.pending_inbound_htlcs.iter_mut() { let new_forward = if let &InboundHTLCState::RemoteAnnounced(ref forward_info) = &htlc.state { @@ -1922,7 +1821,6 @@ impl Channel { } self.cur_local_commitment_transaction_number -= 1; - self.last_local_commitment_txn = new_local_commitment_txn; // Note that if we need_our_commitment & !AwaitingRemoteRevoke we'll call // send_commitment_no_status_check() next which will reset this to RAAFirst. self.resend_order = RAACommitmentOrder::CommitmentFirst; @@ -2444,7 +2342,7 @@ impl Channel { if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 { return Err(ChannelError::Close("Peer sent update_fee when we needed a channel_reestablish")); } - Channel::check_remote_fee(fee_estimator, msg.feerate_per_kw)?; + Channel::::check_remote_fee(fee_estimator, msg.feerate_per_kw)?; self.pending_update_fee = Some(msg.feerate_per_kw as u64); self.channel_update_count += 1; Ok(()) @@ -2452,7 +2350,7 @@ impl Channel { fn get_last_revoke_and_ack(&self) -> msgs::RevokeAndACK { let next_per_commitment_point = PublicKey::from_secret_key(&self.secp_ctx, &self.build_local_commitment_secret(self.cur_local_commitment_transaction_number)); - let per_commitment_secret = chan_utils::build_commitment_secret(self.local_keys.commitment_seed, self.cur_local_commitment_transaction_number + 2); + let per_commitment_secret = chan_utils::build_commitment_secret(self.local_keys.commitment_seed(), self.cur_local_commitment_transaction_number + 2); msgs::RevokeAndACK { channel_id: self.channel_id, per_commitment_secret, @@ -2535,7 +2433,7 @@ impl Channel { if msg.next_remote_commitment_number > 0 { match msg.data_loss_protect { OptionalField::Present(ref data_loss) => { - if chan_utils::build_commitment_secret(self.local_keys.commitment_seed, INITIAL_COMMITMENT_NUMBER - msg.next_remote_commitment_number + 1) != data_loss.your_last_per_commitment_secret { + if chan_utils::build_commitment_secret(self.local_keys.commitment_seed(), INITIAL_COMMITMENT_NUMBER - msg.next_remote_commitment_number + 1) != data_loss.your_last_per_commitment_secret { return Err(ChannelError::Close("Peer sent a garbage channel_reestablish with secret key not matching the commitment height provided")); } if msg.next_remote_commitment_number > INITIAL_COMMITMENT_NUMBER - self.cur_local_commitment_transaction_number { @@ -2664,14 +2562,16 @@ impl Channel { let proposed_total_fee_satoshis = proposed_feerate * tx_weight / 1000; let (closing_tx, total_fee_satoshis) = self.build_closing_transaction(proposed_total_fee_satoshis, false); - let funding_redeemscript = self.get_funding_redeemscript(); - let sighash = hash_to_message!(&bip143::SighashComponents::new(&closing_tx).sighash_all(&closing_tx.input[0], &funding_redeemscript, self.channel_value_satoshis)[..]); + let our_sig = self.local_keys + .sign_closing_transaction(self.channel_value_satoshis, &self.get_funding_redeemscript(), &closing_tx, &self.secp_ctx) + .ok(); + if our_sig.is_none() { return None; } - self.last_sent_closing_fee = Some((proposed_feerate, total_fee_satoshis)); + self.last_sent_closing_fee = Some((proposed_feerate, total_fee_satoshis, our_sig.clone().unwrap())); Some(msgs::ClosingSigned { channel_id: self.channel_id, fee_satoshis: total_fee_satoshis, - signature: self.secp_ctx.sign(&sighash, &self.local_keys.funding_key), + signature: our_sig.unwrap(), }) } @@ -2745,9 +2645,32 @@ impl Channel { self.channel_state |= ChannelState::LocalShutdownSent as u32; self.channel_update_count += 1; + Ok((our_shutdown, self.maybe_propose_first_closing_signed(fee_estimator), dropped_outbound_htlcs)) } + fn build_signed_closing_transaction(&self, tx: &mut Transaction, their_sig: &Signature, our_sig: &Signature) { + if tx.input.len() != 1 { panic!("Tried to sign closing transaction that had input count != 1!"); } + if tx.input[0].witness.len() != 0 { panic!("Tried to re-sign closing transaction"); } + if tx.output.len() > 2 { panic!("Tried to sign bogus closing transaction"); } + + tx.input[0].witness.push(Vec::new()); // First is the multisig dummy + + let our_funding_key = PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.funding_key()).serialize(); + let their_funding_key = self.their_funding_pubkey().serialize(); + if our_funding_key[..] < their_funding_key[..] { + tx.input[0].witness.push(our_sig.serialize_der().to_vec()); + tx.input[0].witness.push(their_sig.serialize_der().to_vec()); + } else { + tx.input[0].witness.push(their_sig.serialize_der().to_vec()); + tx.input[0].witness.push(our_sig.serialize_der().to_vec()); + } + tx.input[0].witness[1].push(SigHashType::All as u8); + tx.input[0].witness[2].push(SigHashType::All as u8); + + tx.input[0].witness.push(self.get_funding_redeemscript().into_bytes()); + } + pub fn closing_signed(&mut self, fee_estimator: &FeeEstimator, msg: &msgs::ClosingSigned) -> Result<(Option, Option), ChannelError> { if self.channel_state & BOTH_SIDES_SHUTDOWN_MASK != BOTH_SIDES_SHUTDOWN_MASK { return Err(ChannelError::Close("Remote end sent us a closing_signed before both sides provided a shutdown")); @@ -2769,20 +2692,22 @@ impl Channel { } let mut sighash = hash_to_message!(&bip143::SighashComponents::new(&closing_tx).sighash_all(&closing_tx.input[0], &funding_redeemscript, self.channel_value_satoshis)[..]); - match self.secp_ctx.verify(&sighash, &msg.signature, &self.their_funding_pubkey.unwrap()) { + let their_funding_pubkey = &self.their_pubkeys.as_ref().unwrap().funding_pubkey; + + match self.secp_ctx.verify(&sighash, &msg.signature, their_funding_pubkey) { Ok(_) => {}, Err(_e) => { // The remote end may have decided to revoke their output due to inconsistent dust // limits, so check for that case by re-checking the signature here. closing_tx = self.build_closing_transaction(msg.fee_satoshis, true).0; sighash = hash_to_message!(&bip143::SighashComponents::new(&closing_tx).sighash_all(&closing_tx.input[0], &funding_redeemscript, self.channel_value_satoshis)[..]); - secp_check!(self.secp_ctx.verify(&sighash, &msg.signature, &self.their_funding_pubkey.unwrap()), "Invalid closing tx signature from peer"); + secp_check!(self.secp_ctx.verify(&sighash, &msg.signature, self.their_funding_pubkey()), "Invalid closing tx signature from peer"); }, }; - if let Some((_, last_fee)) = self.last_sent_closing_fee { + if let Some((_, last_fee, our_sig)) = self.last_sent_closing_fee { if last_fee == msg.fee_satoshis { - self.sign_commitment_transaction(&mut closing_tx, &msg.signature); + self.build_signed_closing_transaction(&mut closing_tx, &msg.signature, &our_sig); self.channel_state = ChannelState::ShutdownComplete as u32; self.channel_update_count += 1; return Ok((None, Some(closing_tx))); @@ -2793,9 +2718,10 @@ impl Channel { ($new_feerate: expr) => { let closing_tx_max_weight = Self::get_closing_transaction_weight(&self.get_closing_scriptpubkey(), self.their_shutdown_scriptpubkey.as_ref().unwrap()); let (closing_tx, used_total_fee) = self.build_closing_transaction($new_feerate * closing_tx_max_weight / 1000, false); - sighash = hash_to_message!(&bip143::SighashComponents::new(&closing_tx).sighash_all(&closing_tx.input[0], &funding_redeemscript, self.channel_value_satoshis)[..]); - let our_sig = self.secp_ctx.sign(&sighash, &self.local_keys.funding_key); - self.last_sent_closing_fee = Some(($new_feerate, used_total_fee)); + let our_sig = self.local_keys + .sign_closing_transaction(self.channel_value_satoshis, &funding_redeemscript, &closing_tx, &self.secp_ctx) + .map_err(|_| ChannelError::Close("External signer refused to sign closing transaction"))?; + self.last_sent_closing_fee = Some(($new_feerate, used_total_fee, our_sig.clone())); return Ok((Some(msgs::ClosingSigned { channel_id: self.channel_id, fee_satoshis: used_total_fee, @@ -2808,7 +2734,7 @@ impl Channel { if self.channel_outbound { let our_max_feerate = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Normal); if proposed_sat_per_kw > our_max_feerate { - if let Some((last_feerate, _)) = self.last_sent_closing_fee { + if let Some((last_feerate, _, _)) = self.last_sent_closing_fee { if our_max_feerate <= last_feerate { return Err(ChannelError::Close("Unable to come to consensus about closing feerate, remote wanted something higher than our Normal feerate")); } @@ -2818,7 +2744,7 @@ impl Channel { } else { let our_min_feerate = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Background); if proposed_sat_per_kw < our_min_feerate { - if let Some((last_feerate, _)) = self.last_sent_closing_fee { + if let Some((last_feerate, _, _)) = self.last_sent_closing_fee { if our_min_feerate >= last_feerate { return Err(ChannelError::Close("Unable to come to consensus about closing feerate, remote wanted something lower than our Background feerate")); } @@ -2827,7 +2753,11 @@ impl Channel { } } - let our_sig = self.sign_commitment_transaction(&mut closing_tx, &msg.signature); + let our_sig = self.local_keys + .sign_closing_transaction(self.channel_value_satoshis, &funding_redeemscript, &closing_tx, &self.secp_ctx) + .map_err(|_| ChannelError::Close("External signer refused to sign closing transaction"))?; + self.build_signed_closing_transaction(&mut closing_tx, &msg.signature, &our_sig); + self.channel_state = ChannelState::ShutdownComplete as u32; self.channel_update_count += 1; @@ -2851,11 +2781,11 @@ impl Channel { } /// May only be called after funding has been initiated (ie is_funding_initiated() is true) - pub fn channel_monitor(&self) -> ChannelMonitor { + pub fn channel_monitor(&mut self) -> &mut ChannelMonitor { if self.channel_state < ChannelState::FundingCreated as u32 { panic!("Can't get a channel monitor until funding has been created"); } - self.channel_monitor.clone() + &mut self.channel_monitor } /// Guaranteed to be Some after both FundingLocked messages have been exchanged (and, thus, @@ -2912,7 +2842,7 @@ impl Channel { } #[cfg(test)] - pub fn get_local_keys(&self) -> &ChannelKeys { + pub fn get_local_keys(&self) -> &ChanSigner { &self.local_keys } @@ -3171,17 +3101,17 @@ impl Channel { funding_satoshis: self.channel_value_satoshis, push_msat: self.channel_value_satoshis * 1000 - self.value_to_self_msat, dust_limit_satoshis: self.our_dust_limit_satoshis, - max_htlc_value_in_flight_msat: Channel::get_our_max_htlc_value_in_flight_msat(self.channel_value_satoshis), - channel_reserve_satoshis: Channel::get_our_channel_reserve_satoshis(self.channel_value_satoshis), + max_htlc_value_in_flight_msat: Channel::::get_our_max_htlc_value_in_flight_msat(self.channel_value_satoshis), + channel_reserve_satoshis: Channel::::get_our_channel_reserve_satoshis(self.channel_value_satoshis), htlc_minimum_msat: self.our_htlc_minimum_msat, feerate_per_kw: fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Background) as u32, to_self_delay: self.our_to_self_delay, max_accepted_htlcs: OUR_MAX_HTLCS, - funding_pubkey: PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.funding_key), - revocation_basepoint: PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.revocation_base_key), - payment_basepoint: PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.payment_base_key), - delayed_payment_basepoint: PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.delayed_payment_base_key), - htlc_basepoint: PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.htlc_base_key), + funding_pubkey: PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.funding_key()), + revocation_basepoint: PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.revocation_base_key()), + payment_basepoint: PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.payment_base_key()), + delayed_payment_basepoint: PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.delayed_payment_base_key()), + htlc_basepoint: PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.htlc_base_key()), first_per_commitment_point: PublicKey::from_secret_key(&self.secp_ctx, &local_commitment_secret), channel_flags: if self.config.announced_channel {1} else {0}, shutdown_scriptpubkey: OptionalField::Present(if self.config.commit_upfront_shutdown_pubkey { self.get_closing_scriptpubkey() } else { Builder::new().into_script() }) @@ -3204,17 +3134,17 @@ impl Channel { msgs::AcceptChannel { temporary_channel_id: self.channel_id, dust_limit_satoshis: self.our_dust_limit_satoshis, - max_htlc_value_in_flight_msat: Channel::get_our_max_htlc_value_in_flight_msat(self.channel_value_satoshis), - channel_reserve_satoshis: Channel::get_our_channel_reserve_satoshis(self.channel_value_satoshis), + max_htlc_value_in_flight_msat: Channel::::get_our_max_htlc_value_in_flight_msat(self.channel_value_satoshis), + channel_reserve_satoshis: Channel::::get_our_channel_reserve_satoshis(self.channel_value_satoshis), htlc_minimum_msat: self.our_htlc_minimum_msat, minimum_depth: self.minimum_depth, to_self_delay: self.our_to_self_delay, max_accepted_htlcs: OUR_MAX_HTLCS, - funding_pubkey: PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.funding_key), - revocation_basepoint: PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.revocation_base_key), - payment_basepoint: PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.payment_base_key), - delayed_payment_basepoint: PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.delayed_payment_base_key), - htlc_basepoint: PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.htlc_base_key), + funding_pubkey: PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.funding_key()), + revocation_basepoint: PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.revocation_base_key()), + payment_basepoint: PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.payment_base_key()), + delayed_payment_basepoint: PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.delayed_payment_base_key()), + htlc_basepoint: PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.htlc_base_key()), first_per_commitment_point: PublicKey::from_secret_key(&self.secp_ctx, &local_commitment_secret), shutdown_scriptpubkey: OptionalField::Present(if self.config.commit_upfront_shutdown_pubkey { self.get_closing_scriptpubkey() } else { Builder::new().into_script() }) } @@ -3222,14 +3152,10 @@ impl Channel { /// If an Err is returned, it is a ChannelError::Close (for get_outbound_funding_created) fn get_outbound_funding_created_signature(&mut self) -> Result<(Signature, Transaction), ChannelError> { - let funding_script = self.get_funding_redeemscript(); - let remote_keys = self.build_remote_transaction_keys()?; let remote_initial_commitment_tx = self.build_commitment_transaction(self.cur_remote_commitment_transaction_number, &remote_keys, false, false, self.feerate_per_kw).0; - let remote_sighash = hash_to_message!(&bip143::SighashComponents::new(&remote_initial_commitment_tx).sighash_all(&remote_initial_commitment_tx.input[0], &funding_script, self.channel_value_satoshis)[..]); - - // We sign the "remote" commitment transaction, allowing them to broadcast the tx if they wish. - Ok((self.secp_ctx.sign(&remote_sighash, &self.local_keys.funding_key), remote_initial_commitment_tx)) + Ok((self.local_keys.sign_remote_commitment(self.channel_value_satoshis, self.feerate_per_kw, &remote_initial_commitment_tx, &remote_keys, &Vec::new(), self.our_to_self_delay, &self.secp_ctx) + .map_err(|_| ChannelError::Close("Failed to get signatures for new commitment_signed"))?.0, remote_initial_commitment_tx)) } /// Updates channel state with knowledge of the funding transaction's txid/index, and generates @@ -3300,21 +3226,21 @@ impl Channel { } let were_node_one = our_node_id.serialize()[..] < self.their_node_id.serialize()[..]; - let our_bitcoin_key = PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.funding_key); + let our_bitcoin_key = PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.funding_key()); let msg = msgs::UnsignedChannelAnnouncement { - features: msgs::GlobalFeatures::new(), + features: ChannelFeatures::supported(), chain_hash: chain_hash, short_channel_id: self.get_short_channel_id().unwrap(), node_id_1: if were_node_one { our_node_id } else { self.get_their_node_id() }, node_id_2: if were_node_one { self.get_their_node_id() } else { our_node_id }, - bitcoin_key_1: if were_node_one { our_bitcoin_key } else { self.their_funding_pubkey.unwrap() }, - bitcoin_key_2: if were_node_one { self.their_funding_pubkey.unwrap() } else { our_bitcoin_key }, + bitcoin_key_1: if were_node_one { our_bitcoin_key } else { self.their_funding_pubkey().clone() }, + bitcoin_key_2: if were_node_one { self.their_funding_pubkey().clone() } else { our_bitcoin_key }, excess_data: Vec::new(), }; - let msghash = hash_to_message!(&Sha256dHash::hash(&msg.encode()[..])[..]); - let sig = self.secp_ctx.sign(&msghash, &self.local_keys.funding_key); + let sig = self.local_keys.sign_channel_announcement(&msg, &self.secp_ctx) + .map_err(|_| ChannelError::Ignore("Signer rejected channel_announcement"))?; Ok((msg, sig)) } @@ -3519,8 +3445,6 @@ impl Channel { /// Only fails in case of bad keys. Used for channel_reestablish commitment_signed generation /// when we shouldn't change HTLC/channel state. fn send_commitment_no_state_update(&self) -> Result<(msgs::CommitmentSigned, (Transaction, Vec<(HTLCOutputInCommitment, Option<&HTLCSource>)>)), ChannelError> { - let funding_script = self.get_funding_redeemscript(); - let mut feerate_per_kw = self.feerate_per_kw; if let Some(feerate) = self.pending_update_fee { if self.channel_outbound { @@ -3530,27 +3454,37 @@ impl Channel { let remote_keys = self.build_remote_transaction_keys()?; let remote_commitment_tx = self.build_commitment_transaction(self.cur_remote_commitment_transaction_number, &remote_keys, false, true, feerate_per_kw); - let remote_commitment_txid = remote_commitment_tx.0.txid(); - let remote_sighash = hash_to_message!(&bip143::SighashComponents::new(&remote_commitment_tx.0).sighash_all(&remote_commitment_tx.0.input[0], &funding_script, self.channel_value_satoshis)[..]); - let our_sig = self.secp_ctx.sign(&remote_sighash, &self.local_keys.funding_key); - log_trace!(self, "Signing remote commitment tx {} with redeemscript {} with pubkey {} -> {}", encode::serialize_hex(&remote_commitment_tx.0), encode::serialize_hex(&funding_script), log_bytes!(PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.funding_key).serialize()), log_bytes!(our_sig.serialize_compact()[..])); + let (signature, htlc_signatures); - let mut htlc_sigs = Vec::with_capacity(remote_commitment_tx.1); - for &(ref htlc, _) in remote_commitment_tx.2.iter() { - if let Some(_) = htlc.transaction_output_index { - let htlc_tx = self.build_htlc_transaction(&remote_commitment_txid, htlc, false, &remote_keys, feerate_per_kw); - let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &remote_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 our_htlc_key = secp_check!(chan_utils::derive_private_key(&self.secp_ctx, &remote_keys.per_commitment_point, &self.local_keys.htlc_base_key), "Derived invalid key, peer is maliciously selecting parameters"); - htlc_sigs.push(self.secp_ctx.sign(&htlc_sighash, &our_htlc_key)); - log_trace!(self, "Signing remote HTLC tx {} with redeemscript {} with pubkey {} -> {}", encode::serialize_hex(&htlc_tx), encode::serialize_hex(&htlc_redeemscript), log_bytes!(PublicKey::from_secret_key(&self.secp_ctx, &our_htlc_key).serialize()), log_bytes!(htlc_sigs.last().unwrap().serialize_compact()[..])); + { + let mut htlcs = Vec::with_capacity(remote_commitment_tx.2.len()); + for &(ref htlc, _) in remote_commitment_tx.2.iter() { + htlcs.push(htlc); + } + + let res = self.local_keys.sign_remote_commitment(self.channel_value_satoshis, feerate_per_kw, &remote_commitment_tx.0, &remote_keys, &htlcs, self.our_to_self_delay, &self.secp_ctx) + .map_err(|_| ChannelError::Close("Failed to get signatures for new commitment_signed"))?; + signature = res.0; + htlc_signatures = res.1; + + log_trace!(self, "Signed remote commitment tx {} with redeemscript {} -> {}", + encode::serialize_hex(&remote_commitment_tx.0), + encode::serialize_hex(&self.get_funding_redeemscript()), + log_bytes!(signature.serialize_compact()[..])); + + for (ref htlc_sig, ref htlc) in htlc_signatures.iter().zip(htlcs) { + log_trace!(self, "Signed remote HTLC tx {} with redeemscript {} with pubkey {} -> {}", + encode::serialize_hex(&chan_utils::build_htlc_transaction(&remote_commitment_tx.0.txid(), feerate_per_kw, self.our_to_self_delay, htlc, &remote_keys.a_delayed_payment_key, &remote_keys.revocation_key)), + encode::serialize_hex(&chan_utils::get_htlc_redeemscript(&htlc, &remote_keys)), + log_bytes!(remote_keys.a_htlc_key.serialize()), + log_bytes!(htlc_sig.serialize_compact()[..])); } } Ok((msgs::CommitmentSigned { channel_id: self.channel_id, - signature: our_sig, - htlc_signatures: htlc_sigs, + signature, + htlc_signatures, }, (remote_commitment_tx.0, remote_commitment_tx.2))) } @@ -3647,9 +3581,7 @@ impl Channel { self.channel_state = ChannelState::ShutdownComplete as u32; self.channel_update_count += 1; - let mut res = Vec::new(); - mem::swap(&mut res, &mut self.last_local_commitment_txn); - (res, dropped_outbound_htlcs) + (self.channel_monitor.get_latest_local_commitment_txn(), dropped_outbound_htlcs) } } @@ -3688,7 +3620,7 @@ impl Readable for InboundHTLCRemovalReason { } } -impl Writeable for Channel { +impl Writeable for Channel { fn write(&self, writer: &mut W) -> Result<(), ::std::io::Error> { // Note that we write out as if remove_uncommitted_htlcs_and_mark_paused had just been // called but include holding cell updates (and obviously we don't modify self). @@ -3839,21 +3771,12 @@ impl Writeable for Channel { self.channel_update_count.write(writer)?; self.feerate_per_kw.write(writer)?; - (self.last_local_commitment_txn.len() as u64).write(writer)?; - for tx in self.last_local_commitment_txn.iter() { - if let Err(e) = tx.consensus_encode(&mut WriterWriteAdaptor(writer)) { - match e { - encode::Error::Io(e) => return Err(e), - _ => panic!("last_local_commitment_txn must have been well-formed!"), - } - } - } - match self.last_sent_closing_fee { - Some((feerate, fee)) => { + Some((feerate, fee, sig)) => { 1u8.write(writer)?; feerate.write(writer)?; fee.write(writer)?; + sig.write(writer)?; }, None => 0u8.write(writer)?, } @@ -3875,11 +3798,7 @@ impl Writeable for Channel { self.their_max_accepted_htlcs.write(writer)?; self.minimum_depth.write(writer)?; - write_option!(self.their_funding_pubkey); - write_option!(self.their_revocation_basepoint); - write_option!(self.their_payment_basepoint); - write_option!(self.their_delayed_payment_basepoint); - write_option!(self.their_htlc_basepoint); + write_option!(self.their_pubkeys); write_option!(self.their_cur_commitment_point); write_option!(self.their_prev_commitment_point); @@ -3892,7 +3811,7 @@ impl Writeable for Channel { } } -impl ReadableArgs> for Channel { +impl> ReadableArgs> for Channel { fn read(reader: &mut R, logger: Arc) -> Result { let _ver: u8 = Readable::read(reader)?; let min_ver: u8 = Readable::read(reader)?; @@ -4006,18 +3925,9 @@ impl ReadableArgs> for Channel { let channel_update_count = Readable::read(reader)?; let feerate_per_kw = Readable::read(reader)?; - let last_local_commitment_txn_count: u64 = Readable::read(reader)?; - let mut last_local_commitment_txn = Vec::with_capacity(cmp::min(last_local_commitment_txn_count as usize, OUR_MAX_HTLCS as usize*2 + 1)); - for _ in 0..last_local_commitment_txn_count { - last_local_commitment_txn.push(match Transaction::consensus_decode(reader.by_ref()) { - Ok(tx) => tx, - Err(_) => return Err(DecodeError::InvalidValue), - }); - } - let last_sent_closing_fee = match >::read(reader)? { 0 => None, - 1 => Some((Readable::read(reader)?, Readable::read(reader)?)), + 1 => Some((Readable::read(reader)?, Readable::read(reader)?, Readable::read(reader)?)), _ => return Err(DecodeError::InvalidValue), }; @@ -4038,11 +3948,7 @@ impl ReadableArgs> for Channel { let their_max_accepted_htlcs = Readable::read(reader)?; let minimum_depth = Readable::read(reader)?; - let their_funding_pubkey = Readable::read(reader)?; - let their_revocation_basepoint = Readable::read(reader)?; - let their_payment_basepoint = Readable::read(reader)?; - let their_delayed_payment_basepoint = Readable::read(reader)?; - let their_htlc_basepoint = Readable::read(reader)?; + let their_pubkeys = Readable::read(reader)?; let their_cur_commitment_point = Readable::read(reader)?; let their_prev_commitment_point = Readable::read(reader)?; @@ -4097,8 +4003,6 @@ impl ReadableArgs> for Channel { #[cfg(debug_assertions)] max_commitment_tx_output_remote: ::std::sync::Mutex::new((0, 0)), - last_local_commitment_txn, - last_sent_closing_fee, funding_tx_confirmed_in, @@ -4117,11 +4021,7 @@ impl ReadableArgs> for Channel { their_max_accepted_htlcs, minimum_depth, - their_funding_pubkey, - their_revocation_basepoint, - their_payment_basepoint, - their_delayed_payment_basepoint, - their_htlc_basepoint, + their_pubkeys, their_cur_commitment_point, their_prev_commitment_point, @@ -4151,13 +4051,14 @@ mod tests { use ln::channel::{Channel,ChannelKeys,InboundHTLCOutput,OutboundHTLCOutput,InboundHTLCState,OutboundHTLCState,HTLCOutputInCommitment,TxCreationKeys}; use ln::channel::MAX_FUNDING_SATOSHIS; use ln::chan_utils; + use ln::chan_utils::{LocalCommitmentTransaction, ChannelPublicKeys}; use chain::chaininterface::{FeeEstimator,ConfirmationTarget}; - use chain::keysinterface::KeysInterface; + use chain::keysinterface::{InMemoryChannelKeys, KeysInterface}; use chain::transaction::OutPoint; use util::config::UserConfig; use util::test_utils; use util::logger::Logger; - use secp256k1::{Secp256k1,Message,Signature}; + use secp256k1::{Secp256k1, Message, Signature, All}; use secp256k1::key::{SecretKey,PublicKey}; use bitcoin_hashes::sha256::Hash as Sha256; use bitcoin_hashes::sha256d::Hash as Sha256dHash; @@ -4181,9 +4082,11 @@ mod tests { } struct Keys { - chan_keys: ChannelKeys, + chan_keys: InMemoryChannelKeys, } impl KeysInterface for Keys { + type ChanKeySigner = InMemoryChannelKeys; + fn get_node_secret(&self) -> SecretKey { panic!(); } fn get_destination_script(&self) -> Script { let secp_ctx = Secp256k1::signing_only(); @@ -4198,11 +4101,15 @@ mod tests { PublicKey::from_secret_key(&secp_ctx, &channel_close_key) } - fn get_channel_keys(&self, _inbound: bool) -> ChannelKeys { self.chan_keys.clone() } + fn get_channel_keys(&self, _inbound: bool) -> InMemoryChannelKeys { self.chan_keys.clone() } fn get_onion_rand(&self) -> (SecretKey, [u8; 32]) { panic!(); } fn get_channel_id(&self) -> [u8; 32] { [0; 32] } } + fn public_from_secret_hex(secp_ctx: &Secp256k1, hex: &str) -> PublicKey { + PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&hex::decode(hex).unwrap()[..]).unwrap()) + } + #[test] fn outbound_commitment_test() { // Test vectors from BOLT 3 Appendix C: @@ -4210,7 +4117,7 @@ mod tests { let logger : Arc = Arc::new(test_utils::TestLogger::new()); let secp_ctx = Secp256k1::new(); - let chan_keys = ChannelKeys { + let chan_keys = InMemoryChannelKeys { funding_key: SecretKey::from_slice(&hex::decode("30ff4956bbdd3222d44cc5e8a1261dab1e07957bdac5ae88fe3261ef321f3749").unwrap()[..]).unwrap(), payment_base_key: SecretKey::from_slice(&hex::decode("1111111111111111111111111111111111111111111111111111111111111111").unwrap()[..]).unwrap(), delayed_payment_base_key: SecretKey::from_slice(&hex::decode("3333333333333333333333333333333333333333333333333333333333333333").unwrap()[..]).unwrap(), @@ -4219,43 +4126,49 @@ mod tests { // These aren't set in the test vectors: revocation_base_key: SecretKey::from_slice(&hex::decode("0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap()[..]).unwrap(), commitment_seed: [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff], + remote_channel_pubkeys: None, }; - assert_eq!(PublicKey::from_secret_key(&secp_ctx, &chan_keys.funding_key).serialize()[..], + assert_eq!(PublicKey::from_secret_key(&secp_ctx, chan_keys.funding_key()).serialize()[..], hex::decode("023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb").unwrap()[..]); - let keys_provider: Arc = Arc::new(Keys { chan_keys }); + let keys_provider: Arc> = Arc::new(Keys { chan_keys }); let their_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); - let mut config = UserConfig::new(); + let mut config = UserConfig::default(); config.channel_options.announced_channel = false; - let mut chan = Channel::new_outbound(&feeest, &keys_provider, their_node_id, 10000000, 100000, 42, Arc::clone(&logger), &config).unwrap(); // Nothing uses their network key in this test + let mut chan = Channel::::new_outbound(&feeest, &keys_provider, their_node_id, 10000000, 100000, 42, Arc::clone(&logger), &config).unwrap(); // Nothing uses their network key in this test chan.their_to_self_delay = 144; chan.our_dust_limit_satoshis = 546; let funding_info = OutPoint::new(Sha256dHash::from_hex("8984484a580b825b9972d7adb15050b3ab624ccd731946b3eeddb92f4e7ef6be").unwrap(), 0); chan.channel_monitor.set_funding_info((funding_info, Script::new())); - chan.their_payment_basepoint = Some(PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&hex::decode("4444444444444444444444444444444444444444444444444444444444444444").unwrap()[..]).unwrap())); - assert_eq!(chan.their_payment_basepoint.unwrap().serialize()[..], - hex::decode("032c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991").unwrap()[..]); + let their_pubkeys = ChannelPublicKeys { + funding_pubkey: public_from_secret_hex(&secp_ctx, "1552dfba4f6cf29a62a0af13c8d6981d36d0ef8d61ba10fb0fe90da7634d7e13"), + revocation_basepoint: PublicKey::from_slice(&hex::decode("02466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f27").unwrap()[..]).unwrap(), + payment_basepoint: public_from_secret_hex(&secp_ctx, "4444444444444444444444444444444444444444444444444444444444444444"), + delayed_payment_basepoint: public_from_secret_hex(&secp_ctx, "1552dfba4f6cf29a62a0af13c8d6981d36d0ef8d61ba10fb0fe90da7634d7e13"), + htlc_basepoint: public_from_secret_hex(&secp_ctx, "4444444444444444444444444444444444444444444444444444444444444444") + }; - chan.their_funding_pubkey = Some(PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&hex::decode("1552dfba4f6cf29a62a0af13c8d6981d36d0ef8d61ba10fb0fe90da7634d7e13").unwrap()[..]).unwrap())); - assert_eq!(chan.their_funding_pubkey.unwrap().serialize()[..], - hex::decode("030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c1").unwrap()[..]); + assert_eq!(their_pubkeys.payment_basepoint.serialize()[..], + hex::decode("032c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991").unwrap()[..]); - chan.their_htlc_basepoint = Some(PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&hex::decode("4444444444444444444444444444444444444444444444444444444444444444").unwrap()[..]).unwrap())); - assert_eq!(chan.their_htlc_basepoint.unwrap().serialize()[..], - hex::decode("032c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991").unwrap()[..]); + assert_eq!(their_pubkeys.funding_pubkey.serialize()[..], + hex::decode("030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c1").unwrap()[..]); - chan.their_revocation_basepoint = Some(PublicKey::from_slice(&hex::decode("02466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f27").unwrap()[..]).unwrap()); + assert_eq!(their_pubkeys.htlc_basepoint.serialize()[..], + hex::decode("032c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991").unwrap()[..]); // We can't just use build_local_transaction_keys here as the per_commitment_secret is not // derived from a commitment_seed, so instead we copy it here and call // build_commitment_transaction. - let delayed_payment_base = PublicKey::from_secret_key(&secp_ctx, &chan.local_keys.delayed_payment_base_key); + let delayed_payment_base = PublicKey::from_secret_key(&secp_ctx, chan.local_keys.delayed_payment_base_key()); let per_commitment_secret = SecretKey::from_slice(&hex::decode("1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100").unwrap()[..]).unwrap(); let per_commitment_point = PublicKey::from_secret_key(&secp_ctx, &per_commitment_secret); - let htlc_basepoint = PublicKey::from_secret_key(&secp_ctx, &chan.local_keys.htlc_base_key); - let keys = TxCreationKeys::new(&secp_ctx, &per_commitment_point, &delayed_payment_base, &htlc_basepoint, &chan.their_revocation_basepoint.unwrap(), &chan.their_payment_basepoint.unwrap(), &chan.their_htlc_basepoint.unwrap()).unwrap(); + let htlc_basepoint = PublicKey::from_secret_key(&secp_ctx, chan.local_keys.htlc_base_key()); + let keys = TxCreationKeys::new(&secp_ctx, &per_commitment_point, &delayed_payment_base, &htlc_basepoint, &their_pubkeys.revocation_basepoint, &their_pubkeys.payment_basepoint, &their_pubkeys.htlc_basepoint).unwrap(); + + chan.their_pubkeys = Some(their_pubkeys); let mut unsigned_tx: (Transaction, Vec); @@ -4268,13 +4181,15 @@ mod tests { .collect(); (res.0, htlcs) }; + let redeemscript = chan.get_funding_redeemscript(); let their_signature = Signature::from_der(&hex::decode($their_sig_hex).unwrap()[..]).unwrap(); - let sighash = Message::from_slice(&bip143::SighashComponents::new(&unsigned_tx.0).sighash_all(&unsigned_tx.0.input[0], &chan.get_funding_redeemscript(), chan.channel_value_satoshis)[..]).unwrap(); - secp_ctx.verify(&sighash, &their_signature, &chan.their_funding_pubkey.unwrap()).unwrap(); + let sighash = Message::from_slice(&bip143::SighashComponents::new(&unsigned_tx.0).sighash_all(&unsigned_tx.0.input[0], &redeemscript, chan.channel_value_satoshis)[..]).unwrap(); + secp_ctx.verify(&sighash, &their_signature, chan.their_funding_pubkey()).unwrap(); - chan.sign_commitment_transaction(&mut unsigned_tx.0, &their_signature); + let mut localtx = LocalCommitmentTransaction::new_missing_local_sig(unsigned_tx.0.clone(), &their_signature, &PublicKey::from_secret_key(&secp_ctx, chan.local_keys.funding_key()), chan.their_funding_pubkey()); + localtx.add_local_sig(chan.local_keys.funding_key(), &redeemscript, chan.channel_value_satoshis, &chan.secp_ctx); - assert_eq!(serialize(&unsigned_tx.0)[..], + assert_eq!(serialize(localtx.with_valid_witness())[..], hex::decode($tx_hex).unwrap()[..]); }; } @@ -4301,7 +4216,7 @@ mod tests { assert!(preimage.is_some()); } - chan.sign_htlc_transaction(&mut htlc_tx, &remote_signature, &preimage, &htlc, &keys).unwrap(); + chan_utils::sign_htlc_transaction(&mut htlc_tx, &remote_signature, &preimage, &htlc, &keys.a_htlc_key, &keys.b_htlc_key, &keys.revocation_key, &keys.per_commitment_point, chan.local_keys.htlc_base_key(), &chan.secp_ctx).unwrap(); assert_eq!(serialize(&htlc_tx)[..], hex::decode($tx_hex).unwrap()[..]); }; @@ -4699,21 +4614,21 @@ mod tests { let mut seed = [0; 32]; seed[0..32].clone_from_slice(&hex::decode("0000000000000000000000000000000000000000000000000000000000000000").unwrap()); - assert_eq!(chan_utils::build_commitment_secret(seed, 281474976710655), + assert_eq!(chan_utils::build_commitment_secret(&seed, 281474976710655), hex::decode("02a40c85b6f28da08dfdbe0926c53fab2de6d28c10301f8f7c4073d5e42e3148").unwrap()[..]); seed[0..32].clone_from_slice(&hex::decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF").unwrap()); - assert_eq!(chan_utils::build_commitment_secret(seed, 281474976710655), + assert_eq!(chan_utils::build_commitment_secret(&seed, 281474976710655), hex::decode("7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc").unwrap()[..]); - assert_eq!(chan_utils::build_commitment_secret(seed, 0xaaaaaaaaaaa), + assert_eq!(chan_utils::build_commitment_secret(&seed, 0xaaaaaaaaaaa), hex::decode("56f4008fb007ca9acf0e15b054d5c9fd12ee06cea347914ddbaed70d1c13a528").unwrap()[..]); - assert_eq!(chan_utils::build_commitment_secret(seed, 0x555555555555), + assert_eq!(chan_utils::build_commitment_secret(&seed, 0x555555555555), hex::decode("9015daaeb06dba4ccc05b91b2f73bd54405f2be9f217fbacd3c5ac2e62327d31").unwrap()[..]); seed[0..32].clone_from_slice(&hex::decode("0101010101010101010101010101010101010101010101010101010101010101").unwrap()); - assert_eq!(chan_utils::build_commitment_secret(seed, 1), + assert_eq!(chan_utils::build_commitment_secret(&seed, 1), hex::decode("915c75942a26bb3a433a8ce2cb0427c29ec6c1775cfc78328b57f6ba7bfeaa9c").unwrap()[..]); }