Skip to content

Commit dfe2a56

Browse files
committed
Improve error message.
... for ChannelError and APIMisuseError Before this commit, When rl returns error, we don't know The actual parameter which caused the error. By returning parameterised `String` instead of predefined `&'static str`, We can give a caller improved error message.
1 parent cd13364 commit dfe2a56

File tree

10 files changed

+279
-267
lines changed

10 files changed

+279
-267
lines changed

lightning/src/ln/channel.rs

Lines changed: 183 additions & 174 deletions
Large diffs are not rendered by default.

lightning/src/ln/channelmanager.rs

Lines changed: 59 additions & 58 deletions
Large diffs are not rendered by default.

lightning/src/ln/functional_test_utils.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -278,14 +278,14 @@ macro_rules! unwrap_send_err {
278278
match &$res {
279279
&Err(PaymentSendFailure::AllFailedRetrySafe(ref fails)) if $all_failed => {
280280
assert_eq!(fails.len(), 1);
281-
match fails[0] {
281+
match &fails[0] {
282282
$type => { $check },
283283
_ => panic!(),
284284
}
285285
},
286286
&Err(PaymentSendFailure::PartialFailure(ref fails)) if !$all_failed => {
287287
assert_eq!(fails.len(), 1);
288-
match fails[0] {
288+
match &fails[0] {
289289
Err($type) => { $check },
290290
_ => panic!(),
291291
}
@@ -973,7 +973,7 @@ pub fn route_over_limit<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_rou
973973

974974
let (_, our_payment_hash) = get_payment_preimage_hash!(origin_node);
975975
unwrap_send_err!(origin_node.node.send_payment(&route, our_payment_hash, &None), true, APIError::ChannelUnavailable { err },
976-
assert_eq!(err, "Cannot send value that would put us over the max HTLC value in flight our peer will accept"));
976+
assert!(err.contains("Cannot send value that would put us over the max HTLC value in flight our peer will accept")));
977977
}
978978

979979
pub fn send_payment<'a, 'b, 'c>(origin: &Node<'a, 'b, 'c>, expected_route: &[&Node<'a, 'b, 'c>], recv_value: u64, expected_value: u64) {

lightning/src/ln/functional_tests.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1322,7 +1322,7 @@ fn holding_cell_htlc_counting() {
13221322
let net_graph_msg_handler = &nodes[1].net_graph_msg_handler;
13231323
let route = get_route(&nodes[1].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[2].node.get_our_node_id(), None, &Vec::new(), 100000, TEST_FINAL_CLTV, &logger).unwrap();
13241324
unwrap_send_err!(nodes[1].node.send_payment(&route, payment_hash_1, &None), true, APIError::ChannelUnavailable { err },
1325-
assert_eq!(err, "Cannot push more than their max accepted HTLCs"));
1325+
assert!(err.contains("Cannot push more than their max accepted HTLCs")));
13261326
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
13271327
nodes[1].logger.assert_log("lightning::ln::channelmanager".to_string(), "Cannot push more than their max accepted HTLCs".to_string(), 1);
13281328
}
@@ -1540,7 +1540,7 @@ fn test_basic_channel_reserve() {
15401540
let err = nodes[0].node.send_payment(&route, our_payment_hash, &None).err().unwrap();
15411541
match err {
15421542
PaymentSendFailure::AllFailedRetrySafe(ref fails) => {
1543-
match fails[0] {
1543+
match &fails[0] {
15441544
APIError::ChannelUnavailable{err} =>
15451545
assert_eq!(err, "Cannot send value that would put us under local channel reserve value"),
15461546
_ => panic!("Unexpected error variant"),
@@ -1930,7 +1930,7 @@ fn test_channel_reserve_holding_cell_htlcs() {
19301930
let (route, our_payment_hash, _) = get_route_and_payment_hash!(recv_value_0 + 1);
19311931
assert!(route.paths[0].iter().rev().skip(1).all(|h| h.fee_msat == feemsat));
19321932
unwrap_send_err!(nodes[0].node.send_payment(&route, our_payment_hash, &None), true, APIError::ChannelUnavailable { err },
1933-
assert_eq!(err, "Cannot send value that would put us over the max HTLC value in flight our peer will accept"));
1933+
assert_eq!(err, "Cannot send value that would put us over the max HTLC value in flight our peer will accept (10000000)"));
19341934
assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
19351935
nodes[0].logger.assert_log("lightning::ln::channelmanager".to_string(), "Cannot send value that would put us over the max HTLC value in flight our peer will accept".to_string(), 1);
19361936
}
@@ -2105,7 +2105,7 @@ fn test_channel_reserve_holding_cell_htlcs() {
21052105
let err = nodes[0].node.send_payment(&route, our_payment_hash, &None).err().unwrap();
21062106
match err {
21072107
PaymentSendFailure::AllFailedRetrySafe(ref fails) => {
2108-
match fails[0] {
2108+
match &fails[0] {
21092109
APIError::ChannelUnavailable{err} =>
21102110
assert_eq!(err, "Cannot send value that would put us under local channel reserve value"),
21112111
_ => panic!("Unexpected error variant"),
@@ -6470,7 +6470,7 @@ fn test_update_add_htlc_bolt2_sender_cltv_expiry_too_high() {
64706470
let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
64716471
let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), None, &[], 100000000, 500000001, &logger).unwrap();
64726472
unwrap_send_err!(nodes[0].node.send_payment(&route, our_payment_hash, &None), true, APIError::RouteError { err },
6473-
assert_eq!(err, "Channel CLTV overflowed?!"));
6473+
assert_eq!(err, &"Channel CLTV overflowed?"));
64746474
}
64756475

64766476
#[test]

lightning/src/ln/msgs.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -461,7 +461,7 @@ pub enum ErrorAction {
461461
/// An Err type for failure to process messages.
462462
pub struct LightningError {
463463
/// A human-readable message describing the error
464-
pub err: &'static str,
464+
pub err: String,
465465
/// The action which should be taken against the offending peer.
466466
pub action: ErrorAction,
467467
}
@@ -701,7 +701,7 @@ impl fmt::Display for DecodeError {
701701

702702
impl fmt::Debug for LightningError {
703703
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
704-
f.write_str(self.err)
704+
f.write_str(self.err.as_str())
705705
}
706706
}
707707

lightning/src/ln/peer_channel_encryptor.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use bitcoin::secp256k1;
1111

1212
use util::chacha20poly1305rfc::ChaCha20Poly1305RFC;
1313
use util::byte_utils;
14+
use bitcoin::hashes::hex::ToHex;
1415

1516
// Sha256("Noise_XK_secp256k1_ChaChaPoly_SHA256")
1617
const NOISE_CK: [u8; 32] = [0x26, 0x40, 0xf5, 0x2e, 0xeb, 0xcd, 0x9e, 0x88, 0x29, 0x58, 0x95, 0x1c, 0x79, 0x42, 0x50, 0xee, 0xdb, 0x28, 0x00, 0x2c, 0x05, 0xd7, 0xdc, 0x2e, 0xa0, 0xf1, 0x95, 0x40, 0x60, 0x42, 0xca, 0xf1];
@@ -139,7 +140,7 @@ impl PeerChannelEncryptor {
139140

140141
let mut chacha = ChaCha20Poly1305RFC::new(key, &nonce, h);
141142
if !chacha.decrypt(&cyphertext[0..cyphertext.len() - 16], res, &cyphertext[cyphertext.len() - 16..]) {
142-
return Err(LightningError{err: "Bad MAC", action: msgs::ErrorAction::DisconnectPeer{ msg: None }});
143+
return Err(LightningError{err: "Bad MAC".to_owned(), action: msgs::ErrorAction::DisconnectPeer{ msg: None }});
143144
}
144145
Ok(())
145146
}
@@ -193,11 +194,11 @@ impl PeerChannelEncryptor {
193194
assert_eq!(act.len(), 50);
194195

195196
if act[0] != 0 {
196-
return Err(LightningError{err: "Unknown handshake version number", action: msgs::ErrorAction::DisconnectPeer{ msg: None }});
197+
return Err(LightningError{err: format!("Unknown handshake version number {}", act[0]), action: msgs::ErrorAction::DisconnectPeer{ msg: None }});
197198
}
198199

199200
let their_pub = match PublicKey::from_slice(&act[1..34]) {
200-
Err(_) => return Err(LightningError{err: "Invalid public key", action: msgs::ErrorAction::DisconnectPeer{ msg: None }}),
201+
Err(_) => return Err(LightningError{err: format!("Invalid public key {}", &act[1..34].to_hex()), action: msgs::ErrorAction::DisconnectPeer{ msg: None }}),
201202
Ok(key) => key,
202203
};
203204

@@ -330,14 +331,14 @@ impl PeerChannelEncryptor {
330331
panic!("Requested act at wrong step");
331332
}
332333
if act_three[0] != 0 {
333-
return Err(LightningError{err: "Unknown handshake version number", action: msgs::ErrorAction::DisconnectPeer{ msg: None }});
334+
return Err(LightningError{err: format!("Unknown handshake version number {}", act_three[0]), action: msgs::ErrorAction::DisconnectPeer{ msg: None }});
334335
}
335336

336337
let mut their_node_id = [0; 33];
337338
PeerChannelEncryptor::decrypt_with_ad(&mut their_node_id, 1, &temp_k2.unwrap(), &bidirectional_state.h, &act_three[1..50])?;
338339
self.their_node_id = Some(match PublicKey::from_slice(&their_node_id) {
339340
Ok(key) => key,
340-
Err(_) => return Err(LightningError{err: "Bad node_id from peer", action: msgs::ErrorAction::DisconnectPeer{ msg: None }}),
341+
Err(_) => return Err(LightningError{err: format!("Bad node_id from peer, {}", &their_node_id.to_hex()), action: msgs::ErrorAction::DisconnectPeer{ msg: None }}),
341342
});
342343

343344
let mut sha = Sha256::engine();

lightning/src/routing/network_graph.rs

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use std::sync::atomic::{AtomicUsize, Ordering};
2222
use std::collections::BTreeMap;
2323
use std::collections::btree_map::Entry as BtreeEntry;
2424
use std::ops::Deref;
25+
use bitcoin::hashes::hex::ToHex;
2526

2627
/// Receives and validates network updates from peers,
2728
/// stores authentic and relevant data as a network graph.
@@ -74,7 +75,7 @@ macro_rules! secp_verify_sig {
7475
( $secp_ctx: expr, $msg: expr, $sig: expr, $pubkey: expr ) => {
7576
match $secp_ctx.verify($msg, $sig, $pubkey) {
7677
Ok(_) => {},
77-
Err(_) => return Err(LightningError{err: "Invalid signature from remote node", action: ErrorAction::IgnoreError}),
78+
Err(_) => return Err(LightningError{err: "Invalid signature from remote node".to_owned(), action: ErrorAction::IgnoreError}),
7879
}
7980
};
8081
}
@@ -86,7 +87,7 @@ impl<C: Deref + Sync + Send, L: Deref + Sync + Send> RoutingMessageHandler for N
8687

8788
fn handle_channel_announcement(&self, msg: &msgs::ChannelAnnouncement) -> Result<bool, LightningError> {
8889
if msg.contents.node_id_1 == msg.contents.node_id_2 || msg.contents.bitcoin_key_1 == msg.contents.bitcoin_key_2 {
89-
return Err(LightningError{err: "Channel announcement node had a channel with itself", action: ErrorAction::IgnoreError});
90+
return Err(LightningError{err: "Channel announcement node had a channel with itself".to_owned(), action: ErrorAction::IgnoreError});
9091
}
9192

9293
let checked_utxo = match self.chain_monitor.get_chain_utxo(msg.contents.chain_hash, msg.contents.short_channel_id) {
@@ -97,7 +98,7 @@ impl<C: Deref + Sync + Send, L: Deref + Sync + Send> RoutingMessageHandler for N
9798
.push_opcode(opcodes::all::OP_PUSHNUM_2)
9899
.push_opcode(opcodes::all::OP_CHECKMULTISIG).into_script().to_v0_p2wsh();
99100
if script_pubkey != expected_script {
100-
return Err(LightningError{err: "Channel announcement keys didn't match on-chain script", action: ErrorAction::IgnoreError});
101+
return Err(LightningError{err: format!("Channel announcement key({}) didn't match on-chain script ({})", script_pubkey.to_hex(), expected_script.to_hex()), action: ErrorAction::IgnoreError});
101102
}
102103
//TODO: Check if value is worth storing, use it to inform routing, and compare it
103104
//to the new HTLC max field in channel_update
@@ -108,10 +109,10 @@ impl<C: Deref + Sync + Send, L: Deref + Sync + Send> RoutingMessageHandler for N
108109
false
109110
},
110111
Err(ChainError::NotWatched) => {
111-
return Err(LightningError{err: "Channel announced on an unknown chain", action: ErrorAction::IgnoreError});
112+
return Err(LightningError{err: format!("Channel announced on an unknown chain ({})", msg.contents.chain_hash.encode().to_hex()), action: ErrorAction::IgnoreError});
112113
},
113114
Err(ChainError::UnknownTx) => {
114-
return Err(LightningError{err: "Channel announced without corresponding UTXO entry", action: ErrorAction::IgnoreError});
115+
return Err(LightningError{err: "Channel announced without corresponding UTXO entry".to_owned(), action: ErrorAction::IgnoreError});
115116
},
116117
};
117118
let result = self.network_graph.write().unwrap().update_channel_from_announcement(msg, checked_utxo, Some(&self.secp_ctx));
@@ -522,11 +523,11 @@ impl NetworkGraph {
522523
}
523524

524525
match self.nodes.get_mut(&msg.contents.node_id) {
525-
None => Err(LightningError{err: "No existing channels for node_announcement", action: ErrorAction::IgnoreError}),
526+
None => Err(LightningError{err: "No existing channels for node_announcement".to_owned(), action: ErrorAction::IgnoreError}),
526527
Some(node) => {
527528
if let Some(node_info) = node.announcement_info.as_ref() {
528529
if node_info.last_update >= msg.contents.timestamp {
529-
return Err(LightningError{err: "Update older than last processed update", action: ErrorAction::IgnoreError});
530+
return Err(LightningError{err: "Update older than last processed update".to_owned(), action: ErrorAction::IgnoreError});
530531
}
531532
}
532533

@@ -588,7 +589,7 @@ impl NetworkGraph {
588589
Self::remove_channel_in_nodes(&mut self.nodes, &entry.get(), msg.contents.short_channel_id);
589590
*entry.get_mut() = chan_info;
590591
} else {
591-
return Err(LightningError{err: "Already have knowledge of channel", action: ErrorAction::IgnoreError})
592+
return Err(LightningError{err: "Already have knowledge of channel".to_owned(), action: ErrorAction::IgnoreError})
592593
}
593594
},
594595
BtreeEntry::Vacant(entry) => {
@@ -656,13 +657,13 @@ impl NetworkGraph {
656657
let chan_was_enabled;
657658

658659
match self.channels.get_mut(&msg.contents.short_channel_id) {
659-
None => return Err(LightningError{err: "Couldn't find channel for update", action: ErrorAction::IgnoreError}),
660+
None => return Err(LightningError{err: "Couldn't find channel for update".to_owned(), action: ErrorAction::IgnoreError}),
660661
Some(channel) => {
661662
macro_rules! maybe_update_channel_info {
662663
( $target: expr, $src_node: expr) => {
663664
if let Some(existing_chan_info) = $target.as_ref() {
664665
if existing_chan_info.last_update >= msg.contents.timestamp {
665-
return Err(LightningError{err: "Update older than last processed update", action: ErrorAction::IgnoreError});
666+
return Err(LightningError{err: "Update older than last processed update".to_owned(), action: ErrorAction::IgnoreError});
666667
}
667668
chan_was_enabled = existing_chan_info.enabled;
668669
} else {

lightning/src/routing/router.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -165,11 +165,11 @@ pub fn get_route<L: Deref>(our_node_id: &PublicKey, network: &NetworkGraph, targ
165165
// TODO: Obviously *only* using total fee cost sucks. We should consider weighting by
166166
// uptime/success in using a node in the past.
167167
if *target == *our_node_id {
168-
return Err(LightningError{err: "Cannot generate a route to ourselves", action: ErrorAction::IgnoreError});
168+
return Err(LightningError{err: "Cannot generate a route to ourselves".to_owned(), action: ErrorAction::IgnoreError});
169169
}
170170

171171
if final_value_msat > 21_000_000 * 1_0000_0000 * 1000 {
172-
return Err(LightningError{err: "Cannot generate a route of more value than all existing satoshis", action: ErrorAction::IgnoreError});
172+
return Err(LightningError{err: "Cannot generate a route of more value than all existing satoshis".to_owned(), action: ErrorAction::IgnoreError});
173173
}
174174

175175
// We do a dest-to-source Dijkstra's sorting by each node's distance from the destination
@@ -209,7 +209,7 @@ pub fn get_route<L: Deref>(our_node_id: &PublicKey, network: &NetworkGraph, targ
209209
first_hop_targets.insert(chan.remote_network_id, (short_channel_id, chan.counterparty_features.clone()));
210210
}
211211
if first_hop_targets.is_empty() {
212-
return Err(LightningError{err: "Cannot route when there are no outbound routes away from us", action: ErrorAction::IgnoreError});
212+
return Err(LightningError{err: "Cannot route when there are no outbound routes away from us".to_owned(), action: ErrorAction::IgnoreError});
213213
}
214214
}
215215

@@ -374,7 +374,7 @@ pub fn get_route<L: Deref>(our_node_id: &PublicKey, network: &NetworkGraph, targ
374374

375375
let new_entry = match dist.remove(&res.last().unwrap().pubkey) {
376376
Some(hop) => hop.3,
377-
None => return Err(LightningError{err: "Failed to find a non-fee-overflowing path to the given destination", action: ErrorAction::IgnoreError}),
377+
None => return Err(LightningError{err: "Failed to find a non-fee-overflowing path to the given destination".to_owned(), action: ErrorAction::IgnoreError}),
378378
};
379379
res.last_mut().unwrap().fee_msat = new_entry.fee_msat;
380380
res.last_mut().unwrap().cltv_expiry_delta = new_entry.cltv_expiry_delta;
@@ -395,7 +395,7 @@ pub fn get_route<L: Deref>(our_node_id: &PublicKey, network: &NetworkGraph, targ
395395
}
396396
}
397397

398-
Err(LightningError{err: "Failed to find a path to the given destination", action: ErrorAction::IgnoreError})
398+
Err(LightningError{err: "Failed to find a path to the given destination".to_owned(), action: ErrorAction::IgnoreError})
399399
}
400400

401401
#[cfg(test)]

lightning/src/util/errors.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ pub enum APIError {
99
/// are documented, but generally indicates some precondition of a function was violated.
1010
APIMisuseError {
1111
/// A human-readable error message
12-
err: &'static str
12+
err: String
1313
},
1414
/// Due to a high feerate, we were unable to complete the request.
1515
/// For example, this may be returned if the feerate implies we cannot open a channel at the
@@ -31,7 +31,7 @@ pub enum APIError {
3131
/// peer, channel at capacity, channel shutting down, etc.
3232
ChannelUnavailable {
3333
/// A human-readable error message
34-
err: &'static str
34+
err: String
3535
},
3636
/// An attempt to call add/update_monitor returned an Err (ie you did this!), causing the
3737
/// attempted action to fail.

lightning/src/util/test_utils.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -240,15 +240,15 @@ impl TestRoutingMessageHandler {
240240
}
241241
impl msgs::RoutingMessageHandler for TestRoutingMessageHandler {
242242
fn handle_node_announcement(&self, _msg: &msgs::NodeAnnouncement) -> Result<bool, msgs::LightningError> {
243-
Err(msgs::LightningError { err: "", action: msgs::ErrorAction::IgnoreError })
243+
Err(msgs::LightningError { err: "".to_owned(), action: msgs::ErrorAction::IgnoreError })
244244
}
245245
fn handle_channel_announcement(&self, _msg: &msgs::ChannelAnnouncement) -> Result<bool, msgs::LightningError> {
246246
self.chan_anns_recvd.fetch_add(1, Ordering::AcqRel);
247-
Err(msgs::LightningError { err: "", action: msgs::ErrorAction::IgnoreError })
247+
Err(msgs::LightningError { err: "".to_owned(), action: msgs::ErrorAction::IgnoreError })
248248
}
249249
fn handle_channel_update(&self, _msg: &msgs::ChannelUpdate) -> Result<bool, msgs::LightningError> {
250250
self.chan_upds_recvd.fetch_add(1, Ordering::AcqRel);
251-
Err(msgs::LightningError { err: "", action: msgs::ErrorAction::IgnoreError })
251+
Err(msgs::LightningError { err: "".to_owned(), action: msgs::ErrorAction::IgnoreError })
252252
}
253253
fn handle_htlc_fail_channel_update(&self, _update: &msgs::HTLCFailChannelUpdate) {}
254254
fn get_next_channel_announcements(&self, starting_point: u64, batch_amount: u8) -> Vec<(msgs::ChannelAnnouncement, Option<msgs::ChannelUpdate>, Option<msgs::ChannelUpdate>)> {

0 commit comments

Comments
 (0)