Skip to content

Commit b138615

Browse files
committed
fuzz: Add upgrade/downgrade simulation to chanmon_consistency and fix chacha20 build
1 parent cb951b4 commit b138615

2 files changed

Lines changed: 194 additions & 39 deletions

File tree

fuzz/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ lightning-invoice = { path = "../lightning-invoice" }
2323
lightning-liquidity = { path = "../lightning-liquidity" }
2424
lightning-rapid-gossip-sync = { path = "../lightning-rapid-gossip-sync" }
2525
lightning-persister = { path = "../lightning-persister", features = ["tokio"]}
26+
lightning_0_2 = { package = "lightning", version = "0.2.0", features = ["_test_utils"] }
2627
bech32 = "0.11.0"
2728
bitcoin = { version = "0.32.4", features = ["secp-lowmemory"] }
2829
tokio = { version = "~1.35", default-features = false, features = ["rt-multi-thread"] }

fuzz/src/chanmon_consistency.rs

Lines changed: 193 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,28 @@ impl FeeEstimator for FuzzEstimator {
130130
}
131131
}
132132

133+
impl lightning_0_2::chain::chaininterface::FeeEstimator for FuzzEstimator {
134+
fn get_est_sat_per_1000_weight(
135+
&self, conf_target: lightning_0_2::chain::chaininterface::ConfirmationTarget,
136+
) -> u32 {
137+
match conf_target {
138+
lightning_0_2::chain::chaininterface::ConfirmationTarget::MaximumFeeEstimate
139+
| lightning_0_2::chain::chaininterface::ConfirmationTarget::UrgentOnChainSweep => {
140+
MAX_FEE
141+
},
142+
lightning_0_2::chain::chaininterface::ConfirmationTarget::ChannelCloseMinimum
143+
| lightning_0_2::chain::chaininterface::ConfirmationTarget::AnchorChannelFee
144+
| lightning_0_2::chain::chaininterface::ConfirmationTarget::MinAllowedAnchorChannelRemoteFee
145+
| lightning_0_2::chain::chaininterface::ConfirmationTarget::MinAllowedNonAnchorChannelRemoteFee
146+
| lightning_0_2::chain::chaininterface::ConfirmationTarget::OutputSpendingFee => 253,
147+
lightning_0_2::chain::chaininterface::ConfirmationTarget::NonAnchorChannelFee => {
148+
let val = self.ret_val.load(atomic::Ordering::Relaxed);
149+
cmp::min(val, MAX_FEE)
150+
},
151+
}
152+
}
153+
}
154+
133155
impl FuzzEstimator {
134156
fn feerate_sat_per_kw(&self) -> FeeRate {
135157
let feerate = self.ret_val.load(atomic::Ordering::Acquire);
@@ -182,6 +204,14 @@ impl BroadcasterInterface for TestBroadcaster {
182204
}
183205
}
184206

207+
impl lightning_0_2::chain::chaininterface::BroadcasterInterface for TestBroadcaster {
208+
fn broadcast_transactions(&self, txs: &[&bitcoin::Transaction]) {
209+
for tx in txs {
210+
self.txn_broadcasted.borrow_mut().push((*tx).clone());
211+
}
212+
}
213+
}
214+
185215
struct ChainState {
186216
blocks: Vec<(Header, Vec<Transaction>)>,
187217
confirmed_txids: HashSet<Txid>,
@@ -290,34 +320,49 @@ impl TestChainMonitor {
290320
latest_monitors: Mutex::new(new_hash_map()),
291321
}
292322
}
293-
}
294-
impl chain::Watch<TestChannelSigner> for TestChainMonitor {
295-
fn watch_channel(
296-
&self, channel_id: ChannelId, monitor: channelmonitor::ChannelMonitor<TestChannelSigner>,
297-
) -> Result<chain::ChannelMonitorUpdateStatus, ()> {
298-
let mut ser = VecWriter(Vec::new());
299-
monitor.write(&mut ser).unwrap();
300-
let monitor_id = monitor.get_latest_update_id();
301-
let res = self.chain_monitor.watch_channel(channel_id, monitor);
302-
let state = match res {
303-
Ok(chain::ChannelMonitorUpdateStatus::Completed) => LatestMonitorState {
304-
persisted_monitor_id: monitor_id,
305-
persisted_monitor: ser.0,
306-
pending_monitors: Vec::new(),
307-
},
308-
Ok(chain::ChannelMonitorUpdateStatus::InProgress) => LatestMonitorState {
309-
persisted_monitor_id: monitor_id,
310-
persisted_monitor: Vec::new(),
311-
pending_monitors: vec![(monitor_id, ser.0)],
312-
},
313-
Ok(chain::ChannelMonitorUpdateStatus::UnrecoverableError) => panic!(),
314-
Err(()) => panic!(),
323+
fn do_watch_channel_bytes(
324+
&self, channel_id_bytes: [u8; 32], monitor_id: u64, serialized_monitor: Vec<u8>,
325+
) {
326+
let channel_id = ChannelId(channel_id_bytes);
327+
let state = LatestMonitorState {
328+
persisted_monitor_id: monitor_id,
329+
persisted_monitor: serialized_monitor,
330+
pending_monitors: Vec::new(),
315331
};
316-
if self.latest_monitors.lock().unwrap().insert(channel_id, state).is_some() {
332+
let mut latest_monitors = self.latest_monitors.lock().unwrap();
333+
if latest_monitors.insert(channel_id, state).is_some() {
317334
panic!("Already had monitor pre-watch_channel");
318335
}
319-
res
320336
}
337+
}
338+
impl lightning::chain::Watch<TestChannelSigner> for TestChainMonitor {
339+
fn watch_channel(
340+
&self, channel_id: lightning::ln::types::ChannelId,
341+
monitor: channelmonitor::ChannelMonitor<TestChannelSigner>,
342+
) -> Result<chain::ChannelMonitorUpdateStatus, ()> {
343+
let mut ser = VecWriter(Vec::new());
344+
lightning::util::ser::Writeable::write(&(BlockHash::all_zeros(), monitor.clone()), &mut ser,).unwrap();
345+
let monitor_id = monitor.get_latest_update_id();
346+
let res = self.chain_monitor.watch_channel(channel_id, monitor);
347+
let state = match res {
348+
Ok(chain::ChannelMonitorUpdateStatus::Completed) => LatestMonitorState {
349+
persisted_monitor_id: monitor_id,
350+
persisted_monitor: ser.0,
351+
pending_monitors: Vec::new(),
352+
},
353+
Ok(chain::ChannelMonitorUpdateStatus::InProgress) => LatestMonitorState {
354+
persisted_monitor_id: monitor_id,
355+
persisted_monitor: ser.0.clone(),
356+
pending_monitors: vec![(monitor_id, ser.0)],
357+
},
358+
Ok(chain::ChannelMonitorUpdateStatus::UnrecoverableError) => panic!(),
359+
Err(()) => panic!(),
360+
};
361+
if self.latest_monitors.lock().unwrap().insert(channel_id, state).is_some() {
362+
panic!("Already had monitor pre-watch_channel");
363+
}
364+
res
365+
}
321366

322367
fn update_channel(
323368
&self, channel_id: ChannelId, update: &channelmonitor::ChannelMonitorUpdate,
@@ -330,13 +375,9 @@ impl chain::Watch<TestChannelSigner> for TestChainMonitor {
330375
.as_ref()
331376
.map(|(_, data)| data)
332377
.unwrap_or(&map_entry.persisted_monitor);
333-
let deserialized_monitor =
334-
<(BlockHash, channelmonitor::ChannelMonitor<TestChannelSigner>)>::read(
335-
&mut &latest_monitor_data[..],
336-
(&*self.keys, &*self.keys),
337-
)
338-
.unwrap()
339-
.1;
378+
let deserialized_monitor: (BlockHash, channelmonitor::ChannelMonitor<TestChannelSigner>) =
379+
ReadableArgs::read(&mut &latest_monitor_data[..], (&*self.keys, &*self.keys)).unwrap();
380+
let deserialized_monitor = deserialized_monitor.1;
340381
deserialized_monitor
341382
.update_monitor(
342383
update,
@@ -346,7 +387,9 @@ impl chain::Watch<TestChannelSigner> for TestChainMonitor {
346387
)
347388
.unwrap();
348389
let mut ser = VecWriter(Vec::new());
349-
deserialized_monitor.write(&mut ser).unwrap();
390+
lightning::util::ser::Writeable::write(
391+
&(BlockHash::all_zeros(), deserialized_monitor), &mut ser,
392+
).unwrap();
350393
let res = self.chain_monitor.update_channel(channel_id, update);
351394
match res {
352395
chain::ChannelMonitorUpdateStatus::Completed => {
@@ -368,6 +411,40 @@ impl chain::Watch<TestChannelSigner> for TestChainMonitor {
368411
}
369412
}
370413

414+
impl lightning_0_2::chain::Watch<lightning_0_2::util::test_channel_signer::TestChannelSigner> for TestChainMonitor {
415+
fn watch_channel(
416+
&self,
417+
channel_id: lightning_0_2::ln::types::ChannelId,
418+
monitor: lightning_0_2::chain::channelmonitor::ChannelMonitor<lightning_0_2::util::test_channel_signer::TestChannelSigner>
419+
) -> Result<lightning_0_2::chain::ChannelMonitorUpdateStatus, ()> {
420+
let monitor_id = monitor.get_latest_update_id();
421+
let mut ser = Vec::new();
422+
lightning_0_2::util::ser::Writeable::write(
423+
&(BlockHash::all_zeros(), monitor.clone()),
424+
&mut ser,
425+
).unwrap();
426+
self.do_watch_channel_bytes(channel_id.0, monitor_id, ser);
427+
Ok(lightning_0_2::chain::ChannelMonitorUpdateStatus::Completed)
428+
}
429+
fn update_channel(
430+
&self, _channel_id: lightning_0_2::ln::types::ChannelId,
431+
_update: &lightning_0_2::chain::channelmonitor::ChannelMonitorUpdate,
432+
) -> lightning_0_2::chain::ChannelMonitorUpdateStatus {
433+
lightning_0_2::chain::ChannelMonitorUpdateStatus::Completed
434+
}
435+
436+
fn release_pending_monitor_events(
437+
&self,
438+
) -> Vec<(
439+
lightning_0_2::chain::transaction::OutPoint,
440+
lightning_0_2::ln::types::ChannelId,
441+
Vec<lightning_0_2::chain::channelmonitor::MonitorEvent>,
442+
PublicKey,
443+
)> {
444+
Vec::new()
445+
}
446+
}
447+
371448
struct KeyProvider {
372449
node_secret: SecretKey,
373450
rand_bytes_id: atomic::AtomicU32,
@@ -385,6 +462,33 @@ impl EntropySource for KeyProvider {
385462
}
386463
}
387464

465+
impl lightning_0_2::sign::EntropySource for KeyProvider {
466+
fn get_secure_random_bytes(&self) -> [u8; 32] {
467+
lightning::sign::EntropySource::get_secure_random_bytes(self)
468+
}
469+
}
470+
471+
impl lightning_0_2::sign::SignerProvider for KeyProvider {
472+
type EcdsaSigner = lightning_0_2::util::test_channel_signer::TestChannelSigner;
473+
474+
fn generate_channel_keys_id(&self, _inbound: bool, _user_channel_id: u128) -> [u8; 32] {
475+
let id = self.rand_bytes_id.fetch_add(1, atomic::Ordering::Relaxed) as u8;
476+
[id; 32]
477+
}
478+
479+
fn derive_channel_signer(&self, _channel_keys_id: [u8; 32]) -> Self::EcdsaSigner {
480+
unreachable!()
481+
}
482+
483+
fn get_destination_script(&self, _channel_keys_id: [u8; 32]) -> Result<bitcoin::ScriptBuf, ()> {
484+
unreachable!()
485+
}
486+
487+
fn get_shutdown_scriptpubkey(&self) -> Result<lightning_0_2::ln::script::ShutdownScript, ()> {
488+
unreachable!()
489+
}
490+
}
491+
388492
impl NodeSigner for KeyProvider {
389493
fn get_node_id(&self, recipient: Recipient) -> Result<PublicKey, ()> {
390494
let node_secret = match recipient {
@@ -916,7 +1020,7 @@ pub fn do_test<Out: Output + MaybeSend + MaybeSync>(
9161020
logger.clone(),
9171021
$fee_estimator.clone(),
9181022
Arc::new(TestPersister {
919-
update_ret: Mutex::new(mon_style[$node_id as usize].borrow().clone()),
1023+
update_ret: Mutex::new(ChannelMonitorUpdateStatus::Completed),
9201024
}),
9211025
Arc::clone(&keys_manager),
9221026
));
@@ -999,12 +1103,47 @@ pub fn do_test<Out: Output + MaybeSend + MaybeSync>(
9991103
};
10001104
// Use a different value of `use_old_mons` if we have another monitor (only for node B)
10011105
// by shifting `use_old_mons` one in base-3.
1106+
let cross_version_round_trip = use_old_mons % 3 == 2;
10021107
use_old_mons /= 3;
1003-
let mon = <(BlockHash, ChannelMonitor<TestChannelSigner>)>::read(
1108+
let mut serialized_mon = serialized_mon;
1109+
if cross_version_round_trip {
1110+
let old_mon_res: Result<
1111+
(
1112+
BlockHash,
1113+
lightning_0_2::chain::channelmonitor::ChannelMonitor<
1114+
lightning_0_2::util::test_channel_signer::TestChannelSigner
1115+
>
1116+
),
1117+
_
1118+
> = lightning_0_2::util::ser::ReadableArgs::read(
10041119
&mut &serialized_mon[..],
10051120
(&**keys, &**keys),
1006-
)
1007-
.expect("Failed to read monitor");
1121+
);
1122+
1123+
if let Ok((block_hash, old_monitor)) = old_mon_res {
1124+
let mut out = Vec::new();
1125+
1126+
if lightning_0_2::util::ser::Writeable::write(
1127+
&(block_hash, old_monitor), &mut out
1128+
).is_ok() {
1129+
1130+
let check_res: Result<(BlockHash, ChannelMonitor<TestChannelSigner>), _> =
1131+
lightning::util::ser::ReadableArgs::read(
1132+
&mut &out[..], (&**keys, &**keys)
1133+
);
1134+
1135+
if check_res.is_ok() {
1136+
serialized_mon = out;
1137+
}
1138+
}
1139+
}
1140+
}
1141+
1142+
let mon: (BlockHash, ChannelMonitor<TestChannelSigner>) =
1143+
lightning::util::ser::ReadableArgs::read(
1144+
&mut &serialized_mon[..],
1145+
(&**keys, &**keys),
1146+
).expect("Failed to read monitor");
10081147
monitors.insert(channel_id, mon.1);
10091148
// Update the latest `ChannelMonitor` state to match what we just told LDK.
10101149
prev_state.persisted_monitor = serialized_mon;
@@ -1034,8 +1173,8 @@ pub fn do_test<Out: Output + MaybeSend + MaybeSync>(
10341173
channel_monitors: monitor_refs,
10351174
};
10361175

1037-
let manager =
1038-
<(BlockHash, ChanMan)>::read(&mut &ser[..], read_args).expect("Failed to read manager");
1176+
let manager: (BlockHash, ChanMan) =
1177+
lightning::util::ser::ReadableArgs::read(&mut &ser[..], read_args).expect("Failed to read manager");
10391178
let res = (manager.1, chain_monitor.clone());
10401179
for (channel_id, mon) in monitors.drain() {
10411180
assert_eq!(
@@ -1341,6 +1480,11 @@ pub fn do_test<Out: Output + MaybeSend + MaybeSync>(
13411480
let chan_a_id = chan_ab_ids[0];
13421481
let chan_b_id = chan_bc_ids[0];
13431482

1483+
1484+
*monitor_a.persister.update_ret.lock().unwrap() = *mon_style[0].borrow();
1485+
*monitor_b.persister.update_ret.lock().unwrap() = *mon_style[1].borrow();
1486+
*monitor_c.persister.update_ret.lock().unwrap() = *mon_style[2].borrow();
1487+
13441488
let mut p_ctr: u64 = 0;
13451489

13461490
let mut peers_ab_disconnected = false;
@@ -2657,7 +2801,7 @@ pub fn do_test<Out: Output + MaybeSend + MaybeSync>(
26572801
() => { {
26582802
let mut last_pass_no_updates = false;
26592803
for i in 0..std::usize::MAX {
2660-
if i == 100 {
2804+
if i == 10000 {
26612805
panic!("It may take may iterations to settle the state, but it should not take forever");
26622806
}
26632807
// Next, make sure no monitor updates are pending
@@ -2718,6 +2862,16 @@ pub fn do_test<Out: Output + MaybeSend + MaybeSync>(
27182862
for node in &nodes {
27192863
node.timer_tick_occurred();
27202864
}
2865+
2866+
for id in &chan_ab_ids {
2867+
complete_all_monitor_updates(&monitor_a, id);
2868+
complete_all_monitor_updates(&monitor_b, id);
2869+
}
2870+
for id in &chan_bc_ids {
2871+
complete_all_monitor_updates(&monitor_b, id);
2872+
complete_all_monitor_updates(&monitor_c, id);
2873+
}
2874+
27212875
process_all_events!();
27222876

27232877
// Verify no payments are stuck - all should have resolved

0 commit comments

Comments
 (0)