AsyncPaymentsMessageHandler trait for OnionMessenger
[rust-lightning] / lightning / src / onion_message / async_payments.rs
1 // This file is Copyright its original authors, visible in version control
2 // history.
3 //
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
8 // licenses.
9
10 //! Message handling for async payments.
11
12 use crate::io;
13 use crate::ln::msgs::DecodeError;
14 use crate::onion_message::messenger::PendingOnionMessage;
15 use crate::onion_message::messenger::{Responder, ResponseInstruction};
16 use crate::onion_message::packet::OnionMessageContents;
17 use crate::prelude::*;
18 use crate::util::ser::{Readable, ReadableArgs, Writeable, Writer};
19
20 // TLV record types for the `onionmsg_tlv` TLV stream as defined in BOLT 4.
21 const HELD_HTLC_AVAILABLE_TLV_TYPE: u64 = 72;
22 const RELEASE_HELD_HTLC_TLV_TYPE: u64 = 74;
23
24 /// A handler for an [`OnionMessage`] containing an async payments message as its payload.
25 ///
26 /// [`OnionMessage`]: crate::ln::msgs::OnionMessage
27 pub trait AsyncPaymentsMessageHandler {
28         /// Handle a [`HeldHtlcAvailable`] message. A [`ReleaseHeldHtlc`] should be returned to release
29         /// the held funds.
30         fn held_htlc_available(
31                 &self, message: HeldHtlcAvailable, responder: Option<Responder>,
32         ) -> ResponseInstruction<ReleaseHeldHtlc>;
33
34         /// Handle a [`ReleaseHeldHtlc`] message. If authentication of the message succeeds, an HTLC
35         /// should be released to the corresponding payee.
36         fn release_held_htlc(&self, message: ReleaseHeldHtlc);
37
38         /// Release any [`AsyncPaymentsMessage`]s that need to be sent.
39         ///
40         /// Typically, this is used for messages initiating an async payment flow rather than in response
41         /// to another message.
42         #[cfg(not(c_bindings))]
43         fn release_pending_messages(&self) -> Vec<PendingOnionMessage<AsyncPaymentsMessage>> {
44                 vec![]
45         }
46
47         /// Release any [`AsyncPaymentsMessage`]s that need to be sent.
48         ///
49         /// Typically, this is used for messages initiating a payment flow rather than in response to
50         /// another message.
51         #[cfg(c_bindings)]
52         fn release_pending_messages(
53                 &self,
54         ) -> Vec<(
55                 AsyncPaymentsMessage,
56                 crate::onion_message::messenger::Destination,
57                 Option<crate::blinded_path::BlindedPath>,
58         )> {
59                 vec![]
60         }
61 }
62
63 /// Possible async payment messages sent and received via an [`OnionMessage`].
64 ///
65 /// [`OnionMessage`]: crate::ln::msgs::OnionMessage
66 #[derive(Clone, Debug)]
67 pub enum AsyncPaymentsMessage {
68         /// An HTLC is being held upstream for the often-offline recipient, to be released via
69         /// [`ReleaseHeldHtlc`].
70         HeldHtlcAvailable(HeldHtlcAvailable),
71
72         /// Releases the HTLC corresponding to an inbound [`HeldHtlcAvailable`] message.
73         ReleaseHeldHtlc(ReleaseHeldHtlc),
74 }
75
76 /// An HTLC destined for the recipient of this message is being held upstream. The reply path
77 /// accompanying this onion message should be used to send a [`ReleaseHeldHtlc`] response, which
78 /// will cause the upstream HTLC to be released.
79 #[derive(Clone, Debug)]
80 pub struct HeldHtlcAvailable {
81         /// The secret that will be used by the recipient of this message to release the held HTLC.
82         pub payment_release_secret: [u8; 32],
83 }
84
85 /// Releases the HTLC corresponding to an inbound [`HeldHtlcAvailable`] message.
86 #[derive(Clone, Debug)]
87 pub struct ReleaseHeldHtlc {
88         /// Used to release the HTLC held upstream if it matches the corresponding
89         /// [`HeldHtlcAvailable::payment_release_secret`].
90         pub payment_release_secret: [u8; 32],
91 }
92
93 impl OnionMessageContents for ReleaseHeldHtlc {
94         fn tlv_type(&self) -> u64 {
95                 RELEASE_HELD_HTLC_TLV_TYPE
96         }
97         fn msg_type(&self) -> &'static str {
98                 "Release Held HTLC"
99         }
100 }
101
102 impl_writeable_tlv_based!(HeldHtlcAvailable, {
103         (0, payment_release_secret, required),
104 });
105
106 impl_writeable_tlv_based!(ReleaseHeldHtlc, {
107         (0, payment_release_secret, required),
108 });
109
110 impl AsyncPaymentsMessage {
111         /// Returns whether `tlv_type` corresponds to a TLV record for async payment messages.
112         pub fn is_known_type(tlv_type: u64) -> bool {
113                 match tlv_type {
114                         HELD_HTLC_AVAILABLE_TLV_TYPE | RELEASE_HELD_HTLC_TLV_TYPE => true,
115                         _ => false,
116                 }
117         }
118 }
119
120 impl OnionMessageContents for AsyncPaymentsMessage {
121         fn tlv_type(&self) -> u64 {
122                 match self {
123                         Self::HeldHtlcAvailable(_) => HELD_HTLC_AVAILABLE_TLV_TYPE,
124                         Self::ReleaseHeldHtlc(msg) => msg.tlv_type(),
125                 }
126         }
127         fn msg_type(&self) -> &'static str {
128                 match &self {
129                         Self::HeldHtlcAvailable(_) => "Held HTLC Available",
130                         Self::ReleaseHeldHtlc(msg) => msg.msg_type(),
131                 }
132         }
133 }
134
135 impl Writeable for AsyncPaymentsMessage {
136         fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
137                 match self {
138                         Self::HeldHtlcAvailable(message) => message.write(w),
139                         Self::ReleaseHeldHtlc(message) => message.write(w),
140                 }
141         }
142 }
143
144 impl ReadableArgs<u64> for AsyncPaymentsMessage {
145         fn read<R: io::Read>(r: &mut R, tlv_type: u64) -> Result<Self, DecodeError> {
146                 match tlv_type {
147                         HELD_HTLC_AVAILABLE_TLV_TYPE => Ok(Self::HeldHtlcAvailable(Readable::read(r)?)),
148                         RELEASE_HELD_HTLC_TLV_TYPE => Ok(Self::ReleaseHeldHtlc(Readable::read(r)?)),
149                         _ => Err(DecodeError::InvalidValue),
150                 }
151         }
152 }