lightning/onion_message/
offers.rs1use core::fmt;
13use crate::blinded_path::message::OffersContext;
14use crate::io::{self, Read};
15use crate::ln::msgs::DecodeError;
16use crate::offers::invoice_error::InvoiceError;
17use crate::offers::invoice_request::InvoiceRequest;
18use crate::offers::invoice::Bolt12Invoice;
19use crate::offers::parse::Bolt12ParseError;
20#[cfg(async_payments)]
21use crate::offers::static_invoice::StaticInvoice;
22use crate::onion_message::packet::OnionMessageContents;
23use crate::util::logger::Logger;
24use crate::util::ser::{Readable, ReadableArgs, Writeable, Writer};
25use crate::onion_message::messenger::{ResponseInstruction, Responder, MessageSendInstructions};
26
27use crate::prelude::*;
28
29const INVOICE_REQUEST_TLV_TYPE: u64 = 64;
31const INVOICE_TLV_TYPE: u64 = 66;
32const INVOICE_ERROR_TLV_TYPE: u64 = 68;
33#[cfg(async_payments)]
34const STATIC_INVOICE_TLV_TYPE: u64 = 70;
35
36pub trait OffersMessageHandler {
40 fn handle_message(
47 &self, message: OffersMessage, context: Option<OffersContext>, responder: Option<Responder>,
48 ) -> Option<(OffersMessage, ResponseInstruction)>;
49
50 fn release_pending_messages(&self) -> Vec<(OffersMessage, MessageSendInstructions)> { vec![] }
55}
56
57#[derive(Clone)]
61pub enum OffersMessage {
62 InvoiceRequest(InvoiceRequest),
66
67 Invoice(Bolt12Invoice),
71
72 #[cfg(async_payments)]
73 StaticInvoice(StaticInvoice),
75
76 InvoiceError(InvoiceError),
78}
79
80impl OffersMessage {
81 pub fn is_known_type(tlv_type: u64) -> bool {
83 match tlv_type {
84 INVOICE_REQUEST_TLV_TYPE
85 | INVOICE_TLV_TYPE
86 | INVOICE_ERROR_TLV_TYPE => true,
87 #[cfg(async_payments)]
88 STATIC_INVOICE_TLV_TYPE => true,
89 _ => false,
90 }
91 }
92
93 fn parse(tlv_type: u64, bytes: Vec<u8>) -> Result<Self, Bolt12ParseError> {
94 match tlv_type {
95 INVOICE_REQUEST_TLV_TYPE => Ok(Self::InvoiceRequest(InvoiceRequest::try_from(bytes)?)),
96 INVOICE_TLV_TYPE => Ok(Self::Invoice(Bolt12Invoice::try_from(bytes)?)),
97 #[cfg(async_payments)]
98 STATIC_INVOICE_TLV_TYPE => Ok(Self::StaticInvoice(StaticInvoice::try_from(bytes)?)),
99 _ => Err(Bolt12ParseError::Decode(DecodeError::InvalidValue)),
100 }
101 }
102
103 fn get_msg_type(&self) -> &'static str {
104 match &self {
105 OffersMessage::InvoiceRequest(_) => "Invoice Request",
106 OffersMessage::Invoice(_) => "Invoice",
107 #[cfg(async_payments)]
108 OffersMessage::StaticInvoice(_) => "Static Invoice",
109 OffersMessage::InvoiceError(_) => "Invoice Error",
110 }
111 }
112}
113
114impl fmt::Debug for OffersMessage {
115 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
116 match self {
117 OffersMessage::InvoiceRequest(message) => {
118 write!(f, "{:?}", message.as_tlv_stream())
119 }
120 OffersMessage::Invoice(message) => {
121 write!(f, "{:?}", message.as_tlv_stream())
122 }
123 #[cfg(async_payments)]
124 OffersMessage::StaticInvoice(message) => {
125 write!(f, "{:?}", message)
126 }
127 OffersMessage::InvoiceError(message) => {
128 write!(f, "{:?}", message)
129 }
130 }
131 }
132}
133
134impl OnionMessageContents for OffersMessage {
135 fn tlv_type(&self) -> u64 {
136 match self {
137 OffersMessage::InvoiceRequest(_) => INVOICE_REQUEST_TLV_TYPE,
138 OffersMessage::Invoice(_) => INVOICE_TLV_TYPE,
139 #[cfg(async_payments)]
140 OffersMessage::StaticInvoice(_) => STATIC_INVOICE_TLV_TYPE,
141 OffersMessage::InvoiceError(_) => INVOICE_ERROR_TLV_TYPE,
142 }
143 }
144 #[cfg(c_bindings)]
145 fn msg_type(&self) -> String {
146 self.get_msg_type().to_string()
147 }
148 #[cfg(not(c_bindings))]
149 fn msg_type(&self) -> &'static str {
150 self.get_msg_type()
151 }
152}
153
154impl Writeable for OffersMessage {
155 fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
156 match self {
157 OffersMessage::InvoiceRequest(message) => message.write(w),
158 OffersMessage::Invoice(message) => message.write(w),
159 #[cfg(async_payments)]
160 OffersMessage::StaticInvoice(message) => message.write(w),
161 OffersMessage::InvoiceError(message) => message.write(w),
162 }
163 }
164}
165
166impl<L: Logger + ?Sized> ReadableArgs<(u64, &L)> for OffersMessage {
167 fn read<R: Read>(r: &mut R, read_args: (u64, &L)) -> Result<Self, DecodeError> {
168 let (tlv_type, logger) = read_args;
169 if tlv_type == INVOICE_ERROR_TLV_TYPE {
170 return Ok(Self::InvoiceError(InvoiceError::read(r)?));
171 }
172
173 let mut bytes = Vec::new();
174 r.read_to_limit(&mut bytes, u64::MAX).unwrap();
175
176 match Self::parse(tlv_type, bytes) {
177 Ok(message) => Ok(message),
178 Err(Bolt12ParseError::Decode(e)) => Err(e),
179 Err(Bolt12ParseError::InvalidSemantics(e)) => {
180 log_trace!(logger, "Invalid semantics for TLV type {}: {:?}", tlv_type, e);
181 Err(DecodeError::InvalidValue)
182 },
183 Err(Bolt12ParseError::InvalidSignature(e)) => {
184 log_trace!(logger, "Invalid signature for TLV type {}: {:?}", tlv_type, e);
185 Err(DecodeError::InvalidValue)
186 },
187 Err(_) => Err(DecodeError::InvalidValue),
188 }
189 }
190}