]> git.bitcoin.ninja Git - rust-lightning/commitdiff
Merge pull request #334 from ariard/2019-04-fee-estimation-monitor
authorMatt Corallo <649246+TheBlueMatt@users.noreply.github.com>
Sun, 21 Apr 2019 23:44:58 +0000 (19:44 -0400)
committerGitHub <noreply@github.com>
Sun, 21 Apr 2019 23:44:58 +0000 (19:44 -0400)
Add Fee Estimation in ChannelMonitor

1  2 
fuzz/fuzz_targets/chanmon_fail_consistency.rs
fuzz/fuzz_targets/full_stack_target.rs
src/ln/channelmonitor.rs
src/ln/functional_test_utils.rs

index 1cfc4df06078704451cfa44d56beb890029051c0,dd8023ecddc9f10a1b2d4a7e553ea8285bbc7f0d..b12ebea60f5d43806e46f7d2cafb4db2cc6e43a0
@@@ -69,9 -69,9 +69,9 @@@ pub struct TestChannelMonitor 
        pub update_ret: Mutex<Result<(), channelmonitor::ChannelMonitorUpdateErr>>,
  }
  impl TestChannelMonitor {
-       pub fn new(chain_monitor: Arc<chaininterface::ChainWatchInterface>, broadcaster: Arc<chaininterface::BroadcasterInterface>, logger: Arc<Logger>) -> Self {
+       pub fn new(chain_monitor: Arc<chaininterface::ChainWatchInterface>, broadcaster: Arc<chaininterface::BroadcasterInterface>, logger: Arc<Logger>, feeest: Arc<chaininterface::FeeEstimator>) -> Self {
                Self {
-                       simple_monitor: channelmonitor::SimpleManyChannelMonitor::new(chain_monitor, broadcaster, logger),
+                       simple_monitor: channelmonitor::SimpleManyChannelMonitor::new(chain_monitor, broadcaster, logger, feeest),
                        update_ret: Mutex::new(Ok(())),
                }
        }
@@@ -142,13 -142,13 +142,13 @@@ pub fn do_test(data: &[u8]) 
                ($node_id: expr) => { {
                        let logger: Arc<Logger> = Arc::new(test_logger::TestLogger::new($node_id.to_string()));
                        let watch = Arc::new(ChainWatchInterfaceUtil::new(Network::Bitcoin, Arc::clone(&logger)));
-                       let monitor = Arc::new(TestChannelMonitor::new(watch.clone(), broadcast.clone(), logger.clone()));
+                       let monitor = Arc::new(TestChannelMonitor::new(watch.clone(), broadcast.clone(), logger.clone(), fee_est.clone()));
  
                        let keys_manager = Arc::new(KeyProvider { node_id: $node_id });
                        let mut config = UserConfig::new();
                        config.channel_options.fee_proportional_millionths = 0;
                        config.channel_options.announced_channel = true;
 -                      config.channel_limits.min_dust_limit_satoshis = 0;
 +                      config.peer_channel_config_limits.min_dust_limit_satoshis = 0;
                        (ChannelManager::new(Network::Bitcoin, fee_est.clone(), monitor.clone(), watch.clone(), broadcast.clone(), Arc::clone(&logger), keys_manager.clone(), config).unwrap(),
                        monitor)
                } }
index acdfb179a2aca0ed53faed9864ea59f83c6b5bb9,8b477dfa905c90ca9caf16522dca75575d2c80f9..16bebfbd01bde8b64908d5cbf58ab0645d67a794
@@@ -344,13 -344,13 +344,13 @@@ pub fn do_test(data: &[u8], logger: &Ar
  
        let watch = Arc::new(ChainWatchInterfaceUtil::new(Network::Bitcoin, Arc::clone(&logger)));
        let broadcast = Arc::new(TestBroadcaster{});
-       let monitor = channelmonitor::SimpleManyChannelMonitor::new(watch.clone(), broadcast.clone(), Arc::clone(&logger));
+       let monitor = channelmonitor::SimpleManyChannelMonitor::new(watch.clone(), broadcast.clone(), Arc::clone(&logger), fee_est.clone());
  
        let keys_manager = Arc::new(KeyProvider { node_secret: our_network_key.clone() });
        let mut config = UserConfig::new();
        config.channel_options.fee_proportional_millionths =  slice_to_be32(get_slice!(4));
        config.channel_options.announced_channel = get_slice!(1)[0] != 0;
 -      config.channel_limits.min_dust_limit_satoshis = 0;
 +      config.peer_channel_config_limits.min_dust_limit_satoshis = 0;
        let channelmanager = ChannelManager::new(Network::Bitcoin, fee_est.clone(), monitor.clone(), watch.clone(), broadcast.clone(), Arc::clone(&logger), keys_manager.clone(), config).unwrap();
        let router = Arc::new(Router::new(PublicKey::from_secret_key(&Secp256k1::signing_only(), &keys_manager.get_node_secret()), watch.clone(), Arc::clone(&logger)));
  
diff --combined src/ln/channelmonitor.rs
index cc77003cd9fb29be0c1eb9e25e1cf3467c85429c,0b0838781d14fc5369000a8b007305d9df638b92..e1d960e5130baaff7a7622f24e01c6d785efe4a0
@@@ -34,7 -34,7 +34,7 @@@ use ln::chan_utils
  use ln::chan_utils::HTLCOutputInCommitment;
  use ln::channelmanager::{HTLCSource, PaymentPreimage, PaymentHash};
  use ln::channel::{ACCEPTED_HTLC_SCRIPT_WEIGHT, OFFERED_HTLC_SCRIPT_WEIGHT};
- use chain::chaininterface::{ChainListener, ChainWatchInterface, BroadcasterInterface};
+ use chain::chaininterface::{ChainListener, ChainWatchInterface, BroadcasterInterface, FeeEstimator, ConfirmationTarget};
  use chain::transaction::OutPoint;
  use chain::keysinterface::SpendableOutputDescriptor;
  use util::logger::Logger;
@@@ -143,6 -143,7 +143,7 @@@ pub struct SimpleManyChannelMonitor<Key
        pending_events: Mutex<Vec<events::Event>>,
        pending_htlc_updated: Mutex<HashMap<PaymentHash, Vec<(HTLCSource, Option<PaymentPreimage>)>>>,
        logger: Arc<Logger>,
+       fee_estimator: Arc<FeeEstimator>
  }
  
  impl<Key : Send + cmp::Eq + hash::Hash> ChainListener for SimpleManyChannelMonitor<Key> {
                {
                        let mut monitors = self.monitors.lock().unwrap();
                        for monitor in monitors.values_mut() {
-                               let (txn_outputs, spendable_outputs, mut htlc_updated) = monitor.block_connected(txn_matched, height, &block_hash, &*self.broadcaster);
+                               let (txn_outputs, spendable_outputs, mut htlc_updated) = monitor.block_connected(txn_matched, height, &block_hash, &*self.broadcaster, &*self.fee_estimator);
                                if spendable_outputs.len() > 0 {
                                        new_events.push(events::Event::SpendableOutputs {
                                                outputs: spendable_outputs,
  impl<Key : Send + cmp::Eq + hash::Hash + 'static> SimpleManyChannelMonitor<Key> {
        /// Creates a new object which can be used to monitor several channels given the chain
        /// interface with which to register to receive notifications.
-       pub fn new(chain_monitor: Arc<ChainWatchInterface>, broadcaster: Arc<BroadcasterInterface>, logger: Arc<Logger>) -> Arc<SimpleManyChannelMonitor<Key>> {
+       pub fn new(chain_monitor: Arc<ChainWatchInterface>, broadcaster: Arc<BroadcasterInterface>, logger: Arc<Logger>, feeest: Arc<FeeEstimator>) -> Arc<SimpleManyChannelMonitor<Key>> {
                let res = Arc::new(SimpleManyChannelMonitor {
                        monitors: Mutex::new(HashMap::new()),
                        chain_monitor,
                        pending_events: Mutex::new(Vec::new()),
                        pending_htlc_updated: Mutex::new(HashMap::new()),
                        logger,
+                       fee_estimator: feeest,
                });
                let weak_res = Arc::downgrade(&res);
                res.chain_monitor.register_listener(weak_res);
@@@ -340,6 -342,15 +342,15 @@@ struct LocalSignedTx 
        htlc_outputs: Vec<(HTLCOutputInCommitment, Option<(Signature, Signature)>, Option<HTLCSource>)>,
  }
  
+ #[derive(PartialEq)]
+ enum InputDescriptors {
+       RevokedOfferedHTLC,
+       RevokedReceivedHTLC,
+       OfferedHTLC,
+       ReceivedHTLC,
+       RevokedOutput, // either a revoked to_local output on commitment tx, a revoked HTLC-Timeout output or a revoked HTLC-Success output
+ }
  const SERIALIZATION_VERSION: u8 = 1;
  const MIN_SERIALIZATION_VERSION: u8 = 1;
  
@@@ -475,6 -486,36 +486,36 @@@ impl ChannelMonitor 
                }
        }
  
+       fn get_witnesses_weight(inputs: &[InputDescriptors]) -> u64 {
+               let mut tx_weight = 2; // count segwit flags
+               for inp in inputs {
+                       // We use expected weight (and not actual) as signatures and time lock delays may vary
+                       tx_weight +=  match inp {
+                               // number_of_witness_elements + sig_length + revocation_sig + pubkey_length + revocationpubkey + witness_script_length + witness_script
+                               &InputDescriptors::RevokedOfferedHTLC => {
+                                       1 + 1 + 73 + 1 + 33 + 1 + 133
+                               },
+                               // number_of_witness_elements + sig_length + revocation_sig + pubkey_length + revocationpubkey + witness_script_length + witness_script
+                               &InputDescriptors::RevokedReceivedHTLC => {
+                                       1 + 1 + 73 + 1 + 33 + 1 + 139
+                               },
+                               // number_of_witness_elements + sig_length + remotehtlc_sig  + preimage_length + preimage + witness_script_length + witness_script
+                               &InputDescriptors::OfferedHTLC => {
+                                       1 + 1 + 73 + 1 + 32 + 1 + 133
+                               },
+                               // number_of_witness_elements + sig_length + revocation_sig + pubkey_length + revocationpubkey + witness_script_length + witness_script
+                               &InputDescriptors::ReceivedHTLC => {
+                                       1 + 1 + 73 + 1 + 1 + 1 + 139
+                               },
+                               // number_of_witness_elements + sig_length + revocation_sig + true_length + op_true + witness_script_length + witness_script
+                               &InputDescriptors::RevokedOutput => {
+                                       1 + 1 + 73 + 1 + 1 + 1 + 77
+                               },
+                       };
+               }
+               tx_weight
+       }
        #[inline]
        fn place_secret(idx: u64) -> u8 {
                for i in 0..48 {
                                writer.write_all(&delayed_payment_base_key[..])?;
                                writer.write_all(&payment_base_key[..])?;
                                writer.write_all(&shutdown_pubkey.serialize())?;
 -                              if let Some(ref prev_latest_per_commitment_point) = *prev_latest_per_commitment_point {
 -                                      writer.write_all(&[1; 1])?;
 -                                      writer.write_all(&prev_latest_per_commitment_point.serialize())?;
 -                              } else {
 -                                      writer.write_all(&[0; 1])?;
 -                              }
 -                              if let Some(ref latest_per_commitment_point) = *latest_per_commitment_point {
 -                                      writer.write_all(&[1; 1])?;
 -                                      writer.write_all(&latest_per_commitment_point.serialize())?;
 -                              } else {
 -                                      writer.write_all(&[0; 1])?;
 -                              }
 +                              prev_latest_per_commitment_point.write(writer)?;
 +                              latest_per_commitment_point.write(writer)?;
                                match funding_info  {
                                        &Some((ref outpoint, ref script)) => {
                                                writer.write_all(&outpoint.txid[..])?;
                                                debug_assert!(false, "Try to serialize a useless Local monitor !");
                                        },
                                }
 -                              write_option!(current_remote_commitment_txid);
 -                              write_option!(prev_remote_commitment_txid);
 +                              current_remote_commitment_txid.write(writer)?;
 +                              prev_remote_commitment_txid.write(writer)?;
                        },
                        Storage::Watchtower { .. } => unimplemented!(),
                }
                                writer.write_all(&byte_utils::be64_to_array($htlc_output.amount_msat))?;
                                writer.write_all(&byte_utils::be32_to_array($htlc_output.cltv_expiry))?;
                                writer.write_all(&$htlc_output.payment_hash.0[..])?;
 -                              write_option!(&$htlc_output.transaction_output_index);
 +                              $htlc_output.transaction_output_index.write(writer)?;
                        }
                }
  
        /// HTLC-Success/HTLC-Timeout transactions.
        /// Return updates for HTLC pending in the channel and failed automatically by the broadcast of
        /// revoked remote commitment tx
-       fn check_spend_remote_transaction(&mut self, tx: &Transaction, height: u32) -> (Vec<Transaction>, (Sha256dHash, Vec<TxOut>), Vec<SpendableOutputDescriptor>, Vec<(HTLCSource, Option<PaymentPreimage>, PaymentHash)>)  {
+       fn check_spend_remote_transaction(&mut self, tx: &Transaction, height: u32, fee_estimator: &FeeEstimator) -> (Vec<Transaction>, (Sha256dHash, Vec<TxOut>), Vec<SpendableOutputDescriptor>, Vec<(HTLCSource, Option<PaymentPreimage>, PaymentHash)>)  {
                // Most secp and related errors trying to create keys means we have no hope of constructing
                // a spend transaction...so we return no transactions to broadcast
                let mut txn_to_broadcast = Vec::new();
                        let mut values = Vec::new();
                        let mut inputs = Vec::new();
                        let mut htlc_idxs = Vec::new();
+                       let mut input_descriptors = Vec::new();
  
                        for (idx, outp) in tx.output.iter().enumerate() {
                                if outp.script_pubkey == revokeable_p2wsh {
                                        htlc_idxs.push(None);
                                        values.push(outp.value);
                                        total_value += outp.value;
+                                       input_descriptors.push(InputDescriptors::RevokedOutput);
                                } else if Some(&outp.script_pubkey) == local_payment_p2wpkh.as_ref() {
                                        spendable_outputs.push(SpendableOutputDescriptor::DynamicOutputP2WPKH {
                                                outpoint: BitcoinOutPoint { txid: commitment_txid, vout: idx as u32 },
                                                        htlc_idxs.push(Some(idx));
                                                        values.push(tx.output[transaction_output_index as usize].value);
                                                        total_value += htlc.amount_msat / 1000;
+                                                       input_descriptors.push(if htlc.offered { InputDescriptors::RevokedOfferedHTLC } else { InputDescriptors::RevokedReceivedHTLC });
                                                } else {
                                                        let mut single_htlc_tx = Transaction {
                                                                version: 2,
                                                                input: vec![input],
                                                                output: vec!(TxOut {
                                                                        script_pubkey: self.destination_script.clone(),
-                                                                       value: htlc.amount_msat / 1000, //TODO: - fee
+                                                                       value: htlc.amount_msat / 1000,
                                                                }),
                                                        };
+                                                       let predicted_weight = single_htlc_tx.get_weight() + Self::get_witnesses_weight(&[if htlc.offered { InputDescriptors::RevokedOfferedHTLC } else { InputDescriptors::RevokedReceivedHTLC }]);
+                                                       single_htlc_tx.output[0].value -= fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::HighPriority) * predicted_weight / 1000;
                                                        let sighash_parts = bip143::SighashComponents::new(&single_htlc_tx);
                                                        sign_input!(sighash_parts, single_htlc_tx.input[0], Some(idx), htlc.amount_msat / 1000);
+                                                       assert!(predicted_weight >= single_htlc_tx.get_weight());
                                                        txn_to_broadcast.push(single_htlc_tx);
                                                }
                                        }
  
                        let outputs = vec!(TxOut {
                                script_pubkey: self.destination_script.clone(),
-                               value: total_value, //TODO: - fee
+                               value: total_value,
                        });
                        let mut spend_tx = Transaction {
                                version: 2,
                                input: inputs,
                                output: outputs,
                        };
+                       let predicted_weight = spend_tx.get_weight() + Self::get_witnesses_weight(&input_descriptors[..]);
+                       spend_tx.output[0].value -= fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::HighPriority) * predicted_weight / 1000;
  
                        let mut values_drain = values.drain(..);
                        let sighash_parts = bip143::SighashComponents::new(&spend_tx);
                                let value = values_drain.next().unwrap();
                                sign_input!(sighash_parts, input, htlc_idx, value);
                        }
+                       assert!(predicted_weight >= spend_tx.get_weight());
  
                        spendable_outputs.push(SpendableOutputDescriptor::StaticOutput {
                                outpoint: BitcoinOutPoint { txid: spend_tx.txid(), vout: 0 },
                                        let mut total_value = 0;
                                        let mut values = Vec::new();
                                        let mut inputs = Vec::new();
+                                       let mut input_descriptors = Vec::new();
  
                                        macro_rules! sign_input {
                                                ($sighash_parts: expr, $input: expr, $amount: expr, $preimage: expr) => {
                                                                        inputs.push(input);
                                                                        values.push((tx.output[transaction_output_index as usize].value, payment_preimage));
                                                                        total_value += htlc.amount_msat / 1000;
+                                                                       input_descriptors.push(if htlc.offered { InputDescriptors::OfferedHTLC } else { InputDescriptors::ReceivedHTLC });
                                                                } else {
                                                                        let mut single_htlc_tx = Transaction {
                                                                                version: 2,
                                                                                input: vec![input],
                                                                                output: vec!(TxOut {
                                                                                        script_pubkey: self.destination_script.clone(),
-                                                                                       value: htlc.amount_msat / 1000, //TODO: - fee
+                                                                                       value: htlc.amount_msat / 1000,
                                                                                }),
                                                                        };
+                                                                       let predicted_weight = single_htlc_tx.get_weight() + Self::get_witnesses_weight(&[if htlc.offered { InputDescriptors::OfferedHTLC } else { InputDescriptors::ReceivedHTLC }]);
+                                                                       single_htlc_tx.output[0].value -= fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::HighPriority) * predicted_weight / 1000;
                                                                        let sighash_parts = bip143::SighashComponents::new(&single_htlc_tx);
                                                                        sign_input!(sighash_parts, single_htlc_tx.input[0], htlc.amount_msat / 1000, payment_preimage.0.to_vec());
+                                                                       assert!(predicted_weight >= single_htlc_tx.get_weight());
                                                                        spendable_outputs.push(SpendableOutputDescriptor::StaticOutput {
                                                                                outpoint: BitcoinOutPoint { txid: single_htlc_tx.txid(), vout: 0 },
                                                                                output: single_htlc_tx.output[0].clone(),
  
                                        let outputs = vec!(TxOut {
                                                script_pubkey: self.destination_script.clone(),
-                                               value: total_value, //TODO: - fee
+                                               value: total_value
                                        });
                                        let mut spend_tx = Transaction {
                                                version: 2,
                                                input: inputs,
                                                output: outputs,
                                        };
+                                       let predicted_weight = spend_tx.get_weight() + Self::get_witnesses_weight(&input_descriptors[..]);
+                                       spend_tx.output[0].value -= fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::HighPriority) * predicted_weight / 1000;
  
                                        let mut values_drain = values.drain(..);
                                        let sighash_parts = bip143::SighashComponents::new(&spend_tx);
                                                sign_input!(sighash_parts, input, value.0, (value.1).0.to_vec());
                                        }
  
+                                       assert!(predicted_weight >= spend_tx.get_weight());
                                        spendable_outputs.push(SpendableOutputDescriptor::StaticOutput {
                                                outpoint: BitcoinOutPoint { txid: spend_tx.txid(), vout: 0 },
                                                output: spend_tx.output[0].clone(),
        }
  
        /// Attempts to claim a remote HTLC-Success/HTLC-Timeout's outputs using the revocation key
-       fn check_spend_remote_htlc(&self, tx: &Transaction, commitment_number: u64) -> (Option<Transaction>, Option<SpendableOutputDescriptor>) {
+       fn check_spend_remote_htlc(&self, tx: &Transaction, commitment_number: u64, fee_estimator: &FeeEstimator) -> (Option<Transaction>, Option<SpendableOutputDescriptor>) {
                if tx.input.len() != 1 || tx.output.len() != 1 {
                        return (None, None)
                }
                if !inputs.is_empty() {
                        let outputs = vec!(TxOut {
                                script_pubkey: self.destination_script.clone(),
-                               value: amount, //TODO: - fee
+                               value: amount
                        });
  
                        let mut spend_tx = Transaction {
                                input: inputs,
                                output: outputs,
                        };
+                       let predicted_weight = spend_tx.get_weight() + Self::get_witnesses_weight(&[InputDescriptors::RevokedOutput]);
+                       spend_tx.output[0].value -= fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::HighPriority) * predicted_weight / 1000;
  
                        let sighash_parts = bip143::SighashComponents::new(&spend_tx);
  
                        spend_tx.input[0].witness.push(vec!(1));
                        spend_tx.input[0].witness.push(redeemscript.into_bytes());
  
+                       assert!(predicted_weight >= spend_tx.get_weight());
                        let outpoint = BitcoinOutPoint { txid: spend_tx.txid(), vout: 0 };
                        let output = spend_tx.output[0].clone();
                        (Some(spend_tx), Some(SpendableOutputDescriptor::StaticOutput { outpoint, output }))
                }
        }
  
-       fn block_connected(&mut self, txn_matched: &[&Transaction], height: u32, block_hash: &Sha256dHash, broadcaster: &BroadcasterInterface)-> (Vec<(Sha256dHash, Vec<TxOut>)>, Vec<SpendableOutputDescriptor>, Vec<(HTLCSource, Option<PaymentPreimage>, PaymentHash)>) {
+       fn block_connected(&mut self, txn_matched: &[&Transaction], height: u32, block_hash: &Sha256dHash, broadcaster: &BroadcasterInterface, fee_estimator: &FeeEstimator)-> (Vec<(Sha256dHash, Vec<TxOut>)>, Vec<SpendableOutputDescriptor>, Vec<(HTLCSource, Option<PaymentPreimage>, PaymentHash)>) {
                let mut watch_outputs = Vec::new();
                let mut spendable_outputs = Vec::new();
                let mut htlc_updated = Vec::new();
                                        }
                                };
                                if funding_txo.is_none() || (prevout.txid == funding_txo.as_ref().unwrap().0.txid && prevout.vout == funding_txo.as_ref().unwrap().0.index as u32) {
-                                       let (remote_txn, new_outputs, mut spendable_output, mut updated) = self.check_spend_remote_transaction(tx, height);
+                                       let (remote_txn, new_outputs, mut spendable_output, mut updated) = self.check_spend_remote_transaction(tx, height, fee_estimator);
                                        txn = remote_txn;
                                        spendable_outputs.append(&mut spendable_output);
                                        if !new_outputs.1.is_empty() {
                                        }
                                } else {
                                        if let Some(&(commitment_number, _)) = self.remote_commitment_txn_on_chain.get(&prevout.txid) {
-                                               let (tx, spendable_output) = self.check_spend_remote_htlc(tx, commitment_number);
+                                               let (tx, spendable_output) = self.check_spend_remote_htlc(tx, commitment_number, fee_estimator);
                                                if let Some(tx) = tx {
                                                        txn.push(tx);
                                                }
@@@ -2214,13 -2285,19 +2275,19 @@@ impl<R: ::std::io::Read> ReadableArgs<R
  
  #[cfg(test)]
  mod tests {
-       use bitcoin::blockdata::script::Script;
-       use bitcoin::blockdata::transaction::Transaction;
+       use bitcoin::blockdata::script::{Script, Builder};
+       use bitcoin::blockdata::opcodes;
+       use bitcoin::blockdata::transaction::{Transaction, TxIn, TxOut, SigHashType};
+       use bitcoin::blockdata::transaction::OutPoint as BitcoinOutPoint;
+       use bitcoin::util::bip143;
        use bitcoin_hashes::Hash;
        use bitcoin_hashes::sha256::Hash as Sha256;
+       use bitcoin_hashes::sha256d::Hash as Sha256dHash;
+       use bitcoin_hashes::hex::FromHex;
        use hex;
        use ln::channelmanager::{PaymentPreimage, PaymentHash};
-       use ln::channelmonitor::ChannelMonitor;
+       use ln::channelmonitor::{ChannelMonitor, InputDescriptors};
+       use ln::chan_utils;
        use ln::chan_utils::{HTLCOutputInCommitment, TxCreationKeys};
        use util::test_utils::TestLogger;
        use secp256k1::key::{SecretKey,PublicKey};
                test_preimages_exist!(&preimages[0..5], monitor);
        }
  
+       #[test]
+       fn test_claim_txn_weight_computation() {
+               // We test Claim txn weight, knowing that we want expected weigth and
+               // not actual case to avoid sigs and time-lock delays hell variances.
+               let secp_ctx = Secp256k1::new();
+               let privkey = SecretKey::from_slice(&hex::decode("0101010101010101010101010101010101010101010101010101010101010101").unwrap()[..]).unwrap();
+               let pubkey = PublicKey::from_secret_key(&secp_ctx, &privkey);
+               let mut sum_actual_sigs: u64 = 0;
+               macro_rules! sign_input {
+                       ($sighash_parts: expr, $input: expr, $idx: expr, $amount: expr, $input_type: expr, $sum_actual_sigs: expr) => {
+                               let htlc = HTLCOutputInCommitment {
+                                       offered: if *$input_type == InputDescriptors::RevokedOfferedHTLC || *$input_type == InputDescriptors::OfferedHTLC { true } else { false },
+                                       amount_msat: 0,
+                                       cltv_expiry: 2 << 16,
+                                       payment_hash: PaymentHash([1; 32]),
+                                       transaction_output_index: Some($idx),
+                               };
+                               let redeem_script = if *$input_type == InputDescriptors::RevokedOutput { chan_utils::get_revokeable_redeemscript(&pubkey, 256, &pubkey) } else { chan_utils::get_htlc_redeemscript_with_explicit_keys(&htlc, &pubkey, &pubkey, &pubkey) };
+                               let sighash = hash_to_message!(&$sighash_parts.sighash_all(&$input, &redeem_script, $amount)[..]);
+                               let sig = secp_ctx.sign(&sighash, &privkey);
+                               $input.witness.push(sig.serialize_der().to_vec());
+                               $input.witness[0].push(SigHashType::All as u8);
+                               sum_actual_sigs += $input.witness[0].len() as u64;
+                               if *$input_type == InputDescriptors::RevokedOutput {
+                                       $input.witness.push(vec!(1));
+                               } else if *$input_type == InputDescriptors::RevokedOfferedHTLC || *$input_type == InputDescriptors::RevokedReceivedHTLC {
+                                       $input.witness.push(pubkey.clone().serialize().to_vec());
+                               } else if *$input_type == InputDescriptors::ReceivedHTLC {
+                                       $input.witness.push(vec![0]);
+                               } else {
+                                       $input.witness.push(PaymentPreimage([1; 32]).0.to_vec());
+                               }
+                               $input.witness.push(redeem_script.into_bytes());
+                               println!("witness[0] {}", $input.witness[0].len());
+                               println!("witness[1] {}", $input.witness[1].len());
+                               println!("witness[2] {}", $input.witness[2].len());
+                       }
+               }
+               let script_pubkey = Builder::new().push_opcode(opcodes::all::OP_RETURN).into_script();
+               let txid = Sha256dHash::from_hex("56944c5d3f98413ef45cf54545538103cc9f298e0575820ad3591376e2e0f65d").unwrap();
+               // Justice tx with 1 to_local, 2 revoked offered HTLCs, 1 revoked received HTLCs
+               let mut claim_tx = Transaction { version: 0, lock_time: 0, input: Vec::new(), output: Vec::new() };
+               for i in 0..4 {
+                       claim_tx.input.push(TxIn {
+                               previous_output: BitcoinOutPoint {
+                                       txid,
+                                       vout: i,
+                               },
+                               script_sig: Script::new(),
+                               sequence: 0xfffffffd,
+                               witness: Vec::new(),
+                       });
+               }
+               claim_tx.output.push(TxOut {
+                       script_pubkey: script_pubkey.clone(),
+                       value: 0,
+               });
+               let base_weight = claim_tx.get_weight();
+               let sighash_parts = bip143::SighashComponents::new(&claim_tx);
+               let inputs_des = vec![InputDescriptors::RevokedOutput, InputDescriptors::RevokedOfferedHTLC, InputDescriptors::RevokedOfferedHTLC, InputDescriptors::RevokedReceivedHTLC];
+               for (idx, inp) in claim_tx.input.iter_mut().zip(inputs_des.iter()).enumerate() {
+                       sign_input!(sighash_parts, inp.0, idx as u32, 0, inp.1, sum_actual_sigs);
+               }
+               assert_eq!(base_weight + ChannelMonitor::get_witnesses_weight(&inputs_des[..]),  claim_tx.get_weight() + /* max_length_sig */ (73 * inputs_des.len() as u64 - sum_actual_sigs));
+               // Claim tx with 1 offered HTLCs, 3 received HTLCs
+               claim_tx.input.clear();
+               sum_actual_sigs = 0;
+               for i in 0..4 {
+                       claim_tx.input.push(TxIn {
+                               previous_output: BitcoinOutPoint {
+                                       txid,
+                                       vout: i,
+                               },
+                               script_sig: Script::new(),
+                               sequence: 0xfffffffd,
+                               witness: Vec::new(),
+                       });
+               }
+               let base_weight = claim_tx.get_weight();
+               let sighash_parts = bip143::SighashComponents::new(&claim_tx);
+               let inputs_des = vec![InputDescriptors::OfferedHTLC, InputDescriptors::ReceivedHTLC, InputDescriptors::ReceivedHTLC, InputDescriptors::ReceivedHTLC];
+               for (idx, inp) in claim_tx.input.iter_mut().zip(inputs_des.iter()).enumerate() {
+                       sign_input!(sighash_parts, inp.0, idx as u32, 0, inp.1, sum_actual_sigs);
+               }
+               assert_eq!(base_weight + ChannelMonitor::get_witnesses_weight(&inputs_des[..]),  claim_tx.get_weight() + /* max_length_sig */ (73 * inputs_des.len() as u64 - sum_actual_sigs));
+               // Justice tx with 1 revoked HTLC-Success tx output
+               claim_tx.input.clear();
+               sum_actual_sigs = 0;
+               claim_tx.input.push(TxIn {
+                       previous_output: BitcoinOutPoint {
+                               txid,
+                               vout: 0,
+                       },
+                       script_sig: Script::new(),
+                       sequence: 0xfffffffd,
+                       witness: Vec::new(),
+               });
+               let base_weight = claim_tx.get_weight();
+               let sighash_parts = bip143::SighashComponents::new(&claim_tx);
+               let inputs_des = vec![InputDescriptors::RevokedOutput];
+               for (idx, inp) in claim_tx.input.iter_mut().zip(inputs_des.iter()).enumerate() {
+                       sign_input!(sighash_parts, inp.0, idx as u32, 0, inp.1, sum_actual_sigs);
+               }
+               assert_eq!(base_weight + ChannelMonitor::get_witnesses_weight(&inputs_des[..]), claim_tx.get_weight() + /* max_length_isg */ (73 * inputs_des.len() as u64 - sum_actual_sigs));
+       }
        // Further testing is done in the ChannelManager integration tests.
  }
index ecd1529c0c0e8fb37e3b03debb767dcd90eedaf6,c5d6751d9a999c6ecc19119dd8ff121f2bff6092..9a24d503ceea3d5323ab8783f84d274f56d0388f
@@@ -821,10 -821,10 +821,10 @@@ pub fn create_network(node_count: usize
                let mut seed = [0; 32];
                rng.fill_bytes(&mut seed);
                let keys_manager = Arc::new(test_utils::TestKeysInterface::new(&seed, Network::Testnet, Arc::clone(&logger)));
-               let chan_monitor = Arc::new(test_utils::TestChannelMonitor::new(chain_monitor.clone(), tx_broadcaster.clone(), logger.clone()));
+               let chan_monitor = Arc::new(test_utils::TestChannelMonitor::new(chain_monitor.clone(), tx_broadcaster.clone(), logger.clone(), feeest.clone()));
                let mut config = UserConfig::new();
                config.channel_options.announced_channel = true;
 -              config.channel_limits.force_announced_channel_preference = false;
 +              config.peer_channel_config_limits.force_announced_channel_preference = false;
                let node = ChannelManager::new(Network::Testnet, feeest.clone(), chan_monitor.clone(), chain_monitor.clone(), tx_broadcaster.clone(), Arc::clone(&logger), keys_manager.clone(), config).unwrap();
                let router = Router::new(PublicKey::from_secret_key(&secp_ctx, &keys_manager.get_node_secret()), chain_monitor.clone(), Arc::clone(&logger));
                nodes.push(Node { chain_monitor, tx_broadcaster, chan_monitor, node, router, keys_manager, node_seed: seed,