1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
use crate::ln::script::ShutdownScript;
use alloc::string::String;
use core::fmt;
#[derive(Clone, PartialEq, Eq)]
pub enum APIError {
APIMisuseError {
err: String
},
FeeRateTooHigh {
err: String,
feerate: u32
},
InvalidRoute {
err: String
},
ChannelUnavailable {
err: String
},
MonitorUpdateInProgress,
IncompatibleShutdownScript {
script: ShutdownScript,
},
}
impl fmt::Debug for APIError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
APIError::APIMisuseError {ref err} => write!(f, "Misuse error: {}", err),
APIError::FeeRateTooHigh {ref err, ref feerate} => write!(f, "{} feerate: {}", err, feerate),
APIError::InvalidRoute {ref err} => write!(f, "Invalid route provided: {}", err),
APIError::ChannelUnavailable {ref err} => write!(f, "Channel unavailable: {}", err),
APIError::MonitorUpdateInProgress => f.write_str("Client indicated a channel monitor update is in progress but not yet complete"),
APIError::IncompatibleShutdownScript { ref script } => {
write!(f, "Provided a scriptpubkey format not accepted by peer: {}", script)
},
}
}
}
impl_writeable_tlv_based_enum_upgradable!(APIError,
(0, APIMisuseError) => { (0, err, required), },
(2, FeeRateTooHigh) => {
(0, err, required),
(2, feerate, required),
},
(4, InvalidRoute) => { (0, err, required), },
(6, ChannelUnavailable) => { (0, err, required), },
(8, MonitorUpdateInProgress) => {},
(10, IncompatibleShutdownScript) => { (0, script, required), },
);
#[inline]
pub(crate) fn get_onion_debug_field(error_code: u16) -> (&'static str, usize) {
match error_code & 0xff {
4|5|6 => ("sha256_of_onion", 32),
11|12 => ("htlc_msat", 8),
13|18 => ("cltv_expiry", 4),
19 => ("incoming_htlc_msat", 8),
20 => ("flags", 2),
_ => ("", 0),
}
}
#[inline]
pub(crate) fn get_onion_error_description(error_code: u16) -> (&'static str, &'static str) {
const BADONION: u16 = 0x8000;
const PERM: u16 = 0x4000;
const NODE: u16 = 0x2000;
const UPDATE: u16 = 0x1000;
match error_code {
_c if _c == PERM|1 => ("The realm byte was not understood by the processing node", "invalid_realm"),
_c if _c == NODE|2 => ("Node indicated temporary node failure", "temporary_node_failure"),
_c if _c == PERM|NODE|2 => ("Node indicated permanent node failure", "permanent_node_failure"),
_c if _c == PERM|NODE|3 => ("Node indicated the required node feature is missing in the onion", "required_node_feature_missing"),
_c if _c == BADONION|PERM|4 => ("Node indicated the version by is not understood", "invalid_onion_version"),
_c if _c == BADONION|PERM|5 => ("Node indicated the HMAC of the onion is incorrect", "invalid_onion_hmac"),
_c if _c == BADONION|PERM|6 => ("Node indicated the ephemeral public keys is not parseable", "invalid_onion_key"),
_c if _c == UPDATE|7 => ("Node indicated the outgoing channel is unable to handle the HTLC temporarily", "temporary_channel_failure"),
_c if _c == PERM|8 => ("Node indicated the outgoing channel is unable to handle the HTLC peramanently", "permanent_channel_failure"),
_c if _c == PERM|9 => ("Node indicated the required feature for the outgoing channel is not satisfied", "required_channel_feature_missing"),
_c if _c == PERM|10 => ("Node indicated the outbound channel is not found for the specified short_channel_id in the onion packet", "unknown_next_peer"),
_c if _c == UPDATE|11 => ("Node indicated the HTLC amount was below the required minmum for the outbound channel", "amount_below_minimum"),
_c if _c == UPDATE|12 => ("Node indicated the fee amount does not meet the required level", "fee_insufficient"),
_c if _c == UPDATE|13 => ("Node indicated the cltv_expiry does not comply with the cltv_expiry_delta required by the outgoing channel", "incorrect_cltv_expiry"),
_c if _c == UPDATE|14 => ("Node indicated the CLTV expiry too close to the current block height for safe handling", "expiry_too_soon"),
_c if _c == PERM|15 => ("The final node indicated the payment hash is unknown or amount is incorrect", "incorrect_or_unknown_payment_details"),
_c if _c == PERM|16 => ("The final node indicated the payment amount is incorrect", "incorrect_payment_amount"),
_c if _c == 17 => ("The final node indicated the CLTV expiry is too close to the current block height for safe handling", "final_expiry_too_soon"),
_c if _c == 18 => ("The final node indicated the CLTV expiry in the HTLC does not match the value in the onion", "final_incorrect_cltv_expiry"),
_c if _c == 19 => ("The final node indicated the amount in the HTLC does not match the value in the onion", "final_incorrect_htlc_amount"),
_c if _c == UPDATE|20 => ("Node indicated the outbound channel has been disabled", "channel_disabled"),
_c if _c == 21 => ("Node indicated the CLTV expiry in the HTLC is too far in the future", "expiry_too_far"),
_c if _c == PERM|22 => ("Node indicated that the decrypted onion per-hop payload was not understood by it or is incomplete", "invalid_onion_payload"),
_c if _c == 23 => ("The final node indicated the complete amount of the multi-part payment was not received within a reasonable time", "mpp_timeout"),
_ => ("Unknown", ""),
}
}