Skip to content

Commit 2f954ac

Browse files
committed
Present a configured fee claim on register_node
Read fee_claim into NodeConfig and hand it to the LSPS4 client builder, which forwards it on register_node. The LSP verifies the grant and, if valid, drops the node off the standard 2% skim. The claim is node config, not a secret, so it lives in [node] fee_claim. The MDK_FEE_CLAIM env var is a fallback for deployments that inject config through the environment. config.toml wins when both are set. Unset everywhere is the default until the issuer starts minting, which leaves fee_claim None and the node on the standard policy. The ldk-node bumps carry the client plumbing for the third set_liquidity_source_lsps4 argument: - ldk-node (variant client dep) f13fcead -> 06509b7a, pulling rust-lightning 9b5f40f0 (M1 + M2 + the register_node fee_claim parameter). - ldk-node-lsp (lsp-0.7.0 dev-dep) e5fcce06 -> 6449e1b8, pulling rust-lightning bdcdf57d (M1 + M2, no client parameter; this copy is the verifier). The two pull different rust-lightning revs: existing arrangement, not a regression. Client and LSP talk over the wire, so duplicate compilation is fine. The integration test runs a node with a claim bound to its node id and asserts the full 100k arrives instead of 98k, mirroring test_getbalance_after_payment. It only passes if the LSP verifies the signature, so it covers the whole loop. The claim hex is minted offline against the in-tree issuer secret; the regeneration recipe is in a comment next to it. MDK-998 tracks replacing it with a reusable mnemonic-bound vector once lightning-liquidity exposes a mint helper.
1 parent 9ffea5f commit 2f954ac

8 files changed

Lines changed: 266 additions & 150 deletions

File tree

Cargo.lock

Lines changed: 92 additions & 92 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ demo = []
1616

1717
[dependencies]
1818
# Branch: https://github.com/moneydevkit/ldk-node/tree/lsp-0.7.0_accept-underpaying-htlcs_with_timing_logs
19-
ldk-node = { git = "https://github.com/moneydevkit/ldk-node", rev = "f13fcead7e02ef4b77489a83854f204de11e902b" }
19+
ldk-node = { git = "https://github.com/moneydevkit/ldk-node", rev = "06509b7a27952fc42ad6a519bbecd39cd64e7107" }
2020

2121
# Pinned to the same git rev as ldk-node's transitive pull to avoid duplicate
2222
# crate compilation. Verify with `cargo tree -d | grep bitcoin-payment-instructions`.
@@ -45,7 +45,7 @@ base64 = "0.22"
4545
corepc-node = { version = "0.10", features = ["29_0"] }
4646
futures-util = "0.3"
4747
http-body-util = "0.1.3"
48-
ldk-node-lsp = { package = "ldk-node", git = "https://github.com/moneydevkit/ldk-node", rev = "e5fcce065fa97c522de0f8fec87beb9e7e541456" }
48+
ldk-node-lsp = { package = "ldk-node", git = "https://github.com/moneydevkit/ldk-node", rev = "6449e1b8e829a4038512946897dc380179422d87" }
4949
tempfile = "3"
5050
tokio-tungstenite = "0.26"
5151
tower = "0.5.3"

flake.nix

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -72,14 +72,14 @@
7272
"sha256-kJz+7u55DiSy+/7Rpvm9aiB2ZGpds91M3QQ0CzOi9q4=";
7373
"git+https://github.com/moneydevkit/bitcoin-payment-instructions?rev=bdcef061488bcc619142010a2a69cd49462d8843#bdcef061488bcc619142010a2a69cd49462d8843" =
7474
"sha256-oj2zEt1iTQhK+m/2qXzRMHeZ7a+rm3pAO2ZbQXV1h18=";
75-
"git+https://github.com/moneydevkit/ldk-node?rev=e5fcce065fa97c522de0f8fec87beb9e7e541456#e5fcce065fa97c522de0f8fec87beb9e7e541456" =
76-
"sha256-LsodimSQabrGNw0vgoVKWC8pBglRJJYFvLqLL2/TIrA=";
77-
"git+https://github.com/moneydevkit/ldk-node?rev=f13fcead7e02ef4b77489a83854f204de11e902b#f13fcead7e02ef4b77489a83854f204de11e902b" =
78-
"sha256-w1AbC0s3SEuxCVMr0F8Uujw/MG0WyN5afHQK0h0S4Zw=";
79-
"git+https://github.com/moneydevkit/rust-lightning?rev=eecf53e7c763e8ae8e436585858db506a7aac588#eecf53e7c763e8ae8e436585858db506a7aac588" =
80-
"sha256-gRxr9GIIn9fWHhbg/xx2DT4z2CiBS6wVghiIXks/gsI=";
81-
"git+https://github.com/moneydevkit/rust-lightning?rev=f56f47fe6c874771cd079faaacf96c42b32fbe72#f56f47fe6c874771cd079faaacf96c42b32fbe72" =
82-
"sha256-g4+lUlGQVvURW1zizRQjcHfkFVbSV3jjFsyV3ah/kOo=";
75+
"git+https://github.com/moneydevkit/ldk-node?rev=6449e1b8e829a4038512946897dc380179422d87#6449e1b8e829a4038512946897dc380179422d87" =
76+
"sha256-dJam/azTnxC08hiLtNE/5CYp5UWdAJkQnBy6czwFraA=";
77+
"git+https://github.com/moneydevkit/ldk-node?rev=06509b7a27952fc42ad6a519bbecd39cd64e7107#06509b7a27952fc42ad6a519bbecd39cd64e7107" =
78+
"sha256-nSk5PZIN/GrEPDUYt/dsLGmhwY0cneX2DSla6qlXrKE=";
79+
"git+https://github.com/moneydevkit/rust-lightning?rev=bdcdf57de38baeabce4bf8486769bc60d0aa0f8d#bdcdf57de38baeabce4bf8486769bc60d0aa0f8d" =
80+
"sha256-9IDjszL8KOPsTUiOIAy2nU2DTvUaOGDMIutjIYjfc2M=";
81+
"git+https://github.com/moneydevkit/rust-lightning?rev=9b5f40f00a623ff5e1cbe2540d79c3665589be6e#9b5f40f00a623ff5e1cbe2540d79c3665589be6e" =
82+
"sha256-UB1MxvE88orgXTEGxyIzalJ7NLP9n4B66Gm07wHF/DM=";
8383
};
8484
};
8585

src/daemon/config.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ struct NodeSection {
3131
rest_service_address: Option<String>,
3232
alias: Option<String>,
3333
pathfinding_scores_source_url: Option<String>,
34+
fee_claim: Option<String>,
3435
scoring: Option<ScoringSection>,
3536
}
3637

@@ -108,6 +109,7 @@ pub struct MdkConfig {
108109
pub storage_dir_path: Option<String>,
109110
pub log_level: LevelFilter,
110111
pub pathfinding_scores_source_url: Option<String>,
112+
pub fee_claim: Option<String>,
111113
pub scoring_overrides: ScoringOverrides,
112114
pub splice: SpliceConfig,
113115
pub max_sendable: MaxSendableConfig,
@@ -208,6 +210,7 @@ pub fn load_config(path: &str) -> io::Result<MdkConfig> {
208210
storage_dir_path,
209211
log_level,
210212
pathfinding_scores_source_url: node.pathfinding_scores_source_url,
213+
fee_claim: node.fee_claim,
211214
scoring_overrides,
212215
splice,
213216
max_sendable,

src/main.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,12 @@ fn main() {
129129
alias: config_file.alias.map(|a| a.to_string()),
130130
socks_proxy: socks_proxy.clone(),
131131
pathfinding_scores_source_url: config_file.pathfinding_scores_source_url,
132+
// config.toml is the documented surface; MDK_FEE_CLAIM is an undocumented fallback for
133+
// deployments that inject config through the environment (the open-money container, whose
134+
// only runtime seam is env vars and whose baked config.toml cannot carry a per-wallet claim).
135+
fee_claim: config_file
136+
.fee_claim
137+
.or_else(|| std::env::var("MDK_FEE_CLAIM").ok()),
132138
mnemonic: mnemonic_phrase,
133139
infra,
134140
scoring_overrides: config_file.scoring_overrides,

src/mdk/node.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ pub struct NodeConfig {
2929
pub alias: Option<String>,
3030
pub socks_proxy: Option<String>,
3131
pub pathfinding_scores_source_url: Option<String>,
32+
pub fee_claim: Option<String>,
3233
pub mnemonic: String,
3334
pub infra: NetworkInfra,
3435
pub scoring_overrides: ScoringOverrides,
@@ -168,7 +169,7 @@ pub fn build_node(
168169
.map_err(|e| MdkError::InvalidInput(format!("bad lsp_node_id: {e}")))?;
169170
let lsp_addr = SocketAddress::from_str(&infra.lsp_address)
170171
.map_err(|e| MdkError::InvalidInput(format!("bad lsp_address: {e}")))?;
171-
builder.set_liquidity_source_lsps4(lsp_pubkey, lsp_addr);
172+
builder.set_liquidity_source_lsps4(lsp_pubkey, lsp_addr, config.fee_claim);
172173
info!("LSPS4 liquidity source: {}", infra.lsp_node_id);
173174

174175
builder.set_runtime(runtime);

tests/common/mod.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use ldk_node::lightning::ln::msgs::SocketAddress;
1414
use ldk_node::lightning_invoice::Bolt11Invoice;
1515
use ldk_node::{Builder, Node};
1616

17+
use ldk_node_lsp::bitcoin::secp256k1::XOnlyPublicKey;
1718
use ldk_node_lsp::config::Config as LspNodeConfig;
1819
use ldk_node_lsp::lightning::ln::msgs::SocketAddress as LspSocketAddress;
1920
use ldk_node_lsp::liquidity::LSPS4ServiceConfig;
@@ -89,11 +90,14 @@ pub struct MdkdHandle {
8990
}
9091

9192
impl MdkdHandle {
93+
/// `fee_claim`, when set, is written into the `[node]` section of the generated config.toml
94+
/// so the node presents a signed fee-policy grant on `register_node`. `None` omits the key.
9295
pub async fn start(
9396
bitcoind: &TestBitcoind,
9497
webhook_port: Option<u16>,
9598
lsp: Option<&LspNode>,
9699
mnemonic: &str,
100+
fee_claim: Option<&str>,
97101
) -> Self {
98102
#[allow(deprecated)]
99103
let storage_dir = tempfile::tempdir().unwrap().into_path();
@@ -120,12 +124,15 @@ impl MdkdHandle {
120124
let http_password_full = "test_full_password";
121125
let http_password_read_only = "test_readonly_password";
122126

127+
let fee_claim_line = fee_claim
128+
.map(|claim| format!("fee_claim = \"{claim}\"\n"))
129+
.unwrap_or_default();
123130
let config = format!(
124131
r#"[node]
125132
network = "regtest"
126133
listening_addresses = ["127.0.0.1:{p2p_port}"]
127134
rest_service_address = "127.0.0.1:{api_port}"
128-
135+
{fee_claim_line}
129136
[storage.disk]
130137
dir_path = "{storage_dir}"
131138
@@ -375,6 +382,12 @@ pub struct LspNode {
375382

376383
impl LspNode {
377384
pub fn new(bitcoind: &TestBitcoind) -> Self {
385+
Self::with_issuer_keys(bitcoind, vec![])
386+
}
387+
388+
/// Stand up the LSP trusting `issuer_pubkeys` to grant non-standard fee policies via a signed
389+
/// `MDK_FEE_CLAIM`. An empty set (the default `new`) keeps every node on the standard 2% skim.
390+
pub fn with_issuer_keys(bitcoind: &TestBitcoind, issuer_pubkeys: Vec<XOnlyPublicKey>) -> Self {
378391
#[allow(deprecated)]
379392
let storage_dir = tempfile::tempdir().unwrap().into_path();
380393
let p2p_port = find_available_port();
@@ -401,6 +414,7 @@ impl LspNode {
401414
channel_over_provisioning_ppm: 500_000,
402415
forwarding_fee_proportional_millionths: 20_000,
403416
channel_size_tiers: vec![],
417+
issuer_pubkeys,
404418
});
405419

406420
let node = Arc::new(builder.build().unwrap());
@@ -702,6 +716,11 @@ pub fn random_mnemonic() -> String {
702716
.to_string()
703717
}
704718

719+
/// Parse a 32-byte x-only public key from hex, for configuring the LSP's trusted issuer set.
720+
pub fn xonly_from_hex(hex: &str) -> XOnlyPublicKey {
721+
XOnlyPublicKey::from_str(hex).expect("valid x-only pubkey hex")
722+
}
723+
705724
// ---------------------------------------------------------------------------
706725
// LNURL bech32 helper
707726
// ---------------------------------------------------------------------------

0 commit comments

Comments
 (0)