Skip to content

Commit b8a18c1

Browse files
committed
[fuzz] Test chanmon_consistency payment-send errors are sane
Instead of simply always considering a payment-send failure as acceptable (and aborting fuzzing), we check that a payment send failure is from a list of errors that we know we can hit, mostly around maxing out our channel balance. Critically, we keep going after hitting an error, as there's no reason channels should get out of sync even if a send fails.
1 parent 4e82003 commit b8a18c1

File tree

1 file changed

+48
-10
lines changed

1 file changed

+48
-10
lines changed

fuzz/src/chanmon_consistency.rs

Lines changed: 48 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,11 @@ use lightning::chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdateErr,
3535
use lightning::chain::transaction::OutPoint;
3636
use lightning::chain::chaininterface::{BroadcasterInterface, ConfirmationTarget, FeeEstimator};
3737
use lightning::chain::keysinterface::{KeysInterface, InMemoryChannelKeys};
38-
use lightning::ln::channelmanager::{ChannelManager, PaymentHash, PaymentPreimage, PaymentSecret, ChannelManagerReadArgs};
38+
use lightning::ln::channelmanager::{ChannelManager, PaymentHash, PaymentPreimage, PaymentSecret, PaymentSendFailure, ChannelManagerReadArgs};
3939
use lightning::ln::features::{ChannelFeatures, InitFeatures, NodeFeatures};
4040
use lightning::ln::msgs::{CommitmentUpdate, ChannelMessageHandler, ErrorAction, UpdateAddHTLC, Init};
4141
use lightning::util::enforcing_trait_impls::EnforcingChannelKeys;
42+
use lightning::util::errors::APIError;
4243
use lightning::util::events;
4344
use lightning::util::logger::Logger;
4445
use lightning::util::config::UserConfig;
@@ -403,11 +404,51 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
403404
}
404405

405406
loop {
407+
macro_rules! check_send_res { ($send_err: expr) => { {
408+
macro_rules! check_res { ($api_err: expr) => { {
409+
match $api_err {
410+
APIError::APIMisuseError { .. } => panic!("We can't misuse the API"),
411+
APIError::FeeRateTooHigh { .. } => panic!("We can't send too much fee?"),
412+
APIError::RouteError { .. } => panic!("Our routes should work"),
413+
APIError::ChannelUnavailable { err } => {
414+
// Test the error against a list of errors we can hit, and reject
415+
// all others. If you hit this panic, the list of acceptable errors
416+
// is probably just stale and you should add new messages here.
417+
match err.as_str() {
418+
"Peer for first hop currently disconnected/pending monitor update!" => test_return!(),
419+
_ if err.starts_with("Cannot push more than their max accepted HTLCs ") => test_return!(),
420+
_ if err.starts_with("Cannot send value that would put us over the max HTLC value in flight our peer will accept ") => test_return!(),
421+
_ if err.starts_with("Cannot send value that would put our balance under counterparty-announced channel reserve value") => test_return!(),
422+
_ if err.starts_with("Cannot send value that would overdraw remaining funds.") => test_return!(),
423+
_ if err.starts_with("Cannot send value that would not leave enough to pay for fees.") => test_return!(),
424+
_ => panic!(err),
425+
}
426+
},
427+
APIError::MonitorUpdateFailed => {
428+
// We can (obviously) temp-fail a monitor update
429+
test_return!()
430+
},
431+
}
432+
} } }
433+
match $send_err {
434+
PaymentSendFailure::ParameterError(api_err) => check_res!(api_err),
435+
PaymentSendFailure::PathParameterError(per_path_results) => {
436+
for res in per_path_results { if let Err(api_err) = res { check_res!(api_err); } }
437+
},
438+
PaymentSendFailure::AllFailedRetrySafe(per_path_results) => {
439+
for api_err in per_path_results { check_res!(api_err); }
440+
},
441+
PaymentSendFailure::PartialFailure(per_path_results) => {
442+
for res in per_path_results { if let Err(api_err) = res { check_res!(api_err); } }
443+
},
444+
}
445+
} } }
446+
406447
macro_rules! send_payment {
407448
($source: expr, $dest: expr, $amt: expr) => { {
408449
let payment_hash = Sha256::hash(&[payment_id; 1]);
409450
payment_id = payment_id.wrapping_add(1);
410-
if let Err(_) = $source.send_payment(&Route {
451+
if let Err(err) = $source.send_payment(&Route {
411452
paths: vec![vec![RouteHop {
412453
pubkey: $dest.0.get_our_node_id(),
413454
node_features: NodeFeatures::empty(),
@@ -417,14 +458,13 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
417458
cltv_expiry_delta: 200,
418459
}]],
419460
}, PaymentHash(payment_hash.into_inner()), &None) {
420-
// Probably ran out of funds
421-
test_return!();
461+
check_send_res!(err);
422462
}
423463
} };
424464
($source: expr, $middle: expr, $dest: expr, $amt: expr) => { {
425465
let payment_hash = Sha256::hash(&[payment_id; 1]);
426466
payment_id = payment_id.wrapping_add(1);
427-
if let Err(_) = $source.send_payment(&Route {
467+
if let Err(err) = $source.send_payment(&Route {
428468
paths: vec![vec![RouteHop {
429469
pubkey: $middle.0.get_our_node_id(),
430470
node_features: NodeFeatures::empty(),
@@ -441,8 +481,7 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
441481
cltv_expiry_delta: 200,
442482
}]],
443483
}, PaymentHash(payment_hash.into_inner()), &None) {
444-
// Probably ran out of funds
445-
test_return!();
484+
check_send_res!(err);
446485
}
447486
} }
448487
}
@@ -452,7 +491,7 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
452491
payment_id = payment_id.wrapping_add(1);
453492
let payment_secret = Sha256::hash(&[payment_id; 1]);
454493
payment_id = payment_id.wrapping_add(1);
455-
if let Err(_) = $source.send_payment(&Route {
494+
if let Err(err) = $source.send_payment(&Route {
456495
paths: vec![vec![RouteHop {
457496
pubkey: $middle.0.get_our_node_id(),
458497
node_features: NodeFeatures::empty(),
@@ -483,8 +522,7 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
483522
cltv_expiry_delta: 200,
484523
}]],
485524
}, PaymentHash(payment_hash.into_inner()), &Some(PaymentSecret(payment_secret.into_inner()))) {
486-
// Probably ran out of funds
487-
test_return!();
525+
check_send_res!(err);
488526
}
489527
} }
490528
}

0 commit comments

Comments
 (0)