Skip to content

Commit cf42bf7

Browse files
committed
Make ChannelMonitor round-trip tests more robust
During testsing, we check that a `ChannelMonitor` will round-trip through serialization exactly. However, we recently added a fix to change a value in `PackageTemplate` on reload to fix some issues in the field in 0.1. This can cause the round-trip tests to fail as a field is modified during read. We fix it here by simply exempting the field from the equality test in the condition where it would be updated on read. We also make the `ChannelMonitor` `PartialEq` trait implementation non-public as weird workarounds like this make clear that such a comparison is a britle API at best. Backport of a8ec966 Resolved `use` and `rustfmt` conflicts in: * lightning/src/chain/channelmonitor.rs In the upstream version of this commit, the `PartialEq` implementation for `ChannelMonitor` was made test-only however to avoid breaking a public API we do not do so here. However, the changes to `PartialEq` for `PackageTemplate` are `test`-only, so it shouldn't result in any behavioral change (not that the marginal `PartialEq` changes are likely to impact downstream crates in any case).
1 parent b341a09 commit cf42bf7

File tree

2 files changed

+57
-4
lines changed

2 files changed

+57
-4
lines changed

lightning/src/chain/channelmonitor.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ use crate::prelude::*;
5959
use core::{cmp, mem};
6060
use crate::io::{self, Error};
6161
use core::ops::Deref;
62-
use crate::sync::{Mutex, LockTestExt};
62+
use crate::sync::Mutex;
6363

6464
/// An update generated by the underlying channel itself which contains some new information the
6565
/// [`ChannelMonitor`] should be made aware of.
@@ -1040,12 +1040,21 @@ pub type TransactionOutputs = (Txid, Vec<(u32, TxOut)>);
10401040

10411041
impl<Signer: EcdsaChannelSigner> PartialEq for ChannelMonitor<Signer> where Signer: PartialEq {
10421042
fn eq(&self, other: &Self) -> bool {
1043+
use crate::sync::LockTestExt;
10431044
// We need some kind of total lockorder. Absent a better idea, we sort by position in
10441045
// memory and take locks in that order (assuming that we can't move within memory while a
10451046
// lock is held).
10461047
let ord = ((self as *const _) as usize) < ((other as *const _) as usize);
1047-
let a = if ord { self.inner.unsafe_well_ordered_double_lock_self() } else { other.inner.unsafe_well_ordered_double_lock_self() };
1048-
let b = if ord { other.inner.unsafe_well_ordered_double_lock_self() } else { self.inner.unsafe_well_ordered_double_lock_self() };
1048+
let a = if ord {
1049+
self.inner.unsafe_well_ordered_double_lock_self()
1050+
} else {
1051+
other.inner.unsafe_well_ordered_double_lock_self()
1052+
};
1053+
let b = if ord {
1054+
other.inner.unsafe_well_ordered_double_lock_self()
1055+
} else {
1056+
self.inner.unsafe_well_ordered_double_lock_self()
1057+
};
10491058
a.eq(&b)
10501059
}
10511060
}

lightning/src/chain/package.rs

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -820,7 +820,7 @@ enum PackageMalleability {
820820
///
821821
/// As packages are time-sensitive, we fee-bump and rebroadcast them at scheduled intervals.
822822
/// Failing to confirm a package translate as a loss of funds for the user.
823-
#[derive(Clone, Debug, PartialEq, Eq)]
823+
#[derive(Clone, Debug, Eq)]
824824
pub struct PackageTemplate {
825825
// List of onchain outputs and solving data to generate satisfying witnesses.
826826
inputs: Vec<(BitcoinOutPoint, PackageSolvingData)>,
@@ -849,6 +849,50 @@ pub struct PackageTemplate {
849849
height_timer: u32,
850850
}
851851

852+
impl PartialEq for PackageTemplate {
853+
fn eq(&self, o: &Self) -> bool {
854+
if self.inputs != o.inputs
855+
|| self.malleability != o.malleability
856+
|| self.feerate_previous != o.feerate_previous
857+
|| self.height_timer != o.height_timer
858+
{
859+
return false;
860+
}
861+
#[cfg(test)]
862+
{
863+
// In some cases we may reset `counterparty_spendable_height` to zero on reload, which
864+
// can cause our test assertions that ChannelMonitors round-trip exactly to trip. Here
865+
// we allow exactly the same case as we tweak in the `PackageTemplate` `Readable`
866+
// implementation.
867+
if self.counterparty_spendable_height == 0 {
868+
for (_, input) in self.inputs.iter() {
869+
if let PackageSolvingData::RevokedHTLCOutput(RevokedHTLCOutput {
870+
htlc, ..
871+
}) = input
872+
{
873+
if !htlc.offered && htlc.cltv_expiry != 0 {
874+
return true;
875+
}
876+
}
877+
}
878+
}
879+
if o.counterparty_spendable_height == 0 {
880+
for (_, input) in o.inputs.iter() {
881+
if let PackageSolvingData::RevokedHTLCOutput(RevokedHTLCOutput {
882+
htlc, ..
883+
}) = input
884+
{
885+
if !htlc.offered && htlc.cltv_expiry != 0 {
886+
return true;
887+
}
888+
}
889+
}
890+
}
891+
}
892+
self.counterparty_spendable_height == o.counterparty_spendable_height
893+
}
894+
}
895+
852896
impl PackageTemplate {
853897
pub(crate) fn can_merge_with(&self, other: &PackageTemplate, cur_height: u32) -> bool {
854898
match (self.malleability, other.malleability) {

0 commit comments

Comments
 (0)