Store to-self value in the current commitment tx in ChannelMonitor
authorMatt Corallo <git@bluematt.me>
Tue, 27 Jul 2021 15:52:21 +0000 (15:52 +0000)
committerMatt Corallo <git@bluematt.me>
Wed, 15 Sep 2021 18:07:34 +0000 (18:07 +0000)
lightning/src/chain/channelmonitor.rs
lightning/src/chain/onchaintx.rs

index dc009c4d52cf3e5ef228e505abda9bf3b25d5ea2..aa66603615f9ce7e3dd3806bfcbe5a6b78854e94 100644 (file)
@@ -272,11 +272,15 @@ struct HolderSignedTx {
        b_htlc_key: PublicKey,
        delayed_payment_key: PublicKey,
        per_commitment_point: PublicKey,
-       feerate_per_kw: u32,
        htlc_outputs: Vec<(HTLCOutputInCommitment, Option<Signature>, Option<HTLCSource>)>,
+       to_self_value_sat: u64,
+       feerate_per_kw: u32,
 }
 impl_writeable_tlv_based!(HolderSignedTx, {
        (0, txid, required),
+       // Note that this is filled in with data from OnchainTxHandler if it's missing.
+       // For HolderSignedTx objects serialized with 0.0.100+, this should be filled in.
+       (1, to_self_value_sat, (default_value, u64::max_value())),
        (2, revocation_key, required),
        (4, a_htlc_key, required),
        (6, b_htlc_key, required),
@@ -869,8 +873,9 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
                                b_htlc_key: tx_keys.countersignatory_htlc_key,
                                delayed_payment_key: tx_keys.broadcaster_delayed_payment_key,
                                per_commitment_point: tx_keys.per_commitment_point,
-                               feerate_per_kw: trusted_tx.feerate_per_kw(),
                                htlc_outputs: Vec::new(), // There are never any HTLCs in the initial commitment transactions
+                               to_self_value_sat: initial_holder_commitment_tx.to_broadcaster_value_sat(),
+                               feerate_per_kw: trusted_tx.feerate_per_kw(),
                        };
                        (holder_commitment_tx, trusted_tx.commitment_number())
                };
@@ -1424,8 +1429,9 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
                                b_htlc_key: tx_keys.countersignatory_htlc_key,
                                delayed_payment_key: tx_keys.broadcaster_delayed_payment_key,
                                per_commitment_point: tx_keys.per_commitment_point,
-                               feerate_per_kw: trusted_tx.feerate_per_kw(),
                                htlc_outputs,
+                               to_self_value_sat: holder_commitment_tx.to_broadcaster_value_sat(),
+                               feerate_per_kw: trusted_tx.feerate_per_kw(),
                        }
                };
                self.onchain_tx_handler.provide_latest_holder_tx(holder_commitment_tx);
@@ -2708,14 +2714,15 @@ impl<'a, Signer: Sign, K: KeysInterface<Signer = Signer>> ReadableArgs<&'a K>
                        }
                }
 
-               let prev_holder_signed_commitment_tx = match <u8 as Readable>::read(reader)? {
-                       0 => None,
-                       1 => {
-                               Some(Readable::read(reader)?)
-                       },
-                       _ => return Err(DecodeError::InvalidValue),
-               };
-               let current_holder_commitment_tx = Readable::read(reader)?;
+               let mut prev_holder_signed_commitment_tx: Option<HolderSignedTx> =
+                       match <u8 as Readable>::read(reader)? {
+                               0 => None,
+                               1 => {
+                                       Some(Readable::read(reader)?)
+                               },
+                               _ => return Err(DecodeError::InvalidValue),
+                       };
+               let mut current_holder_commitment_tx: HolderSignedTx = Readable::read(reader)?;
 
                let current_counterparty_commitment_number = <U48 as Readable>::read(reader)?.0;
                let current_holder_commitment_number = <U48 as Readable>::read(reader)?.0;
@@ -2772,11 +2779,28 @@ impl<'a, Signer: Sign, K: KeysInterface<Signer = Signer>> ReadableArgs<&'a K>
                                return Err(DecodeError::InvalidValue);
                        }
                }
-               let onchain_tx_handler = ReadableArgs::read(reader, keys_manager)?;
+               let onchain_tx_handler: OnchainTxHandler<Signer> = ReadableArgs::read(reader, keys_manager)?;
 
                let lockdown_from_offchain = Readable::read(reader)?;
                let holder_tx_signed = Readable::read(reader)?;
 
+               if let Some(prev_commitment_tx) = prev_holder_signed_commitment_tx.as_mut() {
+                       let prev_holder_value = onchain_tx_handler.get_prev_holder_commitment_to_self_value();
+                       if prev_holder_value.is_none() { return Err(DecodeError::InvalidValue); }
+                       if prev_commitment_tx.to_self_value_sat == u64::max_value() {
+                               prev_commitment_tx.to_self_value_sat = prev_holder_value.unwrap();
+                       } else if prev_commitment_tx.to_self_value_sat != prev_holder_value.unwrap() {
+                               return Err(DecodeError::InvalidValue);
+                       }
+               }
+
+               let cur_holder_value = onchain_tx_handler.get_cur_holder_commitment_to_self_value();
+               if current_holder_commitment_tx.to_self_value_sat == u64::max_value() {
+                       current_holder_commitment_tx.to_self_value_sat = cur_holder_value;
+               } else if current_holder_commitment_tx.to_self_value_sat != cur_holder_value {
+                       return Err(DecodeError::InvalidValue);
+               }
+
                read_tlv_fields!(reader, {});
 
                let mut secp_ctx = Secp256k1::new();
index d6777cc5c8cfd494409f5832f29efb3699bc21ab..b4f5438adfb144645aa3acff008580a7fd74a8fc 100644 (file)
@@ -365,6 +365,14 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
                }
        }
 
+       pub(crate) fn get_prev_holder_commitment_to_self_value(&self) -> Option<u64> {
+               self.prev_holder_commitment.as_ref().map(|commitment| commitment.to_broadcaster_value_sat())
+       }
+
+       pub(crate) fn get_cur_holder_commitment_to_self_value(&self) -> u64 {
+               self.holder_commitment.to_broadcaster_value_sat()
+       }
+
        /// 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.
        /// Panics if there are signing errors, because signing operations in reaction to on-chain events