Merge pull request #52 from TheBlueMatt/master
[rust-lightning] / src / ln / channel.rs
index 37d435cefc1a2ca4336ae0e23376a01f545a0c73..f36ce1c506f767e4f1b0821e96bc981813abdd4d 100644 (file)
@@ -245,6 +245,10 @@ pub struct Channel {
 
        local_keys: ChannelKeys,
 
+       // 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
+       // cost of others, but should really just be changed.
+
        cur_local_commitment_transaction_number: u64,
        cur_remote_commitment_transaction_number: u64,
        value_to_self_msat: u64, // Excluding all pending_htlcs, excluding fees
@@ -316,6 +320,9 @@ const COMMITMENT_TX_BASE_WEIGHT: u64 = 724;
 const COMMITMENT_TX_WEIGHT_PER_HTLC: u64 = 172;
 const SPENDING_INPUT_FOR_A_OUTPUT_WEIGHT: u64 = 79; // prevout: 36, nSequence: 4, script len: 1, witness lengths: (3+1)/4, sig: 73/4, if-selector: 1, redeemScript: (6 ops + 2*33 pubkeys + 1*2 delay)/4
 const B_OUTPUT_PLUS_SPENDING_INPUT_WEIGHT: u64 = 104; // prevout: 40, nSequence: 4, script len: 1, witness lengths: 3/4, sig: 73/4, pubkey: 33/4, output: 31 (TODO: Wrong? Useless?)
+/// Maximmum `funding_satoshis` value, according to the BOLT #2 specification
+/// it's 2^24.
+pub const MAX_FUNDING_SATOSHIS: u64 = (1 << 24);
 
 macro_rules! secp_call {
        ( $res: expr, $err: expr ) => {
@@ -340,7 +347,7 @@ impl Channel {
 
        /// Guaranteed to return a value no larger than channel_value_satoshis
        fn get_our_channel_reserve_satoshis(channel_value_satoshis: u64) -> u64 {
-               cmp::min(channel_value_satoshis, 10) //TODO
+               cmp::min(channel_value_satoshis, 1000) //TODO
        }
 
        fn derive_our_dust_limit_satoshis(at_open_background_feerate: u64) -> u64 {
@@ -353,9 +360,9 @@ impl Channel {
 
        // Constructors:
 
-       /// panics if channel_value_satoshis is >= (1 << 24)
+       /// 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) -> Channel {
-               if channel_value_satoshis >= (1 << 24) {
+               if channel_value_satoshis >= MAX_FUNDING_SATOSHIS {
                        panic!("funding value > 2^24");
                }
 
@@ -441,12 +448,9 @@ impl Channel {
        /// that we're rejecting the new channel.
        pub fn new_from_req(fee_estimator: &FeeEstimator, chan_keys: ChannelKeys, their_node_id: PublicKey, msg: &msgs::OpenChannel, user_id: u64, announce_publicly: bool) -> Result<Channel, HandleError> {
                // Check sanity of message fields:
-               if msg.funding_satoshis >= (1 << 24) {
+               if msg.funding_satoshis >= MAX_FUNDING_SATOSHIS {
                        return Err(HandleError{err: "funding value > 2^24", msg: Some(msgs::ErrorAction::DisconnectPeer{})});
                }
-               if msg.funding_satoshis > 21000000 * 100000000 {
-                       return Err(HandleError{err: "More funding_satoshis than there are satoshis!", msg: Some(msgs::ErrorAction::DisconnectPeer{})});
-               }
                if msg.channel_reserve_satoshis > msg.funding_satoshis {
                        return Err(HandleError{err: "Bogus channel_reserve_satoshis", msg: Some(msgs::ErrorAction::DisconnectPeer{})});
                }
@@ -456,9 +460,6 @@ impl Channel {
                if msg.dust_limit_satoshis > msg.funding_satoshis {
                        return Err(HandleError{err: "Peer never wants payout outputs?", msg: Some(msgs::ErrorAction::DisconnectPeer{})});
                }
-               if msg.max_htlc_value_in_flight_msat > msg.funding_satoshis * 1000 {
-                       return Err(HandleError{err: "Bogus max_htlc_value_in_flight_satoshis", msg: Some(msgs::ErrorAction::DisconnectPeer{})});
-               }
                if msg.htlc_minimum_msat >= (msg.funding_satoshis - msg.channel_reserve_satoshis) * 1000 {
                        return Err(HandleError{err: "Minimum htlc value is full channel value", msg: Some(msgs::ErrorAction::DisconnectPeer{})});
                }
@@ -521,7 +522,7 @@ impl Channel {
                        channel_value_satoshis: msg.funding_satoshis,
                        their_dust_limit_satoshis: msg.dust_limit_satoshis,
                        our_dust_limit_satoshis: Channel::derive_our_dust_limit_satoshis(background_feerate),
-                       their_max_htlc_value_in_flight_msat: msg.max_htlc_value_in_flight_msat,
+                       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),
@@ -595,7 +596,7 @@ impl Channel {
        /// which peer generated this transaction and "to whom" this transaction flows.
        #[inline]
        fn build_commitment_transaction(&self, commitment_number: u64, keys: &TxCreationKeys, local: bool, generated_by_local: bool) -> (Transaction, Vec<HTLCOutputInCommitment>) {
-               let obscured_commitment_transaction_number = self.get_commitment_transaction_number_obscure_factor() ^ commitment_number;
+               let obscured_commitment_transaction_number = self.get_commitment_transaction_number_obscure_factor() ^ (0xffffffffffff - commitment_number);
 
                let txins = {
                        let mut ins: Vec<TxIn> = Vec::new();
@@ -1081,9 +1082,6 @@ impl Channel {
                if msg.dust_limit_satoshis > 21000000 * 100000000 {
                        return Err(HandleError{err: "Peer never wants payout outputs?", msg: None});
                }
-               if msg.max_htlc_value_in_flight_msat > self.channel_value_satoshis * 1000 {
-                       return Err(HandleError{err: "Bogus max_htlc_value_in_flight_satoshis", msg: None});
-               }
                if msg.channel_reserve_satoshis > self.channel_value_satoshis {
                        return Err(HandleError{err: "Bogus channel_reserve_satoshis", msg: None});
                }
@@ -1101,7 +1099,7 @@ impl Channel {
                self.channel_monitor.set_their_htlc_base_key(&msg.htlc_basepoint);
 
                self.their_dust_limit_satoshis = msg.dust_limit_satoshis;
-               self.their_max_htlc_value_in_flight_msat = msg.max_htlc_value_in_flight_msat;
+               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;
                self.their_htlc_minimum_msat = msg.htlc_minimum_msat;
                self.their_to_self_delay = msg.to_self_delay;
@@ -1164,7 +1162,7 @@ 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.channel_monitor.provide_latest_remote_commitment_tx_info(&remote_initial_commitment_tx, Vec::new(), self.cur_remote_commitment_transaction_number);
                self.channel_state = ChannelState::FundingSent as u32;
                self.channel_id = funding_txo.to_channel_id();
                self.cur_remote_commitment_transaction_number -= 1;
@@ -1313,7 +1311,7 @@ impl Channel {
        /// Removes an outbound HTLC which has been commitment_signed by the remote end
        #[inline]
        fn mark_outbound_htlc_removed(&mut self, htlc_id: u64, check_preimage: Option<[u8; 32]>, fail_reason: Option<HTLCFailReason>) -> Result<[u8; 32], HandleError> {
-               for mut htlc in self.pending_htlcs.iter_mut() {
+               for htlc in self.pending_htlcs.iter_mut() {
                        if htlc.outbound && htlc.htlc_id == htlc_id {
                                match check_preimage {
                                        None => {},
@@ -2068,7 +2066,7 @@ impl Channel {
                let temporary_channel_id = self.channel_id;
 
                // Now that we're past error-generating stuff, update our local state:
-               self.channel_monitor.provide_latest_remote_commitment_tx_info(&commitment_tx, Vec::new());
+               self.channel_monitor.provide_latest_remote_commitment_tx_info(&commitment_tx, Vec::new(), self.cur_remote_commitment_transaction_number);
                self.channel_state = ChannelState::FundingCreated as u32;
                self.channel_id = funding_txo.to_channel_id();
                self.cur_remote_commitment_transaction_number -= 1;
@@ -2241,7 +2239,7 @@ impl Channel {
                }
 
                // Update state now that we've passed all the can-fail calls...
-               self.channel_monitor.provide_latest_remote_commitment_tx_info(&remote_commitment_tx.0, remote_commitment_tx.1);
+               self.channel_monitor.provide_latest_remote_commitment_tx_info(&remote_commitment_tx.0, remote_commitment_tx.1, self.cur_remote_commitment_transaction_number);
                self.channel_state |= ChannelState::AwaitingRemoteRevoke as u32;
 
                Ok((msgs::CommitmentSigned {
@@ -2328,6 +2326,7 @@ mod tests {
        use bitcoin::network::serialize::serialize;
        use bitcoin::blockdata::transaction::Transaction;
        use ln::channel::{Channel,ChannelKeys,HTLCOutput,HTLCState,HTLCOutputInCommitment,TxCreationKeys};
+       use ln::channel::MAX_FUNDING_SATOSHIS;
        use ln::chan_utils;
        use chain::chaininterface::{FeeEstimator,ConfirmationTarget};
        use chain::transaction::OutPoint;
@@ -2345,6 +2344,12 @@ mod tests {
                }
        }
 
+       #[test]
+       fn test_max_funding_satoshis() {
+               assert!(MAX_FUNDING_SATOSHIS <= 21_000_000 * 100_000_000,
+                       "MAX_FUNDING_SATOSHIS is greater than all satoshis on existence");
+       }
+
        #[test]
        fn outbound_commitment_test() {
                // Test vectors from BOLT 3 Appendix C:
@@ -2400,7 +2405,7 @@ mod tests {
 
                macro_rules! test_commitment {
                        ( $their_sig_hex: expr, $our_sig_hex: expr, $tx_hex: expr) => {
-                               unsigned_tx = chan.build_commitment_transaction(42, &keys, true, false);
+                               unsigned_tx = chan.build_commitment_transaction(0xffffffffffff - 42, &keys, true, false);
                                let their_signature = Signature::from_der(&secp_ctx, &hex_bytes($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();