Skip to content
This repository was archived by the owner on Jan 6, 2025. It is now read-only.

Commit 0f52cc6

Browse files
authored
Merge pull request #124 from tnull/2024-03-fix-payload-serialization
Fix `payload` encoding, `jit_channel_scid` serialization, error codes
2 parents 6c5d4a2 + ca150c4 commit 0f52cc6

File tree

5 files changed

+82
-14
lines changed

5 files changed

+82
-14
lines changed

src/lsps0/ser.rs

+21-3
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@ use crate::lsps1::msgs::{
1515
use crate::lsps2::msgs::{
1616
LSPS2Message, LSPS2Request, LSPS2Response, LSPS2_BUY_METHOD_NAME, LSPS2_GET_INFO_METHOD_NAME,
1717
};
18-
use crate::prelude::{HashMap, String, ToString, Vec};
18+
use crate::prelude::{HashMap, String, ToString};
1919

20-
use lightning::impl_writeable_msg;
2120
use lightning::ln::msgs::LightningError;
2221
use lightning::ln::wire;
22+
use lightning::util::ser::WithoutLength;
2323

2424
use bitcoin::secp256k1::PublicKey;
2525

@@ -42,6 +42,8 @@ pub(crate) const JSONRPC_ERROR_FIELD_KEY: &str = "error";
4242
pub(crate) const JSONRPC_INVALID_MESSAGE_ERROR_CODE: i32 = -32700;
4343
pub(crate) const JSONRPC_INVALID_MESSAGE_ERROR_MESSAGE: &str = "parse error";
4444

45+
pub(crate) const _LSPS0_CLIENT_REJECTED_ERROR_CODE: i32 = 001;
46+
4547
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
4648
pub(crate) enum LSPSMethod {
4749
LSPS0ListProtocols,
@@ -160,7 +162,23 @@ pub struct RawLSPSMessage {
160162
pub payload: String,
161163
}
162164

163-
impl_writeable_msg!(RawLSPSMessage, { payload }, {});
165+
// We encode `RawLSPSMessage`'s payload without a length prefix as LSPS0 expects it to be the
166+
// remainder of the object.
167+
impl lightning::util::ser::Writeable for RawLSPSMessage {
168+
fn write<W: lightning::util::ser::Writer>(
169+
&self, w: &mut W,
170+
) -> Result<(), lightning::io::Error> {
171+
WithoutLength(&self.payload).write(w)?;
172+
Ok(())
173+
}
174+
}
175+
176+
impl lightning::util::ser::Readable for RawLSPSMessage {
177+
fn read<R: lightning::io::Read>(r: &mut R) -> Result<Self, lightning::ln::msgs::DecodeError> {
178+
let payload_without_length = WithoutLength::read(r)?;
179+
Ok(Self { payload: payload_without_length.0 })
180+
}
181+
}
164182

165183
impl wire::Type for RawLSPSMessage {
166184
fn type_id(&self) -> u16 {

src/lsps1/msgs.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,7 @@ pub(crate) const LSPS1_CREATE_ORDER_METHOD_NAME: &str = "lsps1.create_order";
2121
pub(crate) const LSPS1_GET_ORDER_METHOD_NAME: &str = "lsps1.get_order";
2222

2323
pub(crate) const LSPS1_CREATE_ORDER_REQUEST_INVALID_PARAMS_ERROR_CODE: i32 = -32602;
24-
pub(crate) const LSPS1_CREATE_ORDER_REQUEST_ORDER_MISMATCH_ERROR_CODE: i32 = 1000;
25-
pub(crate) const LSPS1_CREATE_ORDER_REQUEST_CLIENT_REJECTED_ERROR_CODE: i32 = 1001;
26-
pub(crate) const LSPS1_CREATE_ORDER_REQUEST_INVALID_TOKEN_ERROR_CODE: i32 = 2;
24+
pub(crate) const LSPS1_CREATE_ORDER_REQUEST_ORDER_MISMATCH_ERROR_CODE: i32 = 100;
2725

2826
/// The identifier of an order.
2927
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize, Hash)]

src/lsps2/client.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ where
269269
action: ErrorAction::IgnoreAndLog(Level::Info),
270270
})?;
271271

272-
if let Ok(intercept_scid) = result.intercept_scid.to_scid() {
272+
if let Ok(intercept_scid) = result.jit_channel_scid.to_scid() {
273273
self.pending_events.enqueue(Event::LSPS2Client(
274274
LSPS2ClientEvent::InvoiceParametersReady {
275275
request_id,
@@ -283,7 +283,7 @@ where
283283
return Err(LightningError {
284284
err: format!(
285285
"Received buy response with an invalid intercept scid {:?}",
286-
result.intercept_scid
286+
result.jit_channel_scid
287287
),
288288
action: ErrorAction::IgnoreAndLog(Level::Info),
289289
});

src/lsps2/msgs.rs

+57-5
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@ use crate::utils;
1717
pub(crate) const LSPS2_GET_INFO_METHOD_NAME: &str = "lsps2.get_info";
1818
pub(crate) const LSPS2_BUY_METHOD_NAME: &str = "lsps2.buy";
1919

20-
pub(crate) const LSPS2_GET_INFO_REQUEST_UNRECOGNIZED_OR_STALE_TOKEN_ERROR_CODE: i32 = 2;
20+
pub(crate) const LSPS2_GET_INFO_REQUEST_UNRECOGNIZED_OR_STALE_TOKEN_ERROR_CODE: i32 = 200;
2121

22-
pub(crate) const LSPS2_BUY_REQUEST_INVALID_OPENING_FEE_PARAMS_ERROR_CODE: i32 = 2;
23-
pub(crate) const LSPS2_BUY_REQUEST_PAYMENT_SIZE_TOO_SMALL_ERROR_CODE: i32 = 3;
24-
pub(crate) const LSPS2_BUY_REQUEST_PAYMENT_SIZE_TOO_LARGE_ERROR_CODE: i32 = 4;
22+
pub(crate) const LSPS2_BUY_REQUEST_INVALID_OPENING_FEE_PARAMS_ERROR_CODE: i32 = 201;
23+
pub(crate) const LSPS2_BUY_REQUEST_PAYMENT_SIZE_TOO_SMALL_ERROR_CODE: i32 = 202;
24+
pub(crate) const LSPS2_BUY_REQUEST_PAYMENT_SIZE_TOO_LARGE_ERROR_CODE: i32 = 203;
2525

2626
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
2727
/// A request made to an LSP to learn their current channel fees and parameters.
@@ -150,7 +150,7 @@ impl InterceptScid {
150150
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
151151
pub struct BuyResponse {
152152
/// The intercept short channel id used by LSP to identify need to open channel.
153-
pub intercept_scid: InterceptScid,
153+
pub jit_channel_scid: InterceptScid,
154154
/// The locktime expiry delta the lsp requires.
155155
pub lsp_cltv_expiry_delta: u32,
156156
/// A flag that indicates who is trusting who.
@@ -375,4 +375,56 @@ mod tests {
375375
let json_str = r#"{"opening_fee_params":{"max_client_to_self_delay":128,"max_payment_size_msat":"100000000","min_fee_msat":"100","min_lifetime":144,"min_payment_size_msat":"1","promise":"1134a5c51e3ba2e8f4259610d5e12c1bf4c50ddcd3f8af563e0a00d1fff41dea","proportional":21,"valid_until":"2023-05-20T08:30:45Z"},"payment_size_msat":null}"#;
376376
assert_eq!(buy_request_variable, serde_json::from_str(json_str).unwrap());
377377
}
378+
379+
#[test]
380+
fn parse_spec_test_vectors() {
381+
// Here, we simply assert that we're able to parse all examples given in LSPS2.
382+
let json_str = r#"{
383+
"opening_fee_params_menu": [
384+
{
385+
"min_fee_msat": "546000",
386+
"proportional": 1200,
387+
"valid_until": "2023-02-23T08:47:30.511Z",
388+
"min_lifetime": 1008,
389+
"max_client_to_self_delay": 2016,
390+
"min_payment_size_msat": "1000",
391+
"max_payment_size_msat": "1000000",
392+
"promise": "abcdefghijklmnopqrstuvwxyz"
393+
},
394+
{
395+
"min_fee_msat": "1092000",
396+
"proportional": 2400,
397+
"valid_until": "2023-02-27T21:23:57.984Z",
398+
"min_lifetime": 1008,
399+
"max_client_to_self_delay": 2016,
400+
"min_payment_size_msat": "1000",
401+
"max_payment_size_msat": "1000000",
402+
"promise": "abcdefghijklmnopqrstuvwxyz"
403+
}
404+
]
405+
}"#;
406+
let _get_info_response: GetInfoResponse = serde_json::from_str(json_str).unwrap();
407+
408+
let json_str = r#"{
409+
"opening_fee_params": {
410+
"min_fee_msat": "546000",
411+
"proportional": 1200,
412+
"valid_until": "2023-02-23T08:47:30.511Z",
413+
"min_lifetime": 1008,
414+
"max_client_to_self_delay": 2016,
415+
"min_payment_size_msat": "1000",
416+
"max_payment_size_msat": "1000000",
417+
"promise": "abcdefghijklmnopqrstuvwxyz"
418+
},
419+
"payment_size_msat": "42000"
420+
}"#;
421+
let _buy_request: BuyRequest = serde_json::from_str(json_str).unwrap();
422+
423+
let json_str = r#"{
424+
"jit_channel_scid": "29451x4815x1",
425+
"lsp_cltv_expiry_delta" : 144,
426+
"client_trusts_lsp": false
427+
}"#;
428+
let _buy_response: BuyResponse = serde_json::from_str(json_str).unwrap();
429+
}
378430
}

src/lsps2/service.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -639,7 +639,7 @@ where
639639
.insert_outbound_channel(intercept_scid, outbound_jit_channel);
640640

641641
let response = LSPS2Response::Buy(BuyResponse {
642-
intercept_scid: intercept_scid.into(),
642+
jit_channel_scid: intercept_scid.into(),
643643
lsp_cltv_expiry_delta: cltv_expiry_delta,
644644
client_trusts_lsp,
645645
});

0 commit comments

Comments
 (0)