Skip to content

Commit f932902

Browse files
committed
Sometimes use new mon state when reloading in chanmon_consistency
When we reload a node in the `chanmon_consistency` fuzzer, we always reload with the latest `ChannelMonitor` state which was confirmed as persisted to the running `ChannelManager`. This is nice in that it tests losing the latest `ChannelMonitor`, but there may also be bugs in the on-startup `ChannelMonitor` replay. Thus, here, we optionally reload with a newer `ChannelMonitor` than the last-persisted one.
1 parent 38bd353 commit f932902

File tree

1 file changed

+49
-29
lines changed

1 file changed

+49
-29
lines changed

fuzz/src/chanmon_consistency.rs

+49-29
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,6 @@ use bitcoin::secp256k1::ecdsa::{RecoverableSignature, Signature};
8080
use bitcoin::secp256k1::schnorr;
8181
use bitcoin::secp256k1::{self, Message, PublicKey, Scalar, Secp256k1, SecretKey};
8282

83-
use lightning::io::Cursor;
8483
use lightning::util::dyn_signer::DynSigner;
8584

8685
use std::cell::RefCell;
@@ -253,7 +252,7 @@ impl chain::Watch<TestChannelSigner> for TestChainMonitor {
253252
.unwrap_or(&map_entry.persisted_monitor);
254253
let deserialized_monitor =
255254
<(BlockHash, channelmonitor::ChannelMonitor<TestChannelSigner>)>::read(
256-
&mut Cursor::new(&latest_monitor_data),
255+
&mut &latest_monitor_data[..],
257256
(&*self.keys, &*self.keys),
258257
)
259258
.unwrap()
@@ -680,8 +679,8 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
680679
let mon_style = [default_mon_style.clone(), default_mon_style.clone(), default_mon_style];
681680

682681
macro_rules! reload_node {
683-
($ser: expr, $node_id: expr, $old_monitors: expr, $keys_manager: expr, $fee_estimator: expr) => {{
684-
let keys_manager = Arc::clone(&$keys_manager);
682+
($ser: expr, $node_id: expr, $old_monitors: expr, $use_old_mons: expr, $keys: expr, $fee_estimator: expr) => {{
683+
let keys_manager = Arc::clone(&$keys);
685684
let logger: Arc<dyn Logger> =
686685
Arc::new(test_logger::TestLogger::new($node_id.to_string(), out.clone()));
687686
let chain_monitor = Arc::new(TestChainMonitor::new(
@@ -691,7 +690,7 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
691690
Arc::new(TestPersister {
692691
update_ret: Mutex::new(ChannelMonitorUpdateStatus::Completed),
693692
}),
694-
Arc::clone(&$keys_manager),
693+
Arc::clone(&$keys),
695694
));
696695

697696
let mut config = UserConfig::default();
@@ -705,15 +704,27 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
705704
let mut monitors = new_hash_map();
706705
let mut old_monitors = $old_monitors.latest_monitors.lock().unwrap();
707706
for (channel_id, mut prev_state) in old_monitors.drain() {
708-
monitors.insert(
709-
channel_id,
710-
<(BlockHash, ChannelMonitor<TestChannelSigner>)>::read(
711-
&mut Cursor::new(&prev_state.persisted_monitor),
712-
(&*$keys_manager, &*$keys_manager),
713-
)
714-
.expect("Failed to read monitor")
715-
.1,
716-
);
707+
let serialized_mon = if $use_old_mons % 3 == 0 {
708+
// Reload with the oldest `ChannelMonitor` (the one that we already told
709+
// `ChannelManager` we finished persisting).
710+
prev_state.persisted_monitor
711+
} else if $use_old_mons % 3 == 1 {
712+
// Reload with the second-oldest `ChannelMonitor`
713+
let old_mon = prev_state.persisted_monitor;
714+
prev_state.pending_monitors.drain(..).next().map(|(_, v)| v).unwrap_or(old_mon)
715+
} else {
716+
// Reload with the newest `ChannelMonitor`
717+
let old_mon = prev_state.persisted_monitor;
718+
prev_state.pending_monitors.pop().map(|(_, v)| v).unwrap_or(old_mon)
719+
};
720+
let mon = <(BlockHash, ChannelMonitor<TestChannelSigner>)>::read(
721+
&mut &serialized_mon[..],
722+
(&*$keys, &*$keys),
723+
)
724+
.expect("Failed to read monitor");
725+
monitors.insert(channel_id, mon.1);
726+
// Update the latest `ChannelMonitor` state to match what we just told LDK.
727+
prev_state.persisted_monitor = serialized_mon;
717728
// Wipe any `ChannelMonitor`s which we never told LDK we finished persisting,
718729
// considering them discarded. LDK should replay these for us as they're stored in
719730
// the `ChannelManager`.
@@ -726,9 +737,9 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
726737
}
727738

728739
let read_args = ChannelManagerReadArgs {
729-
entropy_source: keys_manager.clone(),
730-
node_signer: keys_manager.clone(),
731-
signer_provider: keys_manager.clone(),
740+
entropy_source: Arc::clone(&keys_manager),
741+
node_signer: Arc::clone(&keys_manager),
742+
signer_provider: keys_manager,
732743
fee_estimator: $fee_estimator.clone(),
733744
chain_monitor: chain_monitor.clone(),
734745
tx_broadcaster: broadcast.clone(),
@@ -739,12 +750,9 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
739750
channel_monitors: monitor_refs,
740751
};
741752

742-
let res = (
743-
<(BlockHash, ChanMan)>::read(&mut Cursor::new(&$ser.0), read_args)
744-
.expect("Failed to read manager")
745-
.1,
746-
chain_monitor.clone(),
747-
);
753+
let manager = <(BlockHash, ChanMan)>::read(&mut &$ser.0[..], read_args)
754+
.expect("Failed to read manager");
755+
let res = (manager.1, chain_monitor.clone());
748756
for (channel_id, mon) in monitors.drain() {
749757
assert_eq!(
750758
chain_monitor.chain_monitor.watch_channel(channel_id, mon),
@@ -1503,7 +1511,9 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
15031511
0x26 => process_ev_noret!(2, true),
15041512
0x27 => process_ev_noret!(2, false),
15051513

1506-
0x2c => {
1514+
0x2a | 0x2b | 0x2c => {
1515+
// Restart node A, picking among the in-flight `ChannelMonitor`s to use based on
1516+
// the value of `v` we're matching.
15071517
if !chan_a_disconnected {
15081518
nodes[1].peer_disconnected(nodes[0].get_our_node_id());
15091519
chan_a_disconnected = true;
@@ -1514,12 +1524,16 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
15141524
ab_events.clear();
15151525
ba_events.clear();
15161526
}
1527+
// Note that we ensure 0x2c represents "use oldest monitor" to retain backwards
1528+
// compatibility with existing fuzz corpuses by using setting (v + 1) % 3 == 0
15171529
let (new_node_a, new_monitor_a) =
1518-
reload_node!(node_a_ser, 0, monitor_a, keys_manager_a, fee_est_a);
1530+
reload_node!(node_a_ser, 0, monitor_a, v + 1, keys_manager_a, fee_est_a);
15191531
nodes[0] = new_node_a;
15201532
monitor_a = new_monitor_a;
15211533
},
1522-
0x2d => {
1534+
0x28 | 0x29 | 0x2d => {
1535+
// Restart node B, picking among the in-flight `ChannelMonitor`s to use based on
1536+
// the value of `v` we're matching.
15231537
if !chan_a_disconnected {
15241538
nodes[0].peer_disconnected(nodes[1].get_our_node_id());
15251539
chan_a_disconnected = true;
@@ -1534,12 +1548,16 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
15341548
bc_events.clear();
15351549
cb_events.clear();
15361550
}
1551+
// Note that we ensure 0x2d represents "use oldest monitor" to retain backwards
1552+
// compatibility with existing fuzz corpuses by using setting v % 3 == 0
15371553
let (new_node_b, new_monitor_b) =
1538-
reload_node!(node_b_ser, 1, monitor_b, keys_manager_b, fee_est_b);
1554+
reload_node!(node_b_ser, 1, monitor_b, v, keys_manager_b, fee_est_b);
15391555
nodes[1] = new_node_b;
15401556
monitor_b = new_monitor_b;
15411557
},
1542-
0x2e => {
1558+
0x2e | 0x2f => {
1559+
// Restart node B, picking among the in-flight `ChannelMonitor`s to use based on
1560+
// the value of `v` we're matching.
15431561
if !chan_b_disconnected {
15441562
nodes[1].peer_disconnected(nodes[2].get_our_node_id());
15451563
chan_b_disconnected = true;
@@ -1550,8 +1568,10 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
15501568
bc_events.clear();
15511569
cb_events.clear();
15521570
}
1571+
// Note that we ensure 0x2e represents "use oldest monitor" to retain backwards
1572+
// compatibility with existing fuzz corpuses by using setting (v + 2) % 3 == 0
15531573
let (new_node_c, new_monitor_c) =
1554-
reload_node!(node_c_ser, 2, monitor_c, keys_manager_c, fee_est_c);
1574+
reload_node!(node_c_ser, 2, monitor_c, v + 2, keys_manager_c, fee_est_c);
15551575
nodes[2] = new_node_c;
15561576
monitor_c = new_monitor_c;
15571577
},

0 commit comments

Comments
 (0)