1use crate::io;
13use crate::ln::msgs::DecodeError;
14use crate::offers::merkle::SignError;
15use crate::offers::parse::Bolt12SemanticError;
16use crate::util::ser::{HighZeroBytesDroppedBigSize, Readable, WithoutLength, Writeable, Writer};
17use crate::util::string::UntrustedString;
18
19#[allow(unused_imports)]
20use crate::prelude::*;
21
22#[derive(Clone, Debug)]
27#[cfg_attr(test, derive(PartialEq))]
28pub struct InvoiceError {
29 pub erroneous_field: Option<ErroneousField>,
34
35 pub message: UntrustedString,
37}
38
39#[derive(Clone, Debug)]
44#[cfg_attr(test, derive(PartialEq))]
45pub struct ErroneousField {
46 pub tlv_fieldnum: u64,
48
49 pub suggested_value: Option<Vec<u8>>,
51}
52
53impl InvoiceError {
54 pub fn from_string(s: String) -> Self {
56 Self {
57 erroneous_field: None,
58 message: UntrustedString(s),
59 }
60 }
61}
62
63impl core::fmt::Display for InvoiceError {
64 fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
65 self.message.fmt(f)
66 }
67}
68
69impl Writeable for InvoiceError {
70 fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
71 let tlv_fieldnum = self.erroneous_field.as_ref().map(|f| f.tlv_fieldnum);
72 let suggested_value =
73 self.erroneous_field.as_ref().and_then(|f| f.suggested_value.as_ref());
74 write_tlv_fields!(writer, {
75 (1, tlv_fieldnum, (option, encoding: (u64, HighZeroBytesDroppedBigSize))),
76 (3, suggested_value, (option, encoding: (Vec<u8>, WithoutLength))),
77 (5, WithoutLength(&self.message), required),
78 });
79 Ok(())
80 }
81}
82
83impl Readable for InvoiceError {
84 fn read<R: io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
85 _init_and_read_len_prefixed_tlv_fields!(reader, {
86 (1, erroneous_field, (option, encoding: (u64, HighZeroBytesDroppedBigSize))),
87 (3, suggested_value, (option, encoding: (Vec<u8>, WithoutLength))),
88 (5, error, (option, encoding: (UntrustedString, WithoutLength))),
89 });
90
91 let erroneous_field = match (erroneous_field, suggested_value) {
92 (None, None) => None,
93 (None, Some(_)) => return Err(DecodeError::InvalidValue),
94 (Some(tlv_fieldnum), suggested_value) => {
95 Some(ErroneousField { tlv_fieldnum, suggested_value })
96 },
97 };
98
99 let message = match error {
100 None => return Err(DecodeError::InvalidValue),
101 Some(error) => error,
102 };
103
104 Ok(InvoiceError { erroneous_field, message })
105 }
106}
107
108impl From<Bolt12SemanticError> for InvoiceError {
109 fn from(error: Bolt12SemanticError) -> Self {
110 InvoiceError {
111 erroneous_field: None,
112 message: UntrustedString(format!("{:?}", error)),
113 }
114 }
115}
116
117impl From<SignError> for InvoiceError {
118 fn from(error: SignError) -> Self {
119 let message = match error {
120 SignError::Signing => "Failed signing invoice",
121 SignError::Verification(_) => "Failed invoice signature verification",
122 };
123 InvoiceError {
124 erroneous_field: None,
125 message: UntrustedString(message.to_string()),
126 }
127 }
128}
129
130#[cfg(test)]
131mod tests {
132 use super::{ErroneousField, InvoiceError};
133
134 use crate::ln::msgs::DecodeError;
135 use crate::util::ser::{HighZeroBytesDroppedBigSize, Readable, VecWriter, WithoutLength, Writeable};
136 use crate::util::string::UntrustedString;
137
138 #[test]
139 fn parses_invoice_error_without_erroneous_field() {
140 let mut writer = VecWriter(Vec::new());
141 let invoice_error = InvoiceError {
142 erroneous_field: None,
143 message: UntrustedString("Invalid value".to_string()),
144 };
145 invoice_error.write(&mut writer).unwrap();
146
147 let buffer = writer.0;
148 match InvoiceError::read(&mut &buffer[..]) {
149 Ok(invoice_error) => {
150 assert_eq!(invoice_error.message, UntrustedString("Invalid value".to_string()));
151 assert_eq!(invoice_error.erroneous_field, None);
152 }
153 Err(e) => panic!("Unexpected error: {:?}", e),
154 }
155 }
156
157 #[test]
158 fn parses_invoice_error_with_erroneous_field() {
159 let mut writer = VecWriter(Vec::new());
160 let invoice_error = InvoiceError {
161 erroneous_field: Some(ErroneousField {
162 tlv_fieldnum: 42,
163 suggested_value: Some(vec![42; 32]),
164 }),
165 message: UntrustedString("Invalid value".to_string()),
166 };
167 invoice_error.write(&mut writer).unwrap();
168
169 let buffer = writer.0;
170 match InvoiceError::read(&mut &buffer[..]) {
171 Ok(invoice_error) => {
172 assert_eq!(invoice_error.message, UntrustedString("Invalid value".to_string()));
173 assert_eq!(
174 invoice_error.erroneous_field,
175 Some(ErroneousField { tlv_fieldnum: 42, suggested_value: Some(vec![42; 32]) }),
176 );
177 }
178 Err(e) => panic!("Unexpected error: {:?}", e),
179 }
180 }
181
182 #[test]
183 fn parses_invoice_error_without_suggested_value() {
184 let mut writer = VecWriter(Vec::new());
185 let invoice_error = InvoiceError {
186 erroneous_field: Some(ErroneousField {
187 tlv_fieldnum: 42,
188 suggested_value: None,
189 }),
190 message: UntrustedString("Invalid value".to_string()),
191 };
192 invoice_error.write(&mut writer).unwrap();
193
194 let buffer = writer.0;
195 match InvoiceError::read(&mut &buffer[..]) {
196 Ok(invoice_error) => {
197 assert_eq!(invoice_error.message, UntrustedString("Invalid value".to_string()));
198 assert_eq!(
199 invoice_error.erroneous_field,
200 Some(ErroneousField { tlv_fieldnum: 42, suggested_value: None }),
201 );
202 }
203 Err(e) => panic!("Unexpected error: {:?}", e),
204 }
205 }
206
207 #[test]
208 fn fails_parsing_invoice_error_without_message() {
209 let tlv_fieldnum: Option<u64> = None;
210 let suggested_value: Option<&Vec<u8>> = None;
211 let error: Option<&String> = None;
212
213 let mut writer = VecWriter(Vec::new());
214 let mut write_tlv = || -> Result<(), DecodeError> {
215 write_tlv_fields!(&mut writer, {
216 (1, tlv_fieldnum, (option, encoding: (u64, HighZeroBytesDroppedBigSize))),
217 (3, suggested_value, (option, encoding: (Vec<u8>, WithoutLength))),
218 (5, error, (option, encoding: (String, WithoutLength))),
219 });
220 Ok(())
221 };
222 write_tlv().unwrap();
223
224 let buffer = writer.0;
225 match InvoiceError::read(&mut &buffer[..]) {
226 Ok(_) => panic!("Expected error"),
227 Err(e) => {
228 assert_eq!(e, DecodeError::InvalidValue);
229 },
230 }
231 }
232
233 #[test]
234 fn fails_parsing_invoice_error_without_field() {
235 let tlv_fieldnum: Option<u64> = None;
236 let suggested_value = vec![42; 32];
237 let error = "Invalid value".to_string();
238
239 let mut writer = VecWriter(Vec::new());
240 let mut write_tlv = || -> Result<(), DecodeError> {
241 write_tlv_fields!(&mut writer, {
242 (1, tlv_fieldnum, (option, encoding: (u64, HighZeroBytesDroppedBigSize))),
243 (3, Some(&suggested_value), (option, encoding: (Vec<u8>, WithoutLength))),
244 (5, Some(&error), (option, encoding: (String, WithoutLength))),
245 });
246 Ok(())
247 };
248 write_tlv().unwrap();
249
250 let buffer = writer.0;
251 match InvoiceError::read(&mut &buffer[..]) {
252 Ok(_) => panic!("Expected error"),
253 Err(e) => {
254 assert_eq!(e, DecodeError::InvalidValue);
255 },
256 }
257 }
258}