Skip to content

Commit 02ef1ef

Browse files
committed
Implement serialization for LSPS2 state types
1 parent 65758a0 commit 02ef1ef

File tree

5 files changed

+131
-1
lines changed

5 files changed

+131
-1
lines changed

lightning-liquidity/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ _test_utils = []
2424
lightning = { version = "0.2.0", path = "../lightning", default-features = false }
2525
lightning-types = { version = "0.3.0", path = "../lightning-types", default-features = false }
2626
lightning-invoice = { version = "0.34.0", path = "../lightning-invoice", default-features = false, features = ["serde"] }
27+
lightning-macros = { version = "0.2", path = "../lightning-macros" }
2728

2829
bitcoin = { version = "0.32.2", default-features = false, features = ["serde"] }
2930

lightning-liquidity/src/lsps0/ser.rs

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ use crate::prelude::HashMap;
3030

3131
use lightning::ln::msgs::{DecodeError, LightningError};
3232
use lightning::ln::wire;
33-
use lightning::util::ser::{LengthLimitedRead, LengthReadable, WithoutLength};
33+
use lightning::util::ser::{LengthLimitedRead, LengthReadable, Readable, WithoutLength, Writeable};
3434

3535
use bitcoin::secp256k1::PublicKey;
3636

@@ -217,6 +217,22 @@ impl wire::Type for RawLSPSMessage {
217217
#[serde(transparent)]
218218
pub struct LSPSRequestId(pub String);
219219

220+
impl Writeable for LSPSRequestId {
221+
fn write<W: lightning::util::ser::Writer>(
222+
&self, writer: &mut W,
223+
) -> Result<(), lightning::io::Error> {
224+
self.0.write(writer)?;
225+
Ok(())
226+
}
227+
}
228+
229+
impl Readable for LSPSRequestId {
230+
fn read<R: lightning::io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
231+
let s: String = Readable::read(reader)?;
232+
Ok(Self(s))
233+
}
234+
}
235+
220236
/// An object representing datetimes as described in bLIP-50 / LSPS0.
221237
#[derive(Clone, Debug, Copy, PartialEq, Eq, Hash, Deserialize, Serialize)]
222238
#[serde(transparent)]
@@ -266,6 +282,23 @@ impl Display for LSPSDateTime {
266282
}
267283
}
268284

285+
impl Writeable for LSPSDateTime {
286+
fn write<W: lightning::util::ser::Writer>(
287+
&self, writer: &mut W,
288+
) -> Result<(), lightning::io::Error> {
289+
self.to_rfc3339().write(writer)?;
290+
Ok(())
291+
}
292+
}
293+
294+
impl Readable for LSPSDateTime {
295+
fn read<R: lightning::io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
296+
let s: String = Readable::read(reader)?;
297+
let val = Self::from_str(&s).map_err(|_| lightning::ln::msgs::DecodeError::InvalidValue)?;
298+
Ok(val)
299+
}
300+
}
301+
269302
/// An error returned in response to an JSON-RPC request.
270303
///
271304
/// Please refer to the [JSON-RPC 2.0 specification](https://www.jsonrpc.org/specification#error_object) for
@@ -933,3 +966,19 @@ pub(crate) mod u32_fee_rate {
933966
Ok(FeeRate::from_sat_per_kwu(fee_rate_sat_kwu as u64))
934967
}
935968
}
969+
970+
#[cfg(test)]
971+
mod tests {
972+
use super::*;
973+
974+
use lightning::io::Cursor;
975+
976+
#[test]
977+
fn datetime_serializaton() {
978+
let expected_datetime = LSPSDateTime::from_str("2035-05-20T08:30:45Z").unwrap();
979+
let mut buf = Vec::new();
980+
expected_datetime.write(&mut buf).unwrap();
981+
let decoded_datetime: LSPSDateTime = Readable::read(&mut Cursor::new(buf)).unwrap();
982+
assert_eq!(expected_datetime, decoded_datetime);
983+
}
984+
}

lightning-liquidity/src/lsps2/msgs.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use bitcoin::secp256k1::PublicKey;
2222
use serde::{Deserialize, Serialize};
2323

2424
use lightning::util::scid_utils;
25+
use lightning::{impl_writeable_tlv_based, impl_writeable_tlv_based_enum};
2526

2627
use crate::lsps0::ser::{
2728
string_amount, string_amount_option, LSPSDateTime, LSPSMessage, LSPSRequestId,
@@ -45,6 +46,10 @@ pub struct LSPS2GetInfoRequest {
4546
pub token: Option<String>,
4647
}
4748

49+
impl_writeable_tlv_based!(LSPS2GetInfoRequest, {
50+
(0, token, option),
51+
});
52+
4853
/// Fees and parameters for a JIT Channel without the promise.
4954
///
5055
/// The promise will be calculated automatically for the LSP and this type converted
@@ -122,6 +127,17 @@ pub struct LSPS2OpeningFeeParams {
122127
pub promise: String,
123128
}
124129

130+
impl_writeable_tlv_based!(LSPS2OpeningFeeParams, {
131+
(0, min_fee_msat, required),
132+
(2, proportional, required),
133+
(4, valid_until, required),
134+
(6, min_lifetime, required),
135+
(8, max_client_to_self_delay, required),
136+
(10, min_payment_size_msat, required),
137+
(12, max_payment_size_msat, required),
138+
(14, promise, required),
139+
});
140+
125141
/// A response to a [`LSPS2GetInfoRequest`]
126142
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
127143
pub struct LSPS2GetInfoResponse {
@@ -141,6 +157,11 @@ pub struct LSPS2BuyRequest {
141157
pub payment_size_msat: Option<u64>,
142158
}
143159

160+
impl_writeable_tlv_based!(LSPS2BuyRequest, {
161+
(0, opening_fee_params, required),
162+
(2, payment_size_msat, option),
163+
});
164+
144165
/// A newtype that holds a `short_channel_id` in human readable format of BBBxTTTx000.
145166
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
146167
pub struct LSPS2InterceptScid(String);
@@ -185,6 +206,11 @@ pub enum LSPS2Request {
185206
Buy(LSPS2BuyRequest),
186207
}
187208

209+
impl_writeable_tlv_based_enum!(LSPS2Request,
210+
{0, GetInfo} => (),
211+
{2, Buy} => (),
212+
);
213+
188214
#[derive(Clone, Debug, PartialEq, Eq)]
189215
/// An enum that captures all the valid JSON-RPC responses in the bLIP-52 / LSPS2 protocol.
190216
pub enum LSPS2Response {

lightning-liquidity/src/lsps2/payment_queue.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
use alloc::vec::Vec;
1111

12+
use lightning::impl_writeable_tlv_based;
1213
use lightning::ln::channelmanager::InterceptId;
1314
use lightning_types::payment::PaymentHash;
1415

@@ -62,19 +63,34 @@ impl PaymentQueue {
6263
}
6364
}
6465

66+
impl_writeable_tlv_based!(PaymentQueue, {
67+
(0, payments, optional_vec),
68+
});
69+
6570
#[derive(Clone, PartialEq, Eq, Debug)]
6671
pub(crate) struct PaymentQueueEntry {
6772
pub(crate) payment_hash: PaymentHash,
6873
pub(crate) htlcs: Vec<InterceptedHTLC>,
6974
}
7075

76+
impl_writeable_tlv_based!(PaymentQueueEntry, {
77+
(0, payment_hash, required),
78+
(2, htlcs, optional_vec),
79+
});
80+
7181
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
7282
pub(crate) struct InterceptedHTLC {
7383
pub(crate) intercept_id: InterceptId,
7484
pub(crate) expected_outbound_amount_msat: u64,
7585
pub(crate) payment_hash: PaymentHash,
7686
}
7787

88+
impl_writeable_tlv_based!(InterceptedHTLC, {
89+
(0, intercept_id, required),
90+
(2, expected_outbound_amount_msat, required),
91+
(4, payment_hash, required),
92+
});
93+
7894
#[cfg(test)]
7995
mod tests {
8096
use super::*;

lightning-liquidity/src/lsps2/service.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ use lightning::ln::msgs::{ErrorAction, LightningError};
3838
use lightning::ln::types::ChannelId;
3939
use lightning::util::errors::APIError;
4040
use lightning::util::logger::Level;
41+
use lightning::{impl_writeable_tlv_based, impl_writeable_tlv_based_enum};
4142

4243
use lightning_types::payment::PaymentHash;
4344

@@ -372,13 +373,43 @@ impl OutboundJITChannelState {
372373
}
373374
}
374375

376+
impl_writeable_tlv_based_enum!(OutboundJITChannelState,
377+
(0, PendingInitialPayment) => {
378+
(0, payment_queue, required),
379+
},
380+
(2, PendingChannelOpen) => {
381+
(0, payment_queue, required),
382+
(2, opening_fee_msat, required),
383+
},
384+
(4, PendingPaymentForward) => {
385+
(0, payment_queue, required),
386+
(2, opening_fee_msat, required),
387+
(4, channel_id, required),
388+
},
389+
(6, PendingPayment) => {
390+
(0, payment_queue, required),
391+
(2, opening_fee_msat, required),
392+
(4, channel_id, required),
393+
},
394+
(8, PaymentForwarded) => {
395+
(0, channel_id, required),
396+
},
397+
);
398+
375399
struct OutboundJITChannel {
376400
state: OutboundJITChannelState,
377401
user_channel_id: u128,
378402
opening_fee_params: LSPS2OpeningFeeParams,
379403
payment_size_msat: Option<u64>,
380404
}
381405

406+
impl_writeable_tlv_based!(OutboundJITChannel, {
407+
(0, state, required),
408+
(2, user_channel_id, required),
409+
(4, opening_fee_params, required),
410+
(6, payment_size_msat, option),
411+
});
412+
382413
impl OutboundJITChannel {
383414
fn new(
384415
payment_size_msat: Option<u64>, opening_fee_params: LSPS2OpeningFeeParams,
@@ -492,6 +523,13 @@ impl PeerState {
492523
}
493524
}
494525

526+
impl_writeable_tlv_based!(PeerState, {
527+
(0, outbound_channels_by_intercept_scid, required),
528+
(2, intercept_scid_by_user_channel_id, required),
529+
(4, intercept_scid_by_channel_id, required),
530+
(_unused, pending_requests, (static_value, new_hash_map())),
531+
});
532+
495533
macro_rules! get_or_insert_peer_state_entry {
496534
($self: ident, $outer_state_lock: expr, $message_queue_notifier: expr, $counterparty_node_id: expr) => {{
497535
// Return an internal error and abort if we hit the maximum allowed number of total peers.

0 commit comments

Comments
 (0)