WIP
[rust-lightning] / lightning / src / ln / channel.rs
index 151564e556dc76bc3da752b4875ce0a3636c76a9..9a586254beaad85cce559fa898846db5135b2ffe 100644 (file)
@@ -371,14 +371,16 @@ const SPENDING_INPUT_FOR_A_OUTPUT_WEIGHT: u64 = 79; // prevout: 36, nSequence: 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?)
 
 #[cfg(not(test))]
-const COMMITMENT_TX_BASE_WEIGHT: u64 = 724;
+const COMMITMENT_TX_BASE_WEIGHT: u64 = 896;
 #[cfg(test)]
-pub const COMMITMENT_TX_BASE_WEIGHT: u64 = 724;
+pub const COMMITMENT_TX_BASE_WEIGHT: u64 = 896;
 #[cfg(not(test))]
 const COMMITMENT_TX_WEIGHT_PER_HTLC: u64 = 172;
 #[cfg(test)]
 pub const COMMITMENT_TX_WEIGHT_PER_HTLC: u64 = 172;
 
+const ANCHOR_VALUE_SATOSHIS: u64 = 330;
+
 /// Maximmum `funding_satoshis` value, according to the BOLT #2 specification
 /// it's 2^24.
 pub const MAX_FUNDING_SATOSHIS: u64 = 1 << 24;
@@ -648,13 +650,14 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
                // check if the funder's amount for the initial commitment tx is sufficient
                // for full fee payment
                let funders_amount_msat = msg.funding_satoshis * 1000 - msg.push_msat;
-               if funders_amount_msat < background_feerate * COMMITMENT_TX_BASE_WEIGHT {
+               if funders_amount_msat < background_feerate * COMMITMENT_TX_BASE_WEIGHT + ANCHOR_VALUE_SATOSHIS * 1000 {
                        return Err(ChannelError::Close("Insufficient funding amount for initial commitment"));
                }
 
-               let to_local_msat = msg.push_msat;
-               let to_remote_msat = funders_amount_msat - background_feerate * COMMITMENT_TX_BASE_WEIGHT;
-               if to_local_msat <= msg.channel_reserve_satoshis * 1000 && to_remote_msat <= remote_channel_reserve_satoshis * 1000 {
+               let to_remote_msat = funders_amount_msat - background_feerate * COMMITMENT_TX_BASE_WEIGHT - ANCHOR_VALUE_SATOSHIS * 1000;
+               // While its reasonable for us to not meet the channel reserve initially (if they don't
+               // want to push much to us), our counterparty should always have more than the reserve.
+               if to_remote_msat <= remote_channel_reserve_satoshis * 1000 {
                        return Err(ChannelError::Close("Insufficient funding amount for initial commitment"));
                }
 
@@ -954,14 +957,24 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
 
                let total_fee: u64 = feerate_per_kw * (COMMITMENT_TX_BASE_WEIGHT + (txouts.len() as u64) * COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000;
                let (value_to_self, value_to_remote) = if self.channel_outbound {
-                       (value_to_self_msat / 1000 - total_fee as i64, value_to_remote_msat / 1000)
+                       (value_to_self_msat / 1000 - total_fee as i64 - ANCHOR_VALUE_SATOSHIS as i64, value_to_remote_msat / 1000)
                } else {
-                       (value_to_self_msat / 1000, value_to_remote_msat / 1000 - total_fee as i64)
+                       (value_to_self_msat / 1000, value_to_remote_msat / 1000 - total_fee as i64 - ANCHOR_VALUE_SATOSHIS as i64)
                };
+               debug_assert!(value_to_self >= 0);
+               debug_assert!(value_to_remote >= 0);
 
                let value_to_a = if local { value_to_self } else { value_to_remote };
                let value_to_b = if local { value_to_remote } else { value_to_self };
 
+               if value_to_a >= (dust_limit_satoshis as i64) || !txouts.is_empty() {
+                       // Always push the anchor output so that local can get the transaction confirmed.
+                       txouts.push((TxOut {
+                               script_pubkey: Script::new(), //XXX
+                               value: ANCHOR_VALUE_SATOSHIS
+                       }, None));
+               }
+
                if value_to_a >= (dust_limit_satoshis as i64) {
                        log_trace!(logger, "   ...including {} output with value {}", if local { "to_local" } else { "to_remote" }, value_to_a);
                        txouts.push((TxOut {
@@ -987,6 +1000,7 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
                        }, None));
                }
 
+
                transaction_utils::sort_outputs(&mut txouts, |a, b| {
                        if let &Some(ref a_htlc) = a {
                                if let &Some(ref b_htlc) = b {
@@ -1847,7 +1861,7 @@ debug_assert!(false, "This should be triggerable, and we should add a test case
                //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 {
                        let num_htlcs = local_commitment_tx.1;
-                       let total_fee: u64 = feerate_per_kw as u64 * (COMMITMENT_TX_BASE_WEIGHT + (num_htlcs as u64) * COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000;
+                       let total_fee: u64 = feerate_per_kw as u64 * (COMMITMENT_TX_BASE_WEIGHT + (num_htlcs as u64) * COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000 + ANCHOR_VALUE_SATOSHIS;
 
                        let remote_reserve_we_require = Channel::<ChanSigner>::get_remote_channel_reserve_satoshis(self.channel_value_satoshis);
                        if self.channel_value_satoshis - self.value_to_self_msat / 1000 < total_fee + remote_reserve_we_require {
@@ -2493,6 +2507,7 @@ debug_assert!(false, "This should be triggerable, and we should add a test case
                let commitment_update = if self.monitor_pending_commitment_signed {
                        Some(self.get_last_commitment_update(logger))
                } else { None };
+//XXX: Should we free_holding_cell_htlcs() here if we dont need a cs normally?
 
                self.monitor_pending_revoke_and_ack = false;
                self.monitor_pending_commitment_signed = false;