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::SemanticError;
15 use crate::util::ser::{HighZeroBytesDroppedBigSize, Readable, WithoutLength, Writeable, Writer};
16 use crate::util::string::UntrustedString;
18 use crate::prelude::*;
20 /// An error in response to an [`InvoiceRequest`] or an [`Invoice`].
22 /// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
23 /// [`Invoice`]: crate::offers::invoice::Invoice
24 #[derive(Clone, Debug)]
25 #[cfg_attr(test, derive(PartialEq))]
26 pub struct InvoiceError {
27 /// The field in the [`InvoiceRequest`] or the [`Invoice`] that contained an error.
29 /// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
30 /// [`Invoice`]: crate::offers::invoice::Invoice
31 pub erroneous_field: Option<ErroneousField>,
33 /// An explanation of the error.
34 pub message: UntrustedString,
37 /// The field in the [`InvoiceRequest`] or the [`Invoice`] that contained an error.
39 /// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
40 /// [`Invoice`]: crate::offers::invoice::Invoice
41 #[derive(Clone, Debug)]
42 #[cfg_attr(test, derive(PartialEq))]
43 pub struct ErroneousField {
44 /// The type number of the TLV field containing the error.
45 pub tlv_fieldnum: u64,
47 /// A value to use for the TLV field to avoid the error.
48 pub suggested_value: Option<Vec<u8>>,
51 impl core::fmt::Display for InvoiceError {
52 fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
57 impl Writeable for InvoiceError {
58 fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
59 let tlv_fieldnum = self.erroneous_field.as_ref().map(|f| f.tlv_fieldnum);
61 self.erroneous_field.as_ref().and_then(|f| f.suggested_value.as_ref());
62 write_tlv_fields!(writer, {
63 (1, tlv_fieldnum, (option, encoding: (u64, HighZeroBytesDroppedBigSize))),
64 (3, suggested_value, (option, encoding: (Vec<u8>, WithoutLength))),
65 (5, WithoutLength(&self.message), required),
71 impl Readable for InvoiceError {
72 fn read<R: io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
73 _init_and_read_tlv_fields!(reader, {
74 (1, erroneous_field, (option, encoding: (u64, HighZeroBytesDroppedBigSize))),
75 (3, suggested_value, (option, encoding: (Vec<u8>, WithoutLength))),
76 (5, error, (option, encoding: (UntrustedString, WithoutLength))),
79 let erroneous_field = match (erroneous_field, suggested_value) {
81 (None, Some(_)) => return Err(DecodeError::InvalidValue),
82 (Some(tlv_fieldnum), suggested_value) => {
83 Some(ErroneousField { tlv_fieldnum, suggested_value })
87 let message = match error {
88 None => return Err(DecodeError::InvalidValue),
92 Ok(InvoiceError { erroneous_field, message })
96 impl From<SemanticError> for InvoiceError {
97 fn from(error: SemanticError) -> Self {
99 erroneous_field: None,
100 message: UntrustedString(format!("{:?}", error)),
107 use super::{ErroneousField, InvoiceError};
109 use crate::ln::msgs::DecodeError;
110 use crate::util::ser::{HighZeroBytesDroppedBigSize, Readable, VecWriter, WithoutLength, Writeable};
111 use crate::util::string::UntrustedString;
114 fn parses_invoice_error_without_erroneous_field() {
115 let mut writer = VecWriter(Vec::new());
116 let invoice_error = InvoiceError {
117 erroneous_field: None,
118 message: UntrustedString("Invalid value".to_string()),
120 invoice_error.write(&mut writer).unwrap();
122 let buffer = writer.0;
123 match InvoiceError::read(&mut &buffer[..]) {
124 Ok(invoice_error) => {
125 assert_eq!(invoice_error.message, UntrustedString("Invalid value".to_string()));
126 assert_eq!(invoice_error.erroneous_field, None);
128 Err(e) => panic!("Unexpected error: {:?}", e),
133 fn parses_invoice_error_with_erroneous_field() {
134 let mut writer = VecWriter(Vec::new());
135 let invoice_error = InvoiceError {
136 erroneous_field: Some(ErroneousField {
138 suggested_value: Some(vec![42; 32]),
140 message: UntrustedString("Invalid value".to_string()),
142 invoice_error.write(&mut writer).unwrap();
144 let buffer = writer.0;
145 match InvoiceError::read(&mut &buffer[..]) {
146 Ok(invoice_error) => {
147 assert_eq!(invoice_error.message, UntrustedString("Invalid value".to_string()));
149 invoice_error.erroneous_field,
150 Some(ErroneousField { tlv_fieldnum: 42, suggested_value: Some(vec![42; 32]) }),
153 Err(e) => panic!("Unexpected error: {:?}", e),
158 fn parses_invoice_error_without_suggested_value() {
159 let mut writer = VecWriter(Vec::new());
160 let invoice_error = InvoiceError {
161 erroneous_field: Some(ErroneousField {
163 suggested_value: None,
165 message: UntrustedString("Invalid value".to_string()),
167 invoice_error.write(&mut writer).unwrap();
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()));
174 invoice_error.erroneous_field,
175 Some(ErroneousField { tlv_fieldnum: 42, suggested_value: None }),
178 Err(e) => panic!("Unexpected error: {:?}", e),
183 fn fails_parsing_invoice_error_without_message() {
184 let tlv_fieldnum: Option<u64> = None;
185 let suggested_value: Option<&Vec<u8>> = None;
186 let error: Option<&String> = None;
188 let mut writer = VecWriter(Vec::new());
189 let mut write_tlv = || -> Result<(), DecodeError> {
190 write_tlv_fields!(&mut writer, {
191 (1, tlv_fieldnum, (option, encoding: (u64, HighZeroBytesDroppedBigSize))),
192 (3, suggested_value, (option, encoding: (Vec<u8>, WithoutLength))),
193 (5, error, (option, encoding: (String, WithoutLength))),
197 write_tlv().unwrap();
199 let buffer = writer.0;
200 match InvoiceError::read(&mut &buffer[..]) {
201 Ok(_) => panic!("Expected error"),
203 assert_eq!(e, DecodeError::InvalidValue);
209 fn fails_parsing_invoice_error_without_field() {
210 let tlv_fieldnum: Option<u64> = None;
211 let suggested_value = vec![42; 32];
212 let error = "Invalid value".to_string();
214 let mut writer = VecWriter(Vec::new());
215 let mut write_tlv = || -> Result<(), DecodeError> {
216 write_tlv_fields!(&mut writer, {
217 (1, tlv_fieldnum, (option, encoding: (u64, HighZeroBytesDroppedBigSize))),
218 (3, Some(&suggested_value), (option, encoding: (Vec<u8>, WithoutLength))),
219 (5, Some(&error), (option, encoding: (String, WithoutLength))),
223 write_tlv().unwrap();
225 let buffer = writer.0;
226 match InvoiceError::read(&mut &buffer[..]) {
227 Ok(_) => panic!("Expected error"),
229 assert_eq!(e, DecodeError::InvalidValue);