1 // This file is Copyright its original authors, visible in version control
4 // This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
5 // or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
7 // You may not use this file except in accordance with one or both of these
10 //! Data structures and encoding for `invoice_error` messages.
13 use crate::ln::msgs::DecodeError;
14 use crate::offers::parse::Bolt12SemanticError;
15 use crate::util::ser::{HighZeroBytesDroppedBigSize, Readable, WithoutLength, Writeable, Writer};
16 use crate::util::string::UntrustedString;
18 #[allow(unused_imports)]
19 use crate::prelude::*;
21 /// An error in response to an [`InvoiceRequest`] or an [`Bolt12Invoice`].
23 /// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
24 /// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
25 #[derive(Clone, Debug)]
26 #[cfg_attr(test, derive(PartialEq))]
27 pub struct InvoiceError {
28 /// The field in the [`InvoiceRequest`] or the [`Bolt12Invoice`] that contained an error.
30 /// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
31 /// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
32 pub erroneous_field: Option<ErroneousField>,
34 /// An explanation of the error.
35 pub message: UntrustedString,
38 /// The field in the [`InvoiceRequest`] or the [`Bolt12Invoice`] that contained an error.
40 /// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
41 /// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
42 #[derive(Clone, Debug)]
43 #[cfg_attr(test, derive(PartialEq))]
44 pub struct ErroneousField {
45 /// The type number of the TLV field containing the error.
46 pub tlv_fieldnum: u64,
48 /// A value to use for the TLV field to avoid the error.
49 pub suggested_value: Option<Vec<u8>>,
53 /// Creates an [`InvoiceError`] with the given message.
54 pub fn from_string(s: String) -> Self {
56 erroneous_field: None,
57 message: UntrustedString(s),
62 impl core::fmt::Display for InvoiceError {
63 fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
68 impl Writeable for InvoiceError {
69 fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
70 let tlv_fieldnum = self.erroneous_field.as_ref().map(|f| f.tlv_fieldnum);
72 self.erroneous_field.as_ref().and_then(|f| f.suggested_value.as_ref());
73 write_tlv_fields!(writer, {
74 (1, tlv_fieldnum, (option, encoding: (u64, HighZeroBytesDroppedBigSize))),
75 (3, suggested_value, (option, encoding: (Vec<u8>, WithoutLength))),
76 (5, WithoutLength(&self.message), required),
82 impl Readable for InvoiceError {
83 fn read<R: io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
84 _init_and_read_len_prefixed_tlv_fields!(reader, {
85 (1, erroneous_field, (option, encoding: (u64, HighZeroBytesDroppedBigSize))),
86 (3, suggested_value, (option, encoding: (Vec<u8>, WithoutLength))),
87 (5, error, (option, encoding: (UntrustedString, WithoutLength))),
90 let erroneous_field = match (erroneous_field, suggested_value) {
92 (None, Some(_)) => return Err(DecodeError::InvalidValue),
93 (Some(tlv_fieldnum), suggested_value) => {
94 Some(ErroneousField { tlv_fieldnum, suggested_value })
98 let message = match error {
99 None => return Err(DecodeError::InvalidValue),
100 Some(error) => error,
103 Ok(InvoiceError { erroneous_field, message })
107 impl From<Bolt12SemanticError> for InvoiceError {
108 fn from(error: Bolt12SemanticError) -> Self {
110 erroneous_field: None,
111 message: UntrustedString(format!("{:?}", error)),
118 use super::{ErroneousField, InvoiceError};
120 use crate::ln::msgs::DecodeError;
121 use crate::util::ser::{HighZeroBytesDroppedBigSize, Readable, VecWriter, WithoutLength, Writeable};
122 use crate::util::string::UntrustedString;
125 fn parses_invoice_error_without_erroneous_field() {
126 let mut writer = VecWriter(Vec::new());
127 let invoice_error = InvoiceError {
128 erroneous_field: None,
129 message: UntrustedString("Invalid value".to_string()),
131 invoice_error.write(&mut writer).unwrap();
133 let buffer = writer.0;
134 match InvoiceError::read(&mut &buffer[..]) {
135 Ok(invoice_error) => {
136 assert_eq!(invoice_error.message, UntrustedString("Invalid value".to_string()));
137 assert_eq!(invoice_error.erroneous_field, None);
139 Err(e) => panic!("Unexpected error: {:?}", e),
144 fn parses_invoice_error_with_erroneous_field() {
145 let mut writer = VecWriter(Vec::new());
146 let invoice_error = InvoiceError {
147 erroneous_field: Some(ErroneousField {
149 suggested_value: Some(vec![42; 32]),
151 message: UntrustedString("Invalid value".to_string()),
153 invoice_error.write(&mut writer).unwrap();
155 let buffer = writer.0;
156 match InvoiceError::read(&mut &buffer[..]) {
157 Ok(invoice_error) => {
158 assert_eq!(invoice_error.message, UntrustedString("Invalid value".to_string()));
160 invoice_error.erroneous_field,
161 Some(ErroneousField { tlv_fieldnum: 42, suggested_value: Some(vec![42; 32]) }),
164 Err(e) => panic!("Unexpected error: {:?}", e),
169 fn parses_invoice_error_without_suggested_value() {
170 let mut writer = VecWriter(Vec::new());
171 let invoice_error = InvoiceError {
172 erroneous_field: Some(ErroneousField {
174 suggested_value: None,
176 message: UntrustedString("Invalid value".to_string()),
178 invoice_error.write(&mut writer).unwrap();
180 let buffer = writer.0;
181 match InvoiceError::read(&mut &buffer[..]) {
182 Ok(invoice_error) => {
183 assert_eq!(invoice_error.message, UntrustedString("Invalid value".to_string()));
185 invoice_error.erroneous_field,
186 Some(ErroneousField { tlv_fieldnum: 42, suggested_value: None }),
189 Err(e) => panic!("Unexpected error: {:?}", e),
194 fn fails_parsing_invoice_error_without_message() {
195 let tlv_fieldnum: Option<u64> = None;
196 let suggested_value: Option<&Vec<u8>> = None;
197 let error: Option<&String> = None;
199 let mut writer = VecWriter(Vec::new());
200 let mut write_tlv = || -> Result<(), DecodeError> {
201 write_tlv_fields!(&mut writer, {
202 (1, tlv_fieldnum, (option, encoding: (u64, HighZeroBytesDroppedBigSize))),
203 (3, suggested_value, (option, encoding: (Vec<u8>, WithoutLength))),
204 (5, error, (option, encoding: (String, WithoutLength))),
208 write_tlv().unwrap();
210 let buffer = writer.0;
211 match InvoiceError::read(&mut &buffer[..]) {
212 Ok(_) => panic!("Expected error"),
214 assert_eq!(e, DecodeError::InvalidValue);
220 fn fails_parsing_invoice_error_without_field() {
221 let tlv_fieldnum: Option<u64> = None;
222 let suggested_value = vec![42; 32];
223 let error = "Invalid value".to_string();
225 let mut writer = VecWriter(Vec::new());
226 let mut write_tlv = || -> Result<(), DecodeError> {
227 write_tlv_fields!(&mut writer, {
228 (1, tlv_fieldnum, (option, encoding: (u64, HighZeroBytesDroppedBigSize))),
229 (3, Some(&suggested_value), (option, encoding: (Vec<u8>, WithoutLength))),
230 (5, Some(&error), (option, encoding: (String, WithoutLength))),
234 write_tlv().unwrap();
236 let buffer = writer.0;
237 match InvoiceError::read(&mut &buffer[..]) {
238 Ok(_) => panic!("Expected error"),
240 assert_eq!(e, DecodeError::InvalidValue);