Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions libs/gl-client-py/glclient/greenlight.proto
Original file line number Diff line number Diff line change
Expand Up @@ -187,8 +187,8 @@ message NodeConfig {


// The `GlConfig` is used to pass greenlight-specific startup parameters
// to the node. The `gl-plugin` will look for a serialized config object in
// the node's datastore to load these values from. Please refer to the
// to the node. The `gl-plugin` will look for a serialized config object in
// the node's datastore to load these values from. Please refer to the
// individual fields to learn what they do.
message GlConfig {
string close_to_addr = 1;
Expand Down Expand Up @@ -240,7 +240,7 @@ message LspInvoiceRequest {
// Optional: for discounts/API keys
string token = 2; // len=0 => None
// Pass-through of cln invoice rpc params
uint64 amount_msat = 3; // 0 => Any
uint64 amount_msat = 3; // 0 => Any
string description = 4;
string label = 5;
}
Expand All @@ -250,6 +250,10 @@ message LspInvoiceResponse {
uint32 expires_at = 3;
bytes payment_hash = 4;
bytes payment_secret = 5;
// The fee charged by the LSP for opening a JIT channel, in
// millisatoshi. This is 0 if the node already had sufficient
// incoming capacity and no JIT channel was needed.
uint64 opening_fee_msat = 6;
}

// Request for streaming node events. Currently empty but defined as
Expand Down
26 changes: 13 additions & 13 deletions libs/gl-client-py/glclient/greenlight_pb2.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 10 additions & 3 deletions libs/gl-client-py/glclient/greenlight_pb2.pyi

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions libs/gl-client-py/tests/test_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,3 +236,8 @@ def test_lsps_plugin_calls(clients, bitcoind, node_factory, lsps_server):
assert len(inv.route_hints.route_hints) == 1
rh = inv.route_hints.route_hints[0]
assert rh.pubkey == bytes.fromhex(lsp_id)

# The response should include the LSP opening fee computed from
# the LSPS2 fee parameters (min_fee_msat=1000, proportional=1000).
# For 31337 msat: max(1000, ceil(31337 * 1000 / 1_000_000)) = 1000
assert res.opening_fee_msat == 1000
10 changes: 7 additions & 3 deletions libs/gl-client/.resources/proto/glclient/greenlight.proto

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 7 additions & 3 deletions libs/gl-plugin/.resources/proto/glclient/greenlight.proto

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 13 additions & 1 deletion libs/gl-plugin/src/node/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@ impl Node for PluginNodeServer {
expires_at: res.expires_at as u32,
payment_hash: <cln_rpc::primitives::Sha256 as Borrow<[u8]>>::borrow(&res.payment_hash).to_vec(),
payment_secret: res.payment_secret.to_vec(),
opening_fee_msat: 0,
}));
}

Expand Down Expand Up @@ -279,8 +280,18 @@ impl Node for PluginNodeServer {
let lsp = &lsps[0];
log::info!("Selecting {:?} for invoice negotiation", lsp);

// Compute the expected opening fee from the LSP's fee parameters.
let opening_fee_msat = lsp.params.first().map_or(0, |p| {
let min_fee: u64 = p.min_fee_msat.parse().unwrap_or(0);
let proportional_fee = req
.amount_msat
.saturating_mul(p.proportional)
.div_ceil(1_000_000);
std::cmp::max(min_fee, proportional_fee)
});

// Use the new RPC method name for versions > v25.05gl1
let res = if *version > *"v25.05gl1" {
let mut res = if *version > *"v25.05gl1" {
let mut invreq: crate::requests::LspInvoiceRequestV2 = req.into();
invreq.lsp_id = lsp.node_id.to_owned();
rpc.call_typed(&invreq)
Expand All @@ -294,6 +305,7 @@ impl Node for PluginNodeServer {
.map_err(|e| Status::new(Code::Internal, e.to_string()))?
};

res.opening_fee_msat = opening_fee_msat;
Ok(Response::new(res.into()))
}

Expand Down
Loading
Loading