lightning_signer/policy/
validator.rs

1extern crate scopeguard;
2
3use core::cmp::{max, min};
4use core::fmt::{self, Debug, Formatter};
5
6use bitcoin::bip32::DerivationPath;
7use bitcoin::blockdata::block::Header as BlockHeader;
8use bitcoin::blockdata::script::ScriptBuf;
9use bitcoin::hash_types::FilterHeader;
10use bitcoin::hashes::sha256::Hash as Sha256;
11use bitcoin::hashes::Hash;
12use bitcoin::secp256k1::ecdsa::Signature;
13use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey};
14use bitcoin::sighash::{EcdsaSighashType, SegwitV0Sighash};
15use bitcoin::{BlockHash, Network, OutPoint, Transaction};
16use core::time::Duration;
17use lightning::ln::chan_utils::{ClosingTransaction, HTLCOutputInCommitment, TxCreationKeys};
18use lightning::sign::InMemorySigner;
19use lightning::types::payment::PaymentHash;
20use log::{debug, error};
21use serde_derive::{Deserialize, Serialize};
22use serde_with::{serde_as, Bytes, IfIsHumanReadable};
23use txoo::proof::{TxoProof, VerifyError};
24
25use crate::channel::{ChannelBalance, ChannelId, ChannelSetup, ChannelSlot};
26use crate::invoice::{Invoice, InvoiceAttributes};
27use crate::policy::{Policy, MAX_CLOCK_SKEW, MIN_INVOICE_EXPIRY};
28use crate::prelude::*;
29use crate::tx::tx::{CommitmentInfo, CommitmentInfo2, HTLCInfo2, PreimageMap};
30use crate::util::debug_utils::DebugBytes;
31use crate::wallet::Wallet;
32
33use super::error::ValidationError;
34
35/// A policy checker
36///
37/// Called by Node / Channel as needed.
38pub trait Validator {
39    /// Validate ready channel parameters.
40    /// The holder_shutdown_key_path should be an empty vector if the
41    /// setup.holder_shutdown_script is not set or the address is in
42    /// the allowlist.
43    fn validate_setup_channel(
44        &self,
45        wallet: &dyn Wallet,
46        setup: &ChannelSetup,
47        holder_shutdown_key_path: &DerivationPath,
48    ) -> Result<(), ValidationError>;
49
50    /// Validate channel value after it is late-filled
51    fn validate_channel_value(&self, setup: &ChannelSetup) -> Result<(), ValidationError>;
52
53    /// Validate an onchain transaction (funding tx, simple sweeps).
54    /// This transaction may fund multiple channels at the same time.
55    ///
56    /// `segwit_flags` must be validated by the caller by checking
57    /// the input transactions.
58    ///
59    /// * `channels` the funded channel for each funding output, or
60    ///   None for change outputs
61    /// * `segwit_flags` - whether the corresponding input tx is segwit
62    /// * `values_sat` - the amount in satoshi per input
63    /// * `opaths` - derivation path per output.  Empty for non-wallet/non-xpub-whitelist
64    ///   outputs.
65    /// * `weight_lower_bound` - lower bound of tx size, for feerate checking
66    ///
67    /// Returns the total "non-beneficial value" (i.e. fees) in satoshi
68    fn validate_onchain_tx(
69        &self,
70        wallet: &dyn Wallet,
71        channels: Vec<Option<Arc<Mutex<ChannelSlot>>>>,
72        tx: &Transaction,
73        segwit_flags: &[bool],
74        values_sat: &[u64],
75        opaths: &[DerivationPath],
76        weight_lower_bound: usize,
77    ) -> Result<u64, ValidationError>;
78
79    /// Phase 1 CommitmentInfo
80    fn decode_commitment_tx(
81        &self,
82        keys: &InMemorySigner,
83        setup: &ChannelSetup,
84        is_counterparty: bool,
85        tx: &Transaction,
86        output_witscripts: &[Vec<u8>],
87    ) -> Result<CommitmentInfo, ValidationError>;
88
89    /// Validate a counterparty commitment
90    fn validate_counterparty_commitment_tx(
91        &self,
92        estate: &EnforcementState,
93        commit_num: u64,
94        commitment_point: &PublicKey,
95        setup: &ChannelSetup,
96        cstate: &ChainState,
97        info2: &CommitmentInfo2,
98    ) -> Result<(), ValidationError>;
99
100    /// Validate a holder commitment
101    fn validate_holder_commitment_tx(
102        &self,
103        estate: &EnforcementState,
104        commit_num: u64,
105        commitment_point: &PublicKey,
106        setup: &ChannelSetup,
107        cstate: &ChainState,
108        info2: &CommitmentInfo2,
109    ) -> Result<(), ValidationError>;
110
111    /// Check a counterparty's revocation of an old state.
112    /// This also makes a note that the counterparty has committed to their
113    /// current commitment transaction.
114    fn validate_counterparty_revocation(
115        &self,
116        state: &EnforcementState,
117        revoke_num: u64,
118        commitment_secret: &SecretKey,
119    ) -> Result<(), ValidationError>;
120
121    /// Phase 1 decoding of 2nd level HTLC tx and validation by recomposition
122    fn decode_and_validate_htlc_tx(
123        &self,
124        is_counterparty: bool,
125        setup: &ChannelSetup,
126        txkeys: &TxCreationKeys,
127        tx: &Transaction,
128        redeemscript: &ScriptBuf,
129        htlc_amount_sat: u64,
130        output_witscript: &ScriptBuf,
131    ) -> Result<(u32, HTLCOutputInCommitment, SegwitV0Sighash, EcdsaSighashType), ValidationError>;
132
133    /// Phase 2 validation of 2nd level HTLC tx
134    fn validate_htlc_tx(
135        &self,
136        setup: &ChannelSetup,
137        cstate: &ChainState,
138        is_counterparty: bool,
139        htlc: &HTLCOutputInCommitment,
140        feerate_per_kw: u32,
141    ) -> Result<(), ValidationError>;
142
143    /// Phase 1 decoding and recomposition of mutual_close
144    fn decode_and_validate_mutual_close_tx(
145        &self,
146        wallet: &dyn Wallet,
147        setup: &ChannelSetup,
148        state: &EnforcementState,
149        tx: &Transaction,
150        opaths: &[DerivationPath],
151    ) -> Result<ClosingTransaction, ValidationError>;
152
153    /// Phase 2 Validatation of mutual_close
154    fn validate_mutual_close_tx(
155        &self,
156        wallet: &dyn Wallet,
157        setup: &ChannelSetup,
158        state: &EnforcementState,
159        to_holder_value_sat: u64,
160        to_counterparty_value_sat: u64,
161        holder_shutdown_script: &Option<ScriptBuf>,
162        counterparty_shutdown_script: &Option<ScriptBuf>,
163        holder_wallet_path_hint: &DerivationPath,
164    ) -> Result<(), ValidationError>;
165
166    /// Validation of delayed sweep transaction
167    fn validate_delayed_sweep(
168        &self,
169        wallet: &dyn Wallet,
170        setup: &ChannelSetup,
171        cstate: &ChainState,
172        tx: &Transaction,
173        input: usize,
174        amount_sat: u64,
175        key_path: &DerivationPath,
176    ) -> Result<(), ValidationError>;
177
178    /// Validation of counterparty htlc sweep transaction (first level
179    /// commitment htlc outputs)
180    fn validate_counterparty_htlc_sweep(
181        &self,
182        wallet: &dyn Wallet,
183        setup: &ChannelSetup,
184        cstate: &ChainState,
185        tx: &Transaction,
186        redeemscript: &ScriptBuf,
187        input: usize,
188        amount_sat: u64,
189        key_path: &DerivationPath,
190    ) -> Result<(), ValidationError>;
191
192    /// Validation of justice sweep transaction
193    fn validate_justice_sweep(
194        &self,
195        wallet: &dyn Wallet,
196        setup: &ChannelSetup,
197        cstate: &ChainState,
198        tx: &Transaction,
199        input: usize,
200        amount_sat: u64,
201        key_path: &DerivationPath,
202    ) -> Result<(), ValidationError>;
203
204    /// Validation of the payment state for a payment hash.
205    /// This could include a payment routed through us, or a payment we
206    /// are making, or both.  If we are not making a payment, then the incoming
207    /// must be greater or equal to the outgoing.  Otherwise, the incoming
208    /// minus outgoing should be enough to pay for the invoice and routing fees,
209    /// but no larger.
210    fn validate_payment_balance(
211        &self,
212        incoming_msat: u64,
213        outgoing_msat: u64,
214        invoiced_amount_msat: Option<u64>,
215    ) -> Result<(), ValidationError>;
216
217    /// Whether the policy specifies that holder balance should be tracked and
218    /// enforced.
219    fn enforce_balance(&self) -> bool {
220        false
221    }
222
223    /// The minimum initial commitment transaction balance to us, given
224    /// the funding amount.
225    /// The result is in satoshi.
226    fn minimum_initial_balance(&self, holder_value_msat: u64) -> u64;
227
228    /// Channel ready for normal operation, funding is buried and not closing
229    fn is_ready(&self, cstate: &ChainState) -> bool;
230
231    /// The associated policy
232    fn policy(&self) -> Box<&dyn Policy>;
233
234    /// Set next holder commitment number
235    fn set_next_holder_commit_num(
236        &self,
237        estate: &mut EnforcementState,
238        num: u64,
239        current_commitment_info: CommitmentInfo2,
240        counterparty_signatures: CommitmentSignatures,
241    ) -> Result<(), ValidationError> {
242        let current = estate.next_holder_commit_num;
243        if num != current && num != current + 1 {
244            // the tag is non-obvious, but jumping to an incorrect commitment number can mean that signing and revocation are out of sync
245            policy_err!(
246                self,
247                "policy-revoke-new-commitment-signed",
248                "invalid progression: {} to {}",
249                current,
250                num
251            );
252        }
253        estate.set_next_holder_commit_num(num, current_commitment_info, counterparty_signatures);
254        Ok(())
255    }
256
257    /// Get the current commitment info
258    fn get_current_holder_commitment_info(
259        &self,
260        estate: &mut EnforcementState,
261        commitment_number: u64,
262    ) -> Result<CommitmentInfo2, ValidationError> {
263        // Make sure they are asking for the correct commitment (in sync).
264        if commitment_number + 1 != estate.next_holder_commit_num {
265            policy_err!(
266                self,
267                "policy-other",
268                "invalid next holder commitment number: {} != {}",
269                commitment_number + 1,
270                estate.next_holder_commit_num
271            );
272        }
273        // this is safe because we must have validated a holder commitment
274        let commitment_info = estate.current_holder_commit_info.as_ref().unwrap().clone();
275        Ok(commitment_info)
276    }
277
278    /// Set next counterparty commitment number, assuming prior validation by
279    /// `validate_counterparty_commitment_tx`
280    fn set_next_counterparty_commit_num(
281        &self,
282        estate: &mut EnforcementState,
283        num: u64,
284        current_point: PublicKey,
285        current_commitment_info: CommitmentInfo2,
286    ) -> Result<(), ValidationError> {
287        if num == 0 {
288            policy_err!(self, "policy-other", "can't set next to 0");
289        }
290
291        // The initial commitment is special, it can advance even though next_revoke is 0.
292        let delta = if num == 1 { 1 } else { 2 };
293
294        // Ensure that next_commit is ok relative to next_revoke
295        if num < estate.next_counterparty_revoke_num + delta {
296            policy_err!(
297                self,
298                "policy-commitment-previous-revoked",
299                "{} too small relative to next_counterparty_revoke_num {}",
300                num,
301                estate.next_counterparty_revoke_num
302            );
303        }
304
305        let current = estate.next_counterparty_commit_num;
306        if num != current && num != current + 1 {
307            policy_err!(
308                self,
309                "policy-commitment-previous-revoked",
310                "invalid progression: {} to {}",
311                current,
312                num
313            );
314        }
315
316        estate.set_next_counterparty_commit_num(num, current_point, current_commitment_info);
317        Ok(())
318    }
319
320    /// Set next counterparty revoked commitment number
321    fn set_next_counterparty_revoke_num(
322        &self,
323        estate: &mut EnforcementState,
324        num: u64,
325    ) -> Result<(), ValidationError> {
326        if num == 0 {
327            policy_err!(self, "policy-other", "can't set next to 0");
328        }
329
330        // Ensure that next_revoke is ok relative to next_commit.
331        if num + 2 < estate.next_counterparty_commit_num {
332            policy_err!(
333                self,
334                "policy-commitment-previous-revoked",
335                "{} too small relative to next_counterparty_commit_num {}",
336                num,
337                estate.next_counterparty_commit_num
338            );
339        }
340        if num + 1 > estate.next_counterparty_commit_num {
341            policy_err!(
342                self,
343                "policy-commitment-previous-revoked",
344                "{} too large relative to next_counterparty_commit_num {}",
345                num,
346                estate.next_counterparty_commit_num
347            );
348        }
349
350        let current = estate.next_counterparty_revoke_num;
351        if num != current && num != current + 1 {
352            policy_err!(
353                self,
354                "policy-commitment-previous-revoked",
355                "invalid progression: {} to {}",
356                current,
357                num
358            );
359        }
360
361        estate.set_next_counterparty_revoke_num(num);
362        debug!("next_counterparty_revoke_num {} -> {}", current, num);
363        Ok(())
364    }
365
366    /// Validate a block and a TXOO proof for spent/unspent watched outputs
367    fn validate_block(
368        &self,
369        proof: &TxoProof,
370        height: u32,
371        header: &BlockHeader,
372        external_block_hash: Option<&BlockHash>,
373        prev_filter_header: &FilterHeader,
374        outpoint_watches: &[OutPoint],
375        trusted_oracle_pubkeys: &Vec<PublicKey>,
376    ) -> Result<(), ValidationError> {
377        validate_block(
378            self,
379            proof,
380            height,
381            header,
382            external_block_hash,
383            prev_filter_header,
384            outpoint_watches,
385            trusted_oracle_pubkeys,
386        )
387    }
388
389    /// Validate an invoice
390    fn validate_invoice(&self, invoice: &Invoice, now: Duration) -> Result<(), ValidationError> {
391        // When we are using block headers our now() may be 1 hour behind or 2 hours ahead
392        #[cfg(not(feature = "timeless_workaround"))]
393        let (behind_tolerance, ahead_tolerance) = (Duration::from_secs(0), Duration::from_secs(0));
394        #[cfg(feature = "timeless_workaround")]
395        let (behind_tolerance, ahead_tolerance) =
396            (Duration::from_secs(1 * 60 * 60), Duration::from_secs(2 * 60 * 60));
397
398        // invoice must not have been created in the future
399        if now + MAX_CLOCK_SKEW + behind_tolerance < invoice.duration_since_epoch() {
400            policy_err!(
401                self,
402                "policy-invoice-not-expired",
403                "invoice is not yet valid ({} + {} (skew) + {} (tolerance) < {})",
404                now.as_secs(),
405                MAX_CLOCK_SKEW.as_secs(),
406                behind_tolerance.as_secs(),
407                invoice.duration_since_epoch().as_secs()
408            );
409        }
410
411        // new invoices must not expire too soon
412        if now + MIN_INVOICE_EXPIRY
413            > (invoice.duration_since_epoch() + invoice.expiry_duration())
414                + MAX_CLOCK_SKEW
415                + ahead_tolerance
416        {
417            policy_err!(
418                self,
419                "policy-invoice-not-expired",
420                "invoice is expired ({} + {} (buffer) > {} + {} (skew) + {} (tolerance))",
421                now.as_secs(),
422                MIN_INVOICE_EXPIRY.as_secs(),
423                (invoice.duration_since_epoch() + invoice.expiry_duration()).as_secs(),
424                MAX_CLOCK_SKEW.as_secs(),
425                ahead_tolerance.as_secs()
426            );
427        }
428
429        Ok(())
430    }
431}
432
433/// Validate a block and a TXOO proof for spent/unspent watched outputs
434#[inline]
435pub fn validate_block<T: Validator + ?Sized>(
436    self_: &T,
437    proof: &TxoProof,
438    height: u32,
439    header: &BlockHeader,
440    external_block_hash: Option<&BlockHash>,
441    prev_filter_header: &FilterHeader,
442    outpoint_watches: &[OutPoint],
443    trusted_oracle_pubkeys: &Vec<PublicKey>,
444) -> Result<(), ValidationError> {
445    let secp = Secp256k1::new();
446    let result = proof.verify(
447        height,
448        header,
449        external_block_hash,
450        prev_filter_header,
451        outpoint_watches,
452        &secp,
453    );
454    match result {
455        Ok(()) => {}
456        Err(VerifyError::InvalidAttestation) => {
457            for (pubkey, attestation) in &proof.attestations {
458                error!(
459                    "invalid attestation for oracle {} at height {} block hash {} - {:?}",
460                    pubkey,
461                    height,
462                    header.block_hash(),
463                    &attestation.attestation
464                );
465            }
466            policy_err!(self_, "policy-chain-validated", "invalid attestation");
467        }
468        Err(_) => {
469            policy_err!(self_, "policy-chain-validated", "invalid proof {:?}", result);
470        }
471    }
472
473    let required_majority = (trusted_oracle_pubkeys.len() + 1) / 2;
474    let key_matches = trusted_oracle_pubkeys
475        .iter()
476        .filter(|&trusted_key| {
477            proof.attestations.iter().find(|(a, _)| *a == *trusted_key).is_some()
478        })
479        .count();
480    if key_matches < required_majority {
481        policy_err!(self_, "policy-chain-validated", "attestation from trusted oracles not found");
482    }
483
484    Ok(())
485}
486
487/// Blockchain state used by the validator
488#[derive(Debug)]
489pub struct ChainState {
490    /// The current blockchain height
491    pub current_height: u32,
492    /// Zero or the number of confirmation of the funding tx
493    pub funding_depth: u32,
494    /// Zero or the number of confirmation of a double-spend of the funding tx
495    pub funding_double_spent_depth: u32,
496    /// Zero or the number of confirmations of a closing tx
497    pub closing_depth: u32,
498}
499
500/// A factory for validators
501pub trait ValidatorFactory: Send + Sync {
502    /// Construct a validator
503    fn make_validator(
504        &self,
505        network: Network,
506        node_id: PublicKey,
507        channel_id: Option<ChannelId>,
508    ) -> Arc<dyn Validator>;
509
510    /// Get the policy
511    fn policy(&self, network: Network) -> Box<dyn Policy>;
512}
513
514/// Signatures for a commitment transaction
515#[derive(Clone, Debug, Serialize, Deserialize)]
516pub struct CommitmentSignatures(pub Signature, pub Vec<Signature>);
517
518/// Copied from LDK because we need to serialize it
519#[serde_as]
520#[derive(Clone, Serialize, Deserialize)]
521pub struct CounterpartyCommitmentSecrets {
522    #[serde_as(as = "IfIsHumanReadable<_, Vec<(Bytes, _)>>")]
523    old_secrets: Vec<([u8; 32], u64)>,
524}
525
526impl Debug for CounterpartyCommitmentSecrets {
527    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
528        f.debug_struct("CounterpartyCommitmentSecrets")
529            .field("old_secrets", &DebugOldSecrets(&self.old_secrets))
530            .finish()
531    }
532}
533
534struct DebugOldSecrets<'a>(pub &'a Vec<([u8; 32], u64)>);
535impl<'a> core::fmt::Debug for DebugOldSecrets<'a> {
536    fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
537        f.debug_list().entries(self.0.iter().map(|os| DebugOldSecret(os))).finish()
538    }
539}
540
541struct DebugOldSecret<'a>(pub &'a ([u8; 32], u64));
542impl<'a> core::fmt::Debug for DebugOldSecret<'a> {
543    fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
544        f.debug_tuple("OldSecret").field(&DebugBytes(&self.0 .0)).field(&self.0 .1).finish()
545    }
546}
547
548impl CounterpartyCommitmentSecrets {
549    /// Creates a new empty `CounterpartyCommitmentSecrets` structure.
550    pub fn new() -> Self {
551        let old_secrets = Vec::new();
552        Self { old_secrets }
553    }
554
555    #[inline]
556    fn place_secret(idx: u64) -> u8 {
557        for i in 0..48 {
558            if idx & (1 << i) == (1 << i) {
559                return i;
560            }
561        }
562        48
563    }
564
565    /// Returns the minimum index of all stored secrets. Note that indexes start
566    /// at 1 << 48 and get decremented by one for each new secret.
567    pub fn get_min_seen_secret(&self) -> u64 {
568        let mut min = 1 << 48;
569        for &(_, idx) in self.old_secrets.iter() {
570            if idx < min {
571                min = idx;
572            }
573        }
574        min
575    }
576
577    #[inline]
578    fn derive_secret(secret: [u8; 32], bits: u8, idx: u64) -> [u8; 32] {
579        let mut res: [u8; 32] = secret;
580        for i in 0..bits {
581            let bitpos = bits - 1 - i;
582            if idx & (1 << bitpos) == (1 << bitpos) {
583                res[(bitpos / 8) as usize] ^= 1 << (bitpos & 7);
584                res = Sha256::hash(&res).to_byte_array();
585            }
586        }
587        res
588    }
589
590    /// Inserts the `secret` at `idx`. Returns `Ok(())` if the secret
591    /// was generated in accordance with BOLT 3 and is consistent with previous secrets.
592    pub fn provide_secret(&mut self, idx: u64, secret: [u8; 32]) -> Result<(), ()> {
593        let pos = Self::place_secret(idx);
594        if pos as usize > self.old_secrets.len() {
595            return Err(());
596        }
597        for i in 0..pos {
598            let (old_secret, old_idx) = self.old_secrets[i as usize];
599            if Self::derive_secret(secret, pos, old_idx) != old_secret {
600                return Err(());
601            }
602        }
603        if self.get_min_seen_secret() <= idx {
604            return Ok(());
605        }
606        if (pos as usize) < self.old_secrets.len() {
607            self.old_secrets[pos as usize] = (secret, idx);
608        } else {
609            self.old_secrets.push((secret, idx));
610        }
611        Ok(())
612    }
613
614    /// Returns the secret at `idx`.
615    /// Returns `None` if `idx` is < [`CounterpartyCommitmentSecrets::get_min_seen_secret`].
616    pub fn get_secret(&self, idx: u64) -> Option<[u8; 32]> {
617        for i in 0..self.old_secrets.len() {
618            if (idx & (!((1 << i) - 1))) == self.old_secrets[i].1 {
619                return Some(Self::derive_secret(self.old_secrets[i].0, i as u8, idx));
620            }
621        }
622        assert!(idx < self.get_min_seen_secret());
623        None
624    }
625}
626
627/// Enforcement state for a channel
628///
629/// This keeps track of commitments on both sides and whether the channel
630/// was closed.
631#[allow(missing_docs)]
632#[derive(Clone, Debug, Serialize, Deserialize)]
633pub struct EnforcementState {
634    // the next commitment number we expect to see signed by the counterparty
635    // (set by validate_holder_commitment_tx)
636    pub next_holder_commit_num: u64,
637    // the next commitment number we expect to sign
638    // (set by sign_counterparty_commitment_tx)
639    pub next_counterparty_commit_num: u64,
640    // the next commitment number we expect the counterparty to revoke
641    // (set by validate_counterparty_revocation)
642    pub next_counterparty_revoke_num: u64,
643
644    // (set by sign_counterparty_commitment_tx)
645    pub current_counterparty_point: Option<PublicKey>, // next_counterparty_commit_num - 1
646    // (set by sign_counterparty_commitment_tx)
647    pub previous_counterparty_point: Option<PublicKey>, // next_counterparty_commit_num - 2
648
649    // (set by validate_holder_commitment_tx)
650    pub current_holder_commit_info: Option<CommitmentInfo2>,
651    /// Counterparty signatures on holder's commitment
652    pub current_counterparty_signatures: Option<CommitmentSignatures>,
653
654    /// Next holder commitment
655    pub next_holder_commit_info: Option<(CommitmentInfo2, CommitmentSignatures)>,
656
657    // (set by sign_counterparty_commitment_tx)
658    pub current_counterparty_commit_info: Option<CommitmentInfo2>,
659    // (set by sign_counterparty_commitment_tx)
660    pub previous_counterparty_commit_info: Option<CommitmentInfo2>,
661
662    pub channel_closed: bool,
663    pub initial_holder_value: u64,
664
665    /// Counterparty revocation secrets.
666    /// This is an Option for backwards compatibility with old databases.
667    pub counterparty_secrets: Option<CounterpartyCommitmentSecrets>,
668}
669
670impl EnforcementState {
671    /// Create state for a new channel.
672    ///
673    /// `initial_holder_value` is in satoshi and represents the lowest value
674    /// that we expect the initial commitment to send to us.
675    pub fn new(initial_holder_value: u64) -> EnforcementState {
676        EnforcementState {
677            next_holder_commit_num: 0,
678            next_counterparty_commit_num: 0,
679            next_counterparty_revoke_num: 0,
680            current_counterparty_point: None,
681            previous_counterparty_point: None,
682            current_holder_commit_info: None,
683            current_counterparty_signatures: None,
684            next_holder_commit_info: None,
685            current_counterparty_commit_info: None,
686            previous_counterparty_commit_info: None,
687            channel_closed: false,
688            initial_holder_value,
689            counterparty_secrets: Some(CounterpartyCommitmentSecrets::new()),
690        }
691    }
692
693    /// Returns the minimum amount to_holder from both commitments or
694    /// None if the amounts are not within epsilon_sat.
695    pub fn minimum_to_holder_value(&self, epsilon_sat: u64) -> Option<u64> {
696        if let Some(hinfo) = &self.current_holder_commit_info {
697            if let Some(cinfo) = &self.current_counterparty_commit_info {
698                let hval = hinfo.to_broadcaster_value_sat;
699                let cval = cinfo.to_countersigner_value_sat;
700                debug!("min to_holder: hval={}, cval={}", hval, cval);
701                if hval > cval {
702                    if hval - cval <= epsilon_sat {
703                        return Some(cval);
704                    }
705                } else
706                /* cval >= hval */
707                {
708                    if cval - hval <= epsilon_sat {
709                        return Some(hval);
710                    }
711                }
712            }
713        }
714        None
715    }
716
717    /// Returns the minimum amount to_counterparty from both commitments or
718    /// None if the amounts are not within epsilon_sat.
719    pub fn minimum_to_counterparty_value(&self, epsilon_sat: u64) -> Option<u64> {
720        if let Some(hinfo) = &self.current_holder_commit_info {
721            if let Some(cinfo) = &self.current_counterparty_commit_info {
722                let hval = hinfo.to_countersigner_value_sat;
723                let cval = cinfo.to_broadcaster_value_sat;
724                debug!("min to_cparty: hval={}, cval={}", hval, cval);
725                if hval > cval {
726                    if hval - cval <= epsilon_sat {
727                        return Some(cval);
728                    }
729                } else
730                /* cval >= hval */
731                {
732                    if cval - hval <= epsilon_sat {
733                        return Some(hval);
734                    }
735                }
736            }
737        }
738        None
739    }
740
741    /// Set next holder commitment number
742    /// Policy enforcement must be performed by the caller
743    pub fn set_next_holder_commit_num(
744        &mut self,
745        num: u64,
746        current_commitment_info: CommitmentInfo2,
747        counterparty_signatures: CommitmentSignatures,
748    ) {
749        let current = self.next_holder_commit_num;
750        assert_eq!(num, current + 1);
751        // TODO - should we enforce policy-v2-commitment-retry-same here?
752        debug!("next_holder_commit_num {} -> {}", current, num);
753        self.next_holder_commit_num = num;
754        self.current_holder_commit_info = Some(current_commitment_info);
755        self.current_counterparty_signatures = Some(counterparty_signatures);
756    }
757
758    /// Set next counterparty commitment number
759    pub fn set_next_counterparty_commit_num(
760        &mut self,
761        num: u64,
762        current_point: PublicKey,
763        current_commitment_info: CommitmentInfo2,
764    ) {
765        assert!(num > 0);
766        let current = self.next_counterparty_commit_num;
767
768        if num == current + 1 {
769            // normal progression, move current to previous
770            self.previous_counterparty_point = self.current_counterparty_point;
771            self.previous_counterparty_commit_info = self.current_counterparty_commit_info.take();
772        } else if num > current + 1 || num < current {
773            // we jumped ahead or back, clear out previous info
774            self.previous_counterparty_point = None;
775            self.previous_counterparty_commit_info = None;
776        }
777
778        if num >= current + 1 {
779            // we progressed, set current
780            self.current_counterparty_point = Some(current_point);
781            self.current_counterparty_commit_info = Some(current_commitment_info);
782        }
783
784        self.next_counterparty_commit_num = num;
785        debug!("next_counterparty_commit_num {} -> {} current {}", current, num, current_point);
786    }
787
788    /// Previous counterparty commitment point, or None if unknown
789    pub fn get_previous_counterparty_point(&self, num: u64) -> Option<PublicKey> {
790        if num + 1 == self.next_counterparty_commit_num {
791            self.current_counterparty_point
792        } else if num + 2 == self.next_counterparty_commit_num {
793            self.previous_counterparty_point
794        } else {
795            None
796        }
797    }
798
799    /// Previous counterparty commitment info
800    pub fn get_previous_counterparty_commit_info(&self, num: u64) -> Option<CommitmentInfo2> {
801        if num + 1 == self.next_counterparty_commit_num {
802            self.current_counterparty_commit_info.clone()
803        } else if num + 2 == self.next_counterparty_commit_num {
804            self.previous_counterparty_commit_info.clone()
805        } else {
806            None
807        }
808    }
809
810    /// Set next counterparty revoked commitment number
811    pub fn set_next_counterparty_revoke_num(&mut self, num: u64) {
812        assert_ne!(num, 0);
813        let current = self.next_counterparty_revoke_num;
814
815        // Remove any revoked commitment state.
816        if num + 1 >= self.next_counterparty_commit_num {
817            // We can't remove the previous_counterparty_point, needed for retries.
818            self.previous_counterparty_commit_info = None;
819        }
820
821        self.next_counterparty_revoke_num = num;
822        debug!("next_counterparty_revoke_num {} -> {}", current, num);
823    }
824
825    #[allow(missing_docs)]
826    #[cfg(any(test, feature = "test_utils"))]
827    pub fn set_next_holder_commit_num_for_testing(&mut self, num: u64) {
828        debug!(
829            "set_next_holder_commit_num_for_testing: {} -> {}",
830            self.next_holder_commit_num, num
831        );
832        self.next_holder_commit_num = num;
833    }
834
835    #[allow(missing_docs)]
836    #[cfg(any(test, feature = "test_utils"))]
837    pub fn set_next_counterparty_commit_num_for_testing(
838        &mut self,
839        num: u64,
840        current_point: PublicKey,
841    ) {
842        debug!(
843            "set_next_counterparty_commit_num_for_testing: {} -> {}",
844            self.next_counterparty_commit_num, num
845        );
846        self.previous_counterparty_point = self.current_counterparty_point;
847        self.current_counterparty_point = Some(current_point);
848        self.next_counterparty_commit_num = num;
849    }
850
851    #[allow(missing_docs)]
852    #[cfg(any(test, feature = "test_utils"))]
853    pub fn set_next_counterparty_revoke_num_for_testing(&mut self, num: u64) {
854        debug!(
855            "set_next_counterparty_revoke_num_for_testing: {} -> {}",
856            self.next_counterparty_revoke_num, num
857        );
858        self.next_counterparty_revoke_num = num;
859    }
860
861    /// Summarize in-flight outgoing payments, possibly with new
862    /// holder offered or counterparty received commitment tx.
863    /// The amounts are in satoshi.
864    /// HTLCs belonging to a payment are summed for each of the
865    /// holder and counterparty txs. The greater value is taken as the actual
866    /// in-flight value.
867    pub fn payments_summary(
868        &self,
869        new_holder_tx: Option<&CommitmentInfo2>,
870        new_counterparty_tx: Option<&CommitmentInfo2>,
871    ) -> Map<PaymentHash, u64> {
872        let holder_offered =
873            new_holder_tx.or(self.current_holder_commit_info.as_ref()).map(|h| &h.offered_htlcs);
874        let counterparty_received = new_counterparty_tx
875            .or(self.current_counterparty_commit_info.as_ref())
876            .map(|c| &c.received_htlcs);
877        let holder_summary =
878            holder_offered.map(|h| Self::summarize_payments(h)).unwrap_or_else(|| Map::new());
879        let counterparty_summary = counterparty_received
880            .map(|h| Self::summarize_payments(h))
881            .unwrap_or_else(|| Map::new());
882        // Union the two summaries
883        let mut summary = holder_summary;
884        for (k, v) in counterparty_summary {
885            // Choose higher amount if already there, or insert if not
886            summary.entry(k).and_modify(|e| *e = max(*e, v)).or_insert(v);
887        }
888
889        if let Some(holder_tx) = self.current_holder_commit_info.as_ref() {
890            for h in holder_tx.offered_htlcs.iter() {
891                summary.entry(h.payment_hash).or_insert(0);
892            }
893        }
894
895        if let Some(counterparty_tx) = self.current_counterparty_commit_info.as_ref() {
896            for h in counterparty_tx.received_htlcs.iter() {
897                summary.entry(h.payment_hash).or_insert(0);
898            }
899        }
900        summary
901    }
902
903    /// Summarize in-flight incoming payments, possibly with new
904    /// holder offered or counterparty received commitment tx.
905    /// The amounts are in satoshi.
906    /// HTLCs belonging to a payment are summed for each of the
907    /// holder and counterparty txs. The smaller value is taken as the actual
908    /// in-flight value.
909    //
910    // The smaller value is taken because we should only consider an invoice paid
911    // when both txs contain the payment.
912    pub fn incoming_payments_summary(
913        &self,
914        new_holder_tx: Option<&CommitmentInfo2>,
915        new_counterparty_tx: Option<&CommitmentInfo2>,
916    ) -> Map<PaymentHash, u64> {
917        let holder_received =
918            new_holder_tx.or(self.current_holder_commit_info.as_ref()).map(|h| &h.received_htlcs);
919        let counterparty_offered = new_counterparty_tx
920            .or(self.current_counterparty_commit_info.as_ref())
921            .map(|c| &c.offered_htlcs);
922        let holder_summary =
923            holder_received.map(|h| Self::summarize_payments(h)).unwrap_or_else(|| Map::new());
924        let counterparty_summary =
925            counterparty_offered.map(|h| Self::summarize_payments(h)).unwrap_or_else(|| Map::new());
926        // Intersect the holder and counterparty summaries, because we don't
927        // consider a payment until it is present in both commitment transactions.
928        let mut summary = holder_summary;
929        summary.retain(|k, _| counterparty_summary.contains_key(k));
930        for (k, v) in counterparty_summary {
931            // Choose lower amount
932            summary.entry(k).and_modify(|e| *e = min(*e, v));
933        }
934
935        if let Some(holder_tx) = self.current_holder_commit_info.as_ref() {
936            for h in holder_tx.received_htlcs.iter() {
937                summary.entry(h.payment_hash).or_insert(0);
938            }
939        }
940
941        if let Some(counterparty_tx) = self.current_counterparty_commit_info.as_ref() {
942            for h in counterparty_tx.offered_htlcs.iter() {
943                summary.entry(h.payment_hash).or_insert(0);
944            }
945        }
946        summary
947    }
948
949    fn summarize_payments(htlcs: &[HTLCInfo2]) -> Map<PaymentHash, u64> {
950        let mut summary = Map::new();
951        for h in htlcs {
952            // If there are multiple HTLCs for the same payment, sum them
953            summary.entry(h.payment_hash).and_modify(|e| *e += h.value_sat).or_insert(h.value_sat);
954        }
955        summary
956    }
957
958    /// The claimable balance before and after a new commitment tx
959    ///
960    /// See [`CommitmentInfo2::claimable_balance`]
961    pub fn claimable_balances<T: PreimageMap>(
962        &self,
963        preimage_map: &T,
964        new_holder_tx: Option<&CommitmentInfo2>,
965        new_counterparty_tx: Option<&CommitmentInfo2>,
966        channel_setup: &ChannelSetup,
967    ) -> BalanceDelta {
968        assert!(
969            new_holder_tx.is_some() || new_counterparty_tx.is_some(),
970            "must have at least one new tx"
971        );
972        assert!(
973            new_holder_tx.is_none() || new_counterparty_tx.is_none(),
974            "must have at most one new tx"
975        );
976        // Our balance in the holder commitment tx
977        let cur_holder_bal = self.current_holder_commit_info.as_ref().map(|tx| {
978            tx.claimable_balance(
979                preimage_map,
980                channel_setup.is_outbound,
981                channel_setup.channel_value_sat,
982            )
983        });
984        // Our balance in the counterparty commitment tx
985        let cur_cp_bal = self.current_counterparty_commit_info.as_ref().map(|tx| {
986            tx.claimable_balance(
987                preimage_map,
988                channel_setup.is_outbound,
989                channel_setup.channel_value_sat,
990            )
991        });
992        // Our overall balance is the lower of the two
993        let cur_bal_opt = min_opt(cur_holder_bal, cur_cp_bal);
994
995        // Perform balance calculations given the new transaction
996        let new_holder_bal = new_holder_tx.or(self.current_holder_commit_info.as_ref()).map(|tx| {
997            tx.claimable_balance(
998                preimage_map,
999                channel_setup.is_outbound,
1000                channel_setup.channel_value_sat,
1001            )
1002        });
1003        let new_cp_bal =
1004            new_counterparty_tx.or(self.current_counterparty_commit_info.as_ref()).map(|tx| {
1005                tx.claimable_balance(
1006                    preimage_map,
1007                    channel_setup.is_outbound,
1008                    channel_setup.channel_value_sat,
1009                )
1010            });
1011        let new_bal =
1012            min_opt(new_holder_bal, new_cp_bal).expect("already checked that we have a new tx");
1013
1014        // If this is the first commitment, we will have no current balance.
1015        // We will use our funding amount, or zero if we are not the funder.
1016        let cur_bal = cur_bal_opt.unwrap_or_else(|| self.initial_holder_value);
1017
1018        debug!(
1019            "balance {} -> {} --- cur h {} c {} new h {} c {}",
1020            cur_bal,
1021            new_bal,
1022            self.current_holder_commit_info.is_some(),
1023            self.current_counterparty_commit_info.is_some(),
1024            new_holder_tx.is_some(),
1025            new_counterparty_tx.is_some()
1026        );
1027
1028        BalanceDelta(cur_bal, new_bal)
1029    }
1030
1031    /// Return channel balances
1032    pub fn balance<T: PreimageMap + core::fmt::Debug>(
1033        &self,
1034        preimage_map: &T,
1035        channel_setup: &ChannelSetup,
1036        is_ready: bool,
1037    ) -> ChannelBalance {
1038        #[cfg(not(feature = "log_pretty_print"))]
1039        debug!("{:?}", preimage_map);
1040        #[cfg(feature = "log_pretty_print")]
1041        debug!("{:#?}", preimage_map);
1042
1043        // If either of commitments is missing, return 0.
1044        if self.current_holder_commit_info.is_none()
1045            || self.current_counterparty_commit_info.is_none()
1046        {
1047            return ChannelBalance::zero();
1048        }
1049
1050        let holder_info = self.current_holder_commit_info.as_ref().unwrap();
1051        let counterparty_info = self.current_counterparty_commit_info.as_ref().unwrap();
1052
1053        // Our balance in the holder commitment tx
1054        let cur_holder_bal = holder_info.claimable_balance(
1055            preimage_map,
1056            channel_setup.is_outbound,
1057            channel_setup.channel_value_sat,
1058        );
1059        // Our balance in the counterparty commitment tx
1060        let cur_cp_bal = counterparty_info.claimable_balance(
1061            preimage_map,
1062            channel_setup.is_outbound,
1063            channel_setup.channel_value_sat,
1064        );
1065        // Our overall balance is the lower of the two.  Use the htlc values from the same.
1066        // TODO(514) - might be more correct to check the HTLC value for each payment hash, and do
1067        // Math.min on each one, then sum that.  If an htlc exists in one commitment but not the
1068        // other if we offered, then it would be -value, if we are receiving, it would be
1069        // 0. i.e. Math.min(0, value)
1070        let (cur_bal, received_htlc, offered_htlc, received_htlc_count, offered_htlc_count) =
1071            if cur_holder_bal < cur_cp_bal {
1072                let (received_htlc, offered_htlc, received_count, offered_count) =
1073                    holder_info.htlc_balance();
1074                (cur_holder_bal, received_htlc, offered_htlc, received_count, offered_count)
1075            } else {
1076                let (received_htlc, offered_htlc, received_count, offered_count) =
1077                    counterparty_info.htlc_balance();
1078                (cur_cp_bal, received_htlc, offered_htlc, received_count, offered_count)
1079            };
1080
1081        let (claimable, sweeping) = if self.channel_closed { (0, cur_bal) } else { (cur_bal, 0) };
1082        let (stub_count, unconfirmed_count, channel_count, closing_count) = if self.channel_closed {
1083            (0, 0, 0, 1)
1084        } else if is_ready {
1085            (0, 0, 1, 0)
1086        } else {
1087            (0, 1, 0, 0)
1088        };
1089        let balance = ChannelBalance {
1090            claimable,
1091            received_htlc,
1092            offered_htlc,
1093            sweeping,
1094            stub_count,
1095            unconfirmed_count,
1096            channel_count,
1097            closing_count,
1098            received_htlc_count,
1099            offered_htlc_count,
1100        };
1101        balance
1102    }
1103}
1104
1105/// Claimable balance before and after a new commitment tx, in satoshi
1106pub struct BalanceDelta(pub u64, pub u64);
1107
1108impl Default for BalanceDelta {
1109    fn default() -> Self {
1110        BalanceDelta(0, 0)
1111    }
1112}
1113
1114// The minimum of two optional values.  If both are None, the result is None.
1115fn min_opt(a_opt: Option<u64>, b_opt: Option<u64>) -> Option<u64> {
1116    if let Some(a) = a_opt {
1117        if let Some(b) = b_opt {
1118            Some(a.min(b))
1119        } else {
1120            a_opt
1121        }
1122    } else {
1123        b_opt
1124    }
1125}
1126
1127#[cfg(test)]
1128mod tests {
1129    use super::*;
1130    use crate::tx::tx::{CommitmentInfo2, HTLCInfo2};
1131    use lightning::types::payment::PaymentHash;
1132
1133    #[test]
1134    fn test_per_commitment_storage() {
1135        // Test bad idx
1136        let mut monitor = CounterpartyCommitmentSecrets::new();
1137        let secret: [u8; 32] =
1138            hex::decode("7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc")
1139                .unwrap()
1140                .try_into()
1141                .unwrap();
1142        assert!(monitor.provide_secret(281474976710654, secret).is_err());
1143
1144        // Test vectors from BOLT 3:
1145        let mut secrets: Vec<[u8; 32]> = Vec::new();
1146        let mut monitor;
1147
1148        macro_rules! test_secrets {
1149            () => {
1150                let mut idx = 281474976710655;
1151                for secret in secrets.iter() {
1152                    assert_eq!(monitor.get_secret(idx).unwrap(), *secret);
1153                    idx -= 1;
1154                }
1155                assert_eq!(monitor.get_min_seen_secret(), idx + 1);
1156                assert!(monitor.get_secret(idx).is_none());
1157            };
1158        }
1159
1160        {
1161            // insert_secret correct sequence
1162            monitor = CounterpartyCommitmentSecrets::new();
1163            secrets.clear();
1164
1165            secrets.push([0; 32]);
1166            secrets.last_mut().unwrap()[0..32].clone_from_slice(
1167                &hex::decode("7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc")
1168                    .unwrap(),
1169            );
1170            monitor.provide_secret(281474976710655, secrets.last().unwrap().clone()).unwrap();
1171            test_secrets!();
1172
1173            secrets.push([0; 32]);
1174            secrets.last_mut().unwrap()[0..32].clone_from_slice(
1175                &hex::decode("c7518c8ae4660ed02894df8976fa1a3659c1a8b4b5bec0c4b872abeba4cb8964")
1176                    .unwrap(),
1177            );
1178            monitor.provide_secret(281474976710654, secrets.last().unwrap().clone()).unwrap();
1179            test_secrets!();
1180
1181            secrets.push([0; 32]);
1182            secrets.last_mut().unwrap()[0..32].clone_from_slice(
1183                &hex::decode("2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8")
1184                    .unwrap(),
1185            );
1186            monitor.provide_secret(281474976710653, secrets.last().unwrap().clone()).unwrap();
1187            test_secrets!();
1188
1189            secrets.push([0; 32]);
1190            secrets.last_mut().unwrap()[0..32].clone_from_slice(
1191                &hex::decode("27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116")
1192                    .unwrap(),
1193            );
1194            monitor.provide_secret(281474976710652, secrets.last().unwrap().clone()).unwrap();
1195            test_secrets!();
1196
1197            secrets.push([0; 32]);
1198            secrets.last_mut().unwrap()[0..32].clone_from_slice(
1199                &hex::decode("c65716add7aa98ba7acb236352d665cab17345fe45b55fb879ff80e6bd0c41dd")
1200                    .unwrap(),
1201            );
1202            monitor.provide_secret(281474976710651, secrets.last().unwrap().clone()).unwrap();
1203            test_secrets!();
1204
1205            secrets.push([0; 32]);
1206            secrets.last_mut().unwrap()[0..32].clone_from_slice(
1207                &hex::decode("969660042a28f32d9be17344e09374b379962d03db1574df5a8a5a47e19ce3f2")
1208                    .unwrap(),
1209            );
1210            monitor.provide_secret(281474976710650, secrets.last().unwrap().clone()).unwrap();
1211            test_secrets!();
1212
1213            secrets.push([0; 32]);
1214            secrets.last_mut().unwrap()[0..32].clone_from_slice(
1215                &hex::decode("a5a64476122ca0925fb344bdc1854c1c0a59fc614298e50a33e331980a220f32")
1216                    .unwrap(),
1217            );
1218            monitor.provide_secret(281474976710649, secrets.last().unwrap().clone()).unwrap();
1219            test_secrets!();
1220
1221            secrets.push([0; 32]);
1222            secrets.last_mut().unwrap()[0..32].clone_from_slice(
1223                &hex::decode("05cde6323d949933f7f7b78776bcc1ea6d9b31447732e3802e1f7ac44b650e17")
1224                    .unwrap(),
1225            );
1226            monitor.provide_secret(281474976710648, secrets.last().unwrap().clone()).unwrap();
1227            test_secrets!();
1228        }
1229
1230        {
1231            // insert_secret #1 incorrect
1232            monitor = CounterpartyCommitmentSecrets::new();
1233            secrets.clear();
1234
1235            secrets.push([0; 32]);
1236            secrets.last_mut().unwrap()[0..32].clone_from_slice(
1237                &hex::decode("02a40c85b6f28da08dfdbe0926c53fab2de6d28c10301f8f7c4073d5e42e3148")
1238                    .unwrap(),
1239            );
1240            monitor.provide_secret(281474976710655, secrets.last().unwrap().clone()).unwrap();
1241            test_secrets!();
1242
1243            secrets.push([0; 32]);
1244            secrets.last_mut().unwrap()[0..32].clone_from_slice(
1245                &hex::decode("c7518c8ae4660ed02894df8976fa1a3659c1a8b4b5bec0c4b872abeba4cb8964")
1246                    .unwrap(),
1247            );
1248            assert!(monitor
1249                .provide_secret(281474976710654, secrets.last().unwrap().clone())
1250                .is_err());
1251        }
1252
1253        {
1254            // insert_secret #2 incorrect (#1 derived from incorrect)
1255            monitor = CounterpartyCommitmentSecrets::new();
1256            secrets.clear();
1257
1258            secrets.push([0; 32]);
1259            secrets.last_mut().unwrap()[0..32].clone_from_slice(
1260                &hex::decode("02a40c85b6f28da08dfdbe0926c53fab2de6d28c10301f8f7c4073d5e42e3148")
1261                    .unwrap(),
1262            );
1263            monitor.provide_secret(281474976710655, secrets.last().unwrap().clone()).unwrap();
1264            test_secrets!();
1265
1266            secrets.push([0; 32]);
1267            secrets.last_mut().unwrap()[0..32].clone_from_slice(
1268                &hex::decode("dddc3a8d14fddf2b68fa8c7fbad2748274937479dd0f8930d5ebb4ab6bd866a3")
1269                    .unwrap(),
1270            );
1271            monitor.provide_secret(281474976710654, secrets.last().unwrap().clone()).unwrap();
1272            test_secrets!();
1273
1274            secrets.push([0; 32]);
1275            secrets.last_mut().unwrap()[0..32].clone_from_slice(
1276                &hex::decode("2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8")
1277                    .unwrap(),
1278            );
1279            monitor.provide_secret(281474976710653, secrets.last().unwrap().clone()).unwrap();
1280            test_secrets!();
1281
1282            secrets.push([0; 32]);
1283            secrets.last_mut().unwrap()[0..32].clone_from_slice(
1284                &hex::decode("27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116")
1285                    .unwrap(),
1286            );
1287            assert!(monitor
1288                .provide_secret(281474976710652, secrets.last().unwrap().clone())
1289                .is_err());
1290        }
1291
1292        {
1293            // insert_secret #3 incorrect
1294            monitor = CounterpartyCommitmentSecrets::new();
1295            secrets.clear();
1296
1297            secrets.push([0; 32]);
1298            secrets.last_mut().unwrap()[0..32].clone_from_slice(
1299                &hex::decode("7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc")
1300                    .unwrap(),
1301            );
1302            monitor.provide_secret(281474976710655, secrets.last().unwrap().clone()).unwrap();
1303            test_secrets!();
1304
1305            secrets.push([0; 32]);
1306            secrets.last_mut().unwrap()[0..32].clone_from_slice(
1307                &hex::decode("c7518c8ae4660ed02894df8976fa1a3659c1a8b4b5bec0c4b872abeba4cb8964")
1308                    .unwrap(),
1309            );
1310            monitor.provide_secret(281474976710654, secrets.last().unwrap().clone()).unwrap();
1311            test_secrets!();
1312
1313            secrets.push([0; 32]);
1314            secrets.last_mut().unwrap()[0..32].clone_from_slice(
1315                &hex::decode("c51a18b13e8527e579ec56365482c62f180b7d5760b46e9477dae59e87ed423a")
1316                    .unwrap(),
1317            );
1318            monitor.provide_secret(281474976710653, secrets.last().unwrap().clone()).unwrap();
1319            test_secrets!();
1320
1321            secrets.push([0; 32]);
1322            secrets.last_mut().unwrap()[0..32].clone_from_slice(
1323                &hex::decode("27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116")
1324                    .unwrap(),
1325            );
1326            assert!(monitor
1327                .provide_secret(281474976710652, secrets.last().unwrap().clone())
1328                .is_err());
1329        }
1330
1331        {
1332            // insert_secret #4 incorrect (1,2,3 derived from incorrect)
1333            monitor = CounterpartyCommitmentSecrets::new();
1334            secrets.clear();
1335
1336            secrets.push([0; 32]);
1337            secrets.last_mut().unwrap()[0..32].clone_from_slice(
1338                &hex::decode("02a40c85b6f28da08dfdbe0926c53fab2de6d28c10301f8f7c4073d5e42e3148")
1339                    .unwrap(),
1340            );
1341            monitor.provide_secret(281474976710655, secrets.last().unwrap().clone()).unwrap();
1342            test_secrets!();
1343
1344            secrets.push([0; 32]);
1345            secrets.last_mut().unwrap()[0..32].clone_from_slice(
1346                &hex::decode("dddc3a8d14fddf2b68fa8c7fbad2748274937479dd0f8930d5ebb4ab6bd866a3")
1347                    .unwrap(),
1348            );
1349            monitor.provide_secret(281474976710654, secrets.last().unwrap().clone()).unwrap();
1350            test_secrets!();
1351
1352            secrets.push([0; 32]);
1353            secrets.last_mut().unwrap()[0..32].clone_from_slice(
1354                &hex::decode("c51a18b13e8527e579ec56365482c62f180b7d5760b46e9477dae59e87ed423a")
1355                    .unwrap(),
1356            );
1357            monitor.provide_secret(281474976710653, secrets.last().unwrap().clone()).unwrap();
1358            test_secrets!();
1359
1360            secrets.push([0; 32]);
1361            secrets.last_mut().unwrap()[0..32].clone_from_slice(
1362                &hex::decode("ba65d7b0ef55a3ba300d4e87af29868f394f8f138d78a7011669c79b37b936f4")
1363                    .unwrap(),
1364            );
1365            monitor.provide_secret(281474976710652, secrets.last().unwrap().clone()).unwrap();
1366            test_secrets!();
1367
1368            secrets.push([0; 32]);
1369            secrets.last_mut().unwrap()[0..32].clone_from_slice(
1370                &hex::decode("c65716add7aa98ba7acb236352d665cab17345fe45b55fb879ff80e6bd0c41dd")
1371                    .unwrap(),
1372            );
1373            monitor.provide_secret(281474976710651, secrets.last().unwrap().clone()).unwrap();
1374            test_secrets!();
1375
1376            secrets.push([0; 32]);
1377            secrets.last_mut().unwrap()[0..32].clone_from_slice(
1378                &hex::decode("969660042a28f32d9be17344e09374b379962d03db1574df5a8a5a47e19ce3f2")
1379                    .unwrap(),
1380            );
1381            monitor.provide_secret(281474976710650, secrets.last().unwrap().clone()).unwrap();
1382            test_secrets!();
1383
1384            secrets.push([0; 32]);
1385            secrets.last_mut().unwrap()[0..32].clone_from_slice(
1386                &hex::decode("a5a64476122ca0925fb344bdc1854c1c0a59fc614298e50a33e331980a220f32")
1387                    .unwrap(),
1388            );
1389            monitor.provide_secret(281474976710649, secrets.last().unwrap().clone()).unwrap();
1390            test_secrets!();
1391
1392            secrets.push([0; 32]);
1393            secrets.last_mut().unwrap()[0..32].clone_from_slice(
1394                &hex::decode("05cde6323d949933f7f7b78776bcc1ea6d9b31447732e3802e1f7ac44b650e17")
1395                    .unwrap(),
1396            );
1397            assert!(monitor
1398                .provide_secret(281474976710648, secrets.last().unwrap().clone())
1399                .is_err());
1400        }
1401
1402        {
1403            // insert_secret #5 incorrect
1404            monitor = CounterpartyCommitmentSecrets::new();
1405            secrets.clear();
1406
1407            secrets.push([0; 32]);
1408            secrets.last_mut().unwrap()[0..32].clone_from_slice(
1409                &hex::decode("7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc")
1410                    .unwrap(),
1411            );
1412            monitor.provide_secret(281474976710655, secrets.last().unwrap().clone()).unwrap();
1413            test_secrets!();
1414
1415            secrets.push([0; 32]);
1416            secrets.last_mut().unwrap()[0..32].clone_from_slice(
1417                &hex::decode("c7518c8ae4660ed02894df8976fa1a3659c1a8b4b5bec0c4b872abeba4cb8964")
1418                    .unwrap(),
1419            );
1420            monitor.provide_secret(281474976710654, secrets.last().unwrap().clone()).unwrap();
1421            test_secrets!();
1422
1423            secrets.push([0; 32]);
1424            secrets.last_mut().unwrap()[0..32].clone_from_slice(
1425                &hex::decode("2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8")
1426                    .unwrap(),
1427            );
1428            monitor.provide_secret(281474976710653, secrets.last().unwrap().clone()).unwrap();
1429            test_secrets!();
1430
1431            secrets.push([0; 32]);
1432            secrets.last_mut().unwrap()[0..32].clone_from_slice(
1433                &hex::decode("27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116")
1434                    .unwrap(),
1435            );
1436            monitor.provide_secret(281474976710652, secrets.last().unwrap().clone()).unwrap();
1437            test_secrets!();
1438
1439            secrets.push([0; 32]);
1440            secrets.last_mut().unwrap()[0..32].clone_from_slice(
1441                &hex::decode("631373ad5f9ef654bb3dade742d09504c567edd24320d2fcd68e3cc47e2ff6a6")
1442                    .unwrap(),
1443            );
1444            monitor.provide_secret(281474976710651, secrets.last().unwrap().clone()).unwrap();
1445            test_secrets!();
1446
1447            secrets.push([0; 32]);
1448            secrets.last_mut().unwrap()[0..32].clone_from_slice(
1449                &hex::decode("969660042a28f32d9be17344e09374b379962d03db1574df5a8a5a47e19ce3f2")
1450                    .unwrap(),
1451            );
1452            assert!(monitor
1453                .provide_secret(281474976710650, secrets.last().unwrap().clone())
1454                .is_err());
1455        }
1456
1457        {
1458            // insert_secret #6 incorrect (5 derived from incorrect)
1459            monitor = CounterpartyCommitmentSecrets::new();
1460            secrets.clear();
1461
1462            secrets.push([0; 32]);
1463            secrets.last_mut().unwrap()[0..32].clone_from_slice(
1464                &hex::decode("7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc")
1465                    .unwrap(),
1466            );
1467            monitor.provide_secret(281474976710655, secrets.last().unwrap().clone()).unwrap();
1468            test_secrets!();
1469
1470            secrets.push([0; 32]);
1471            secrets.last_mut().unwrap()[0..32].clone_from_slice(
1472                &hex::decode("c7518c8ae4660ed02894df8976fa1a3659c1a8b4b5bec0c4b872abeba4cb8964")
1473                    .unwrap(),
1474            );
1475            monitor.provide_secret(281474976710654, secrets.last().unwrap().clone()).unwrap();
1476            test_secrets!();
1477
1478            secrets.push([0; 32]);
1479            secrets.last_mut().unwrap()[0..32].clone_from_slice(
1480                &hex::decode("2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8")
1481                    .unwrap(),
1482            );
1483            monitor.provide_secret(281474976710653, secrets.last().unwrap().clone()).unwrap();
1484            test_secrets!();
1485
1486            secrets.push([0; 32]);
1487            secrets.last_mut().unwrap()[0..32].clone_from_slice(
1488                &hex::decode("27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116")
1489                    .unwrap(),
1490            );
1491            monitor.provide_secret(281474976710652, secrets.last().unwrap().clone()).unwrap();
1492            test_secrets!();
1493
1494            secrets.push([0; 32]);
1495            secrets.last_mut().unwrap()[0..32].clone_from_slice(
1496                &hex::decode("631373ad5f9ef654bb3dade742d09504c567edd24320d2fcd68e3cc47e2ff6a6")
1497                    .unwrap(),
1498            );
1499            monitor.provide_secret(281474976710651, secrets.last().unwrap().clone()).unwrap();
1500            test_secrets!();
1501
1502            secrets.push([0; 32]);
1503            secrets.last_mut().unwrap()[0..32].clone_from_slice(
1504                &hex::decode("b7e76a83668bde38b373970155c868a653304308f9896692f904a23731224bb1")
1505                    .unwrap(),
1506            );
1507            monitor.provide_secret(281474976710650, secrets.last().unwrap().clone()).unwrap();
1508            test_secrets!();
1509
1510            secrets.push([0; 32]);
1511            secrets.last_mut().unwrap()[0..32].clone_from_slice(
1512                &hex::decode("a5a64476122ca0925fb344bdc1854c1c0a59fc614298e50a33e331980a220f32")
1513                    .unwrap(),
1514            );
1515            monitor.provide_secret(281474976710649, secrets.last().unwrap().clone()).unwrap();
1516            test_secrets!();
1517
1518            secrets.push([0; 32]);
1519            secrets.last_mut().unwrap()[0..32].clone_from_slice(
1520                &hex::decode("05cde6323d949933f7f7b78776bcc1ea6d9b31447732e3802e1f7ac44b650e17")
1521                    .unwrap(),
1522            );
1523            assert!(monitor
1524                .provide_secret(281474976710648, secrets.last().unwrap().clone())
1525                .is_err());
1526        }
1527
1528        {
1529            // insert_secret #7 incorrect
1530            monitor = CounterpartyCommitmentSecrets::new();
1531            secrets.clear();
1532
1533            secrets.push([0; 32]);
1534            secrets.last_mut().unwrap()[0..32].clone_from_slice(
1535                &hex::decode("7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc")
1536                    .unwrap(),
1537            );
1538            monitor.provide_secret(281474976710655, secrets.last().unwrap().clone()).unwrap();
1539            test_secrets!();
1540
1541            secrets.push([0; 32]);
1542            secrets.last_mut().unwrap()[0..32].clone_from_slice(
1543                &hex::decode("c7518c8ae4660ed02894df8976fa1a3659c1a8b4b5bec0c4b872abeba4cb8964")
1544                    .unwrap(),
1545            );
1546            monitor.provide_secret(281474976710654, secrets.last().unwrap().clone()).unwrap();
1547            test_secrets!();
1548
1549            secrets.push([0; 32]);
1550            secrets.last_mut().unwrap()[0..32].clone_from_slice(
1551                &hex::decode("2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8")
1552                    .unwrap(),
1553            );
1554            monitor.provide_secret(281474976710653, secrets.last().unwrap().clone()).unwrap();
1555            test_secrets!();
1556
1557            secrets.push([0; 32]);
1558            secrets.last_mut().unwrap()[0..32].clone_from_slice(
1559                &hex::decode("27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116")
1560                    .unwrap(),
1561            );
1562            monitor.provide_secret(281474976710652, secrets.last().unwrap().clone()).unwrap();
1563            test_secrets!();
1564
1565            secrets.push([0; 32]);
1566            secrets.last_mut().unwrap()[0..32].clone_from_slice(
1567                &hex::decode("c65716add7aa98ba7acb236352d665cab17345fe45b55fb879ff80e6bd0c41dd")
1568                    .unwrap(),
1569            );
1570            monitor.provide_secret(281474976710651, secrets.last().unwrap().clone()).unwrap();
1571            test_secrets!();
1572
1573            secrets.push([0; 32]);
1574            secrets.last_mut().unwrap()[0..32].clone_from_slice(
1575                &hex::decode("969660042a28f32d9be17344e09374b379962d03db1574df5a8a5a47e19ce3f2")
1576                    .unwrap(),
1577            );
1578            monitor.provide_secret(281474976710650, secrets.last().unwrap().clone()).unwrap();
1579            test_secrets!();
1580
1581            secrets.push([0; 32]);
1582            secrets.last_mut().unwrap()[0..32].clone_from_slice(
1583                &hex::decode("e7971de736e01da8ed58b94c2fc216cb1dca9e326f3a96e7194fe8ea8af6c0a3")
1584                    .unwrap(),
1585            );
1586            monitor.provide_secret(281474976710649, secrets.last().unwrap().clone()).unwrap();
1587            test_secrets!();
1588
1589            secrets.push([0; 32]);
1590            secrets.last_mut().unwrap()[0..32].clone_from_slice(
1591                &hex::decode("05cde6323d949933f7f7b78776bcc1ea6d9b31447732e3802e1f7ac44b650e17")
1592                    .unwrap(),
1593            );
1594            assert!(monitor
1595                .provide_secret(281474976710648, secrets.last().unwrap().clone())
1596                .is_err());
1597        }
1598
1599        {
1600            // insert_secret #8 incorrect
1601            monitor = CounterpartyCommitmentSecrets::new();
1602            secrets.clear();
1603
1604            secrets.push([0; 32]);
1605            secrets.last_mut().unwrap()[0..32].clone_from_slice(
1606                &hex::decode("7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc")
1607                    .unwrap(),
1608            );
1609            monitor.provide_secret(281474976710655, secrets.last().unwrap().clone()).unwrap();
1610            test_secrets!();
1611
1612            secrets.push([0; 32]);
1613            secrets.last_mut().unwrap()[0..32].clone_from_slice(
1614                &hex::decode("c7518c8ae4660ed02894df8976fa1a3659c1a8b4b5bec0c4b872abeba4cb8964")
1615                    .unwrap(),
1616            );
1617            monitor.provide_secret(281474976710654, secrets.last().unwrap().clone()).unwrap();
1618            test_secrets!();
1619
1620            secrets.push([0; 32]);
1621            secrets.last_mut().unwrap()[0..32].clone_from_slice(
1622                &hex::decode("2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8")
1623                    .unwrap(),
1624            );
1625            monitor.provide_secret(281474976710653, secrets.last().unwrap().clone()).unwrap();
1626            test_secrets!();
1627
1628            secrets.push([0; 32]);
1629            secrets.last_mut().unwrap()[0..32].clone_from_slice(
1630                &hex::decode("27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116")
1631                    .unwrap(),
1632            );
1633            monitor.provide_secret(281474976710652, secrets.last().unwrap().clone()).unwrap();
1634            test_secrets!();
1635
1636            secrets.push([0; 32]);
1637            secrets.last_mut().unwrap()[0..32].clone_from_slice(
1638                &hex::decode("c65716add7aa98ba7acb236352d665cab17345fe45b55fb879ff80e6bd0c41dd")
1639                    .unwrap(),
1640            );
1641            monitor.provide_secret(281474976710651, secrets.last().unwrap().clone()).unwrap();
1642            test_secrets!();
1643
1644            secrets.push([0; 32]);
1645            secrets.last_mut().unwrap()[0..32].clone_from_slice(
1646                &hex::decode("969660042a28f32d9be17344e09374b379962d03db1574df5a8a5a47e19ce3f2")
1647                    .unwrap(),
1648            );
1649            monitor.provide_secret(281474976710650, secrets.last().unwrap().clone()).unwrap();
1650            test_secrets!();
1651
1652            secrets.push([0; 32]);
1653            secrets.last_mut().unwrap()[0..32].clone_from_slice(
1654                &hex::decode("a5a64476122ca0925fb344bdc1854c1c0a59fc614298e50a33e331980a220f32")
1655                    .unwrap(),
1656            );
1657            monitor.provide_secret(281474976710649, secrets.last().unwrap().clone()).unwrap();
1658            test_secrets!();
1659
1660            secrets.push([0; 32]);
1661            secrets.last_mut().unwrap()[0..32].clone_from_slice(
1662                &hex::decode("a7efbc61aac46d34f77778bac22c8a20c6a46ca460addc49009bda875ec88fa4")
1663                    .unwrap(),
1664            );
1665            assert!(monitor
1666                .provide_secret(281474976710648, secrets.last().unwrap().clone())
1667                .is_err());
1668        }
1669    }
1670
1671    #[test]
1672    fn payments_summary_test() {
1673        let mut state = EnforcementState::new(1000000);
1674
1675        // COUNTERPARTY
1676        let payment_hash = PaymentHash([3; 32]);
1677        let htlcs = vec![HTLCInfo2 { value_sat: 1000, payment_hash, cltv_expiry: 100 }];
1678
1679        let cp_tx = make_tx(true, htlcs);
1680
1681        // no payments yet
1682        assert!(state.payments_summary(None, None).is_empty());
1683
1684        // pending add of outgoing HTLC
1685        let sum = state.payments_summary(None, Some(&cp_tx));
1686        assert_eq!(sum.get(&payment_hash), Some(&1000));
1687
1688        // outgoing HTLC
1689        state.current_counterparty_commit_info = Some(cp_tx);
1690        let sum = state.payments_summary(None, None);
1691        assert_eq!(sum.get(&payment_hash), Some(&1000));
1692
1693        // pending failed HTLC
1694        let cp_tx2 = make_tx(true, vec![]);
1695        let sum = state.payments_summary(None, Some(&cp_tx2));
1696        assert_eq!(sum.get(&payment_hash), Some(&0));
1697
1698        state.current_counterparty_commit_info = Some(cp_tx2);
1699        let sum = state.payments_summary(None, None);
1700        assert_eq!(sum.get(&payment_hash), None);
1701
1702        // HOLDER
1703        let payment_hash = PaymentHash([4; 32]);
1704        let htlcs = vec![HTLCInfo2 { value_sat: 1000, payment_hash, cltv_expiry: 100 }];
1705        let holder_tx = make_tx(false, htlcs);
1706
1707        // no payments yet
1708        assert!(state.payments_summary(None, None).is_empty());
1709
1710        // pending add of outgoing HTLC
1711        let sum = state.payments_summary(Some(&holder_tx), None);
1712        assert_eq!(sum.get(&payment_hash), Some(&1000));
1713
1714        // outgoing HTLC
1715        state.current_holder_commit_info = Some(holder_tx);
1716        let sum = state.payments_summary(None, None);
1717        assert_eq!(sum.get(&payment_hash), Some(&1000));
1718
1719        // pending failed HTLC
1720        let holder_tx2 = make_tx(false, vec![]);
1721        let sum = state.payments_summary(Some(&holder_tx2), None);
1722        assert_eq!(sum.get(&payment_hash), Some(&0));
1723
1724        state.current_holder_commit_info = Some(holder_tx2);
1725        let sum = state.payments_summary(None, None);
1726        assert_eq!(sum.get(&payment_hash), None);
1727    }
1728
1729    #[test]
1730    fn incoming_payments_summary_test() {
1731        let mut state = EnforcementState::new(1000000);
1732
1733        let payment_hash = PaymentHash([3; 32]);
1734        let htlcs = vec![HTLCInfo2 { value_sat: 1000, payment_hash, cltv_expiry: 100 }];
1735
1736        let cp_tx = make_tx(false, htlcs.clone());
1737        let holder_tx = make_tx(true, htlcs.clone());
1738
1739        // no payments yet
1740        assert!(state.incoming_payments_summary(None, None).is_empty());
1741
1742        // no payments with just one side
1743        assert!(state.incoming_payments_summary(Some(&holder_tx), None).is_empty());
1744        assert!(state.incoming_payments_summary(None, Some(&cp_tx)).is_empty());
1745
1746        // pending add of outgoing HTLC
1747        let sum = state.incoming_payments_summary(Some(&holder_tx), Some(&cp_tx));
1748        assert_eq!(sum.get(&payment_hash), Some(&1000));
1749
1750        // outgoing HTLC
1751        state.current_counterparty_commit_info = Some(cp_tx);
1752        state.current_holder_commit_info = Some(holder_tx);
1753        let sum = state.incoming_payments_summary(None, None);
1754        assert_eq!(sum.get(&payment_hash), Some(&1000));
1755
1756        // pending failed HTLC
1757        let holder_tx2 = make_tx(true, vec![]);
1758        let cp_tx2 = make_tx(false, vec![]);
1759
1760        let sum = state.incoming_payments_summary(None, Some(&cp_tx2));
1761        assert_eq!(sum.get(&payment_hash), Some(&0));
1762
1763        let sum = state.incoming_payments_summary(Some(&holder_tx2), None);
1764        assert_eq!(sum.get(&payment_hash), Some(&0));
1765    }
1766
1767    fn make_tx(is_received: bool, htlcs: Vec<HTLCInfo2>) -> CommitmentInfo2 {
1768        CommitmentInfo2::new(
1769            is_received,
1770            9000,
1771            10000,
1772            if is_received { vec![] } else { htlcs.clone() },
1773            if is_received { htlcs.clone() } else { vec![] },
1774            1000,
1775        )
1776    }
1777}