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

Commit

Permalink
Merge pull request #124 from tnull/2024-03-fix-payload-serialization
Browse files Browse the repository at this point in the history
Fix `payload` encoding, `jit_channel_scid` serialization, error codes
  • Loading branch information
tnull authored Apr 20, 2024
2 parents 6c5d4a2 + ca150c4 commit 0f52cc6
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 14 deletions.
24 changes: 21 additions & 3 deletions src/lsps0/ser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ use crate::lsps1::msgs::{
use crate::lsps2::msgs::{
LSPS2Message, LSPS2Request, LSPS2Response, LSPS2_BUY_METHOD_NAME, LSPS2_GET_INFO_METHOD_NAME,
};
use crate::prelude::{HashMap, String, ToString, Vec};
use crate::prelude::{HashMap, String, ToString};

use lightning::impl_writeable_msg;
use lightning::ln::msgs::LightningError;
use lightning::ln::wire;
use lightning::util::ser::WithoutLength;

use bitcoin::secp256k1::PublicKey;

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

pub(crate) const _LSPS0_CLIENT_REJECTED_ERROR_CODE: i32 = 001;

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub(crate) enum LSPSMethod {
LSPS0ListProtocols,
Expand Down Expand Up @@ -160,7 +162,23 @@ pub struct RawLSPSMessage {
pub payload: String,
}

impl_writeable_msg!(RawLSPSMessage, { payload }, {});
// We encode `RawLSPSMessage`'s payload without a length prefix as LSPS0 expects it to be the
// remainder of the object.
impl lightning::util::ser::Writeable for RawLSPSMessage {
fn write<W: lightning::util::ser::Writer>(
&self, w: &mut W,
) -> Result<(), lightning::io::Error> {
WithoutLength(&self.payload).write(w)?;
Ok(())
}
}

impl lightning::util::ser::Readable for RawLSPSMessage {
fn read<R: lightning::io::Read>(r: &mut R) -> Result<Self, lightning::ln::msgs::DecodeError> {
let payload_without_length = WithoutLength::read(r)?;
Ok(Self { payload: payload_without_length.0 })
}
}

impl wire::Type for RawLSPSMessage {
fn type_id(&self) -> u16 {
Expand Down
4 changes: 1 addition & 3 deletions src/lsps1/msgs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,7 @@ pub(crate) const LSPS1_CREATE_ORDER_METHOD_NAME: &str = "lsps1.create_order";
pub(crate) const LSPS1_GET_ORDER_METHOD_NAME: &str = "lsps1.get_order";

pub(crate) const LSPS1_CREATE_ORDER_REQUEST_INVALID_PARAMS_ERROR_CODE: i32 = -32602;
pub(crate) const LSPS1_CREATE_ORDER_REQUEST_ORDER_MISMATCH_ERROR_CODE: i32 = 1000;
pub(crate) const LSPS1_CREATE_ORDER_REQUEST_CLIENT_REJECTED_ERROR_CODE: i32 = 1001;
pub(crate) const LSPS1_CREATE_ORDER_REQUEST_INVALID_TOKEN_ERROR_CODE: i32 = 2;
pub(crate) const LSPS1_CREATE_ORDER_REQUEST_ORDER_MISMATCH_ERROR_CODE: i32 = 100;

/// The identifier of an order.
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize, Hash)]
Expand Down
4 changes: 2 additions & 2 deletions src/lsps2/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ where
action: ErrorAction::IgnoreAndLog(Level::Info),
})?;

if let Ok(intercept_scid) = result.intercept_scid.to_scid() {
if let Ok(intercept_scid) = result.jit_channel_scid.to_scid() {
self.pending_events.enqueue(Event::LSPS2Client(
LSPS2ClientEvent::InvoiceParametersReady {
request_id,
Expand All @@ -283,7 +283,7 @@ where
return Err(LightningError {
err: format!(
"Received buy response with an invalid intercept scid {:?}",
result.intercept_scid
result.jit_channel_scid
),
action: ErrorAction::IgnoreAndLog(Level::Info),
});
Expand Down
62 changes: 57 additions & 5 deletions src/lsps2/msgs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ use crate::utils;
pub(crate) const LSPS2_GET_INFO_METHOD_NAME: &str = "lsps2.get_info";
pub(crate) const LSPS2_BUY_METHOD_NAME: &str = "lsps2.buy";

pub(crate) const LSPS2_GET_INFO_REQUEST_UNRECOGNIZED_OR_STALE_TOKEN_ERROR_CODE: i32 = 2;
pub(crate) const LSPS2_GET_INFO_REQUEST_UNRECOGNIZED_OR_STALE_TOKEN_ERROR_CODE: i32 = 200;

pub(crate) const LSPS2_BUY_REQUEST_INVALID_OPENING_FEE_PARAMS_ERROR_CODE: i32 = 2;
pub(crate) const LSPS2_BUY_REQUEST_PAYMENT_SIZE_TOO_SMALL_ERROR_CODE: i32 = 3;
pub(crate) const LSPS2_BUY_REQUEST_PAYMENT_SIZE_TOO_LARGE_ERROR_CODE: i32 = 4;
pub(crate) const LSPS2_BUY_REQUEST_INVALID_OPENING_FEE_PARAMS_ERROR_CODE: i32 = 201;
pub(crate) const LSPS2_BUY_REQUEST_PAYMENT_SIZE_TOO_SMALL_ERROR_CODE: i32 = 202;
pub(crate) const LSPS2_BUY_REQUEST_PAYMENT_SIZE_TOO_LARGE_ERROR_CODE: i32 = 203;

#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
/// A request made to an LSP to learn their current channel fees and parameters.
Expand Down Expand Up @@ -150,7 +150,7 @@ impl InterceptScid {
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub struct BuyResponse {
/// The intercept short channel id used by LSP to identify need to open channel.
pub intercept_scid: InterceptScid,
pub jit_channel_scid: InterceptScid,
/// The locktime expiry delta the lsp requires.
pub lsp_cltv_expiry_delta: u32,
/// A flag that indicates who is trusting who.
Expand Down Expand Up @@ -375,4 +375,56 @@ mod tests {
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}"#;
assert_eq!(buy_request_variable, serde_json::from_str(json_str).unwrap());
}

#[test]
fn parse_spec_test_vectors() {
// Here, we simply assert that we're able to parse all examples given in LSPS2.
let json_str = r#"{
"opening_fee_params_menu": [
{
"min_fee_msat": "546000",
"proportional": 1200,
"valid_until": "2023-02-23T08:47:30.511Z",
"min_lifetime": 1008,
"max_client_to_self_delay": 2016,
"min_payment_size_msat": "1000",
"max_payment_size_msat": "1000000",
"promise": "abcdefghijklmnopqrstuvwxyz"
},
{
"min_fee_msat": "1092000",
"proportional": 2400,
"valid_until": "2023-02-27T21:23:57.984Z",
"min_lifetime": 1008,
"max_client_to_self_delay": 2016,
"min_payment_size_msat": "1000",
"max_payment_size_msat": "1000000",
"promise": "abcdefghijklmnopqrstuvwxyz"
}
]
}"#;
let _get_info_response: GetInfoResponse = serde_json::from_str(json_str).unwrap();

let json_str = r#"{
"opening_fee_params": {
"min_fee_msat": "546000",
"proportional": 1200,
"valid_until": "2023-02-23T08:47:30.511Z",
"min_lifetime": 1008,
"max_client_to_self_delay": 2016,
"min_payment_size_msat": "1000",
"max_payment_size_msat": "1000000",
"promise": "abcdefghijklmnopqrstuvwxyz"
},
"payment_size_msat": "42000"
}"#;
let _buy_request: BuyRequest = serde_json::from_str(json_str).unwrap();

let json_str = r#"{
"jit_channel_scid": "29451x4815x1",
"lsp_cltv_expiry_delta" : 144,
"client_trusts_lsp": false
}"#;
let _buy_response: BuyResponse = serde_json::from_str(json_str).unwrap();
}
}
2 changes: 1 addition & 1 deletion src/lsps2/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -639,7 +639,7 @@ where
.insert_outbound_channel(intercept_scid, outbound_jit_channel);

let response = LSPS2Response::Buy(BuyResponse {
intercept_scid: intercept_scid.into(),
jit_channel_scid: intercept_scid.into(),
lsp_cltv_expiry_delta: cltv_expiry_delta,
client_trusts_lsp,
});
Expand Down

0 comments on commit 0f52cc6

Please sign in to comment.