Skip to content

Commit b8db756

Browse files
committed
fuzz: Add cross-version ChannelMonitor roundtrip coverage
1 parent 2af4096 commit b8db756

2 files changed

Lines changed: 47 additions & 3 deletions

File tree

fuzz/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ lightning-invoice = { path = "../lightning-invoice" }
1111
lightning-liquidity = { path = "../lightning-liquidity" }
1212
lightning-rapid-gossip-sync = { path = "../lightning-rapid-gossip-sync" }
1313
lightning-persister = { path = "../lightning-persister", features = ["tokio"]}
14+
lightning_0_2 = { package = "lightning", version = "0.2.0", features = ["_test_utils"] }
1415
bech32 = "0.11.0"
1516
bitcoin = { version = "0.32.4", features = ["secp-lowmemory"] }
1617
tokio = { version = "~1.35", default-features = false, features = ["rt-multi-thread"] }

fuzz/src/chanmon_consistency.rs

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -970,10 +970,53 @@ impl<'a> HarnessNode<'a> {
970970
prev_state.pending_monitors.pop().unwrap_or(old_mon)
971971
};
972972
// Use a different value of `use_old_mons` if we have another monitor
973-
// (only for node B) by shifting `use_old_mons` one in base-3.
974-
use_old_mons /= 3;
973+
// (only for node B) by shifting `use_old_mons` one digit in base-6.
974+
// use_old_mons is decoded as base-6:
975+
// values 0, 1, 2 => oldest, second-oldest, newest monitor
976+
// values 3, 4, 5 => oldest, second-oldest, newest
977+
// monitor with cross-version roundtrip.
978+
let strategy_idx = use_old_mons % 6;
979+
let do_roundtrip = strategy_idx >= 3;
980+
981+
// Shift the base-6 value so the next channel monitor
982+
// iteration can select an independent strategy.
983+
use_old_mons /= 6;
984+
985+
let mut monitor_bytes = serialized_mon.clone();
986+
987+
if do_roundtrip {
988+
// The signer state is reconstructed from serialized
989+
// monitor bytes during deserialization.
990+
let keys_manager_0_2 =
991+
lightning_0_2::sign::KeysManager::new(&[0u8; 32], 0, 0, false);
992+
993+
let read_res: Result<
994+
(
995+
bitcoin::BlockHash,
996+
lightning_0_2::chain::channelmonitor::ChannelMonitor<
997+
lightning_0_2::sign::InMemorySigner,
998+
>,
999+
),
1000+
_,
1001+
> = lightning_0_2::util::ser::ReadableArgs::read(
1002+
&mut &monitor_bytes[..],
1003+
(&keys_manager_0_2, &keys_manager_0_2),
1004+
);
1005+
1006+
// Ignore monitors unreadable by lightning_0_2 so the
1007+
// fuzzer can continue exploring newer-version states.
1008+
if let Ok((block_hash_0_2, old_monitor)) = read_res {
1009+
let mut reserialized = Vec::new();
1010+
lightning_0_2::util::ser::Writeable::write(
1011+
&(block_hash_0_2, &old_monitor),
1012+
&mut reserialized,
1013+
)
1014+
.unwrap();
1015+
monitor_bytes = reserialized;
1016+
}
1017+
}
9751018
let mon = <(BlockLocator, ChannelMonitor<TestChannelSigner>)>::read(
976-
&mut &serialized_mon[..],
1019+
&mut &monitor_bytes[..],
9771020
(&*self.keys_manager, &*self.keys_manager),
9781021
)
9791022
.expect("Failed to read monitor");

0 commit comments

Comments
 (0)