Skip to content

Commit 586d46c

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 5fc2cfb commit 586d46c

File tree

1 file changed

+39
-29
lines changed

1 file changed

+39
-29
lines changed

fuzz/src/chanmon_consistency.rs

+39-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,23 @@ 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+
prev_state.persisted_monitor
709+
} else if $use_old_mons % 3 == 1 {
710+
let old_mon = prev_state.persisted_monitor;
711+
prev_state.pending_monitors.drain(..).next().map(|(_, v)| v).unwrap_or(old_mon)
712+
} else {
713+
let old_mon = prev_state.persisted_monitor;
714+
prev_state.pending_monitors.pop().map(|(_, v)| v).unwrap_or(old_mon)
715+
};
716+
let mon = <(BlockHash, ChannelMonitor<TestChannelSigner>)>::read(
717+
&mut &serialized_mon[..],
718+
(&*$keys, &*$keys),
719+
)
720+
.expect("Failed to read monitor");
721+
monitors.insert(channel_id, mon.1);
722+
// Update the latest `ChannelMonitor` state to match what we just told LDK.
723+
prev_state.persisted_monitor = serialized_mon;
717724
// Wipe any `ChannelMonitor`s which we never told LDK we finished persisting,
718725
// considering them discarded. LDK should replay these for us as they're stored in
719726
// the `ChannelManager`.
@@ -726,9 +733,9 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
726733
}
727734

728735
let read_args = ChannelManagerReadArgs {
729-
entropy_source: keys_manager.clone(),
730-
node_signer: keys_manager.clone(),
731-
signer_provider: keys_manager.clone(),
736+
entropy_source: Arc::clone(&keys_manager),
737+
node_signer: Arc::clone(&keys_manager),
738+
signer_provider: keys_manager,
732739
fee_estimator: $fee_estimator.clone(),
733740
chain_monitor: chain_monitor.clone(),
734741
tx_broadcaster: broadcast.clone(),
@@ -739,12 +746,9 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
739746
channel_monitors: monitor_refs,
740747
};
741748

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-
);
749+
let manager = <(BlockHash, ChanMan)>::read(&mut &$ser.0[..], read_args)
750+
.expect("Failed to read manager");
751+
let res = (manager.1, chain_monitor.clone());
748752
for (channel_id, mon) in monitors.drain() {
749753
assert_eq!(
750754
chain_monitor.chain_monitor.watch_channel(channel_id, mon),
@@ -1503,7 +1507,7 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
15031507
0x26 => process_ev_noret!(2, true),
15041508
0x27 => process_ev_noret!(2, false),
15051509

1506-
0x2c => {
1510+
0x2a | 0x2b | 0x2c => {
15071511
if !chan_a_disconnected {
15081512
nodes[1].peer_disconnected(nodes[0].get_our_node_id());
15091513
chan_a_disconnected = true;
@@ -1514,12 +1518,14 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
15141518
ab_events.clear();
15151519
ba_events.clear();
15161520
}
1521+
// Note that we ensure 0x2c represents "use oldest monitor" to retain backwards
1522+
// compatibility with existing fuzz corpuses by using setting (v + 1) % 3 == 0
15171523
let (new_node_a, new_monitor_a) =
1518-
reload_node!(node_a_ser, 0, monitor_a, keys_manager_a, fee_est_a);
1524+
reload_node!(node_a_ser, 0, monitor_a, v + 1, keys_manager_a, fee_est_a);
15191525
nodes[0] = new_node_a;
15201526
monitor_a = new_monitor_a;
15211527
},
1522-
0x2d => {
1528+
0x28 | 0x29 | 0x2d => {
15231529
if !chan_a_disconnected {
15241530
nodes[0].peer_disconnected(nodes[1].get_our_node_id());
15251531
chan_a_disconnected = true;
@@ -1534,12 +1540,14 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
15341540
bc_events.clear();
15351541
cb_events.clear();
15361542
}
1543+
// Note that we ensure 0x2d represents "use oldest monitor" to retain backwards
1544+
// compatibility with existing fuzz corpuses by using setting v % 3 == 0
15371545
let (new_node_b, new_monitor_b) =
1538-
reload_node!(node_b_ser, 1, monitor_b, keys_manager_b, fee_est_b);
1546+
reload_node!(node_b_ser, 1, monitor_b, v, keys_manager_b, fee_est_b);
15391547
nodes[1] = new_node_b;
15401548
monitor_b = new_monitor_b;
15411549
},
1542-
0x2e => {
1550+
0x2e | 0x2f => {
15431551
if !chan_b_disconnected {
15441552
nodes[1].peer_disconnected(nodes[2].get_our_node_id());
15451553
chan_b_disconnected = true;
@@ -1550,8 +1558,10 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
15501558
bc_events.clear();
15511559
cb_events.clear();
15521560
}
1561+
// Note that we ensure 0x2e represents "use oldest monitor" to retain backwards
1562+
// compatibility with existing fuzz corpuses by using setting (v + 2) % 3 == 0
15531563
let (new_node_c, new_monitor_c) =
1554-
reload_node!(node_c_ser, 2, monitor_c, keys_manager_c, fee_est_c);
1564+
reload_node!(node_c_ser, 2, monitor_c, v + 2, keys_manager_c, fee_est_c);
15551565
nodes[2] = new_node_c;
15561566
monitor_c = new_monitor_c;
15571567
},

0 commit comments

Comments
 (0)