X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=src%2Fln%2Fchannel.rs;h=b9a81f6ebc0465cf34396eb44073b790fd7c3925;hb=224fb05cc53526e7b861e746183451d3d74ad549;hp=6b1511387d61d0048c8e8b1b29b81378df81c1b3;hpb=c36d23107c040f2b4f8109a6fb1d90f85dfefd39;p=rust-lightning diff --git a/src/ln/channel.rs b/src/ln/channel.rs index 6b151138..b9a81f6e 100644 --- a/src/ln/channel.rs +++ b/src/ln/channel.rs @@ -4,28 +4,31 @@ use bitcoin::blockdata::transaction::{TxIn, TxOut, Transaction, SigHashType}; use bitcoin::blockdata::opcodes; use bitcoin::util::hash::{Sha256dHash, Hash160}; use bitcoin::util::bip143; -use bitcoin::network::serialize::BitcoinHash; +use bitcoin::network; +use bitcoin::network::serialize::{BitcoinHash, RawDecoder, RawEncoder}; +use bitcoin::network::encodable::{ConsensusEncodable, ConsensusDecodable}; use secp256k1::key::{PublicKey,SecretKey}; use secp256k1::{Secp256k1,Message,Signature}; use secp256k1; use crypto::digest::Digest; -use crypto::hkdf::{hkdf_extract,hkdf_expand}; use ln::msgs; -use ln::msgs::{ErrorAction, HandleError, RAACommitmentOrder}; +use ln::msgs::{DecodeError, ErrorAction, HandleError}; use ln::channelmonitor::ChannelMonitor; -use ln::channelmanager::{PendingHTLCStatus, HTLCSource, PendingForwardHTLCInfo, HTLCFailReason, HTLCFailureMsg}; +use ln::channelmanager::{PendingHTLCStatus, HTLCSource, HTLCFailReason, HTLCFailureMsg, PendingForwardHTLCInfo, RAACommitmentOrder}; use ln::chan_utils::{TxCreationKeys,HTLCOutputInCommitment,HTLC_SUCCESS_TX_WEIGHT,HTLC_TIMEOUT_TX_WEIGHT}; use ln::chan_utils; use chain::chaininterface::{FeeEstimator,ConfirmationTarget}; use chain::transaction::OutPoint; +use chain::keysinterface::{ChannelKeys, KeysInterface}; use util::{transaction_utils,rng}; -use util::ser::Writeable; +use util::ser::{Readable, ReadableArgs, Writeable, Writer, WriterWriteAdaptor}; use util::sha2::Sha256; use util::logger::Logger; use util::errors::APIError; +use util::config::{UserConfig,ChannelConfig}; use std; use std::default::Default; @@ -33,17 +36,6 @@ use std::{cmp,mem}; use std::time::Instant; use std::sync::{Arc}; -pub struct ChannelKeys { - pub funding_key: SecretKey, - pub revocation_base_key: SecretKey, - pub payment_base_key: SecretKey, - pub delayed_payment_base_key: SecretKey, - pub htlc_base_key: SecretKey, - pub channel_close_key: SecretKey, - pub channel_monitor_claim_key: SecretKey, - pub commitment_seed: [u8; 32], -} - #[cfg(test)] pub struct ChannelValueStat { pub value_to_self_msat: u64, @@ -55,49 +47,6 @@ pub struct ChannelValueStat { pub their_max_htlc_value_in_flight_msat: u64, // outgoing } -impl ChannelKeys { - pub fn new_from_seed(seed: &[u8; 32]) -> Result { - let mut prk = [0; 32]; - hkdf_extract(Sha256::new(), b"rust-lightning key gen salt", seed, &mut prk); - let secp_ctx = Secp256k1::without_caps(); - - let mut okm = [0; 32]; - hkdf_expand(Sha256::new(), &prk, b"rust-lightning funding key info", &mut okm); - let funding_key = SecretKey::from_slice(&secp_ctx, &okm)?; - - hkdf_expand(Sha256::new(), &prk, b"rust-lightning revocation base key info", &mut okm); - let revocation_base_key = SecretKey::from_slice(&secp_ctx, &okm)?; - - hkdf_expand(Sha256::new(), &prk, b"rust-lightning payment base key info", &mut okm); - let payment_base_key = SecretKey::from_slice(&secp_ctx, &okm)?; - - hkdf_expand(Sha256::new(), &prk, b"rust-lightning delayed payment base key info", &mut okm); - let delayed_payment_base_key = SecretKey::from_slice(&secp_ctx, &okm)?; - - hkdf_expand(Sha256::new(), &prk, b"rust-lightning htlc base key info", &mut okm); - let htlc_base_key = SecretKey::from_slice(&secp_ctx, &okm)?; - - hkdf_expand(Sha256::new(), &prk, b"rust-lightning channel close key info", &mut okm); - let channel_close_key = SecretKey::from_slice(&secp_ctx, &okm)?; - - hkdf_expand(Sha256::new(), &prk, b"rust-lightning channel monitor claim key info", &mut okm); - let channel_monitor_claim_key = SecretKey::from_slice(&secp_ctx, &okm)?; - - hkdf_expand(Sha256::new(), &prk, b"rust-lightning local commitment seed info", &mut okm); - - Ok(ChannelKeys { - funding_key: funding_key, - revocation_base_key: revocation_base_key, - payment_base_key: payment_base_key, - delayed_payment_base_key: delayed_payment_base_key, - htlc_base_key: htlc_base_key, - channel_close_key: channel_close_key, - channel_monitor_claim_key: channel_monitor_claim_key, - commitment_seed: okm - }) - } -} - enum InboundHTLCRemovalReason { FailRelay(msgs::OnionErrorPacket), FailMalformed(([u8; 32], u16)), @@ -282,16 +231,18 @@ const INITIAL_COMMITMENT_NUMBER: u64 = (1 << 48) - 1; // calling channel_id() before we're set up or things like get_outbound_funding_signed on an // inbound channel. pub(super) struct Channel { + config: ChannelConfig, + user_id: u64, channel_id: [u8; 32], channel_state: u32, channel_outbound: bool, secp_ctx: Secp256k1, - announce_publicly: bool, channel_value_satoshis: u64, local_keys: ChannelKeys, + shutdown_pubkey: PublicKey, // Our commitment numbers start at 2^48-1 and count down, whereas the ones used in transaction // generation start at 0 and count up...this simplifies some parts of implementation at the @@ -359,8 +310,9 @@ pub(super) struct Channel { /// could miss the funding_tx_confirmed_in block as well, but it serves as a useful fallback. funding_tx_confirmed_in: Option, short_channel_id: Option, - /// Used to deduplicate block_connected callbacks - last_block_connected: Sha256dHash, + /// Used to deduplicate block_connected callbacks, also used to verify consistency during + /// ChannelManager deserialization (hence pub(super)) + pub(super) last_block_connected: Sha256dHash, funding_tx_confirmations: u64, their_dust_limit_satoshis: u64, @@ -376,6 +328,7 @@ pub(super) struct Channel { //implied by BREAKDOWN_TIMEOUT: our_to_self_delay: u16, their_max_accepted_htlcs: u16, //implied by OUR_MAX_HTLCS: our_max_accepted_htlcs: u16, + minimum_depth: u32, their_funding_pubkey: Option, their_revocation_basepoint: Option, @@ -449,7 +402,7 @@ impl Channel { } fn derive_our_dust_limit_satoshis(at_open_background_feerate: u64) -> u64 { - at_open_background_feerate * B_OUTPUT_PLUS_SPENDING_INPUT_WEIGHT / 1000 //TODO + cmp::max(at_open_background_feerate * B_OUTPUT_PLUS_SPENDING_INPUT_WEIGHT / 1000, 546) //TODO } fn derive_our_htlc_minimum_msat(_at_open_channel_feerate_per_kw: u64) -> u64 { @@ -463,13 +416,10 @@ impl Channel { CONF_TARGET } - fn derive_maximum_minimum_depth(_channel_value_satoshis_msat: u64, _value_to_self_msat: u64) -> u32 { - const CONF_TARGET: u32 = 12; //TODO: Should be much higher - CONF_TARGET * 2 - } - // Constructors: - pub fn new_outbound(fee_estimator: &FeeEstimator, chan_keys: ChannelKeys, their_node_id: PublicKey, channel_value_satoshis: u64, push_msat: u64, announce_publicly: bool, user_id: u64, logger: Arc) -> 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 { + let chan_keys = keys_provider.get_channel_keys(false); + if channel_value_satoshis >= MAX_FUNDING_SATOSHIS { return Err(APIError::APIMisuseError{err: "funding value > 2^24"}); } @@ -487,24 +437,22 @@ impl Channel { let feerate = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Normal); let secp_ctx = Secp256k1::new(); - let our_channel_monitor_claim_key_hash = Hash160::from_data(&PublicKey::from_secret_key(&secp_ctx, &chan_keys.channel_monitor_claim_key).serialize()); - let our_channel_monitor_claim_script = Builder::new().push_opcode(opcodes::All::OP_PUSHBYTES_0).push_slice(&our_channel_monitor_claim_key_hash[..]).into_script(); - let channel_monitor = ChannelMonitor::new(&chan_keys.revocation_base_key, - &PublicKey::from_secret_key(&secp_ctx, &chan_keys.delayed_payment_base_key), - &chan_keys.htlc_base_key, - BREAKDOWN_TIMEOUT, our_channel_monitor_claim_script); + let channel_monitor = ChannelMonitor::new(&chan_keys.revocation_base_key, &chan_keys.delayed_payment_base_key, + &chan_keys.htlc_base_key, BREAKDOWN_TIMEOUT, + keys_provider.get_destination_script(), logger.clone()); Ok(Channel { user_id: user_id, + config: config.channel_options.clone(), channel_id: rng::rand_u832(), channel_state: ChannelState::OurInitSent as u32, channel_outbound: true, secp_ctx: secp_ctx, - announce_publicly: announce_publicly, channel_value_satoshis: channel_value_satoshis, local_keys: chan_keys, + shutdown_pubkey: keys_provider.get_shutdown_pubkey(), cur_local_commitment_transaction_number: INITIAL_COMMITMENT_NUMBER, cur_remote_commitment_transaction_number: INITIAL_COMMITMENT_NUMBER, value_to_self_msat: channel_value_satoshis * 1000 - push_msat, @@ -548,6 +496,7 @@ impl Channel { our_htlc_minimum_msat: Channel::derive_our_htlc_minimum_msat(feerate), their_to_self_delay: 0, their_max_accepted_htlcs: 0, + minimum_depth: 0, // Filled in in accept_channel their_funding_pubkey: None, their_revocation_basepoint: None, @@ -579,7 +528,10 @@ 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, chan_keys: ChannelKeys, their_node_id: PublicKey, msg: &msgs::OpenChannel, user_id: u64, require_announce: bool, allow_announce: bool, logger: Arc) -> Result { + pub fn new_from_req(fee_estimator: &FeeEstimator, keys_provider: &Arc, their_node_id: PublicKey, msg: &msgs::OpenChannel, user_id: u64, logger: Arc, config: &UserConfig) -> Result { + let chan_keys = keys_provider.get_channel_keys(true); + let mut local_config = (*config).channel_options.clone(); + // Check sanity of message fields: if msg.funding_satoshis >= MAX_FUNDING_SATOSHIS { return Err(ChannelError::Close("funding value > 2^24")); @@ -611,22 +563,46 @@ impl Channel { return Err(ChannelError::Close("max_accpted_htlcs > 483")); } + // Now check against optional parameters as set by config... + if msg.funding_satoshis < config.channel_limits.min_funding_satoshis { + return Err(ChannelError::Close("funding satoshis is less than the user specified limit")); + } + if msg.htlc_minimum_msat > config.channel_limits.max_htlc_minimum_msat { + return Err(ChannelError::Close("htlc minimum msat is higher than the user specified limit")); + } + if msg.max_htlc_value_in_flight_msat < config.channel_limits.min_max_htlc_value_in_flight_msat { + return Err(ChannelError::Close("max htlc value in flight msat is less than the user specified limit")); + } + if msg.channel_reserve_satoshis > config.channel_limits.max_channel_reserve_satoshis { + return Err(ChannelError::Close("channel reserve satoshis is higher than the user specified limit")); + } + if msg.max_accepted_htlcs < config.channel_limits.min_max_accepted_htlcs { + return Err(ChannelError::Close("max accepted htlcs is less than the user specified limit")); + } + if msg.dust_limit_satoshis < config.channel_limits.min_dust_limit_satoshis { + return Err(ChannelError::Close("dust limit satoshis is less than the user specified limit")); + } + if msg.dust_limit_satoshis > config.channel_limits.max_dust_limit_satoshis { + return Err(ChannelError::Close("dust limit satoshis is greater than the user specified limit")); + } + // Convert things into internal flags and prep our state: let their_announce = if (msg.channel_flags & 1) == 1 { true } else { false }; - if require_announce && !their_announce { - return Err(ChannelError::Close("Peer tried to open unannounced channel, but we require public ones")); - } - if !allow_announce && their_announce { - return Err(ChannelError::Close("Peer tried to open announced channel, but we require private ones")); + if config.channel_limits.force_announced_channel_preference { + if local_config.announced_channel != their_announce { + return Err(ChannelError::Close("Peer tried to open channel but their announcement preference is different from ours")); + } } + // we either accept their preference or the preferences match + local_config.announced_channel = their_announce; 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); if our_channel_reserve_satoshis < our_dust_limit_satoshis { - return Err(ChannelError::Close("Suitalbe channel reserve not found. aborting")); + return Err(ChannelError::Close("Suitable channel reserve not found. aborting")); } if msg.channel_reserve_satoshis < our_dust_limit_satoshis { return Err(ChannelError::Close("channel_reserve_satoshis too small")); @@ -649,25 +625,23 @@ impl Channel { } let secp_ctx = Secp256k1::new(); - let our_channel_monitor_claim_key_hash = Hash160::from_data(&PublicKey::from_secret_key(&secp_ctx, &chan_keys.channel_monitor_claim_key).serialize()); - let our_channel_monitor_claim_script = Builder::new().push_opcode(opcodes::All::OP_PUSHBYTES_0).push_slice(&our_channel_monitor_claim_key_hash[..]).into_script(); - let mut channel_monitor = ChannelMonitor::new(&chan_keys.revocation_base_key, - &PublicKey::from_secret_key(&secp_ctx, &chan_keys.delayed_payment_base_key), - &chan_keys.htlc_base_key, - BREAKDOWN_TIMEOUT, our_channel_monitor_claim_script); + let mut channel_monitor = ChannelMonitor::new(&chan_keys.revocation_base_key, &chan_keys.delayed_payment_base_key, + &chan_keys.htlc_base_key, BREAKDOWN_TIMEOUT, + 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 mut chan = Channel { user_id: user_id, + config: local_config, channel_id: msg.temporary_channel_id, channel_state: (ChannelState::OurInitSent as u32) | (ChannelState::TheirInitSent as u32), channel_outbound: false, secp_ctx: secp_ctx, - announce_publicly: their_announce, local_keys: chan_keys, + shutdown_pubkey: keys_provider.get_shutdown_pubkey(), cur_local_commitment_transaction_number: INITIAL_COMMITMENT_NUMBER, cur_remote_commitment_transaction_number: INITIAL_COMMITMENT_NUMBER, value_to_self_msat: msg.push_msat, @@ -712,6 +686,7 @@ impl Channel { our_htlc_minimum_msat: Channel::derive_our_htlc_minimum_msat(msg.feerate_per_kw as u64), their_to_self_delay: msg.to_self_delay, their_max_accepted_htlcs: msg.max_accepted_htlcs, + minimum_depth: Channel::derive_minimum_depth(msg.funding_satoshis*1000, msg.push_msat), their_funding_pubkey: Some(msg.funding_pubkey), their_revocation_basepoint: Some(msg.revocation_basepoint), @@ -950,7 +925,7 @@ impl Channel { #[inline] fn get_closing_scriptpubkey(&self) -> Script { - let our_channel_close_key_hash = Hash160::from_data(&PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.channel_close_key).serialize()); + let our_channel_close_key_hash = Hash160::from_data(&self.shutdown_pubkey.serialize()); Builder::new().push_opcode(opcodes::All::OP_PUSHBYTES_0).push_slice(&our_channel_close_key_hash[..]).into_script() } @@ -1314,7 +1289,7 @@ impl Channel { // Message handlers: - pub fn accept_channel(&mut self, msg: &msgs::AcceptChannel) -> Result<(), ChannelError> { + pub fn accept_channel(&mut self, msg: &msgs::AcceptChannel, config: &UserConfig) -> Result<(), ChannelError> { // Check sanity of message fields: if !self.channel_outbound { return Err(ChannelError::Close("Got an accept_channel message from an inbound peer")); @@ -1340,9 +1315,6 @@ impl Channel { if msg.htlc_minimum_msat >= (self.channel_value_satoshis - msg.channel_reserve_satoshis) * 1000 { return Err(ChannelError::Close("Minimum htlc value is full channel value")); } - if msg.minimum_depth > Channel::derive_maximum_minimum_depth(self.channel_value_satoshis*1000, self.value_to_self_msat) { - return Err(ChannelError::Close("minimum_depth too large")); - } if msg.to_self_delay > MAX_LOCAL_BREAKDOWN_TIMEOUT { return Err(ChannelError::Close("They wanted our payments to be delayed by a needlessly long period")); } @@ -1353,14 +1325,28 @@ impl Channel { return Err(ChannelError::Close("max_accpted_htlcs > 483")); } - // TODO: Optional additional constraints mentioned in the spec - // MAY fail the channel if - // funding_satoshi is too small - // htlc_minimum_msat too large - // max_htlc_value_in_flight_msat too small - // channel_reserve_satoshis too large - // max_accepted_htlcs too small - // dust_limit_satoshis too small + // Now check against optional parameters as set by config... + if msg.htlc_minimum_msat > config.channel_limits.max_htlc_minimum_msat { + return Err(ChannelError::Close("htlc minimum msat is higher than the user specified limit")); + } + if msg.max_htlc_value_in_flight_msat < config.channel_limits.min_max_htlc_value_in_flight_msat { + return Err(ChannelError::Close("max htlc value in flight msat is less than the user specified limit")); + } + if msg.channel_reserve_satoshis > config.channel_limits.max_channel_reserve_satoshis { + return Err(ChannelError::Close("channel reserve satoshis is higher than the user specified limit")); + } + if msg.max_accepted_htlcs < config.channel_limits.min_max_accepted_htlcs { + return Err(ChannelError::Close("max accepted htlcs is less than the user specified limit")); + } + if msg.dust_limit_satoshis < config.channel_limits.min_dust_limit_satoshis { + return Err(ChannelError::Close("dust limit satoshis is less than the user specified limit")); + } + if msg.dust_limit_satoshis > config.channel_limits.max_dust_limit_satoshis { + return Err(ChannelError::Close("dust limit satoshis is greater than the user specified limit")); + } + if msg.minimum_depth > config.channel_limits.max_minimum_depth { + return Err(ChannelError::Close("We consider the minimum depth to be unreasonably large")); + } self.channel_monitor.set_their_base_keys(&msg.htlc_basepoint, &msg.delayed_payment_basepoint); @@ -1370,6 +1356,7 @@ impl Channel { self.their_htlc_minimum_msat = msg.htlc_minimum_msat; 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); @@ -1566,6 +1553,12 @@ impl Channel { //TODO: Check msg.cltv_expiry further? Do this in channel manager? + if self.channel_state & ChannelState::LocalShutdownSent as u32 != 0 { + if let PendingHTLCStatus::Forward(_) = pending_forward_state { + panic!("ChannelManager shouldn't be trying to add a forwardable HTLC after we've started closing"); + } + } + // Now update local state: self.next_remote_htlc_id += 1; self.pending_inbound_htlcs.push(InboundHTLCOutput { @@ -1645,13 +1638,16 @@ impl Channel { self.mark_outbound_htlc_removed(msg.htlc_id, None, Some(fail_reason)) } - pub fn commitment_signed(&mut self, msg: &msgs::CommitmentSigned) -> Result<(msgs::RevokeAndACK, Option, ChannelMonitor), HandleError> { + pub fn commitment_signed(&mut self, msg: &msgs::CommitmentSigned, fee_estimator: &FeeEstimator) -> Result<(msgs::RevokeAndACK, Option, Option, ChannelMonitor), HandleError> { if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) { return Err(HandleError{err: "Got commitment signed message when channel was not in an operational state", action: None}); } if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 { return Err(HandleError{err: "Peer sent commitment_signed when we needed a channel_reestablish", action: Some(msgs::ErrorAction::SendErrorMessage{msg: msgs::ErrorMessage{data: "Peer sent commitment_signed when we needed a channel_reestablish".to_string(), channel_id: msg.channel_id}})}); } + if self.channel_state & BOTH_SIDES_SHUTDOWN_MASK == BOTH_SIDES_SHUTDOWN_MASK && self.last_sent_closing_fee.is_some() { + return Err(HandleError{err: "Peer sent commitment_signed after we'd started exchanging closing_signeds", action: Some(msgs::ErrorAction::SendErrorMessage{msg: msgs::ErrorMessage{data: "Peer sent commitment_signed after we'd started exchanging closing_signeds".to_string(), channel_id: msg.channel_id}})}); + } let funding_script = self.get_funding_redeemscript(); @@ -1743,19 +1739,21 @@ impl Channel { return Err(HandleError{err: "Previous monitor update failure prevented generation of RAA", action: Some(ErrorAction::IgnoreError)}); } - let (our_commitment_signed, monitor_update) = if need_our_commitment && (self.channel_state & (ChannelState::AwaitingRemoteRevoke as u32)) == 0 { + let (our_commitment_signed, monitor_update, closing_signed) = if need_our_commitment && (self.channel_state & (ChannelState::AwaitingRemoteRevoke as u32)) == 0 { // If we're AwaitingRemoteRevoke we can't send a new commitment here, but that's ok - // we'll send one right away when we get the revoke_and_ack when we // free_holding_cell_htlcs(). let (msg, monitor) = self.send_commitment_no_status_check()?; - (Some(msg), monitor) - } else { (None, self.channel_monitor.clone()) }; + (Some(msg), monitor, None) + } else if !need_our_commitment { + (None, self.channel_monitor.clone(), self.maybe_propose_first_closing_signed(fee_estimator)) + } else { (None, self.channel_monitor.clone(), None) }; Ok((msgs::RevokeAndACK { channel_id: self.channel_id, per_commitment_secret: per_commitment_secret, next_per_commitment_point: next_per_commitment_point, - }, our_commitment_signed, monitor_update)) + }, our_commitment_signed, closing_signed, monitor_update)) } /// Used to fulfill holding_cell_htlcs when we get a remote ack (or implicitly get it by them @@ -1856,13 +1854,16 @@ impl Channel { /// waiting on this revoke_and_ack. The generation of this new commitment_signed may also fail, /// generating an appropriate error *after* the channel state has been updated based on the /// revoke_and_ack message. - pub fn revoke_and_ack(&mut self, msg: &msgs::RevokeAndACK) -> Result<(Option, Vec<(PendingForwardHTLCInfo, u64)>, Vec<(HTLCSource, [u8; 32], HTLCFailReason)>, ChannelMonitor), HandleError> { + pub fn revoke_and_ack(&mut self, msg: &msgs::RevokeAndACK, fee_estimator: &FeeEstimator) -> Result<(Option, Vec<(PendingForwardHTLCInfo, u64)>, Vec<(HTLCSource, [u8; 32], HTLCFailReason)>, Option, ChannelMonitor), HandleError> { if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) { return Err(HandleError{err: "Got revoke/ACK message when channel was not in an operational state", action: None}); } if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 { return Err(HandleError{err: "Peer sent revoke_and_ack when we needed a channel_reestablish", action: Some(msgs::ErrorAction::SendErrorMessage{msg: msgs::ErrorMessage{data: "Peer sent revoke_and_ack when we needed a channel_reestablish".to_string(), channel_id: msg.channel_id}})}); } + if self.channel_state & BOTH_SIDES_SHUTDOWN_MASK == BOTH_SIDES_SHUTDOWN_MASK && self.last_sent_closing_fee.is_some() { + return Err(HandleError{err: "Peer sent revoke_and_ack after we'd started exchanging closing_signeds", action: Some(msgs::ErrorAction::SendErrorMessage{msg: msgs::ErrorMessage{data: "Peer sent revoke_and_ack after we'd started exchanging closing_signeds".to_string(), channel_id: msg.channel_id}})}); + } if let Some(their_prev_commitment_point) = self.their_prev_commitment_point { if PublicKey::from_secret_key(&self.secp_ctx, &secp_call!(SecretKey::from_slice(&self.secp_ctx, &msg.per_commitment_secret), "Peer provided an invalid per_commitment_secret", self.channel_id())) != their_prev_commitment_point { @@ -1984,7 +1985,7 @@ impl Channel { } self.monitor_pending_forwards.append(&mut to_forward_infos); self.monitor_pending_failures.append(&mut revoked_htlcs); - return Ok((None, Vec::new(), Vec::new(), self.channel_monitor.clone())); + return Ok((None, Vec::new(), Vec::new(), None, self.channel_monitor.clone())); } match self.free_holding_cell_htlcs()? { @@ -1997,7 +1998,7 @@ impl Channel { for fail_msg in update_fail_malformed_htlcs.drain(..) { commitment_update.0.update_fail_malformed_htlcs.push(fail_msg); } - Ok((Some(commitment_update.0), to_forward_infos, revoked_htlcs, commitment_update.1)) + Ok((Some(commitment_update.0), to_forward_infos, revoked_htlcs, None, commitment_update.1)) }, None => { if require_commitment { @@ -2009,9 +2010,9 @@ impl Channel { update_fail_malformed_htlcs, update_fee: None, commitment_signed - }), to_forward_infos, revoked_htlcs, monitor_update)) + }), to_forward_infos, revoked_htlcs, None, monitor_update)) } else { - Ok((None, to_forward_infos, revoked_htlcs, self.channel_monitor.clone())) + Ok((None, to_forward_infos, revoked_htlcs, self.maybe_propose_first_closing_signed(fee_estimator), self.channel_monitor.clone())) } } } @@ -2070,6 +2071,9 @@ impl Channel { self.channel_state = ChannelState::ShutdownComplete as u32; return outbound_drops; } + // Upon reconnect we have to start the closing_signed dance over, but shutdown messages + // will be retransmitted. + self.last_sent_closing_fee = None; let mut inbound_drop_count = 0; self.pending_inbound_htlcs.retain(|htlc| { @@ -2097,6 +2101,7 @@ impl Channel { }, } }); + self.next_remote_htlc_id -= inbound_drop_count; for htlc in self.pending_outbound_htlcs.iter_mut() { if let OutboundHTLCState::RemoteRemoved = htlc.state { @@ -2256,7 +2261,7 @@ impl Channel { /// May panic if some calls other than message-handling calls (which will all Err immediately) /// have been called between remove_uncommitted_htlcs_and_mark_paused and this call. - pub fn channel_reestablish(&mut self, msg: &msgs::ChannelReestablish) -> Result<(Option, Option, Option, Option, RAACommitmentOrder), ChannelError> { + pub fn channel_reestablish(&mut self, msg: &msgs::ChannelReestablish) -> Result<(Option, Option, Option, Option, RAACommitmentOrder, Option), ChannelError> { if self.channel_state & (ChannelState::PeerDisconnected as u32) == 0 { // While BOLT 2 doesn't indicate explicitly we should error this channel here, it // almost certainly indicates we are going to end up out-of-sync in some way, so we @@ -2264,8 +2269,7 @@ impl Channel { return Err(ChannelError::Close("Peer sent a loose channel_reestablish not after reconnect")); } - if msg.next_local_commitment_number == 0 || msg.next_local_commitment_number >= INITIAL_COMMITMENT_NUMBER || - msg.next_remote_commitment_number == 0 || msg.next_remote_commitment_number >= INITIAL_COMMITMENT_NUMBER { + if msg.next_local_commitment_number >= INITIAL_COMMITMENT_NUMBER || msg.next_remote_commitment_number >= INITIAL_COMMITMENT_NUMBER { return Err(ChannelError::Close("Peer sent a garbage channel_reestablish")); } @@ -2273,6 +2277,31 @@ impl Channel { // remaining cases either succeed or ErrorMessage-fail). self.channel_state &= !(ChannelState::PeerDisconnected as u32); + let shutdown_msg = if self.channel_state & (ChannelState::LocalShutdownSent as u32) != 0 { + Some(msgs::Shutdown { + channel_id: self.channel_id, + scriptpubkey: self.get_closing_scriptpubkey(), + }) + } else { None }; + + if self.channel_state & (ChannelState::FundingSent as u32 | ChannelState::OurFundingLocked as u32) == ChannelState::FundingSent as u32 { + // Short circuit the whole handler as there is nothing we can resend them + return Ok((None, None, None, None, RAACommitmentOrder::CommitmentFirst, shutdown_msg)); + } + + if msg.next_local_commitment_number == 0 || msg.next_remote_commitment_number == 0 { + if self.channel_state & (ChannelState::FundingSent as u32) != ChannelState::FundingSent as u32 { + return Err(ChannelError::Close("Peer sent a pre-funding channel_reestablish after we exchanged funding_locked")); + } + // We have OurFundingLocked set! + let next_per_commitment_secret = self.build_local_commitment_secret(self.cur_local_commitment_transaction_number); + let next_per_commitment_point = PublicKey::from_secret_key(&self.secp_ctx, &next_per_commitment_secret); + return Ok((Some(msgs::FundingLocked { + channel_id: self.channel_id(), + next_per_commitment_point: next_per_commitment_point, + }), None, None, None, RAACommitmentOrder::CommitmentFirst, shutdown_msg)); + } + let required_revoke = if msg.next_remote_commitment_number == INITIAL_COMMITMENT_NUMBER - self.cur_local_commitment_transaction_number { // Remote isn't waiting on any RevokeAndACK from us! // Note that if we need to repeat our FundingLocked we'll do that in the next if block. @@ -2333,11 +2362,11 @@ impl Channel { panic!("Got non-channel-failing result from free_holding_cell_htlcs"); } }, - Ok(Some((commitment_update, channel_monitor))) => return Ok((resend_funding_locked, required_revoke, Some(commitment_update), Some(channel_monitor), order)), - Ok(None) => return Ok((resend_funding_locked, required_revoke, None, None, order)), + Ok(Some((commitment_update, channel_monitor))) => return Ok((resend_funding_locked, required_revoke, Some(commitment_update), Some(channel_monitor), order, shutdown_msg)), + Ok(None) => return Ok((resend_funding_locked, required_revoke, None, None, order, shutdown_msg)), } } else { - return Ok((resend_funding_locked, required_revoke, None, None, order)); + return Ok((resend_funding_locked, required_revoke, None, None, order, shutdown_msg)); } } else if msg.next_local_commitment_number == our_next_remote_commitment_number - 1 { if required_revoke.is_some() { @@ -2351,71 +2380,78 @@ impl Channel { if self.channel_state & (ChannelState::MonitorUpdateFailed as u32) != 0 { self.monitor_pending_commitment_signed = true; - return Ok((resend_funding_locked, None, None, None, order)); + return Ok((resend_funding_locked, None, None, None, order, shutdown_msg)); } - return Ok((resend_funding_locked, required_revoke, Some(self.get_last_commitment_update()), None, order)); + return Ok((resend_funding_locked, required_revoke, Some(self.get_last_commitment_update()), None, order, shutdown_msg)); } else { return Err(ChannelError::Close("Peer attempted to reestablish channel with a very old remote commitment transaction")); } } - pub fn shutdown(&mut self, fee_estimator: &FeeEstimator, msg: &msgs::Shutdown) -> Result<(Option, Option, Vec<(HTLCSource, [u8; 32])>), HandleError> { + fn maybe_propose_first_closing_signed(&mut self, fee_estimator: &FeeEstimator) -> Option { + if !self.channel_outbound || !self.pending_inbound_htlcs.is_empty() || !self.pending_outbound_htlcs.is_empty() || + self.channel_state & (BOTH_SIDES_SHUTDOWN_MASK | ChannelState::AwaitingRemoteRevoke as u32) != BOTH_SIDES_SHUTDOWN_MASK || + self.last_sent_closing_fee.is_some() || + self.cur_remote_commitment_transaction_number != self.cur_local_commitment_transaction_number{ + return None; + } + + let mut proposed_feerate = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Background); + if self.feerate_per_kw > proposed_feerate { + proposed_feerate = self.feerate_per_kw; + } + let tx_weight = Self::get_closing_transaction_weight(&self.get_closing_scriptpubkey(), self.their_shutdown_scriptpubkey.as_ref().unwrap()); + 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 = Message::from_slice(&bip143::SighashComponents::new(&closing_tx).sighash_all(&closing_tx.input[0], &funding_redeemscript, self.channel_value_satoshis)[..]).unwrap(); + + self.last_sent_closing_fee = Some((proposed_feerate, total_fee_satoshis)); + Some(msgs::ClosingSigned { + channel_id: self.channel_id, + fee_satoshis: total_fee_satoshis, + signature: self.secp_ctx.sign(&sighash, &self.local_keys.funding_key), + }) + } + + pub fn shutdown(&mut self, fee_estimator: &FeeEstimator, msg: &msgs::Shutdown) -> Result<(Option, Option, Vec<(HTLCSource, [u8; 32])>), ChannelError> { if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 { - return Err(HandleError{err: "Peer sent shutdown when we needed a channel_reestablish", action: Some(msgs::ErrorAction::SendErrorMessage{msg: msgs::ErrorMessage{data: "Peer sent shutdown when we needed a channel_reestablish".to_string(), channel_id: msg.channel_id}})}); + return Err(ChannelError::Close("Peer sent shutdown when we needed a channel_reestablish")); } if self.channel_state < ChannelState::FundingSent as u32 { - self.channel_state = ChannelState::ShutdownComplete as u32; - self.channel_update_count += 1; - return Ok((None, None, Vec::new())); + // Spec says we should fail the connection, not the channel, but that's nonsense, there + // are plenty of reasons you may want to fail a channel pre-funding, and spec says you + // can do that via error message without getting a connection fail anyway... + return Err(ChannelError::Close("Peer sent shutdown pre-funding generation")); } for htlc in self.pending_inbound_htlcs.iter() { if let InboundHTLCState::RemoteAnnounced(_) = htlc.state { - return Err(HandleError{err: "Got shutdown with remote pending HTLCs", action: None}); + return Err(ChannelError::Close("Got shutdown with remote pending HTLCs")); } } - if (self.channel_state & ChannelState::RemoteShutdownSent as u32) == ChannelState::RemoteShutdownSent as u32 { - return Err(HandleError{err: "Remote peer sent duplicate shutdown message", action: None}); - } assert_eq!(self.channel_state & ChannelState::ShutdownComplete as u32, 0); // BOLT 2 says we must only send a scriptpubkey of certain standard forms, which are up to // 34 bytes in length, so dont let the remote peer feed us some super fee-heavy script. if self.channel_outbound && msg.scriptpubkey.len() > 34 { - return Err(HandleError{err: "Got shutdown_scriptpubkey of absurd length from remote peer", action: None}); + return Err(ChannelError::Close("Got shutdown_scriptpubkey of absurd length from remote peer")); } //Check shutdown_scriptpubkey form as BOLT says we must - if !(msg.scriptpubkey.is_p2pkh()) && !(msg.scriptpubkey.is_p2sh()) - && !(msg.scriptpubkey.is_v0_p2wpkh()) && !(msg.scriptpubkey.is_v0_p2wsh()){ - return Err(HandleError{err: "Got an invalid scriptpubkey from remote peer", action: Some(msgs::ErrorAction::DisconnectPeer{ msg: None })}); + if !msg.scriptpubkey.is_p2pkh() && !msg.scriptpubkey.is_p2sh() && !msg.scriptpubkey.is_v0_p2wpkh() && !msg.scriptpubkey.is_v0_p2wsh() { + return Err(ChannelError::Close("Got a nonstandard scriptpubkey from remote peer")); } if self.their_shutdown_scriptpubkey.is_some() { if Some(&msg.scriptpubkey) != self.their_shutdown_scriptpubkey.as_ref() { - return Err(HandleError{err: "Got shutdown request with a scriptpubkey which did not match their previous scriptpubkey", action: None}); + return Err(ChannelError::Close("Got shutdown request with a scriptpubkey which did not match their previous scriptpubkey")); } } else { self.their_shutdown_scriptpubkey = Some(msg.scriptpubkey.clone()); } - let our_closing_script = self.get_closing_scriptpubkey(); - - let (proposed_feerate, proposed_fee, our_sig) = if self.channel_outbound && self.pending_inbound_htlcs.is_empty() && self.pending_outbound_htlcs.is_empty() { - let mut proposed_feerate = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Background); - if self.feerate_per_kw > proposed_feerate { - proposed_feerate = self.feerate_per_kw; - } - let tx_weight = Self::get_closing_transaction_weight(&our_closing_script, &msg.scriptpubkey); - 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 = Message::from_slice(&bip143::SighashComponents::new(&closing_tx).sighash_all(&closing_tx.input[0], &funding_redeemscript, self.channel_value_satoshis)[..]).unwrap(); - - (Some(proposed_feerate), Some(total_fee_satoshis), Some(self.secp_ctx.sign(&sighash, &self.local_keys.funding_key))) - } else { (None, None, None) }; - // From here on out, we may not fail! self.channel_state |= ChannelState::RemoteShutdownSent as u32; @@ -2424,6 +2460,7 @@ impl Channel { // We can't send our shutdown until we've committed all of our pending HTLCs, but the // remote side is unlikely to accept any new HTLCs, so we go ahead and "free" any holding // cell HTLCs and return them to fail the payment. + self.holding_cell_update_fee = None; let mut dropped_outbound_htlcs = Vec::with_capacity(self.holding_cell_htlc_updates.len()); self.holding_cell_htlc_updates.retain(|htlc_update| { match htlc_update { @@ -2434,35 +2471,22 @@ impl Channel { _ => true } }); - for htlc in self.pending_outbound_htlcs.iter() { - if let OutboundHTLCState::LocalAnnounced(_) = htlc.state { - return Ok((None, None, dropped_outbound_htlcs)); - } - } + // If we have any LocalAnnounced updates we'll probably just get back a update_fail_htlc + // immediately after the commitment dance, but we can send a Shutdown cause we won't send + // any further commitment updates after we set LocalShutdownSent. let our_shutdown = if (self.channel_state & ChannelState::LocalShutdownSent as u32) == ChannelState::LocalShutdownSent as u32 { None } else { Some(msgs::Shutdown { channel_id: self.channel_id, - scriptpubkey: our_closing_script, + scriptpubkey: self.get_closing_scriptpubkey(), }) }; self.channel_state |= ChannelState::LocalShutdownSent as u32; self.channel_update_count += 1; - if self.pending_inbound_htlcs.is_empty() && self.pending_outbound_htlcs.is_empty() && self.channel_outbound { - // There are no more HTLCs and we're the funder, this means we start the closing_signed - // dance with an initial fee proposal! - self.last_sent_closing_fee = Some((proposed_feerate.unwrap(), proposed_fee.unwrap())); - Ok((our_shutdown, Some(msgs::ClosingSigned { - channel_id: self.channel_id, - fee_satoshis: proposed_fee.unwrap(), - signature: our_sig.unwrap(), - }), dropped_outbound_htlcs)) - } else { - Ok((our_shutdown, None, dropped_outbound_htlcs)) - } + Ok((our_shutdown, self.maybe_propose_first_closing_signed(fee_estimator), dropped_outbound_htlcs)) } pub fn closing_signed(&mut self, fee_estimator: &FeeEstimator, msg: &msgs::ClosingSigned) -> Result<(Option, Option), HandleError> { @@ -2607,11 +2631,27 @@ impl Channel { self.channel_value_satoshis } + pub fn get_fee_proportional_millionths(&self) -> u32 { + self.config.fee_proportional_millionths + } + #[cfg(test)] pub fn get_feerate(&self) -> u64 { self.feerate_per_kw } + pub fn get_cur_local_commitment_transaction_number(&self) -> u64 { + self.cur_local_commitment_transaction_number + 1 + } + + pub fn get_cur_remote_commitment_transaction_number(&self) -> u64 { + self.cur_remote_commitment_transaction_number + 1 - if self.channel_state & (ChannelState::AwaitingRemoteRevoke as u32) != 0 { 1 } else { 0 } + } + + pub fn get_revoked_remote_commitment_transaction_number(&self) -> u64 { + self.cur_remote_commitment_transaction_number + 2 + } + //TODO: Testing purpose only, should be changed in another way after #81 #[cfg(test)] pub fn get_local_keys(&self) -> &ChannelKeys { @@ -2648,7 +2688,7 @@ impl Channel { } pub fn should_announce(&self) -> bool { - self.announce_publicly + self.config.announced_channel } pub fn is_outbound(&self) -> bool { @@ -2723,11 +2763,12 @@ impl Channel { /// Only returns an ErrorAction of DisconnectPeer, if Err. pub fn block_connected(&mut self, header: &BlockHeader, height: u32, txn_matched: &[&Transaction], indexes_of_txn_matched: &[u32]) -> Result, HandleError> { let non_shutdown_state = self.channel_state & (!MULTI_STATE_FLAGS); - if self.funding_tx_confirmations > 0 { - if header.bitcoin_hash() != self.last_block_connected { - self.last_block_connected = header.bitcoin_hash(); + if header.bitcoin_hash() != self.last_block_connected { + self.last_block_connected = header.bitcoin_hash(); + self.channel_monitor.last_block_hash = self.last_block_connected; + if self.funding_tx_confirmations > 0 { self.funding_tx_confirmations += 1; - if self.funding_tx_confirmations == Channel::derive_minimum_depth(self.channel_value_satoshis*1000, self.value_to_self_msat) as u64 { + if self.funding_tx_confirmations == self.minimum_depth as u64 { let need_commitment_update = if non_shutdown_state == ChannelState::FundingSent as u32 { self.channel_state |= ChannelState::OurFundingLocked as u32; true @@ -2804,8 +2845,10 @@ impl Channel { } } if Some(header.bitcoin_hash()) == self.funding_tx_confirmed_in { - self.funding_tx_confirmations = Channel::derive_minimum_depth(self.channel_value_satoshis*1000, self.value_to_self_msat) as u64 - 1; + self.funding_tx_confirmations = self.minimum_depth as u64 - 1; } + self.last_block_connected = header.bitcoin_hash(); + self.channel_monitor.last_block_hash = self.last_block_connected; false } @@ -2844,7 +2887,7 @@ impl Channel { 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.announce_publicly {1} else {0}, + channel_flags: if self.config.announced_channel {1} else {0}, shutdown_scriptpubkey: None, } } @@ -2868,7 +2911,7 @@ impl Channel { 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: Channel::derive_minimum_depth(self.channel_value_satoshis*1000, self.value_to_self_msat), + minimum_depth: self.minimum_depth, to_self_delay: BREAKDOWN_TIMEOUT, max_accepted_htlcs: OUR_MAX_HTLCS, funding_pubkey: PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.funding_key), @@ -2948,7 +2991,7 @@ impl Channel { /// Note that the "channel must be funded" requirement is stricter than BOLT 7 requires - see /// https://github.com/lightningnetwork/lightning-rfc/issues/468 pub fn get_channel_announcement(&self, our_node_id: PublicKey, chain_hash: Sha256dHash) -> Result<(msgs::UnsignedChannelAnnouncement, Signature), ChannelError> { - if !self.announce_publicly { + if !self.config.announced_channel { return Err(ChannelError::Ignore("Channel is not available for public announcements")); } if self.channel_state & (ChannelState::ChannelFunded as u32) == 0 { @@ -2985,7 +3028,8 @@ impl Channel { msgs::ChannelReestablish { channel_id: self.channel_id(), next_local_commitment_number: INITIAL_COMMITMENT_NUMBER - self.cur_local_commitment_transaction_number, - next_remote_commitment_number: INITIAL_COMMITMENT_NUMBER - self.cur_remote_commitment_transaction_number, + next_remote_commitment_number: INITIAL_COMMITMENT_NUMBER - self.cur_remote_commitment_transaction_number - + if self.channel_state & (ChannelState::FundingSent as u32 | ChannelState::OurFundingLocked as u32) == (ChannelState::FundingSent as u32) { 1 } else { 0 }, data_loss_protect: None, } } @@ -3100,7 +3144,7 @@ impl Channel { if (self.channel_state & (ChannelState::PeerDisconnected as u32)) == (ChannelState::PeerDisconnected as u32) { panic!("Cannot create commitment tx while disconnected, as send_htlc will have returned an Err so a send_commitment precondition has been violated"); } - if (self.channel_state & (ChannelState::MonitorUpdateFailed as u32)) == (ChannelState::PeerDisconnected as u32) { + if (self.channel_state & (ChannelState::MonitorUpdateFailed as u32)) == (ChannelState::MonitorUpdateFailed as u32) { panic!("Cannot create commitment tx while awaiting monitor update unfreeze, as send_htlc will have returned an Err so a send_commitment precondition has been violated"); } let mut have_updates = self.pending_update_fee.is_some(); @@ -3225,9 +3269,9 @@ impl Channel { } self.channel_update_count += 1; - // We can't send our shutdown until we've committed all of our pending HTLCs, but the - // remote side is unlikely to accept any new HTLCs, so we go ahead and "free" any holding - // cell HTLCs and return them to fail the payment. + // Go ahead and drop holding cell updates as we'd rather fail payments than wait to send + // our shutdown until we've committed all of the pending changes. + self.holding_cell_update_fee = None; let mut dropped_outbound_htlcs = Vec::with_capacity(self.holding_cell_htlc_updates.len()); self.holding_cell_htlc_updates.retain(|htlc_update| { match htlc_update { @@ -3279,20 +3323,514 @@ impl Channel { } } +const SERIALIZATION_VERSION: u8 = 1; +const MIN_SERIALIZATION_VERSION: u8 = 1; + +impl Writeable for InboundHTLCRemovalReason { + fn write(&self, writer: &mut W) -> Result<(), ::std::io::Error> { + match self { + &InboundHTLCRemovalReason::FailRelay(ref error_packet) => { + 0u8.write(writer)?; + error_packet.write(writer)?; + }, + &InboundHTLCRemovalReason::FailMalformed((ref onion_hash, ref err_code)) => { + 1u8.write(writer)?; + onion_hash.write(writer)?; + err_code.write(writer)?; + }, + &InboundHTLCRemovalReason::Fulfill(ref payment_preimage) => { + 2u8.write(writer)?; + payment_preimage.write(writer)?; + }, + } + Ok(()) + } +} + +impl Readable for InboundHTLCRemovalReason { + fn read(reader: &mut R) -> Result { + Ok(match >::read(reader)? { + 0 => InboundHTLCRemovalReason::FailRelay(Readable::read(reader)?), + 1 => InboundHTLCRemovalReason::FailMalformed((Readable::read(reader)?, Readable::read(reader)?)), + 2 => InboundHTLCRemovalReason::Fulfill(Readable::read(reader)?), + _ => return Err(DecodeError::InvalidValue), + }) + } +} + +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). + + writer.write_all(&[SERIALIZATION_VERSION; 1])?; + writer.write_all(&[MIN_SERIALIZATION_VERSION; 1])?; + + self.user_id.write(writer)?; + self.config.write(writer)?; + + self.channel_id.write(writer)?; + (self.channel_state | ChannelState::PeerDisconnected as u32).write(writer)?; + self.channel_outbound.write(writer)?; + self.channel_value_satoshis.write(writer)?; + + self.local_keys.write(writer)?; + self.shutdown_pubkey.write(writer)?; + + self.cur_local_commitment_transaction_number.write(writer)?; + self.cur_remote_commitment_transaction_number.write(writer)?; + self.value_to_self_msat.write(writer)?; + + self.received_commitment_while_awaiting_raa.write(writer)?; + + let mut dropped_inbound_htlcs = 0; + for htlc in self.pending_inbound_htlcs.iter() { + if let InboundHTLCState::RemoteAnnounced(_) = htlc.state { + dropped_inbound_htlcs += 1; + } + } + (self.pending_inbound_htlcs.len() as u64 - dropped_inbound_htlcs).write(writer)?; + for htlc in self.pending_inbound_htlcs.iter() { + htlc.htlc_id.write(writer)?; + htlc.amount_msat.write(writer)?; + htlc.cltv_expiry.write(writer)?; + htlc.payment_hash.write(writer)?; + match &htlc.state { + &InboundHTLCState::RemoteAnnounced(_) => {}, // Drop + &InboundHTLCState::AwaitingRemoteRevokeToAnnounce(ref htlc_state) => { + 1u8.write(writer)?; + htlc_state.write(writer)?; + }, + &InboundHTLCState::AwaitingAnnouncedRemoteRevoke(ref htlc_state) => { + 2u8.write(writer)?; + htlc_state.write(writer)?; + }, + &InboundHTLCState::Committed => { + 3u8.write(writer)?; + }, + &InboundHTLCState::LocalRemoved(ref removal_reason) => { + 4u8.write(writer)?; + removal_reason.write(writer)?; + }, + } + } + + macro_rules! write_option { + ($thing: expr) => { + match &$thing { + &None => 0u8.write(writer)?, + &Some(ref v) => { + 1u8.write(writer)?; + v.write(writer)?; + }, + } + } + } + + (self.pending_outbound_htlcs.len() as u64).write(writer)?; + for htlc in self.pending_outbound_htlcs.iter() { + htlc.htlc_id.write(writer)?; + htlc.amount_msat.write(writer)?; + htlc.cltv_expiry.write(writer)?; + htlc.payment_hash.write(writer)?; + htlc.source.write(writer)?; + write_option!(htlc.fail_reason); + match &htlc.state { + &OutboundHTLCState::LocalAnnounced(ref onion_packet) => { + 0u8.write(writer)?; + onion_packet.write(writer)?; + }, + &OutboundHTLCState::Committed => { + 1u8.write(writer)?; + }, + &OutboundHTLCState::RemoteRemoved => { + 2u8.write(writer)?; + }, + &OutboundHTLCState::AwaitingRemoteRevokeToRemove => { + 3u8.write(writer)?; + }, + &OutboundHTLCState::AwaitingRemovedRemoteRevoke => { + 4u8.write(writer)?; + }, + } + } + + (self.holding_cell_htlc_updates.len() as u64).write(writer)?; + for update in self.holding_cell_htlc_updates.iter() { + match update { + &HTLCUpdateAwaitingACK::AddHTLC { ref amount_msat, ref cltv_expiry, ref payment_hash, ref source, ref onion_routing_packet, time_created: _ } => { + 0u8.write(writer)?; + amount_msat.write(writer)?; + cltv_expiry.write(writer)?; + payment_hash.write(writer)?; + source.write(writer)?; + onion_routing_packet.write(writer)?; + // time_created is not serialized - we re-init the timeout upon deserialization + }, + &HTLCUpdateAwaitingACK::ClaimHTLC { ref payment_preimage, ref htlc_id } => { + 1u8.write(writer)?; + payment_preimage.write(writer)?; + htlc_id.write(writer)?; + }, + &HTLCUpdateAwaitingACK::FailHTLC { ref htlc_id, ref err_packet } => { + 2u8.write(writer)?; + htlc_id.write(writer)?; + err_packet.write(writer)?; + } + } + } + + self.monitor_pending_revoke_and_ack.write(writer)?; + self.monitor_pending_commitment_signed.write(writer)?; + match self.monitor_pending_order { + None => 0u8.write(writer)?, + Some(RAACommitmentOrder::CommitmentFirst) => 1u8.write(writer)?, + Some(RAACommitmentOrder::RevokeAndACKFirst) => 2u8.write(writer)?, + } + + (self.monitor_pending_forwards.len() as u64).write(writer)?; + for &(ref pending_forward, ref htlc_id) in self.monitor_pending_forwards.iter() { + pending_forward.write(writer)?; + htlc_id.write(writer)?; + } + + (self.monitor_pending_failures.len() as u64).write(writer)?; + for &(ref htlc_source, ref payment_hash, ref fail_reason) in self.monitor_pending_failures.iter() { + htlc_source.write(writer)?; + payment_hash.write(writer)?; + fail_reason.write(writer)?; + } + + write_option!(self.pending_update_fee); + write_option!(self.holding_cell_update_fee); + + self.next_local_htlc_id.write(writer)?; + (self.next_remote_htlc_id - dropped_inbound_htlcs).write(writer)?; + 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 RawEncoder::new(WriterWriteAdaptor(writer))) { + match e { + network::serialize::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)) => { + 1u8.write(writer)?; + feerate.write(writer)?; + fee.write(writer)?; + }, + None => 0u8.write(writer)?, + } + + write_option!(self.funding_tx_confirmed_in); + write_option!(self.short_channel_id); + + self.last_block_connected.write(writer)?; + self.funding_tx_confirmations.write(writer)?; + + self.their_dust_limit_satoshis.write(writer)?; + self.our_dust_limit_satoshis.write(writer)?; + self.their_max_htlc_value_in_flight_msat.write(writer)?; + self.their_channel_reserve_satoshis.write(writer)?; + self.their_htlc_minimum_msat.write(writer)?; + self.our_htlc_minimum_msat.write(writer)?; + self.their_to_self_delay.write(writer)?; + 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_cur_commitment_point); + + write_option!(self.their_prev_commitment_point); + self.their_node_id.write(writer)?; + + write_option!(self.their_shutdown_scriptpubkey); + + self.channel_monitor.write_for_disk(writer)?; + Ok(()) + } +} + +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)?; + if min_ver > SERIALIZATION_VERSION { + return Err(DecodeError::UnknownVersion); + } + + let user_id = Readable::read(reader)?; + let config: ChannelConfig = Readable::read(reader)?; + + let channel_id = Readable::read(reader)?; + let channel_state = Readable::read(reader)?; + let channel_outbound = Readable::read(reader)?; + let channel_value_satoshis = Readable::read(reader)?; + + let local_keys = Readable::read(reader)?; + let shutdown_pubkey = Readable::read(reader)?; + + let cur_local_commitment_transaction_number = Readable::read(reader)?; + let cur_remote_commitment_transaction_number = Readable::read(reader)?; + let value_to_self_msat = Readable::read(reader)?; + + let received_commitment_while_awaiting_raa = Readable::read(reader)?; + + let pending_inbound_htlc_count: u64 = Readable::read(reader)?; + let mut pending_inbound_htlcs = Vec::with_capacity(cmp::min(pending_inbound_htlc_count as usize, OUR_MAX_HTLCS as usize)); + for _ in 0..pending_inbound_htlc_count { + pending_inbound_htlcs.push(InboundHTLCOutput { + htlc_id: Readable::read(reader)?, + amount_msat: Readable::read(reader)?, + cltv_expiry: Readable::read(reader)?, + payment_hash: Readable::read(reader)?, + state: match >::read(reader)? { + 1 => InboundHTLCState::AwaitingRemoteRevokeToAnnounce(Readable::read(reader)?), + 2 => InboundHTLCState::AwaitingAnnouncedRemoteRevoke(Readable::read(reader)?), + 3 => InboundHTLCState::Committed, + 4 => InboundHTLCState::LocalRemoved(Readable::read(reader)?), + _ => return Err(DecodeError::InvalidValue), + }, + }); + } + + macro_rules! read_option { () => { + match >::read(reader)? { + 0 => None, + 1 => Some(Readable::read(reader)?), + _ => return Err(DecodeError::InvalidValue), + } + } } + + let pending_outbound_htlc_count: u64 = Readable::read(reader)?; + let mut pending_outbound_htlcs = Vec::with_capacity(cmp::min(pending_outbound_htlc_count as usize, OUR_MAX_HTLCS as usize)); + for _ in 0..pending_outbound_htlc_count { + pending_outbound_htlcs.push(OutboundHTLCOutput { + htlc_id: Readable::read(reader)?, + amount_msat: Readable::read(reader)?, + cltv_expiry: Readable::read(reader)?, + payment_hash: Readable::read(reader)?, + source: Readable::read(reader)?, + fail_reason: read_option!(), + state: match >::read(reader)? { + 0 => OutboundHTLCState::LocalAnnounced(Box::new(Readable::read(reader)?)), + 1 => OutboundHTLCState::Committed, + 2 => OutboundHTLCState::RemoteRemoved, + 3 => OutboundHTLCState::AwaitingRemoteRevokeToRemove, + 4 => OutboundHTLCState::AwaitingRemovedRemoteRevoke, + _ => return Err(DecodeError::InvalidValue), + }, + }); + } + + let holding_cell_htlc_update_count: u64 = Readable::read(reader)?; + let mut holding_cell_htlc_updates = Vec::with_capacity(cmp::min(holding_cell_htlc_update_count as usize, OUR_MAX_HTLCS as usize*2)); + for _ in 0..holding_cell_htlc_update_count { + holding_cell_htlc_updates.push(match >::read(reader)? { + 0 => HTLCUpdateAwaitingACK::AddHTLC { + amount_msat: Readable::read(reader)?, + cltv_expiry: Readable::read(reader)?, + payment_hash: Readable::read(reader)?, + source: Readable::read(reader)?, + onion_routing_packet: Readable::read(reader)?, + time_created: Instant::now(), + }, + 1 => HTLCUpdateAwaitingACK::ClaimHTLC { + payment_preimage: Readable::read(reader)?, + htlc_id: Readable::read(reader)?, + }, + 2 => HTLCUpdateAwaitingACK::FailHTLC { + htlc_id: Readable::read(reader)?, + err_packet: Readable::read(reader)?, + }, + _ => return Err(DecodeError::InvalidValue), + }); + } + + let monitor_pending_revoke_and_ack = Readable::read(reader)?; + let monitor_pending_commitment_signed = Readable::read(reader)?; + + let monitor_pending_order = match >::read(reader)? { + 0 => None, + 1 => Some(RAACommitmentOrder::CommitmentFirst), + 2 => Some(RAACommitmentOrder::RevokeAndACKFirst), + _ => return Err(DecodeError::InvalidValue), + }; + + let monitor_pending_forwards_count: u64 = Readable::read(reader)?; + let mut monitor_pending_forwards = Vec::with_capacity(cmp::min(monitor_pending_forwards_count as usize, OUR_MAX_HTLCS as usize)); + for _ in 0..monitor_pending_forwards_count { + monitor_pending_forwards.push((Readable::read(reader)?, Readable::read(reader)?)); + } + + let monitor_pending_failures_count: u64 = Readable::read(reader)?; + let mut monitor_pending_failures = Vec::with_capacity(cmp::min(monitor_pending_failures_count as usize, OUR_MAX_HTLCS as usize)); + for _ in 0..monitor_pending_failures_count { + monitor_pending_failures.push((Readable::read(reader)?, Readable::read(reader)?, Readable::read(reader)?)); + } + + let pending_update_fee = read_option!(); + let holding_cell_update_fee = read_option!(); + + let next_local_htlc_id = Readable::read(reader)?; + let next_remote_htlc_id = Readable::read(reader)?; + 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(&mut RawDecoder::new(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)?)), + _ => return Err(DecodeError::InvalidValue), + }; + + let funding_tx_confirmed_in = read_option!(); + let short_channel_id = read_option!(); + + let last_block_connected = Readable::read(reader)?; + let funding_tx_confirmations = Readable::read(reader)?; + + let their_dust_limit_satoshis = Readable::read(reader)?; + let our_dust_limit_satoshis = Readable::read(reader)?; + let their_max_htlc_value_in_flight_msat = Readable::read(reader)?; + let their_channel_reserve_satoshis = Readable::read(reader)?; + let their_htlc_minimum_msat = Readable::read(reader)?; + let our_htlc_minimum_msat = Readable::read(reader)?; + let their_to_self_delay = Readable::read(reader)?; + let their_max_accepted_htlcs = Readable::read(reader)?; + let minimum_depth = Readable::read(reader)?; + + let their_funding_pubkey = read_option!(); + let their_revocation_basepoint = read_option!(); + let their_payment_basepoint = read_option!(); + let their_delayed_payment_basepoint = read_option!(); + let their_htlc_basepoint = read_option!(); + let their_cur_commitment_point = read_option!(); + + let their_prev_commitment_point = read_option!(); + let their_node_id = Readable::read(reader)?; + + let their_shutdown_scriptpubkey = read_option!(); + let (monitor_last_block, channel_monitor) = ReadableArgs::read(reader, logger.clone())?; + // We drop the ChannelMonitor's last block connected hash cause we don't actually bother + // doing full block connection operations on the internal CHannelMonitor copies + if monitor_last_block != last_block_connected { + return Err(DecodeError::InvalidValue); + } + + Ok(Channel { + user_id, + + config, + channel_id, + channel_state, + channel_outbound, + secp_ctx: Secp256k1::new(), + channel_value_satoshis, + + local_keys, + shutdown_pubkey, + + cur_local_commitment_transaction_number, + cur_remote_commitment_transaction_number, + value_to_self_msat, + + received_commitment_while_awaiting_raa, + pending_inbound_htlcs, + pending_outbound_htlcs, + holding_cell_htlc_updates, + + monitor_pending_revoke_and_ack, + monitor_pending_commitment_signed, + monitor_pending_order, + monitor_pending_forwards, + monitor_pending_failures, + + pending_update_fee, + holding_cell_update_fee, + next_local_htlc_id, + next_remote_htlc_id, + channel_update_count, + feerate_per_kw, + + #[cfg(debug_assertions)] + max_commitment_tx_output_local: ::std::sync::Mutex::new((0, 0)), + #[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, + short_channel_id, + last_block_connected, + funding_tx_confirmations, + + their_dust_limit_satoshis, + our_dust_limit_satoshis, + their_max_htlc_value_in_flight_msat, + their_channel_reserve_satoshis, + their_htlc_minimum_msat, + our_htlc_minimum_msat, + their_to_self_delay, + their_max_accepted_htlcs, + minimum_depth, + + their_funding_pubkey, + their_revocation_basepoint, + their_payment_basepoint, + their_delayed_payment_basepoint, + their_htlc_basepoint, + their_cur_commitment_point, + + their_prev_commitment_point, + their_node_id, + + their_shutdown_scriptpubkey, + + channel_monitor, + + logger, + }) + } +} + #[cfg(test)] mod tests { - use bitcoin::util::hash::Sha256dHash; + use bitcoin::util::hash::{Sha256dHash, Hash160}; use bitcoin::util::bip143; use bitcoin::network::serialize::serialize; - use bitcoin::blockdata::script::Script; + use bitcoin::blockdata::script::{Script, Builder}; use bitcoin::blockdata::transaction::Transaction; + use bitcoin::blockdata::opcodes; use hex; use ln::channelmanager::HTLCSource; use ln::channel::{Channel,ChannelKeys,InboundHTLCOutput,OutboundHTLCOutput,InboundHTLCState,OutboundHTLCState,HTLCOutputInCommitment,TxCreationKeys}; use ln::channel::MAX_FUNDING_SATOSHIS; use ln::chan_utils; use chain::chaininterface::{FeeEstimator,ConfirmationTarget}; + use chain::keysinterface::KeysInterface; use chain::transaction::OutPoint; + use util::config::UserConfig; use util::test_utils; use util::logger::Logger; use secp256k1::{Secp256k1,Message,Signature}; @@ -3316,6 +3854,27 @@ mod tests { "MAX_FUNDING_SATOSHIS is greater than all satoshis on existence"); } + struct Keys { + chan_keys: ChannelKeys, + } + impl KeysInterface for Keys { + fn get_node_secret(&self) -> SecretKey { panic!(); } + fn get_destination_script(&self) -> Script { + let secp_ctx = Secp256k1::signing_only(); + let channel_monitor_claim_key = SecretKey::from_slice(&secp_ctx, &hex::decode("0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap()[..]).unwrap(); + let our_channel_monitor_claim_key_hash = Hash160::from_data(&PublicKey::from_secret_key(&secp_ctx, &channel_monitor_claim_key).serialize()); + Builder::new().push_opcode(opcodes::All::OP_PUSHBYTES_0).push_slice(&our_channel_monitor_claim_key_hash[..]).into_script() + } + + fn get_shutdown_pubkey(&self) -> PublicKey { + let secp_ctx = Secp256k1::signing_only(); + let channel_close_key = SecretKey::from_slice(&secp_ctx, &hex::decode("0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap()[..]).unwrap(); + PublicKey::from_secret_key(&secp_ctx, &channel_close_key) + } + + fn get_channel_keys(&self, _inbound: bool) -> ChannelKeys { self.chan_keys.clone() } + } + #[test] fn outbound_commitment_test() { // Test vectors from BOLT 3 Appendix C: @@ -3331,15 +3890,16 @@ mod tests { // These aren't set in the test vectors: revocation_base_key: SecretKey::from_slice(&secp_ctx, &hex::decode("0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap()[..]).unwrap(), - channel_close_key: SecretKey::from_slice(&secp_ctx, &hex::decode("0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap()[..]).unwrap(), - channel_monitor_claim_key: SecretKey::from_slice(&secp_ctx, &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], }; 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 their_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &[42; 32]).unwrap()); - let mut chan = Channel::new_outbound(&feeest, chan_keys, their_node_id, 10000000, 100000, false, 42, Arc::clone(&logger)).unwrap(); // Nothing uses their network key in this test + let mut config = UserConfig::new(); + 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 chan.their_to_self_delay = 144; chan.our_dust_limit_satoshis = 546;