Merge pull request #559 from ariard/2020-03-move-local-commitment
authorMatt Corallo <649246+TheBlueMatt@users.noreply.github.com>
Sat, 18 Apr 2020 00:05:11 +0000 (00:05 +0000)
committerGitHub <noreply@github.com>
Sat, 18 Apr 2020 00:05:11 +0000 (00:05 +0000)
Split parsing and transaction management for local transactions between Chanmon/Onchain

lightning/src/chain/keysinterface.rs
lightning/src/ln/chan_utils.rs
lightning/src/ln/channel.rs
lightning/src/ln/channelmonitor.rs
lightning/src/ln/functional_test_utils.rs
lightning/src/ln/functional_tests.rs
lightning/src/ln/onchaintx.rs
lightning/src/util/enforcing_trait_impls.rs

index 2b90188637c1535bb8ce442a1f5478c914926fcf..58bdd7226097d06382a06cf086c1a0080ab98f51 100644 (file)
@@ -24,7 +24,8 @@ use util::logger::Logger;
 use util::ser::{Writeable, Writer, Readable};
 
 use ln::chan_utils;
-use ln::chan_utils::{TxCreationKeys, HTLCOutputInCommitment, make_funding_redeemscript, ChannelPublicKeys};
+use ln::chan_utils::{TxCreationKeys, HTLCOutputInCommitment, make_funding_redeemscript, ChannelPublicKeys, LocalCommitmentTransaction};
+use ln::channelmanager::PaymentPreimage;
 use ln::msgs;
 
 use std::sync::Arc;
@@ -215,6 +216,26 @@ pub trait ChannelKeys : Send+Clone {
        /// making the callee generate it via some util function we expose)!
        fn sign_remote_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, feerate_per_kw: u64, commitment_tx: &Transaction, keys: &TxCreationKeys, htlcs: &[&HTLCOutputInCommitment], to_self_delay: u16, secp_ctx: &Secp256k1<T>) -> Result<(Signature, Vec<Signature>), ()>;
 
+       /// Create a signature for a local commitment transaction
+       ///
+       /// TODO: Document the things someone using this interface should enforce before signing.
+       /// TODO: Add more input vars to enable better checking (preferably removing commitment_tx and
+       /// TODO: Ensure test-only version doesn't enforce uniqueness of signature when it's enforced in this method
+       /// making the callee generate it via some util function we expose)!
+       fn sign_local_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, local_commitment_tx: &mut LocalCommitmentTransaction, funding_redeemscript: &Script, channel_value_satoshis: u64, secp_ctx: &Secp256k1<T>);
+
+       /// Create a signature for a local commitment transaction without enforcing one-time signing.
+       ///
+       /// Testing revocation logic by our test framework needs to sign multiple local commitment
+       /// transactions. This unsafe test-only version doesn't enforce one-time signing security
+       /// requirement.
+       #[cfg(test)]
+       fn unsafe_sign_local_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, local_commitment_tx: &mut LocalCommitmentTransaction, funding_redeemscript: &Script, channel_value_satoshis: u64, secp_ctx: &Secp256k1<T>);
+
+       /// Signs a transaction created by build_htlc_transaction. If the transaction is an
+       /// HTLC-Success transaction, preimage must be set!
+       /// TODO: should be merged with sign_local_commitment as a slice of HTLC transactions to sign
+       fn sign_htlc_transaction<T: secp256k1::Signing>(&self, local_commitment_tx: &mut LocalCommitmentTransaction, htlc_index: u32, preimage: Option<PaymentPreimage>, local_csv: u16, secp_ctx: &Secp256k1<T>);
        /// Create a signature for a (proposed) closing transaction.
        ///
        /// Note that, due to rounding, there may be one "missing" satoshi, and either party may have
@@ -342,6 +363,19 @@ impl ChannelKeys for InMemoryChannelKeys {
                Ok((commitment_sig, htlc_sigs))
        }
 
+       fn sign_local_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, local_commitment_tx: &mut LocalCommitmentTransaction, funding_redeemscript: &Script, channel_value_satoshis: u64, secp_ctx: &Secp256k1<T>) {
+               local_commitment_tx.add_local_sig(&self.funding_key, funding_redeemscript, channel_value_satoshis, secp_ctx);
+       }
+
+       #[cfg(test)]
+       fn unsafe_sign_local_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, local_commitment_tx: &mut LocalCommitmentTransaction, funding_redeemscript: &Script, channel_value_satoshis: u64, secp_ctx: &Secp256k1<T>) {
+               local_commitment_tx.add_local_sig(&self.funding_key, funding_redeemscript, channel_value_satoshis, secp_ctx);
+       }
+
+       fn sign_htlc_transaction<T: secp256k1::Signing>(&self, local_commitment_tx: &mut LocalCommitmentTransaction, htlc_index: u32, preimage: Option<PaymentPreimage>, local_csv: u16, secp_ctx: &Secp256k1<T>) {
+               local_commitment_tx.add_htlc_sig(&self.htlc_base_key, htlc_index, preimage, local_csv, secp_ctx);
+       }
+
        fn sign_closing_transaction<T: secp256k1::Signing>(&self, closing_tx: &Transaction, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()> {
                if closing_tx.input.len() != 1 { return Err(()); }
                if closing_tx.input[0].witness.len() != 0 { return Err(()); }
index 561448c8fbfd34b355b72ea9abfc73bf8656b403..566fd7b00d8358182c20d9256626d41e791bce68 100644 (file)
@@ -23,6 +23,10 @@ use secp256k1::key::{SecretKey, PublicKey};
 use secp256k1::{Secp256k1, Signature};
 use secp256k1;
 
+use std::{cmp, mem};
+
+const MAX_ALLOC_SIZE: usize = 64*1024;
+
 pub(super) const HTLC_SUCCESS_TX_WEIGHT: u64 = 703;
 pub(super) const HTLC_TIMEOUT_TX_WEIGHT: u64 = 663;
 
@@ -355,7 +359,7 @@ impl_writeable!(HTLCOutputInCommitment, 1 + 8 + 4 + 32 + 5, {
 });
 
 #[inline]
-pub(super) fn get_htlc_redeemscript_with_explicit_keys(htlc: &HTLCOutputInCommitment, a_htlc_key: &PublicKey, b_htlc_key: &PublicKey, revocation_key: &PublicKey) -> Script {
+pub(crate) fn get_htlc_redeemscript_with_explicit_keys(htlc: &HTLCOutputInCommitment, a_htlc_key: &PublicKey, b_htlc_key: &PublicKey, revocation_key: &PublicKey) -> Script {
        let payment_hash160 = Ripemd160::hash(&htlc.payment_hash.0[..]).into_inner();
        if htlc.offered {
                Builder::new().push_opcode(opcodes::all::OP_DUP)
@@ -475,62 +479,44 @@ pub fn build_htlc_transaction(prev_hash: &Sha256dHash, feerate_per_kw: u64, to_s
        }
 }
 
-/// Signs a transaction created by build_htlc_transaction. If the transaction is an
-/// HTLC-Success transaction (ie htlc.offered is false), preimage must be set!
-pub(crate) fn sign_htlc_transaction<T: secp256k1::Signing>(tx: &mut Transaction, their_sig: &Signature, preimage: &Option<PaymentPreimage>, htlc: &HTLCOutputInCommitment, a_htlc_key: &PublicKey, b_htlc_key: &PublicKey, revocation_key: &PublicKey, per_commitment_point: &PublicKey, htlc_base_key: &SecretKey, secp_ctx: &Secp256k1<T>) -> Result<(Signature, Script), ()> {
-       if tx.input.len() != 1 { return Err(()); }
-       if tx.input[0].witness.len() != 0 { return Err(()); }
-
-       let htlc_redeemscript = get_htlc_redeemscript_with_explicit_keys(&htlc, a_htlc_key, b_htlc_key, revocation_key);
-
-       let our_htlc_key = derive_private_key(secp_ctx, per_commitment_point, htlc_base_key).map_err(|_| ())?;
-       let sighash = hash_to_message!(&bip143::SighashComponents::new(&tx).sighash_all(&tx.input[0], &htlc_redeemscript, htlc.amount_msat / 1000)[..]);
-       let local_tx = PublicKey::from_secret_key(&secp_ctx, &our_htlc_key) == *a_htlc_key;
-       let our_sig = secp_ctx.sign(&sighash, &our_htlc_key);
-
-       tx.input[0].witness.push(Vec::new()); // First is the multisig dummy
-
-       if local_tx { // b, then a
-               tx.input[0].witness.push(their_sig.serialize_der().to_vec());
-               tx.input[0].witness.push(our_sig.serialize_der().to_vec());
-       } else {
-               tx.input[0].witness.push(our_sig.serialize_der().to_vec());
-               tx.input[0].witness.push(their_sig.serialize_der().to_vec());
-       }
-       tx.input[0].witness[1].push(SigHashType::All as u8);
-       tx.input[0].witness[2].push(SigHashType::All as u8);
-
-       if htlc.offered {
-               tx.input[0].witness.push(Vec::new());
-               assert!(preimage.is_none());
-       } else {
-               tx.input[0].witness.push(preimage.unwrap().0.to_vec());
-       }
-
-       tx.input[0].witness.push(htlc_redeemscript.as_bytes().to_vec());
-
-       Ok((our_sig, htlc_redeemscript))
-}
-
 #[derive(Clone)]
 /// We use this to track local commitment transactions and put off signing them until we are ready
 /// to broadcast. Eventually this will require a signer which is possibly external, but for now we
 /// just pass in the SecretKeys required.
-pub(crate) struct LocalCommitmentTransaction {
-       tx: Transaction
+pub struct LocalCommitmentTransaction {
+       tx: Transaction,
+       //TODO: modify Channel methods to integrate HTLC material at LocalCommitmentTransaction generation to drop Option here
+       local_keys: Option<TxCreationKeys>,
+       feerate_per_kw: Option<u64>,
+       per_htlc: Vec<(HTLCOutputInCommitment, Option<Signature>, Option<Transaction>)>
 }
 impl LocalCommitmentTransaction {
        #[cfg(test)]
        pub fn dummy() -> Self {
+               let dummy_input = TxIn {
+                       previous_output: OutPoint {
+                               txid: Default::default(),
+                               vout: 0,
+                       },
+                       script_sig: Default::default(),
+                       sequence: 0,
+                       witness: vec![vec![], vec![], vec![]]
+               };
                Self { tx: Transaction {
                        version: 2,
-                       input: Vec::new(),
+                       input: vec![dummy_input],
                        output: Vec::new(),
                        lock_time: 0,
-               } }
+               },
+                       local_keys: None,
+                       feerate_per_kw: None,
+                       per_htlc: Vec::new()
+               }
        }
 
-       pub fn new_missing_local_sig(mut tx: Transaction, their_sig: &Signature, our_funding_key: &PublicKey, their_funding_key: &PublicKey) -> LocalCommitmentTransaction {
+       /// Generate a new LocalCommitmentTransaction based on a raw commitment transaction,
+       /// remote signature and both parties keys
+       pub(crate) fn new_missing_local_sig(mut tx: Transaction, their_sig: &Signature, our_funding_key: &PublicKey, their_funding_key: &PublicKey) -> LocalCommitmentTransaction {
                if tx.input.len() != 1 { panic!("Tried to store a commitment transaction that had input count != 1!"); }
                if tx.input[0].witness.len() != 0 { panic!("Tried to store a signed commitment transaction?"); }
 
@@ -546,13 +532,20 @@ impl LocalCommitmentTransaction {
                        tx.input[0].witness.push(Vec::new());
                }
 
-               Self { tx }
+               Self { tx,
+                       local_keys: None,
+                       feerate_per_kw: None,
+                       per_htlc: Vec::new()
+               }
        }
 
+       /// Get the txid of the local commitment transaction contained in this
+       /// LocalCommitmentTransaction
        pub fn txid(&self) -> Sha256dHash {
                self.tx.txid()
        }
 
+       /// Check if LocalCommitmentTransaction has already been signed by us
        pub fn has_local_sig(&self) -> bool {
                if self.tx.input.len() != 1 { panic!("Commitment transactions must have input count == 1!"); }
                if self.tx.input[0].witness.len() == 4 {
@@ -567,6 +560,15 @@ impl LocalCommitmentTransaction {
                }
        }
 
+       /// Add local signature for LocalCommitmentTransaction, do nothing if signature is already
+       /// present
+       ///
+       /// Funding key is your key included in the 2-2 funding_outpoint lock. Should be provided
+       /// by your ChannelKeys.
+       /// Funding redeemscript is script locking funding_outpoint. This is the mutlsig script
+       /// between your own funding key and your counterparty's. Currently, this is provided in
+       /// ChannelKeys::sign_local_commitment() calls directly.
+       /// Channel value is amount locked in funding_outpoint.
        pub fn add_local_sig<T: secp256k1::Signing>(&mut self, funding_key: &SecretKey, funding_redeemscript: &Script, channel_value_satoshis: u64, secp_ctx: &Secp256k1<T>) {
                if self.has_local_sig() { return; }
                let sighash = hash_to_message!(&bip143::SighashComponents::new(&self.tx)
@@ -584,11 +586,74 @@ impl LocalCommitmentTransaction {
                self.tx.input[0].witness.push(funding_redeemscript.as_bytes().to_vec());
        }
 
-       pub fn without_valid_witness(&self) -> &Transaction { &self.tx }
+       /// Get raw transaction without asserting if witness is complete
+       pub(crate) fn without_valid_witness(&self) -> &Transaction { &self.tx }
+       /// Get raw transaction with panics if witness is incomplete
        pub fn with_valid_witness(&self) -> &Transaction {
                assert!(self.has_local_sig());
                &self.tx
        }
+
+       /// Set HTLC cache to generate any local HTLC transaction spending one of htlc ouput
+       /// from this local commitment transaction
+       pub(crate) fn set_htlc_cache(&mut self, local_keys: TxCreationKeys, feerate_per_kw: u64, htlc_outputs: Vec<(HTLCOutputInCommitment, Option<Signature>, Option<Transaction>)>) {
+               self.local_keys = Some(local_keys);
+               self.feerate_per_kw = Some(feerate_per_kw);
+               self.per_htlc = htlc_outputs;
+       }
+
+       /// Add local signature for a htlc transaction, do nothing if a cached signed transaction is
+       /// already present
+       pub fn add_htlc_sig<T: secp256k1::Signing>(&mut self, htlc_base_key: &SecretKey, htlc_index: u32, preimage: Option<PaymentPreimage>, local_csv: u16, secp_ctx: &Secp256k1<T>) {
+               if self.local_keys.is_none() || self.feerate_per_kw.is_none() { return; }
+               let local_keys = self.local_keys.as_ref().unwrap();
+               let txid = self.txid();
+               for this_htlc in self.per_htlc.iter_mut() {
+                       if this_htlc.0.transaction_output_index.unwrap() == htlc_index {
+                               if this_htlc.2.is_some() { return; } // we already have a cached htlc transaction at provided index
+                               let mut htlc_tx = build_htlc_transaction(&txid, self.feerate_per_kw.unwrap(), local_csv, &this_htlc.0, &local_keys.a_delayed_payment_key, &local_keys.revocation_key);
+                               if !this_htlc.0.offered && preimage.is_none() { return; } // if we don't have preimage for HTLC-Success, don't try to generate
+                               let htlc_secret = if !this_htlc.0.offered { preimage } else { None }; // if we have a preimage for HTLC-Timeout, don't use it that's likely a duplicate HTLC hash
+                               if this_htlc.1.is_none() { return; } // we don't have any remote signature for this htlc
+                               if htlc_tx.input.len() != 1 { return; }
+                               if htlc_tx.input[0].witness.len() != 0 { return; }
+
+                               let htlc_redeemscript = get_htlc_redeemscript_with_explicit_keys(&this_htlc.0, &local_keys.a_htlc_key, &local_keys.b_htlc_key, &local_keys.revocation_key);
+
+                               if let Ok(our_htlc_key) = derive_private_key(secp_ctx, &local_keys.per_commitment_point, htlc_base_key) {
+                                       let sighash = hash_to_message!(&bip143::SighashComponents::new(&htlc_tx).sighash_all(&htlc_tx.input[0], &htlc_redeemscript, this_htlc.0.amount_msat / 1000)[..]);
+                                       let our_sig = secp_ctx.sign(&sighash, &our_htlc_key);
+
+                                       htlc_tx.input[0].witness.push(Vec::new()); // First is the multisig dummy
+
+                                       htlc_tx.input[0].witness.push(this_htlc.1.unwrap().serialize_der().to_vec());
+                                       htlc_tx.input[0].witness.push(our_sig.serialize_der().to_vec());
+                                       htlc_tx.input[0].witness[1].push(SigHashType::All as u8);
+                                       htlc_tx.input[0].witness[2].push(SigHashType::All as u8);
+
+                                       if this_htlc.0.offered {
+                                               htlc_tx.input[0].witness.push(Vec::new());
+                                               assert!(htlc_secret.is_none());
+                                       } else {
+                                               htlc_tx.input[0].witness.push(htlc_secret.unwrap().0.to_vec());
+                                       }
+
+                                       htlc_tx.input[0].witness.push(htlc_redeemscript.as_bytes().to_vec());
+
+                                       this_htlc.2 = Some(htlc_tx);
+                               } else { return; }
+                       }
+               }
+       }
+       /// Expose raw htlc transaction, guarante witness is complete if non-empty
+       pub fn htlc_with_valid_witness(&self, htlc_index: u32) -> &Option<Transaction> {
+               for this_htlc in self.per_htlc.iter() {
+                       if this_htlc.0.transaction_output_index.unwrap() == htlc_index {
+                               return &this_htlc.2;
+                       }
+               }
+               &None
+       }
 }
 impl PartialEq for LocalCommitmentTransaction {
        // We dont care whether we are signed in equality comparison
@@ -604,6 +669,14 @@ impl Writeable for LocalCommitmentTransaction {
                                _ => panic!("local tx must have been well-formed!"),
                        }
                }
+               self.local_keys.write(writer)?;
+               self.feerate_per_kw.write(writer)?;
+               writer.write_all(&byte_utils::be64_to_array(self.per_htlc.len() as u64))?;
+               for &(ref htlc, ref sig, ref htlc_tx) in self.per_htlc.iter() {
+                       htlc.write(writer)?;
+                       sig.write(writer)?;
+                       htlc_tx.write(writer)?;
+               }
                Ok(())
        }
 }
@@ -616,12 +689,27 @@ impl Readable for LocalCommitmentTransaction {
                                _ => return Err(DecodeError::InvalidValue),
                        },
                };
+               let local_keys = Readable::read(reader)?;
+               let feerate_per_kw = Readable::read(reader)?;
+               let htlcs_count: u64 = Readable::read(reader)?;
+               let mut per_htlc = Vec::with_capacity(cmp::min(htlcs_count as usize, MAX_ALLOC_SIZE / mem::size_of::<(HTLCOutputInCommitment, Option<Signature>, Option<Transaction>)>()));
+               for _ in 0..htlcs_count {
+                       let htlc: HTLCOutputInCommitment = Readable::read(reader)?;
+                       let sigs = Readable::read(reader)?;
+                       let htlc_tx = Readable::read(reader)?;
+                       per_htlc.push((htlc, sigs, htlc_tx));
+               }
 
                if tx.input.len() != 1 {
                        // Ensure tx didn't hit the 0-input ambiguity case.
                        return Err(DecodeError::InvalidValue);
                }
-               Ok(Self { tx })
+               Ok(Self {
+                       tx,
+                       local_keys,
+                       feerate_per_kw,
+                       per_htlc,
+               })
        }
 }
 
index 374d74f6c18b578b8123e4f2344375164abff704..47936ea61d1b18bcfc69f76a9a32db125e6f3ed8 100644 (file)
@@ -4433,7 +4433,7 @@ mod tests {
 
                assert_eq!(PublicKey::from_secret_key(&secp_ctx, chan_keys.funding_key()).serialize()[..],
                                hex::decode("023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb").unwrap()[..]);
-               let keys_provider = Keys { chan_keys };
+               let keys_provider = Keys { chan_keys: chan_keys.clone() };
 
                let their_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
                let mut config = UserConfig::default();
@@ -4475,6 +4475,7 @@ mod tests {
 
                let mut unsigned_tx: (Transaction, Vec<HTLCOutputInCommitment>);
 
+               let mut localtx;
                macro_rules! test_commitment {
                        ( $their_sig_hex: expr, $our_sig_hex: expr, $tx_hex: expr) => {
                                unsigned_tx = {
@@ -4489,8 +4490,8 @@ mod tests {
                                let sighash = Message::from_slice(&bip143::SighashComponents::new(&unsigned_tx.0).sighash_all(&unsigned_tx.0.input[0], &redeemscript, chan.channel_value_satoshis)[..]).unwrap();
                                secp_ctx.verify(&sighash, &their_signature, chan.their_funding_pubkey()).unwrap();
 
-                               let mut localtx = LocalCommitmentTransaction::new_missing_local_sig(unsigned_tx.0.clone(), &their_signature, &PublicKey::from_secret_key(&secp_ctx, chan.local_keys.funding_key()), chan.their_funding_pubkey());
-                               localtx.add_local_sig(chan.local_keys.funding_key(), &redeemscript, chan.channel_value_satoshis, &chan.secp_ctx);
+                               localtx = LocalCommitmentTransaction::new_missing_local_sig(unsigned_tx.0.clone(), &their_signature, &PublicKey::from_secret_key(&secp_ctx, chan.local_keys.funding_key()), chan.their_funding_pubkey());
+                               chan_keys.sign_local_commitment(&mut localtx, &redeemscript, chan.channel_value_satoshis, &chan.secp_ctx);
 
                                assert_eq!(serialize(localtx.with_valid_witness())[..],
                                                hex::decode($tx_hex).unwrap()[..]);
@@ -4498,11 +4499,11 @@ mod tests {
                }
 
                macro_rules! test_htlc_output {
-                       ( $htlc_idx: expr, $their_sig_hex: expr, $our_sig_hex: expr, $tx_hex: expr ) => {
+                       ( $htlc_idx: expr, $their_sig_hex: expr, $our_sig_hex: expr, $tx_hex: expr) => {
                                let remote_signature = Signature::from_der(&hex::decode($their_sig_hex).unwrap()[..]).unwrap();
 
                                let ref htlc = unsigned_tx.1[$htlc_idx];
-                               let mut htlc_tx = chan.build_htlc_transaction(&unsigned_tx.0.txid(), &htlc, true, &keys, chan.feerate_per_kw);
+                               let htlc_tx = chan.build_htlc_transaction(&unsigned_tx.0.txid(), &htlc, true, &keys, chan.feerate_per_kw);
                                let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &keys);
                                let htlc_sighash = Message::from_slice(&bip143::SighashComponents::new(&htlc_tx).sighash_all(&htlc_tx.input[0], &htlc_redeemscript, htlc.amount_msat / 1000)[..]).unwrap();
                                secp_ctx.verify(&htlc_sighash, &remote_signature, &keys.b_htlc_key).unwrap();
@@ -4519,8 +4520,12 @@ mod tests {
                                        assert!(preimage.is_some());
                                }
 
-                               chan_utils::sign_htlc_transaction(&mut htlc_tx, &remote_signature, &preimage, &htlc, &keys.a_htlc_key, &keys.b_htlc_key, &keys.revocation_key, &keys.per_commitment_point, chan.local_keys.htlc_base_key(), &chan.secp_ctx).unwrap();
-                               assert_eq!(serialize(&htlc_tx)[..],
+                               let mut per_htlc = Vec::new();
+                               per_htlc.push((htlc.clone(), Some(remote_signature), None));
+                               localtx.set_htlc_cache(keys.clone(), chan.feerate_per_kw, per_htlc);
+                               chan_keys.sign_htlc_transaction(&mut localtx, $htlc_idx, preimage, chan.their_to_self_delay, &chan.secp_ctx);
+
+                               assert_eq!(serialize(localtx.htlc_with_valid_witness($htlc_idx).as_ref().unwrap())[..],
                                                hex::decode($tx_hex).unwrap()[..]);
                        };
                }
index 2ac113b9845eef43391f5758ebad8335f82af453..cba28982d4872dc39aca0c7025c816d88209adab 100644 (file)
@@ -409,7 +409,6 @@ impl<ChanSigner: ChannelKeys> PartialEq for OnchainDetection<ChanSigner> {
 struct LocalSignedTx {
        /// txid of the transaction in tx, just used to make comparison faster
        txid: Sha256dHash,
-       tx: LocalCommitmentTransaction,
        revocation_key: PublicKey,
        a_htlc_key: PublicKey,
        b_htlc_key: PublicKey,
@@ -439,10 +438,11 @@ pub(crate) enum InputMaterial {
                locktime: u32,
        },
        LocalHTLC {
-               witness_script: Script,
-               sigs: (Signature, Signature),
                preimage: Option<PaymentPreimage>,
                amount: u64,
+       },
+       Funding {
+               channel_value: u64,
        }
 }
 
@@ -465,13 +465,14 @@ impl Writeable for InputMaterial  {
                                writer.write_all(&byte_utils::be64_to_array(*amount))?;
                                writer.write_all(&byte_utils::be32_to_array(*locktime))?;
                        },
-                       &InputMaterial::LocalHTLC { ref witness_script, ref sigs, ref preimage, ref amount } => {
+                       &InputMaterial::LocalHTLC { ref preimage, ref amount } => {
                                writer.write_all(&[2; 1])?;
-                               witness_script.write(writer)?;
-                               sigs.0.write(writer)?;
-                               sigs.1.write(writer)?;
                                preimage.write(writer)?;
                                writer.write_all(&byte_utils::be64_to_array(*amount))?;
+                       },
+                       &InputMaterial::Funding { ref channel_value } => {
+                               writer.write_all(&[3; 1])?;
+                               channel_value.write(writer)?;
                        }
                }
                Ok(())
@@ -510,16 +511,17 @@ impl Readable for InputMaterial {
                                }
                        },
                        2 => {
-                               let witness_script = Readable::read(reader)?;
-                               let their_sig = Readable::read(reader)?;
-                               let our_sig = Readable::read(reader)?;
                                let preimage = Readable::read(reader)?;
                                let amount = Readable::read(reader)?;
                                InputMaterial::LocalHTLC {
-                                       witness_script,
-                                       sigs: (their_sig, our_sig),
                                        preimage,
-                                       amount
+                                       amount,
+                               }
+                       },
+                       3 => {
+                               let channel_value = Readable::read(reader)?;
+                               InputMaterial::Funding {
+                                       channel_value
                                }
                        }
                        _ => return Err(DecodeError::InvalidValue),
@@ -767,6 +769,9 @@ pub struct ChannelMonitor<ChanSigner: ChannelKeys> {
        // Used just for ChannelManager to make sure it has the latest channel data during
        // deserialization
        current_remote_commitment_number: u64,
+       // Used just for ChannelManager to make sure it has the latest channel data during
+       // deserialization
+       current_local_commitment_number: u64,
 
        payment_preimages: HashMap<PaymentHash, PaymentPreimage>,
 
@@ -789,6 +794,9 @@ pub struct ChannelMonitor<ChanSigner: ChannelKeys> {
        #[cfg(not(test))]
        onchain_tx_handler: OnchainTxHandler<ChanSigner>,
 
+       // Used to detect programming bug due to unsafe monitor update sequence { ChannelForceClosed, LatestLocalCommitmentTXInfo }
+       lockdown_from_offchain: bool,
+
        // We simply modify last_block_hash in Channel's block_connected so that serialization is
        // consistent but hopefully the users' copy handles block_connected in a consistent way.
        // (we do *not*, however, update them in update_monitor to ensure any local user copies keep
@@ -823,6 +831,7 @@ impl<ChanSigner: ChannelKeys> PartialEq for ChannelMonitor<ChanSigner> {
                        self.remote_hash_commitment_number != other.remote_hash_commitment_number ||
                        self.prev_local_signed_commitment_tx != other.prev_local_signed_commitment_tx ||
                        self.current_remote_commitment_number != other.current_remote_commitment_number ||
+                       self.current_local_commitment_number != other.current_local_commitment_number ||
                        self.current_local_signed_commitment_tx != other.current_local_signed_commitment_tx ||
                        self.payment_preimages != other.payment_preimages ||
                        self.pending_htlcs_updated != other.pending_htlcs_updated ||
@@ -953,7 +962,7 @@ impl<ChanSigner: ChannelKeys + Writeable> ChannelMonitor<ChanSigner> {
 
                macro_rules! serialize_local_tx {
                        ($local_tx: expr) => {
-                               $local_tx.tx.write(writer)?;
+                               $local_tx.txid.write(writer)?;
                                writer.write_all(&$local_tx.revocation_key.serialize())?;
                                writer.write_all(&$local_tx.a_htlc_key.serialize())?;
                                writer.write_all(&$local_tx.b_htlc_key.serialize())?;
@@ -995,6 +1004,12 @@ impl<ChanSigner: ChannelKeys + Writeable> ChannelMonitor<ChanSigner> {
                        writer.write_all(&byte_utils::be48_to_array(0))?;
                }
 
+               if for_local_storage {
+                       writer.write_all(&byte_utils::be48_to_array(self.current_local_commitment_number))?;
+               } else {
+                       writer.write_all(&byte_utils::be48_to_array(0))?;
+               }
+
                writer.write_all(&byte_utils::be64_to_array(self.payment_preimages.len() as u64))?;
                for payment_preimage in self.payment_preimages.values() {
                        writer.write_all(&payment_preimage.0[..])?;
@@ -1041,6 +1056,8 @@ impl<ChanSigner: ChannelKeys + Writeable> ChannelMonitor<ChanSigner> {
                }
                self.onchain_tx_handler.write(writer)?;
 
+               self.lockdown_from_offchain.write(writer)?;
+
                Ok(())
        }
 
@@ -1098,7 +1115,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
                        onchain_detection: onchain_detection,
                        their_htlc_base_key: Some(their_htlc_base_key.clone()),
                        their_delayed_payment_base_key: Some(their_delayed_payment_base_key.clone()),
-                       funding_redeemscript: Some(funding_redeemscript),
+                       funding_redeemscript: Some(funding_redeemscript.clone()),
                        channel_value_satoshis: Some(channel_value_satoshis),
                        their_cur_revocation_points: None,
 
@@ -1113,6 +1130,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
                        prev_local_signed_commitment_tx: None,
                        current_local_signed_commitment_tx: None,
                        current_remote_commitment_number: 1 << 48,
+                       current_local_commitment_number: 0xffff_ffff_ffff,
 
                        payment_preimages: HashMap::new(),
                        pending_htlcs_updated: Vec::new(),
@@ -1121,7 +1139,9 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
                        onchain_events_waiting_threshold_conf: HashMap::new(),
                        outputs_to_watch: HashMap::new(),
 
-                       onchain_tx_handler: OnchainTxHandler::new(destination_script.clone(), keys, logger.clone()),
+                       onchain_tx_handler: OnchainTxHandler::new(destination_script.clone(), keys, funding_redeemscript, their_to_self_delay, logger.clone()),
+
+                       lockdown_from_offchain: false,
 
                        last_block_hash: Default::default(),
                        secp_ctx: Secp256k1::new(),
@@ -1237,21 +1257,39 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
        /// is important that any clones of this channel monitor (including remote clones) by kept
        /// up-to-date as our local commitment transaction is updated.
        /// Panics if set_their_to_self_delay has never been called.
-       pub(super) fn provide_latest_local_commitment_tx_info(&mut self, commitment_tx: LocalCommitmentTransaction, local_keys: chan_utils::TxCreationKeys, feerate_per_kw: u64, htlc_outputs: Vec<(HTLCOutputInCommitment, Option<Signature>, Option<HTLCSource>)>) -> Result<(), MonitorUpdateError> {
+       pub(super) fn provide_latest_local_commitment_tx_info(&mut self, mut commitment_tx: LocalCommitmentTransaction, local_keys: chan_utils::TxCreationKeys, feerate_per_kw: u64, htlc_outputs: Vec<(HTLCOutputInCommitment, Option<Signature>, Option<HTLCSource>)>) -> Result<(), MonitorUpdateError> {
                if self.their_to_self_delay.is_none() {
                        return Err(MonitorUpdateError("Got a local commitment tx info update before we'd set basic information about the channel"));
                }
+               let txid = commitment_tx.txid();
+               let sequence = commitment_tx.without_valid_witness().input[0].sequence as u64;
+               let locktime = commitment_tx.without_valid_witness().lock_time as u64;
+               let mut htlcs = Vec::with_capacity(htlc_outputs.len());
+               for htlc in htlc_outputs.clone() {
+                       if let Some(_) = htlc.0.transaction_output_index {
+                               htlcs.push((htlc.0, htlc.1, None));
+                       }
+               }
+               commitment_tx.set_htlc_cache(local_keys.clone(), feerate_per_kw, htlcs);
+               // Returning a monitor error before updating tracking points means in case of using
+               // a concurrent watchtower implementation for same channel, if this one doesn't
+               // reject update as we do, you MAY have the latest local valid commitment tx onchain
+               // for which you want to spend outputs. We're NOT robust again this scenario right
+               // now but we should consider it later.
+               if let Err(_) = self.onchain_tx_handler.provide_latest_local_tx(commitment_tx) {
+                       return Err(MonitorUpdateError("Local commitment signed has already been signed, no further update of LOCAL commitment transaction is allowed"));
+               }
+               self.current_local_commitment_number = 0xffff_ffff_ffff - ((((sequence & 0xffffff) << 3*8) | (locktime as u64 & 0xffffff)) ^ self.commitment_transaction_number_obscure_factor);
                self.prev_local_signed_commitment_tx = self.current_local_signed_commitment_tx.take();
                self.current_local_signed_commitment_tx = Some(LocalSignedTx {
-                       txid: commitment_tx.txid(),
-                       tx: commitment_tx,
+                       txid,
                        revocation_key: local_keys.revocation_key,
                        a_htlc_key: local_keys.a_htlc_key,
                        b_htlc_key: local_keys.b_htlc_key,
                        delayed_payment_key: local_keys.a_delayed_payment_key,
                        per_commitment_point: local_keys.per_commitment_point,
                        feerate_per_kw,
-                       htlc_outputs,
+                       htlc_outputs: htlc_outputs,
                });
                Ok(())
        }
@@ -1274,8 +1312,10 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
        pub(super) fn update_monitor_ooo(&mut self, mut updates: ChannelMonitorUpdate) -> Result<(), MonitorUpdateError> {
                for update in updates.updates.drain(..) {
                        match update {
-                               ChannelMonitorUpdateStep::LatestLocalCommitmentTXInfo { commitment_tx, local_keys, feerate_per_kw, htlc_outputs } =>
-                                       self.provide_latest_local_commitment_tx_info(commitment_tx, local_keys, feerate_per_kw, htlc_outputs)?,
+                               ChannelMonitorUpdateStep::LatestLocalCommitmentTXInfo { commitment_tx, local_keys, feerate_per_kw, htlc_outputs } => {
+                                       if self.lockdown_from_offchain { panic!(); }
+                                       self.provide_latest_local_commitment_tx_info(commitment_tx, local_keys, feerate_per_kw, htlc_outputs)?
+                               },
                                ChannelMonitorUpdateStep::LatestRemoteCommitmentTXInfo { unsigned_commitment_tx, htlc_outputs, commitment_number, their_revocation_point } =>
                                        self.provide_latest_remote_commitment_tx_info(&unsigned_commitment_tx, htlc_outputs, commitment_number, their_revocation_point),
                                ChannelMonitorUpdateStep::PaymentPreimage { payment_preimage } =>
@@ -1303,8 +1343,10 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
                }
                for update in updates.updates.drain(..) {
                        match update {
-                               ChannelMonitorUpdateStep::LatestLocalCommitmentTXInfo { commitment_tx, local_keys, feerate_per_kw, htlc_outputs } =>
-                                       self.provide_latest_local_commitment_tx_info(commitment_tx, local_keys, feerate_per_kw, htlc_outputs)?,
+                               ChannelMonitorUpdateStep::LatestLocalCommitmentTXInfo { commitment_tx, local_keys, feerate_per_kw, htlc_outputs } => {
+                                       if self.lockdown_from_offchain { panic!(); }
+                                       self.provide_latest_local_commitment_tx_info(commitment_tx, local_keys, feerate_per_kw, htlc_outputs)?
+                               },
                                ChannelMonitorUpdateStep::LatestRemoteCommitmentTXInfo { unsigned_commitment_tx, htlc_outputs, commitment_number, their_revocation_point } =>
                                        self.provide_latest_remote_commitment_tx_info(&unsigned_commitment_tx, htlc_outputs, commitment_number, their_revocation_point),
                                ChannelMonitorUpdateStep::PaymentPreimage { payment_preimage } =>
@@ -1314,6 +1356,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
                                ChannelMonitorUpdateStep::RescueRemoteCommitmentTXInfo { their_current_per_commitment_point } =>
                                        self.provide_rescue_remote_commitment_tx_info(their_current_per_commitment_point),
                                ChannelMonitorUpdateStep::ChannelForceClosed { should_broadcast } => {
+                                       self.lockdown_from_offchain = true;
                                        if should_broadcast {
                                                self.broadcast_latest_local_commitment_txn(broadcaster);
                                        } else {
@@ -1394,9 +1437,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
        }
 
        pub(super) fn get_cur_local_commitment_number(&self) -> u64 {
-               if let &Some(ref local_tx) = &self.current_local_signed_commitment_tx {
-                       0xffff_ffff_ffff - ((((local_tx.tx.without_valid_witness().input[0].sequence as u64 & 0xffffff) << 3*8) | (local_tx.tx.without_valid_witness().lock_time as u64 & 0xffffff)) ^ self.commitment_transaction_number_obscure_factor)
-               } else { 0xffff_ffff_ffff }
+               self.current_local_commitment_number
        }
 
        /// Attempts to claim a remote commitment transaction's outputs using the revocation key and
@@ -1656,8 +1697,8 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
                (claimable_outpoints, Some((htlc_txid, tx.output.clone())))
        }
 
-       fn broadcast_by_local_state(&self, local_tx: &LocalSignedTx) -> (Vec<Transaction>, Vec<TxOut>, Option<(Script, SecretKey, Script)>) {
-               let mut res = Vec::with_capacity(local_tx.htlc_outputs.len());
+       fn broadcast_by_local_state(&self, commitment_tx: &Transaction, local_tx: &LocalSignedTx) -> (Vec<ClaimRequest>, Vec<TxOut>, Option<(Script, SecretKey, Script)>) {
+               let mut claim_requests = Vec::with_capacity(local_tx.htlc_outputs.len());
                let mut watch_outputs = Vec::with_capacity(local_tx.htlc_outputs.len());
 
                let redeemscript = chan_utils::get_revokeable_redeemscript(&local_tx.revocation_key, self.their_to_self_delay.unwrap(), &local_tx.delayed_payment_key);
@@ -1665,54 +1706,23 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
                        Some((redeemscript.to_v0_p2wsh(), local_delayedkey, redeemscript))
                } else { None };
 
-               for &(ref htlc, ref sigs, _) in local_tx.htlc_outputs.iter() {
+               for &(ref htlc, _, _) in local_tx.htlc_outputs.iter() {
                        if let Some(transaction_output_index) = htlc.transaction_output_index {
-                               if let &Some(ref their_sig) = sigs {
-                                       if htlc.offered {
-                                               log_trace!(self, "Broadcasting HTLC-Timeout transaction against local commitment transactions");
-                                               let mut htlc_timeout_tx = chan_utils::build_htlc_transaction(&local_tx.txid, local_tx.feerate_per_kw, self.their_to_self_delay.unwrap(), htlc, &local_tx.delayed_payment_key, &local_tx.revocation_key);
-                                               let (our_sig, htlc_script) = match
-                                                               chan_utils::sign_htlc_transaction(&mut htlc_timeout_tx, their_sig, &None, htlc, &local_tx.a_htlc_key, &local_tx.b_htlc_key, &local_tx.revocation_key, &local_tx.per_commitment_point, &self.onchain_detection.keys.htlc_base_key(), &self.secp_ctx) {
-                                                       Ok(res) => res,
-                                                       Err(_) => continue,
-                                               };
-
-                                               let mut per_input_material = HashMap::with_capacity(1);
-                                               per_input_material.insert(htlc_timeout_tx.input[0].previous_output, InputMaterial::LocalHTLC { witness_script: htlc_script, sigs: (*their_sig, our_sig), preimage: None, amount: htlc.amount_msat / 1000});
-                                               //TODO: with option_simplified_commitment track outpoint too
-                                               log_trace!(self, "Outpoint {}:{} is being being claimed", htlc_timeout_tx.input[0].previous_output.vout, htlc_timeout_tx.input[0].previous_output.txid);
-                                               res.push(htlc_timeout_tx);
-                                       } else {
-                                               if let Some(payment_preimage) = self.payment_preimages.get(&htlc.payment_hash) {
-                                                       log_trace!(self, "Broadcasting HTLC-Success transaction against local commitment transactions");
-                                                       let mut htlc_success_tx = chan_utils::build_htlc_transaction(&local_tx.txid, local_tx.feerate_per_kw, self.their_to_self_delay.unwrap(), htlc, &local_tx.delayed_payment_key, &local_tx.revocation_key);
-                                                       let (our_sig, htlc_script) = match
-                                                                       chan_utils::sign_htlc_transaction(&mut htlc_success_tx, their_sig, &Some(*payment_preimage), htlc, &local_tx.a_htlc_key, &local_tx.b_htlc_key, &local_tx.revocation_key, &local_tx.per_commitment_point, &self.onchain_detection.keys.htlc_base_key(), &self.secp_ctx) {
-                                                               Ok(res) => res,
-                                                               Err(_) => continue,
-                                                       };
-
-                                                       let mut per_input_material = HashMap::with_capacity(1);
-                                                       per_input_material.insert(htlc_success_tx.input[0].previous_output, InputMaterial::LocalHTLC { witness_script: htlc_script, sigs: (*their_sig, our_sig), preimage: Some(*payment_preimage), amount: htlc.amount_msat / 1000});
-                                                       //TODO: with option_simplified_commitment track outpoint too
-                                                       log_trace!(self, "Outpoint {}:{} is being being claimed", htlc_success_tx.input[0].previous_output.vout, htlc_success_tx.input[0].previous_output.txid);
-                                                       res.push(htlc_success_tx);
-                                               }
-                                       }
-                                       watch_outputs.push(local_tx.tx.without_valid_witness().output[transaction_output_index as usize].clone());
-                               } else { panic!("Should have sigs for non-dust local tx outputs!") }
+                               let preimage = if let Some(preimage) = self.payment_preimages.get(&htlc.payment_hash) { Some(*preimage) } else { None };
+                               claim_requests.push(ClaimRequest { absolute_timelock: ::std::u32::MAX, aggregable: false, outpoint: BitcoinOutPoint { txid: local_tx.txid, vout: transaction_output_index as u32 }, witness_data: InputMaterial::LocalHTLC { preimage, amount: htlc.amount_msat / 1000 }});
+                               watch_outputs.push(commitment_tx.output[transaction_output_index as usize].clone());
                        }
                }
 
-               (res, watch_outputs, broadcasted_local_revokable_script)
+               (claim_requests, watch_outputs, broadcasted_local_revokable_script)
        }
 
        /// Attempts to claim any claimable HTLCs in a commitment transaction which was not (yet)
        /// revoked using data in local_claimable_outpoints.
        /// Should not be used if check_spend_revoked_transaction succeeds.
-       fn check_spend_local_transaction(&mut self, tx: &Transaction, height: u32) -> (Vec<Transaction>, (Sha256dHash, Vec<TxOut>)) {
+       fn check_spend_local_transaction(&mut self, tx: &Transaction, height: u32) -> (Vec<ClaimRequest>, (Sha256dHash, Vec<TxOut>)) {
                let commitment_txid = tx.txid();
-               let mut local_txn = Vec::new();
+               let mut claim_requests = Vec::new();
                let mut watch_outputs = Vec::new();
 
                macro_rules! wait_threshold_conf {
@@ -1740,7 +1750,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
 
                macro_rules! append_onchain_update {
                        ($updates: expr) => {
-                               local_txn.append(&mut $updates.0);
+                               claim_requests = $updates.0;
                                watch_outputs.append(&mut $updates.1);
                                self.broadcasted_local_revokable_script = $updates.2;
                        }
@@ -1753,7 +1763,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
                        if local_tx.txid == commitment_txid {
                                is_local_tx = true;
                                log_trace!(self, "Got latest local commitment tx broadcast, searching for available HTLCs to claim");
-                               let mut res = self.broadcast_by_local_state(local_tx);
+                               let mut res = self.broadcast_by_local_state(tx, local_tx);
                                append_onchain_update!(res);
                        }
                }
@@ -1761,8 +1771,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
                        if local_tx.txid == commitment_txid {
                                is_local_tx = true;
                                log_trace!(self, "Got previous local commitment tx broadcast, searching for available HTLCs to claim");
-                               assert!(local_tx.tx.has_local_sig());
-                               let mut res = self.broadcast_by_local_state(local_tx);
+                               let mut res = self.broadcast_by_local_state(tx, local_tx);
                                append_onchain_update!(res);
                        }
                }
@@ -1788,7 +1797,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
                        }
                }
 
-               (local_txn, (commitment_txid, watch_outputs))
+               (claim_requests, (commitment_txid, watch_outputs))
        }
 
        /// Used by ChannelManager deserialization to broadcast the latest local state if its copy of
@@ -1801,22 +1810,49 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
        /// out-of-band the other node operator to coordinate with him if option is available to you.
        /// In any-case, choice is up to the user.
        pub fn get_latest_local_commitment_txn(&mut self) -> Vec<Transaction> {
-               // TODO: We should likely move all of the logic in here into OnChainTxHandler and unify it
-               // to ensure add_local_sig is only ever called once no matter what. This likely includes
-               // tracking state and panic!()ing if we get an update after force-closure/local-tx signing.
                log_trace!(self, "Getting signed latest local commitment transaction!");
-               if let &mut Some(ref mut local_tx) = &mut self.current_local_signed_commitment_tx {
-                       local_tx.tx.add_local_sig(&self.onchain_detection.keys.funding_key(), self.funding_redeemscript.as_ref().unwrap(), self.channel_value_satoshis.unwrap(), &self.secp_ctx);
+               if let Some(commitment_tx) = self.onchain_tx_handler.get_fully_signed_local_tx(self.channel_value_satoshis.unwrap()) {
+                       let txid = commitment_tx.txid();
+                       let mut res = vec![commitment_tx];
+                       if let &Some(ref local_tx) = &self.current_local_signed_commitment_tx {
+                               for htlc in local_tx.htlc_outputs.iter() {
+                                       if let Some(htlc_index) = htlc.0.transaction_output_index {
+                                               let preimage = if let Some(preimage) = self.payment_preimages.get(&htlc.0.payment_hash) { Some(*preimage) } else { None };
+                                               if let Some(htlc_tx) = self.onchain_tx_handler.get_fully_signed_htlc_tx(txid, htlc_index, preimage) {
+                                                       res.push(htlc_tx);
+                                               }
+                                       }
+                               }
+                               // We throw away the generated waiting_first_conf data as we aren't (yet) confirmed and we don't actually know what the caller wants to do.
+                               // The data will be re-generated and tracked in check_spend_local_transaction if we get a confirmation.
+                       }
+                       return res
                }
-               if let &Some(ref local_tx) = &self.current_local_signed_commitment_tx {
-                       let mut res = vec![local_tx.tx.with_valid_witness().clone()];
-                       res.append(&mut self.broadcast_by_local_state(local_tx).0);
-                       // We throw away the generated waiting_first_conf data as we aren't (yet) confirmed and we don't actually know what the caller wants to do.
-                       // The data will be re-generated and tracked in check_spend_local_transaction if we get a confirmation.
-                       res
-               } else {
-                       Vec::new()
+               Vec::new()
+       }
+
+       /// Unsafe test-only version of get_latest_local_commitment_txn used by our test framework
+       /// to bypass LocalCommitmentTransaction state update lockdown after signature and generate
+       /// revoked commitment transaction.
+       #[cfg(test)]
+       pub fn unsafe_get_latest_local_commitment_txn(&mut self) -> Vec<Transaction> {
+               log_trace!(self, "Getting signed copy of latest local commitment transaction!");
+               if let Some(commitment_tx) = self.onchain_tx_handler.get_fully_signed_copy_local_tx(self.channel_value_satoshis.unwrap()) {
+                       let txid = commitment_tx.txid();
+                       let mut res = vec![commitment_tx];
+                       if let &Some(ref local_tx) = &self.current_local_signed_commitment_tx {
+                               for htlc in local_tx.htlc_outputs.iter() {
+                                       if let Some(htlc_index) = htlc.0.transaction_output_index {
+                                               let preimage = if let Some(preimage) = self.payment_preimages.get(&htlc.0.payment_hash) { Some(*preimage) } else { None };
+                                               if let Some(htlc_tx) = self.onchain_tx_handler.get_fully_signed_htlc_tx(txid, htlc_index, preimage) {
+                                                       res.push(htlc_tx);
+                                               }
+                                       }
+                               }
+                       }
+                       return res
                }
+               Vec::new()
        }
 
        /// Called by SimpleManyChannelMonitor::block_connected, which implements
@@ -1855,14 +1891,11 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
                                                        watch_outputs.push(new_outputs);
                                                }
                                                if new_outpoints.is_empty() {
-                                                       let (local_txn, new_outputs) = self.check_spend_local_transaction(&tx, height);
-                                                       for tx in local_txn.iter() {
-                                                               log_trace!(self, "Broadcast onchain {}", log_tx!(tx));
-                                                               broadcaster.broadcast_transaction(tx);
-                                                       }
+                                                       let (mut new_outpoints, new_outputs) = self.check_spend_local_transaction(&tx, height);
                                                        if !new_outputs.1.is_empty() {
                                                                watch_outputs.push(new_outputs);
                                                        }
+                                                       claimable_outpoints.append(&mut new_outpoints);
                                                }
                                                claimable_outpoints.append(&mut new_outpoints);
                                        }
@@ -1886,22 +1919,17 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
                let should_broadcast = if let Some(_) = self.current_local_signed_commitment_tx {
                        self.would_broadcast_at_height(height)
                } else { false };
-               if let Some(ref mut cur_local_tx) = self.current_local_signed_commitment_tx {
-                       if should_broadcast {
-                               cur_local_tx.tx.add_local_sig(&self.onchain_detection.keys.funding_key(), self.funding_redeemscript.as_ref().unwrap(), self.channel_value_satoshis.unwrap(), &self.secp_ctx);
-                       }
+               if should_broadcast {
+                       claimable_outpoints.push(ClaimRequest { absolute_timelock: height, aggregable: false, outpoint: BitcoinOutPoint { txid: self.onchain_detection.funding_info.as_ref().unwrap().0.txid.clone(), vout: self.onchain_detection.funding_info.as_ref().unwrap().0.index as u32 }, witness_data: InputMaterial::Funding { channel_value: self.channel_value_satoshis.unwrap() }});
                }
                if let Some(ref cur_local_tx) = self.current_local_signed_commitment_tx {
                        if should_broadcast {
-                               log_trace!(self, "Broadcast onchain {}", log_tx!(cur_local_tx.tx.with_valid_witness()));
-                               broadcaster.broadcast_transaction(&cur_local_tx.tx.with_valid_witness());
-                               let (txs, new_outputs, _) = self.broadcast_by_local_state(&cur_local_tx);
-                               if !new_outputs.is_empty() {
-                                       watch_outputs.push((cur_local_tx.txid.clone(), new_outputs));
-                               }
-                               for tx in txs {
-                                       log_trace!(self, "Broadcast onchain {}", log_tx!(tx));
-                                       broadcaster.broadcast_transaction(&tx);
+                               if let Some(commitment_tx) = self.onchain_tx_handler.get_fully_signed_local_tx(self.channel_value_satoshis.unwrap()) {
+                                       let (mut new_outpoints, new_outputs, _) = self.broadcast_by_local_state(&commitment_tx, cur_local_tx);
+                                       if !new_outputs.is_empty() {
+                                               watch_outputs.push((cur_local_tx.txid.clone(), new_outputs));
+                                       }
+                                       claimable_outpoints.append(&mut new_outpoints);
                                }
                        }
                }
@@ -2352,7 +2380,7 @@ impl<ChanSigner: ChannelKeys + Readable> ReadableArgs<Arc<Logger>> for (Sha256dH
                macro_rules! read_local_tx {
                        () => {
                                {
-                                       let tx = <LocalCommitmentTransaction as Readable>::read(reader)?;
+                                       let txid = Readable::read(reader)?;
                                        let revocation_key = Readable::read(reader)?;
                                        let a_htlc_key = Readable::read(reader)?;
                                        let b_htlc_key = Readable::read(reader)?;
@@ -2373,8 +2401,8 @@ impl<ChanSigner: ChannelKeys + Readable> ReadableArgs<Arc<Logger>> for (Sha256dH
                                        }
 
                                        LocalSignedTx {
-                                               txid: tx.txid(),
-                                               tx, revocation_key, a_htlc_key, b_htlc_key, delayed_payment_key, per_commitment_point, feerate_per_kw,
+                                               txid,
+                                               revocation_key, a_htlc_key, b_htlc_key, delayed_payment_key, per_commitment_point, feerate_per_kw,
                                                htlc_outputs: htlcs
                                        }
                                }
@@ -2398,6 +2426,7 @@ impl<ChanSigner: ChannelKeys + Readable> ReadableArgs<Arc<Logger>> for (Sha256dH
                };
 
                let current_remote_commitment_number = <U48 as Readable>::read(reader)?.0;
+               let current_local_commitment_number = <U48 as Readable>::read(reader)?.0;
 
                let payment_preimages_len: u64 = Readable::read(reader)?;
                let mut payment_preimages = HashMap::with_capacity(cmp::min(payment_preimages_len as usize, MAX_ALLOC_SIZE / 32));
@@ -2468,6 +2497,8 @@ impl<ChanSigner: ChannelKeys + Readable> ReadableArgs<Arc<Logger>> for (Sha256dH
                }
                let onchain_tx_handler = ReadableArgs::read(reader, logger.clone())?;
 
+               let lockdown_from_offchain = Readable::read(reader)?;
+
                Ok((last_block_hash.clone(), ChannelMonitor {
                        latest_update_id,
                        commitment_transaction_number_obscure_factor,
@@ -2495,6 +2526,7 @@ impl<ChanSigner: ChannelKeys + Readable> ReadableArgs<Arc<Logger>> for (Sha256dH
                        prev_local_signed_commitment_tx,
                        current_local_signed_commitment_tx,
                        current_remote_commitment_number,
+                       current_local_commitment_number,
 
                        payment_preimages,
                        pending_htlcs_updated,
@@ -2505,6 +2537,8 @@ impl<ChanSigner: ChannelKeys + Readable> ReadableArgs<Arc<Logger>> for (Sha256dH
 
                        onchain_tx_handler,
 
+                       lockdown_from_offchain,
+
                        last_block_hash,
                        secp_ctx: Secp256k1::new(),
                        logger,
index 95358208e9de283f2b78837e74cd78875d773a8e..cf0dc1832d8598c3a2220d9856cfc4a8326abaf8 100644 (file)
@@ -264,7 +264,7 @@ macro_rules! get_local_commitment_txn {
                        let mut commitment_txn = None;
                        for (funding_txo, monitor) in monitors.iter_mut() {
                                if funding_txo.to_channel_id() == $channel_id {
-                                       commitment_txn = Some(monitor.get_latest_local_commitment_txn());
+                                       commitment_txn = Some(monitor.unsafe_get_latest_local_commitment_txn());
                                        break;
                                }
                        }
index 8c0f05723bf521fa4904815fb80649f26a24284b..1be967d939db4ceacf4fc8f0f078b4974bf47e65 100644 (file)
@@ -4,10 +4,12 @@
 
 use chain::transaction::OutPoint;
 use chain::keysinterface::{ChannelKeys, KeysInterface, SpendableOutputDescriptor};
+use chain::chaininterface;
 use chain::chaininterface::{ChainListener, ChainWatchInterfaceUtil, BlockNotifier};
 use ln::channel::{COMMITMENT_TX_BASE_WEIGHT, COMMITMENT_TX_WEIGHT_PER_HTLC};
 use ln::channelmanager::{ChannelManager,ChannelManagerReadArgs,HTLCForwardInfo,RAACommitmentOrder, PaymentPreimage, PaymentHash, PaymentSecret, PaymentSendFailure, BREAKDOWN_TIMEOUT};
 use ln::channelmonitor::{ChannelMonitor, CLTV_CLAIM_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS, ManyChannelMonitor, ANTI_REORG_DELAY};
+use ln::channelmonitor;
 use ln::channel::{Channel, ChannelError};
 use ln::{chan_utils, onion_utils};
 use ln::router::{Route, RouteHop};
@@ -2335,48 +2337,32 @@ fn claim_htlc_outputs_single_tx() {
                }
 
                let node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap();
-               assert_eq!(node_txn.len(), 21);
+               assert_eq!(node_txn.len(), 9);
                // ChannelMonitor: justice tx revoked offered htlc, justice tx revoked received htlc, justice tx revoked to_local (3)
                // ChannelManager: local commmitment + local HTLC-timeout (2)
-               // ChannelMonitor: bumped justice tx (4), after one increase, bumps on HTLC aren't generated not being substantial anymore
-               // ChannelMonito r: local commitment + local HTLC-timeout (14)
-
-               assert_eq!(node_txn[0], node_txn[5]);
-               assert_eq!(node_txn[0], node_txn[7]);
-               assert_eq!(node_txn[0], node_txn[9]);
-               assert_eq!(node_txn[0], node_txn[13]);
-               assert_eq!(node_txn[0], node_txn[15]);
-               assert_eq!(node_txn[0], node_txn[17]);
-               assert_eq!(node_txn[0], node_txn[19]);
-
-               assert_eq!(node_txn[1], node_txn[6]);
-               assert_eq!(node_txn[1], node_txn[8]);
-               assert_eq!(node_txn[1], node_txn[10]);
-               assert_eq!(node_txn[1], node_txn[14]);
-               assert_eq!(node_txn[1], node_txn[16]);
-               assert_eq!(node_txn[1], node_txn[18]);
-               assert_eq!(node_txn[1], node_txn[20]);
-
-
-               // Check the pair local commitment and HTLC-timeout broadcast due to HTLC expiration and present 8 times (rebroadcast at every block from 200 to 206)
-               assert_eq!(node_txn[0].input.len(), 1);
-               check_spends!(node_txn[0], chan_1.3);
-               assert_eq!(node_txn[1].input.len(), 1);
-               let witness_script = node_txn[1].input[0].witness.last().unwrap();
-               assert_eq!(witness_script.len(), OFFERED_HTLC_SCRIPT_WEIGHT); //Spending an offered htlc output
-               check_spends!(node_txn[1], node_txn[0]);
+               // ChannelMonitor: bumped justice tx, after one increase, bumps on HTLC aren't generated not being substantial anymore, bump on revoked to_local isn't generated due to more room for expiration (2)
+               // ChannelMonitor: local commitment + local HTLC-timeout (2)
 
-               // Justice transactions are indices 2-3-4
+               // Check the pair local commitment and HTLC-timeout broadcast due to HTLC expiration
                assert_eq!(node_txn[2].input.len(), 1);
+               check_spends!(node_txn[2], chan_1.3);
                assert_eq!(node_txn[3].input.len(), 1);
+               let witness_script = node_txn[3].input[0].witness.last().unwrap();
+               assert_eq!(witness_script.len(), OFFERED_HTLC_SCRIPT_WEIGHT); //Spending an offered htlc output
+               check_spends!(node_txn[3], node_txn[2]);
+
+               // Justice transactions are indices 1-2-4
+               assert_eq!(node_txn[0].input.len(), 1);
+               assert_eq!(node_txn[1].input.len(), 1);
                assert_eq!(node_txn[4].input.len(), 1);
-               check_spends!(node_txn[2], revoked_local_txn[0]);
-               check_spends!(node_txn[3], revoked_local_txn[0]);
+
+               check_spends!(node_txn[0], revoked_local_txn[0]);
+               check_spends!(node_txn[1], revoked_local_txn[0]);
                check_spends!(node_txn[4], revoked_local_txn[0]);
 
                let mut witness_lens = BTreeSet::new();
-               witness_lens.insert(node_txn[2].input[0].witness.last().unwrap().len());
-               witness_lens.insert(node_txn[3].input[0].witness.last().unwrap().len());
+               witness_lens.insert(node_txn[0].input[0].witness.last().unwrap().len());
+               witness_lens.insert(node_txn[1].input[0].witness.last().unwrap().len());
                witness_lens.insert(node_txn[4].input[0].witness.last().unwrap().len());
                assert_eq!(witness_lens.len(), 3);
                assert_eq!(*witness_lens.iter().skip(0).next().unwrap(), 77); // revoked to_local
@@ -2438,12 +2424,10 @@ fn test_htlc_on_chain_success() {
        nodes[2].block_notifier.block_connected(&Block { header, txdata: vec![commitment_tx[0].clone()]}, 1);
        check_closed_broadcast!(nodes[2], false);
        check_added_monitors!(nodes[2], 1);
-       let node_txn = nodes[2].tx_broadcaster.txn_broadcasted.lock().unwrap().clone(); // ChannelManager : 3 (commitment tx, 2*htlc-success tx), ChannelMonitor : 4 (2*2 * HTLC-Success tx)
-       assert_eq!(node_txn.len(), 7);
+       let node_txn = nodes[2].tx_broadcaster.txn_broadcasted.lock().unwrap().clone(); // ChannelManager : 3 (commitment tx, 2*htlc-success tx), ChannelMonitor : 2 (2 * HTLC-Success tx)
+       assert_eq!(node_txn.len(), 5);
        assert_eq!(node_txn[0], node_txn[3]);
        assert_eq!(node_txn[1], node_txn[4]);
-       assert_eq!(node_txn[0], node_txn[5]);
-       assert_eq!(node_txn[1], node_txn[6]);
        assert_eq!(node_txn[2], commitment_tx[0]);
        check_spends!(node_txn[0], commitment_tx[0]);
        check_spends!(node_txn[1], commitment_tx[0]);
@@ -2488,15 +2472,11 @@ fn test_htlc_on_chain_success() {
        macro_rules! check_tx_local_broadcast {
                ($node: expr, $htlc_offered: expr, $commitment_tx: expr, $chan_tx: expr) => { {
                        let mut node_txn = $node.tx_broadcaster.txn_broadcasted.lock().unwrap();
-                       assert_eq!(node_txn.len(), if $htlc_offered { 7 } else { 5 });
+                       assert_eq!(node_txn.len(), 5);
                        // Node[1]: ChannelManager: 3 (commitment tx, 2*HTLC-Timeout tx), ChannelMonitor: 2 (timeout tx)
-                       // Node[0]: ChannelManager: 3 (commtiemtn tx, 2*HTLC-Timeout tx), ChannelMonitor: 2 HTLC-timeout * 2 (block-rescan)
+                       // Node[0]: ChannelManager: 3 (commtiemtn tx, 2*HTLC-Timeout tx), ChannelMonitor: 2 HTLC-timeout
                        check_spends!(node_txn[0], $commitment_tx);
                        check_spends!(node_txn[1], $commitment_tx);
-                       if $htlc_offered {
-                               assert_eq!(node_txn[0], node_txn[5]);
-                               assert_eq!(node_txn[1], node_txn[6]);
-                       }
                        assert_ne!(node_txn[0].lock_time, 0);
                        assert_ne!(node_txn[1].lock_time, 0);
                        if $htlc_offered {
@@ -2633,21 +2613,19 @@ fn test_htlc_on_chain_timeout() {
        let timeout_tx;
        {
                let mut node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap();
-               assert_eq!(node_txn.len(), 7); // ChannelManager : 2 (commitment tx, HTLC-Timeout tx), ChannelMonitor : (local commitment tx + HTLC-timeout) * 2 (block-rescan), timeout tx
-               assert_eq!(node_txn[0], node_txn[3]);
-               assert_eq!(node_txn[0], node_txn[5]);
-               assert_eq!(node_txn[1], node_txn[4]);
-               assert_eq!(node_txn[1], node_txn[6]);
+               assert_eq!(node_txn.len(), 5); // ChannelManager : 2 (commitment tx, HTLC-Timeout tx), ChannelMonitor : 2 (local commitment tx + HTLC-timeout), 1 timeout tx
+               assert_eq!(node_txn[1], node_txn[3]);
+               assert_eq!(node_txn[2], node_txn[4]);
 
-               check_spends!(node_txn[2], commitment_tx[0]);
-               assert_eq!(node_txn[2].clone().input[0].witness.last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT);
+               check_spends!(node_txn[0], commitment_tx[0]);
+               assert_eq!(node_txn[0].clone().input[0].witness.last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT);
 
-               check_spends!(node_txn[0], chan_2.3);
-               check_spends!(node_txn[1], node_txn[0]);
-               assert_eq!(node_txn[0].clone().input[0].witness.last().unwrap().len(), 71);
-               assert_eq!(node_txn[1].clone().input[0].witness.last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT);
+               check_spends!(node_txn[1], chan_2.3);
+               check_spends!(node_txn[2], node_txn[1]);
+               assert_eq!(node_txn[1].clone().input[0].witness.last().unwrap().len(), 71);
+               assert_eq!(node_txn[2].clone().input[0].witness.last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT);
 
-               timeout_tx = node_txn[2].clone();
+               timeout_tx = node_txn[0].clone();
                node_txn.clear();
        }
 
@@ -4377,8 +4355,7 @@ fn test_static_spendable_outputs_justice_tx_revoked_htlc_timeout_tx() {
        check_added_monitors!(nodes[0], 1);
 
        let revoked_htlc_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap();
-       assert_eq!(revoked_htlc_txn.len(), 3);
-       assert_eq!(revoked_htlc_txn[0], revoked_htlc_txn[2]);
+       assert_eq!(revoked_htlc_txn.len(), 2);
        assert_eq!(revoked_htlc_txn[0].input.len(), 1);
        assert_eq!(revoked_htlc_txn[0].input[0].witness.last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT);
        check_spends!(revoked_htlc_txn[0], revoked_local_txn[0]);
@@ -4434,8 +4411,7 @@ fn test_static_spendable_outputs_justice_tx_revoked_htlc_success_tx() {
        check_added_monitors!(nodes[1], 1);
        let revoked_htlc_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap();
 
-       assert_eq!(revoked_htlc_txn.len(), 3);
-       assert_eq!(revoked_htlc_txn[0], revoked_htlc_txn[2]);
+       assert_eq!(revoked_htlc_txn.len(), 2);
        assert_eq!(revoked_htlc_txn[0].input.len(), 1);
        assert_eq!(revoked_htlc_txn[0].input[0].witness.last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT);
        check_spends!(revoked_htlc_txn[0], revoked_local_txn[0]);
@@ -4504,9 +4480,8 @@ fn test_onchain_to_onchain_claim() {
        check_added_monitors!(nodes[2], 1);
 
        let c_txn = nodes[2].tx_broadcaster.txn_broadcasted.lock().unwrap().clone(); // ChannelManager : 2 (commitment tx, HTLC-Success tx), ChannelMonitor : 1 (HTLC-Success tx)
-       assert_eq!(c_txn.len(), 4);
+       assert_eq!(c_txn.len(), 3);
        assert_eq!(c_txn[0], c_txn[2]);
-       assert_eq!(c_txn[0], c_txn[3]);
        assert_eq!(commitment_tx[0], c_txn[1]);
        check_spends!(c_txn[1], chan_2.3);
        check_spends!(c_txn[2], c_txn[1]);
@@ -4622,11 +4597,11 @@ fn test_duplicate_payment_hash_one_failure_one_success() {
                _ => panic!("Unexepected event"),
        }
        let htlc_success_txn: Vec<_> = nodes[2].tx_broadcaster.txn_broadcasted.lock().unwrap().clone();
-       assert_eq!(htlc_success_txn.len(), 7);
+       assert_eq!(htlc_success_txn.len(), 5); // ChannelMonitor: HTLC-Success txn (*2 due to 2-HTLC outputs), ChannelManager: local commitment tx + HTLC-Success txn (*2 due to 2-HTLC outputs)
        check_spends!(htlc_success_txn[2], chan_2.3);
        check_spends!(htlc_success_txn[3], htlc_success_txn[2]);
        check_spends!(htlc_success_txn[4], htlc_success_txn[2]);
-       assert_eq!(htlc_success_txn[0], htlc_success_txn[5]);
+       assert_eq!(htlc_success_txn[0], htlc_success_txn[3]);
        assert_eq!(htlc_success_txn[0].input.len(), 1);
        assert_eq!(htlc_success_txn[0].input[0].witness.last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT);
        assert_eq!(htlc_success_txn[1], htlc_success_txn[4]);
@@ -7142,7 +7117,7 @@ fn test_bump_penalty_txn_on_revoked_htlcs() {
        check_added_monitors!(nodes[1], 1);
 
        let revoked_htlc_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap();
-       assert_eq!(revoked_htlc_txn.len(), 6);
+       assert_eq!(revoked_htlc_txn.len(), 4);
        if revoked_htlc_txn[0].input[0].witness.last().unwrap().len() == ACCEPTED_HTLC_SCRIPT_WEIGHT {
                assert_eq!(revoked_htlc_txn[0].input.len(), 1);
                check_spends!(revoked_htlc_txn[0], revoked_local_txn[0]);
@@ -7608,3 +7583,64 @@ fn test_simple_mpp() {
        // ...but with the right secret we should be able to claim all the way back
        claim_payment_along_route_with_secret(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], false, payment_preimage, Some(payment_secret), 200_000);
 }
+
+#[test]
+fn test_update_err_monitor_lockdown() {
+       // Our monitor will lock update of local commitment transaction if a broadcastion condition
+       // has been fulfilled (either force-close from Channel or block height requiring a HTLC-
+       // timeout). Trying to update monitor after lockdown should return a ChannelMonitorUpdateErr.
+       //
+       // This scenario may happen in a watchtower setup, where watchtower process a block height
+       // triggering a timeout while a slow-block-processing ChannelManager receives a local signed
+       // commitment at same time.
+
+       let chanmon_cfgs = create_chanmon_cfgs(2);
+       let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
+       let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
+       let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
+
+       // Create some initial channel
+       let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::supported(), InitFeatures::supported());
+       let outpoint = OutPoint { txid: chan_1.3.txid(), index: 0 };
+
+       // Rebalance the network to generate htlc in the two directions
+       send_payment(&nodes[0], &vec!(&nodes[1])[..], 10_000_000, 10_000_000);
+
+       // Route a HTLC from node 0 to node 1 (but don't settle)
+       let preimage = route_payment(&nodes[0], &vec!(&nodes[1])[..], 9_000_000).0;
+
+       // Copy SimpleManyChannelMonitor to simulate a watchtower and update block height of node 0 until its ChannelMonitor timeout HTLC onchain
+       let logger = Arc::new(test_utils::TestLogger::with_id(format!("node {}", 0)));
+       let watchtower = {
+               let monitors = nodes[0].chan_monitor.simple_monitor.monitors.lock().unwrap();
+               let monitor = monitors.get(&outpoint).unwrap();
+               let mut w = test_utils::TestVecWriter(Vec::new());
+               monitor.write_for_disk(&mut w).unwrap();
+               let new_monitor = <(Sha256dHash, channelmonitor::ChannelMonitor<EnforcingChannelKeys>)>::read(
+                               &mut ::std::io::Cursor::new(&w.0), Arc::new(test_utils::TestLogger::new())).unwrap().1;
+               assert!(new_monitor == *monitor);
+               let chain_monitor = Arc::new(chaininterface::ChainWatchInterfaceUtil::new(Network::Testnet, logger.clone() as Arc<Logger>));
+               let watchtower = test_utils::TestChannelMonitor::new(chain_monitor, &chanmon_cfgs[0].tx_broadcaster, logger.clone(), &chanmon_cfgs[0].fee_estimator);
+               assert!(watchtower.add_monitor(outpoint, new_monitor).is_ok());
+               watchtower
+       };
+       let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
+       watchtower.simple_monitor.block_connected(&header, 200, &vec![], &vec![]);
+
+       // Try to update ChannelMonitor
+       assert!(nodes[1].node.claim_funds(preimage, &None, 9_000_000));
+       check_added_monitors!(nodes[1], 1);
+       let updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
+       assert_eq!(updates.update_fulfill_htlcs.len(), 1);
+       nodes[0].node.handle_update_fulfill_htlc(&nodes[1].node.get_our_node_id(), &updates.update_fulfill_htlcs[0]);
+       if let Some(ref mut channel) = nodes[0].node.channel_state.lock().unwrap().by_id.get_mut(&chan_1.2) {
+               if let Ok((_, _, _, update)) = channel.commitment_signed(&updates.commitment_signed, &node_cfgs[0].fee_estimator) {
+                       if let Err(_) =  watchtower.simple_monitor.update_monitor(outpoint, update.clone()) {} else { assert!(false); }
+                       if let Ok(_) = nodes[0].chan_monitor.update_monitor(outpoint, update) {} else { assert!(false); }
+               } else { assert!(false); }
+       } else { assert!(false); };
+       // Our local monitor is in-sync and hasn't processed yet timeout
+       check_added_monitors!(nodes[0], 1);
+       let events = nodes[0].node.get_and_clear_pending_events();
+       assert_eq!(events.len(), 1);
+}
index 40d9f18abb71efc445acb26218a6c4e89a3cc99b..2f08fe291d2e922682c41290f597ab30594c235f 100644 (file)
@@ -15,14 +15,15 @@ use secp256k1;
 
 use ln::msgs::DecodeError;
 use ln::channelmonitor::{ANTI_REORG_DELAY, CLTV_SHARED_CLAIM_BUFFER, InputMaterial, ClaimRequest};
-use ln::chan_utils::HTLCType;
+use ln::channelmanager::PaymentPreimage;
+use ln::chan_utils::{HTLCType, LocalCommitmentTransaction};
 use chain::chaininterface::{FeeEstimator, BroadcasterInterface, ConfirmationTarget, MIN_RELAY_FEE_SAT_PER_1000_WEIGHT};
 use chain::keysinterface::ChannelKeys;
 use util::logger::Logger;
 use util::ser::{ReadableArgs, Readable, Writer, Writeable};
 use util::byte_utils;
 
-use std::collections::{HashMap, hash_map, HashSet};
+use std::collections::{HashMap, hash_map};
 use std::sync::Arc;
 use std::cmp;
 use std::ops::Deref;
@@ -52,7 +53,7 @@ enum OnchainEvent {
 pub struct ClaimTxBumpMaterial {
        // At every block tick, used to check if pending claiming tx is taking too
        // much time for confirmation and we need to bump it.
-       height_timer: u32,
+       height_timer: Option<u32>,
        // Tracked in case of reorg to wipe out now-superflous bump material
        feerate_previous: u64,
        // Soonest timelocks among set of outpoints claimed, used to compute
@@ -64,7 +65,7 @@ pub struct ClaimTxBumpMaterial {
 
 impl Writeable for ClaimTxBumpMaterial  {
        fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
-               writer.write_all(&byte_utils::be32_to_array(self.height_timer))?;
+               self.height_timer.write(writer)?;
                writer.write_all(&byte_utils::be64_to_array(self.feerate_previous))?;
                writer.write_all(&byte_utils::be32_to_array(self.soonest_timelock))?;
                writer.write_all(&byte_utils::be64_to_array(self.per_input_material.len() as u64))?;
@@ -141,6 +142,10 @@ macro_rules! subtract_high_prio_fee {
 /// do RBF bumping if possible.
 pub struct OnchainTxHandler<ChanSigner: ChannelKeys> {
        destination_script: Script,
+       funding_redeemscript: Script,
+       local_commitment: Option<LocalCommitmentTransaction>,
+       prev_local_commitment: Option<LocalCommitmentTransaction>,
+       local_csv: u16,
 
        key_storage: ChanSigner,
 
@@ -180,6 +185,11 @@ pub struct OnchainTxHandler<ChanSigner: ChannelKeys> {
 impl<ChanSigner: ChannelKeys + Writeable> OnchainTxHandler<ChanSigner> {
        pub(crate) fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
                self.destination_script.write(writer)?;
+               self.funding_redeemscript.write(writer)?;
+               self.local_commitment.write(writer)?;
+               self.prev_local_commitment.write(writer)?;
+
+               self.local_csv.write(writer)?;
 
                self.key_storage.write(writer)?;
 
@@ -221,6 +231,12 @@ impl<ChanSigner: ChannelKeys + Writeable> OnchainTxHandler<ChanSigner> {
 impl<ChanSigner: ChannelKeys + Readable> ReadableArgs<Arc<Logger>> for OnchainTxHandler<ChanSigner> {
        fn read<R: ::std::io::Read>(reader: &mut R, logger: Arc<Logger>) -> Result<Self, DecodeError> {
                let destination_script = Readable::read(reader)?;
+               let funding_redeemscript = Readable::read(reader)?;
+
+               let local_commitment = Readable::read(reader)?;
+               let prev_local_commitment = Readable::read(reader)?;
+
+               let local_csv = Readable::read(reader)?;
 
                let key_storage = Readable::read(reader)?;
 
@@ -269,6 +285,10 @@ impl<ChanSigner: ChannelKeys + Readable> ReadableArgs<Arc<Logger>> for OnchainTx
 
                Ok(OnchainTxHandler {
                        destination_script,
+                       funding_redeemscript,
+                       local_commitment,
+                       prev_local_commitment,
+                       local_csv,
                        key_storage,
                        claimable_outpoints,
                        pending_claim_requests,
@@ -280,12 +300,16 @@ impl<ChanSigner: ChannelKeys + Readable> ReadableArgs<Arc<Logger>> for OnchainTx
 }
 
 impl<ChanSigner: ChannelKeys> OnchainTxHandler<ChanSigner> {
-       pub(super) fn new(destination_script: Script, keys: ChanSigner, logger: Arc<Logger>) -> Self {
+       pub(super) fn new(destination_script: Script, keys: ChanSigner, funding_redeemscript: Script, local_csv: u16, logger: Arc<Logger>) -> Self {
 
                let key_storage = keys;
 
                OnchainTxHandler {
                        destination_script,
+                       funding_redeemscript,
+                       local_commitment: None,
+                       prev_local_commitment: None,
+                       local_csv,
                        key_storage,
                        pending_claim_requests: HashMap::new(),
                        claimable_outpoints: HashMap::new(),
@@ -342,7 +366,7 @@ impl<ChanSigner: ChannelKeys> OnchainTxHandler<ChanSigner> {
 
        /// Lightning security model (i.e being able to redeem/timeout HTLC or penalize coutnerparty onchain) lays on the assumption of claim transactions getting confirmed before timelock expiration
        /// (CSV or CLTV following cases). In case of high-fee spikes, claim tx may stuck in the mempool, so you need to bump its feerate quickly using Replace-By-Fee or Child-Pay-For-Parent.
-       fn generate_claim_tx<F: Deref>(&self, height: u32, cached_claim_datas: &ClaimTxBumpMaterial, fee_estimator: F) -> Option<(u32, u64, Transaction)>
+       fn generate_claim_tx<F: Deref>(&mut self, height: u32, cached_claim_datas: &ClaimTxBumpMaterial, fee_estimator: F) -> Option<(Option<u32>, u64, Transaction)>
                where F::Target: FeeEstimator
        {
                if cached_claim_datas.per_input_material.len() == 0 { return None } // But don't prune pending claiming request yet, we may have to resurrect HTLCs
@@ -407,9 +431,10 @@ impl<ChanSigner: ChannelKeys> OnchainTxHandler<ChanSigner> {
 
                // Compute new height timer to decide when we need to regenerate a new bumped version of the claim tx (if we
                // didn't receive confirmation of it before, or not enough reorg-safe depth on top of it).
-               let new_timer = Self::get_height_timer(height, cached_claim_datas.soonest_timelock);
+               let new_timer = Some(Self::get_height_timer(height, cached_claim_datas.soonest_timelock));
                let mut inputs_witnesses_weight = 0;
                let mut amt = 0;
+               let mut dynamic_fee = true;
                for per_outp_material in cached_claim_datas.per_input_material.values() {
                        match per_outp_material {
                                &InputMaterial::Revoked { ref witness_script, ref is_htlc, ref amount, .. } => {
@@ -420,72 +445,113 @@ impl<ChanSigner: ChannelKeys> OnchainTxHandler<ChanSigner> {
                                        inputs_witnesses_weight += Self::get_witnesses_weight(if preimage.is_some() { &[InputDescriptors::OfferedHTLC] } else { &[InputDescriptors::ReceivedHTLC] });
                                        amt += *amount;
                                },
-                               &InputMaterial::LocalHTLC { .. } => { return None; }
-                       }
-               }
-
-               let predicted_weight = bumped_tx.get_weight() + inputs_witnesses_weight;
-               let mut new_feerate;
-               // If old feerate is 0, first iteration of this claim, use normal fee calculation
-               if cached_claim_datas.feerate_previous != 0 {
-                       if let Some((new_fee, feerate)) = RBF_bump!(amt, cached_claim_datas.feerate_previous, fee_estimator, predicted_weight as u64) {
-                               // If new computed fee is superior at the whole claimable amount burn all in fees
-                               if new_fee > amt {
-                                       bumped_tx.output[0].value = 0;
-                               } else {
-                                       bumped_tx.output[0].value = amt - new_fee;
+                               &InputMaterial::LocalHTLC { .. } => {
+                                       dynamic_fee = false;
+                               },
+                               &InputMaterial::Funding { .. } => {
+                                       dynamic_fee = false;
                                }
-                               new_feerate = feerate;
-                       } else { return None; }
-               } else {
-                       if subtract_high_prio_fee!(self, fee_estimator, amt, predicted_weight, new_feerate) {
-                               bumped_tx.output[0].value = amt;
-                       } else { return None; }
+                       }
                }
-               assert!(new_feerate != 0);
-
-               for (i, (outp, per_outp_material)) in cached_claim_datas.per_input_material.iter().enumerate() {
-                       match per_outp_material {
-                               &InputMaterial::Revoked { ref witness_script, ref pubkey, ref key, ref is_htlc, ref amount } => {
-                                       let sighash_parts = bip143::SighashComponents::new(&bumped_tx);
-                                       let sighash = hash_to_message!(&sighash_parts.sighash_all(&bumped_tx.input[i], &witness_script, *amount)[..]);
-                                       let sig = self.secp_ctx.sign(&sighash, &key);
-                                       bumped_tx.input[i].witness.push(sig.serialize_der().to_vec());
-                                       bumped_tx.input[i].witness[0].push(SigHashType::All as u8);
-                                       if *is_htlc {
-                                               bumped_tx.input[i].witness.push(pubkey.unwrap().clone().serialize().to_vec());
+               if dynamic_fee {
+                       let predicted_weight = bumped_tx.get_weight() + inputs_witnesses_weight;
+                       let mut new_feerate;
+                       // If old feerate is 0, first iteration of this claim, use normal fee calculation
+                       if cached_claim_datas.feerate_previous != 0 {
+                               if let Some((new_fee, feerate)) = RBF_bump!(amt, cached_claim_datas.feerate_previous, fee_estimator, predicted_weight as u64) {
+                                       // If new computed fee is superior at the whole claimable amount burn all in fees
+                                       if new_fee > amt {
+                                               bumped_tx.output[0].value = 0;
                                        } else {
-                                               bumped_tx.input[i].witness.push(vec!(1));
+                                               bumped_tx.output[0].value = amt - new_fee;
                                        }
-                                       bumped_tx.input[i].witness.push(witness_script.clone().into_bytes());
-                                       log_trace!(self, "Going to broadcast Penalty Transaction {} claiming revoked {} output {} from {} with new feerate {}...", bumped_tx.txid(), if !is_htlc { "to_local" } else if HTLCType::scriptlen_to_htlctype(witness_script.len()) == Some(HTLCType::OfferedHTLC) { "offered" } else if HTLCType::scriptlen_to_htlctype(witness_script.len()) == Some(HTLCType::AcceptedHTLC) { "received" } else { "" }, outp.vout, outp.txid, new_feerate);
-                               },
-                               &InputMaterial::RemoteHTLC { ref witness_script, ref key, ref preimage, ref amount, ref locktime } => {
-                                       if !preimage.is_some() { bumped_tx.lock_time = *locktime }; // Right now we don't aggregate time-locked transaction, if we do we should set lock_time before to avoid breaking hash computation
-                                       let sighash_parts = bip143::SighashComponents::new(&bumped_tx);
-                                       let sighash = hash_to_message!(&sighash_parts.sighash_all(&bumped_tx.input[i], &witness_script, *amount)[..]);
-                                       let sig = self.secp_ctx.sign(&sighash, &key);
-                                       bumped_tx.input[i].witness.push(sig.serialize_der().to_vec());
-                                       bumped_tx.input[i].witness[0].push(SigHashType::All as u8);
-                                       if let &Some(preimage) = preimage {
-                                               bumped_tx.input[i].witness.push(preimage.clone().0.to_vec());
-                                       } else {
-                                               bumped_tx.input[i].witness.push(vec![]);
+                                       new_feerate = feerate;
+                               } else { return None; }
+                       } else {
+                               if subtract_high_prio_fee!(self, fee_estimator, amt, predicted_weight, new_feerate) {
+                                       bumped_tx.output[0].value = amt;
+                               } else { return None; }
+                       }
+                       assert!(new_feerate != 0);
+
+                       for (i, (outp, per_outp_material)) in cached_claim_datas.per_input_material.iter().enumerate() {
+                               match per_outp_material {
+                                       &InputMaterial::Revoked { ref witness_script, ref pubkey, ref key, ref is_htlc, ref amount } => {
+                                               let sighash_parts = bip143::SighashComponents::new(&bumped_tx);
+                                               let sighash = hash_to_message!(&sighash_parts.sighash_all(&bumped_tx.input[i], &witness_script, *amount)[..]);
+                                               let sig = self.secp_ctx.sign(&sighash, &key);
+                                               bumped_tx.input[i].witness.push(sig.serialize_der().to_vec());
+                                               bumped_tx.input[i].witness[0].push(SigHashType::All as u8);
+                                               if *is_htlc {
+                                                       bumped_tx.input[i].witness.push(pubkey.unwrap().clone().serialize().to_vec());
+                                               } else {
+                                                       bumped_tx.input[i].witness.push(vec!(1));
+                                               }
+                                               bumped_tx.input[i].witness.push(witness_script.clone().into_bytes());
+                                               log_trace!(self, "Going to broadcast Penalty Transaction {} claiming revoked {} output {} from {} with new feerate {}...", bumped_tx.txid(), if !is_htlc { "to_local" } else if HTLCType::scriptlen_to_htlctype(witness_script.len()) == Some(HTLCType::OfferedHTLC) { "offered" } else if HTLCType::scriptlen_to_htlctype(witness_script.len()) == Some(HTLCType::AcceptedHTLC) { "received" } else { "" }, outp.vout, outp.txid, new_feerate);
+                                       },
+                                       &InputMaterial::RemoteHTLC { ref witness_script, ref key, ref preimage, ref amount, ref locktime } => {
+                                               if !preimage.is_some() { bumped_tx.lock_time = *locktime }; // Right now we don't aggregate time-locked transaction, if we do we should set lock_time before to avoid breaking hash computation
+                                               let sighash_parts = bip143::SighashComponents::new(&bumped_tx);
+                                               let sighash = hash_to_message!(&sighash_parts.sighash_all(&bumped_tx.input[i], &witness_script, *amount)[..]);
+                                               let sig = self.secp_ctx.sign(&sighash, &key);
+                                               bumped_tx.input[i].witness.push(sig.serialize_der().to_vec());
+                                               bumped_tx.input[i].witness[0].push(SigHashType::All as u8);
+                                               if let &Some(preimage) = preimage {
+                                                       bumped_tx.input[i].witness.push(preimage.clone().0.to_vec());
+                                               } else {
+                                                       bumped_tx.input[i].witness.push(vec![]);
+                                               }
+                                               bumped_tx.input[i].witness.push(witness_script.clone().into_bytes());
+                                               log_trace!(self, "Going to broadcast Claim Transaction {} claiming remote {} htlc output {} from {} with new feerate {}...", bumped_tx.txid(), if preimage.is_some() { "offered" } else { "received" }, outp.vout, outp.txid, new_feerate);
+                                       },
+                                       _ => unreachable!()
+                               }
+                       }
+                       log_trace!(self, "...with timer {}", new_timer.unwrap());
+                       assert!(predicted_weight >= bumped_tx.get_weight());
+                       return Some((new_timer, new_feerate, bumped_tx))
+               } else {
+                       for (_, (outp, per_outp_material)) in cached_claim_datas.per_input_material.iter().enumerate() {
+                               match per_outp_material {
+                                       &InputMaterial::LocalHTLC { ref preimage, ref amount } => {
+                                               let mut htlc_tx = None;
+                                               if let Some(ref mut local_commitment) = self.local_commitment {
+                                                       if local_commitment.txid() == outp.txid {
+                                                               self.key_storage.sign_htlc_transaction(local_commitment, outp.vout, *preimage, self.local_csv, &self.secp_ctx);
+                                                               htlc_tx = local_commitment.htlc_with_valid_witness(outp.vout).clone();
+                                                       }
+                                               }
+                                               if let Some(ref mut prev_local_commitment) = self.prev_local_commitment {
+                                                       if prev_local_commitment.txid() == outp.txid {
+                                                               self.key_storage.sign_htlc_transaction(prev_local_commitment, outp.vout, *preimage, self.local_csv, &self.secp_ctx);
+                                                               htlc_tx = prev_local_commitment.htlc_with_valid_witness(outp.vout).clone();
+                                                       }
+                                               }
+                                               if let Some(htlc_tx) = htlc_tx {
+                                                       let feerate = (amount - htlc_tx.output[0].value) * 1000 / htlc_tx.get_weight() as u64;
+                                                       // Timer set to $NEVER given we can't bump tx without anchor outputs
+                                                       log_trace!(self, "Going to broadcast Local HTLC-{} claiming HTLC output {} from {}...", if preimage.is_some() { "Success" } else { "Timeout" }, outp.vout, outp.txid);
+                                                       return Some((None, feerate, htlc_tx));
+                                               }
+                                               return None;
+                                       },
+                                       &InputMaterial::Funding { ref channel_value } => {
+                                               let signed_tx = self.get_fully_signed_local_tx(*channel_value).unwrap();
+                                               let mut amt_outputs = 0;
+                                               for outp in signed_tx.output.iter() {
+                                                       amt_outputs += outp.value;
+                                               }
+                                               let feerate = (channel_value - amt_outputs) * 1000 / signed_tx.get_weight() as u64;
+                                               // Timer set to $NEVER given we can't bump tx without anchor outputs
+                                               log_trace!(self, "Going to broadcast Local Transaction {} claiming funding output {} from {}...", signed_tx.txid(), outp.vout, outp.txid);
+                                               return Some((None, feerate, signed_tx));
                                        }
-                                       bumped_tx.input[i].witness.push(witness_script.clone().into_bytes());
-                                       log_trace!(self, "Going to broadcast Claim Transaction {} claiming remote {} htlc output {} from {} with new feerate {}...", bumped_tx.txid(), if preimage.is_some() { "offered" } else { "received" }, outp.vout, outp.txid, new_feerate);
-                               },
-                               &InputMaterial::LocalHTLC { .. } => {
-                                       //TODO : Given that Local Commitment Transaction and HTLC-Timeout/HTLC-Success are counter-signed by peer, we can't
-                                       // RBF them. Need a Lightning specs change and package relay modification :
-                                       // https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-November/016518.html
-                                       return None;
+                                       _ => unreachable!()
                                }
                        }
                }
-               log_trace!(self, "...with timer {}", new_timer);
-               assert!(predicted_weight >= bumped_tx.get_weight());
-               Some((new_timer, new_feerate, bumped_tx))
+               None
        }
 
        pub(super) fn block_connected<B: Deref, F: Deref>(&mut self, txn_matched: &[&Transaction], claimable_outpoints: Vec<ClaimRequest>, height: u32, broadcaster: B, fee_estimator: F)
@@ -520,7 +586,7 @@ impl<ChanSigner: ChannelKeys> OnchainTxHandler<ChanSigner> {
                // Generate claim transactions and track them to bump if necessary at
                // height timer expiration (i.e in how many blocks we're going to take action).
                for claim in new_claims {
-                       let mut claim_material = ClaimTxBumpMaterial { height_timer: 0, feerate_previous: 0, soonest_timelock: claim.0, per_input_material: claim.1.clone() };
+                       let mut claim_material = ClaimTxBumpMaterial { height_timer: None, feerate_previous: 0, soonest_timelock: claim.0, per_input_material: claim.1.clone() };
                        if let Some((new_timer, new_feerate, tx)) = self.generate_claim_tx(height, &claim_material, &*fee_estimator) {
                                claim_material.height_timer = new_timer;
                                claim_material.feerate_previous = new_feerate;
@@ -535,7 +601,7 @@ impl<ChanSigner: ChannelKeys> OnchainTxHandler<ChanSigner> {
                        }
                }
 
-               let mut bump_candidates = HashSet::new();
+               let mut bump_candidates = HashMap::new();
                for tx in txn_matched {
                        // Scan all input to verify is one of the outpoint spent is of interest for us
                        let mut claimed_outputs_material = Vec::new();
@@ -592,7 +658,7 @@ impl<ChanSigner: ChannelKeys> OnchainTxHandler<ChanSigner> {
                                                        }
                                                        //TODO: recompute soonest_timelock to avoid wasting a bit on fees
                                                        if at_least_one_drop {
-                                                               bump_candidates.insert(first_claim_txid_height.0.clone());
+                                                               bump_candidates.insert(first_claim_txid_height.0.clone(), claim_material.clone());
                                                        }
                                                }
                                                break; //No need to iterate further, either tx is our or their
@@ -638,27 +704,27 @@ impl<ChanSigner: ChannelKeys> OnchainTxHandler<ChanSigner> {
 
                // Check if any pending claim request must be rescheduled
                for (first_claim_txid, ref claim_data) in self.pending_claim_requests.iter() {
-                       if claim_data.height_timer == height {
-                               bump_candidates.insert(*first_claim_txid);
+                       if let Some(h) = claim_data.height_timer {
+                               if h == height {
+                                       bump_candidates.insert(*first_claim_txid, (*claim_data).clone());
+                               }
                        }
                }
 
                // Build, bump and rebroadcast tx accordingly
                log_trace!(self, "Bumping {} candidates", bump_candidates.len());
-               for first_claim_txid in bump_candidates.iter() {
-                       if let Some((new_timer, new_feerate)) = {
-                               if let Some(claim_material) = self.pending_claim_requests.get(first_claim_txid) {
-                                       if let Some((new_timer, new_feerate, bump_tx)) = self.generate_claim_tx(height, &claim_material, &*fee_estimator) {
-                                               log_trace!(self, "Broadcast onchain {}", log_tx!(bump_tx));
-                                               broadcaster.broadcast_transaction(&bump_tx);
-                                               Some((new_timer, new_feerate))
-                                       } else { None }
-                               } else { unreachable!(); }
-                       } {
-                               if let Some(claim_material) = self.pending_claim_requests.get_mut(first_claim_txid) {
-                                       claim_material.height_timer = new_timer;
-                                       claim_material.feerate_previous = new_feerate;
-                               } else { unreachable!(); }
+               let mut pending_claim_updates = Vec::with_capacity(bump_candidates.len());
+               for (first_claim_txid, claim_material) in bump_candidates.iter() {
+                       if let Some((new_timer, new_feerate, bump_tx)) = self.generate_claim_tx(height, &claim_material, &*fee_estimator) {
+                               log_trace!(self, "Broadcast onchain {}", log_tx!(bump_tx));
+                               broadcaster.broadcast_transaction(&bump_tx);
+                               pending_claim_updates.push((*first_claim_txid, new_timer, new_feerate));
+                       }
+               }
+               for updates in pending_claim_updates {
+                       if let Some(claim_material) = self.pending_claim_requests.get_mut(&updates.0) {
+                               claim_material.height_timer = updates.1;
+                               claim_material.feerate_previous = updates.2;
                        }
                }
        }
@@ -709,4 +775,51 @@ impl<ChanSigner: ChannelKeys> OnchainTxHandler<ChanSigner> {
                        self.pending_claim_requests.remove(&req);
                }
        }
+
+       pub(super) fn provide_latest_local_tx(&mut self, tx: LocalCommitmentTransaction) -> Result<(), ()> {
+               // To prevent any unsafe state discrepancy between offchain and onchain, once local
+               // commitment transaction has been signed due to an event (either block height for
+               // HTLC-timeout or channel force-closure), don't allow any further update of local
+               // commitment transaction view to avoid delivery of revocation secret to counterparty
+               // for the aformentionned signed transaction.
+               if let Some(ref local_commitment) = self.local_commitment {
+                       if local_commitment.has_local_sig() { return Err(()) }
+               }
+               self.prev_local_commitment = self.local_commitment.take();
+               self.local_commitment = Some(tx);
+               Ok(())
+       }
+
+       //TODO: getting lastest local transactions should be infaillible and result in us "force-closing the channel", but we may
+       // have empty local commitment transaction if a ChannelMonitor is asked to force-close just after Channel::get_outbound_funding_created,
+       // before providing a initial commitment transaction. For outbound channel, init ChannelMonitor at Channel::funding_signed, there is nothing
+       // to monitor before.
+       pub(super) fn get_fully_signed_local_tx(&mut self, channel_value_satoshis: u64) -> Option<Transaction> {
+               if let Some(ref mut local_commitment) = self.local_commitment {
+                       self.key_storage.sign_local_commitment(local_commitment, &self.funding_redeemscript, channel_value_satoshis, &self.secp_ctx);
+                       return Some(local_commitment.with_valid_witness().clone());
+               }
+               None
+       }
+
+       #[cfg(test)]
+       pub(super) fn get_fully_signed_copy_local_tx(&mut self, channel_value_satoshis: u64) -> Option<Transaction> {
+               if let Some(ref mut local_commitment) = self.local_commitment {
+                       let mut local_commitment = local_commitment.clone();
+                       self.key_storage.unsafe_sign_local_commitment(&mut local_commitment, &self.funding_redeemscript, channel_value_satoshis, &self.secp_ctx);
+                       return Some(local_commitment.with_valid_witness().clone());
+               }
+               None
+       }
+
+       pub(super) fn get_fully_signed_htlc_tx(&mut self, txid: Sha256dHash, htlc_index: u32, preimage: Option<PaymentPreimage>) -> Option<Transaction> {
+               //TODO: store preimage in OnchainTxHandler
+               if let Some(ref mut local_commitment) = self.local_commitment {
+                       if local_commitment.txid() == txid {
+                               self.key_storage.sign_htlc_transaction(local_commitment, htlc_index, preimage, self.local_csv, &self.secp_ctx);
+                               return local_commitment.htlc_with_valid_witness(htlc_index).clone();
+                       }
+               }
+               None
+       }
 }
index 26c3a07775fa37670d585507499d2d57deaa9aa3..c48424f9da4be18ce1cdaa02ccac038ffe51d3b1 100644 (file)
@@ -1,4 +1,5 @@
-use ln::chan_utils::{HTLCOutputInCommitment, TxCreationKeys, ChannelPublicKeys};
+use ln::chan_utils::{HTLCOutputInCommitment, TxCreationKeys, ChannelPublicKeys, LocalCommitmentTransaction};
+use ln::channelmanager::PaymentPreimage;
 use ln::msgs;
 use chain::keysinterface::{ChannelKeys, InMemoryChannelKeys};
 
@@ -6,6 +7,7 @@ use std::cmp;
 use std::sync::{Mutex, Arc};
 
 use bitcoin::blockdata::transaction::Transaction;
+use bitcoin::blockdata::script::Script;
 
 use secp256k1;
 use secp256k1::key::{SecretKey, PublicKey};
@@ -78,6 +80,19 @@ impl ChannelKeys for EnforcingChannelKeys {
                Ok(self.inner.sign_remote_commitment(feerate_per_kw, commitment_tx, keys, htlcs, to_self_delay, secp_ctx).unwrap())
        }
 
+       fn sign_local_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, local_commitment_tx: &mut LocalCommitmentTransaction, funding_redeemscript: &Script, channel_value_satoshis: u64, secp_ctx: &Secp256k1<T>) {
+               self.inner.sign_local_commitment(local_commitment_tx, funding_redeemscript, channel_value_satoshis, secp_ctx)
+       }
+
+       #[cfg(test)]
+       fn unsafe_sign_local_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, local_commitment_tx: &mut LocalCommitmentTransaction, funding_redeemscript: &Script, channel_value_satoshis: u64, secp_ctx: &Secp256k1<T>) {
+               self.inner.unsafe_sign_local_commitment(local_commitment_tx, funding_redeemscript, channel_value_satoshis, secp_ctx);
+       }
+
+       fn sign_htlc_transaction<T: secp256k1::Signing>(&self, local_commitment_tx: &mut LocalCommitmentTransaction, htlc_index: u32, preimage: Option<PaymentPreimage>, local_csv: u16, secp_ctx: &Secp256k1<T>) {
+               self.inner.sign_htlc_transaction(local_commitment_tx, htlc_index, preimage, local_csv, secp_ctx);
+       }
+
        fn sign_closing_transaction<T: secp256k1::Signing>(&self, closing_tx: &Transaction, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()> {
                Ok(self.inner.sign_closing_transaction(closing_tx, secp_ctx).unwrap())
        }