X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=src%2Fln%2Fchannel.rs;h=c88e1d7763125f118c015cb82bc3dbc5914a2c78;hb=ada2154b40237d22edc72ab553ca4a4d42d4a2c1;hp=a1ca7e25e65a5ea8cff9f5d0a27710751ea5ae94;hpb=1a9ef40203da58e03defd13379983e6474c20d1b;p=rust-lightning diff --git a/src/ln/channel.rs b/src/ln/channel.rs index a1ca7e25..c88e1d77 100644 --- a/src/ln/channel.rs +++ b/src/ln/channel.rs @@ -24,6 +24,7 @@ use chain::transaction::OutPoint; use util::{transaction_utils,rng}; use util::sha2::Sha256; use util::logger::{Logger, Record}; +use util::errors::APIError; use std; use std::default::Default; @@ -88,18 +89,21 @@ impl ChannelKeys { #[derive(PartialEq)] enum HTLCState { /// Added by remote, to be included in next local commitment tx. + /// Implies HTLCOutput::outbound: false RemoteAnnounced, /// Included in a received commitment_signed message (implying we've revoke_and_ack'ed it), but /// the remote side hasn't yet revoked their previous state, which we need them to do before we /// accept this HTLC. Implies AwaitingRemoteRevoke. /// We also have not yet included this HTLC in a commitment_signed message, and are waiting on /// a remote revoke_and_ack on a previous state before we can do so. + /// Implies HTLCOutput::outbound: false AwaitingRemoteRevokeToAnnounce, /// Included in a received commitment_signed message (implying we've revoke_and_ack'ed it), but /// the remote side hasn't yet revoked their previous state, which we need them to do before we /// accept this HTLC. Implies AwaitingRemoteRevoke. /// We have included this HTLC in our latest commitment_signed and are now just waiting on a /// revoke_and_ack. + /// Implies HTLCOutput::outbound: true AwaitingAnnouncedRemoteRevoke, /// Added by us and included in a commitment_signed (if we were AwaitingRemoteRevoke when we /// created it we would have put it in the holding cell instead). When they next revoke_and_ack @@ -111,22 +115,26 @@ enum HTLCState { /// allowed to remove it, the "can only be removed once committed on both sides" requirement /// doesn't matter to us and its up to them to enforce it, worst-case they jump ahead but /// we'll never get out of sync). + /// Implies HTLCOutput::outbound: true LocalAnnounced, Committed, /// Remote removed this (outbound) HTLC. We're waiting on their commitment_signed to finalize /// the change (though they'll need to revoke before we fail the payment). + /// Implies HTLCOutput::outbound: true RemoteRemoved, /// Remote removed this and sent a commitment_signed (implying we've revoke_and_ack'ed it), but /// the remote side hasn't yet revoked their previous state, which we need them to do before we /// can do any backwards failing. Implies AwaitingRemoteRevoke. /// We also have not yet removed this HTLC in a commitment_signed message, and are waiting on a /// remote revoke_and_ack on a previous state before we can do so. + /// Implies HTLCOutput::outbound: true AwaitingRemoteRevokeToRemove, /// Remote removed this and sent a commitment_signed (implying we've revoke_and_ack'ed it), but /// the remote side hasn't yet revoked their previous state, which we need them to do before we /// can do any backwards failing. Implies AwaitingRemoteRevoke. /// We have removed this HTLC in our latest commitment_signed and are now just waiting on a /// revoke_and_ack to drop completely. + /// Implies HTLCOutput::outbound: true AwaitingRemovedRemoteRevoke, /// Removed by us and a new commitment_signed was sent (if we were AwaitingRemoteRevoke when we /// created it we would have put it in the holding cell instead). When they next revoke_and_ack @@ -136,9 +144,11 @@ enum HTLCState { /// commitment transaction without it as otherwise we'll have to force-close the channel to /// claim it before the timeout (obviously doesn't apply to revoked HTLCs that we can't claim /// anyway). + /// Implies HTLCOutput::outbound: false LocalRemoved, /// Removed by us, sent a new commitment_signed and got a revoke_and_ack. Just waiting on an /// updated local commitment transaction. Implies local_removed_fulfilled. + /// Implies HTLCOutput::outbound: false LocalRemovedAwaitingCommitment, } @@ -363,11 +373,13 @@ impl Channel { } // Constructors: - - /// panics if channel_value_satoshis is >= `MAX_FUNDING_SATOSHIS` - pub fn new_outbound(fee_estimator: &FeeEstimator, chan_keys: ChannelKeys, their_node_id: PublicKey, channel_value_satoshis: u64, announce_publicly: bool, user_id: u64, logger: Arc) -> Channel { + 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 { if channel_value_satoshis >= MAX_FUNDING_SATOSHIS { - panic!("funding value > 2^24"); + return Err(APIError::APIMisuseError{err: "funding value > 2^24"}); + } + + if push_msat > channel_value_satoshis * 1000 { + return Err(APIError::APIMisuseError{err: "push value > channel value"}); } let feerate = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Normal); @@ -381,7 +393,7 @@ impl Channel { &chan_keys.htlc_base_key, BREAKDOWN_TIMEOUT, our_channel_monitor_claim_script); - Channel { + Ok(Channel { user_id: user_id, channel_id: rng::rand_u832(), @@ -394,7 +406,7 @@ impl Channel { local_keys: chan_keys, cur_local_commitment_transaction_number: (1 << 48) - 1, cur_remote_commitment_transaction_number: (1 << 48) - 1, - value_to_self_msat: channel_value_satoshis * 1000, //TODO: give them something on open? Parameterize it? + value_to_self_msat: channel_value_satoshis * 1000 - push_msat, pending_htlcs: Vec::new(), holding_cell_htlc_updates: Vec::new(), next_local_htlc_id: 0, @@ -435,7 +447,7 @@ impl Channel { channel_monitor: channel_monitor, logger, - } + }) } fn check_remote_fee(fee_estimator: &FeeEstimator, feerate_per_kw: u32) -> Result<(), HandleError> { @@ -956,7 +968,7 @@ impl Channel { for (idx, htlc) in self.pending_htlcs.iter().enumerate() { if !htlc.outbound && htlc.payment_hash == payment_hash_calc { if pending_idx != std::usize::MAX { - panic!("Duplicate HTLC payment_hash, you probably re-used payment preimages, NEVER DO THIS!"); + panic!("Duplicate HTLC payment_hash, ChannelManager should have prevented this!"); } pending_idx = idx; } @@ -998,8 +1010,14 @@ impl Channel { if htlc.state == HTLCState::Committed { htlc.state = HTLCState::LocalRemoved; htlc.local_removed_fulfilled = true; - } else if htlc.state == HTLCState::RemoteAnnounced { - panic!("Somehow forwarded HTLC prior to remote revocation!"); + } else if htlc.state == HTLCState::RemoteAnnounced || htlc.state == HTLCState::AwaitingRemoteRevokeToAnnounce || htlc.state == HTLCState::AwaitingAnnouncedRemoteRevoke { + // Theoretically we can hit this if we get the preimage on an HTLC prior to us + // having forwarded it to anyone. This implies that the sender is busted as someone + // else knows the preimage, but handling this case and implementing the logic to + // take their money would be a lot of (never-tested) code to handle a case that + // hopefully never happens. Instead, we make sure we get the preimage into the + // channel_monitor and pretend we didn't just see the preimage. + return Ok((None, Some(self.channel_monitor.clone()))); } else if htlc.state == HTLCState::LocalRemoved || htlc.state == HTLCState::LocalRemovedAwaitingCommitment { return Err(HandleError{err: "Unable to find a pending HTLC which matched the given payment preimage", action: None}); } else { @@ -2016,12 +2034,12 @@ impl Channel { // Methods to get unprompted messages to send to the remote end (or where we already returned // something in the handler for the message that prompted this message): - pub fn get_open_channel(&self, chain_hash: Sha256dHash, fee_estimator: &FeeEstimator) -> Result { + pub fn get_open_channel(&self, chain_hash: Sha256dHash, fee_estimator: &FeeEstimator) -> Result { if !self.channel_outbound { panic!("Tried to open a channel for an inbound channel?"); } if self.channel_state != ChannelState::OurInitSent as u32 { - return Err(HandleError{err: "Cannot generate an open_channel after we've moved forward", action: None}); + panic!("Cannot generate an open_channel after we've moved forward"); } if self.cur_local_commitment_transaction_number != (1 << 48) - 1 { @@ -2034,7 +2052,7 @@ impl Channel { chain_hash: chain_hash, temporary_channel_id: self.channel_id, funding_satoshis: self.channel_value_satoshis, - push_msat: 0, //TODO: Something about feerate? + 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), @@ -2463,7 +2481,7 @@ mod tests { assert_eq!(PublicKey::from_secret_key(&secp_ctx, &chan_keys.funding_key).unwrap().serialize()[..], hex::decode("023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb").unwrap()[..]); - let mut chan = Channel::new_outbound(&feeest, chan_keys, PublicKey::new(), 10000000, false, 42, Arc::clone(&logger)); // Nothing uses their network key in this test + let mut chan = Channel::new_outbound(&feeest, chan_keys, PublicKey::new(), 10000000, 100000, false, 42, Arc::clone(&logger)).unwrap(); // Nothing uses their network key in this test chan.their_to_self_delay = 144; chan.our_dust_limit_satoshis = 546;