Skip to content

Commit 8f8bd62

Browse files
benthecarmanclaude
andcommitted
Replace protobuf with JSON everywhere
Protobuf added complexity without much benefit for our use case — the binary encoding is opaque, hard to debug with standard HTTP tools, and requires proto toolchain maintenance. JSON is human-readable, widely supported, and sufficient for our throughput needs. This removes prost and all .proto files entirely, renaming the ldk-server-protos crate to ldk-server-json-models. Types are rewritten as hand-written Rust structs and enums with serde derives rather than prost-generated code. Fixed-size byte fields (hashes, channel IDs, public keys) use [u8; 32] and [u8; 33] with hex serde instead of String, giving type safety at the model layer. Several proto-era patterns are cleaned up: wrapper structs that only existed because protobuf wraps oneof in a message are removed, fields that were Option only because proto message fields are nullable are made required where the server always provides them, and the EventEnvelope wrapper is dropped in favor of using Event directly. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 12ce2d1 commit 8f8bd62

82 files changed

Lines changed: 4027 additions & 5748 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/check-protos.yml

Lines changed: 0 additions & 39 deletions
This file was deleted.

CLAUDE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for build commands, testing, code style,
99
- **ldk-server** - Main daemon server (entry point: `src/main.rs`)
1010
- **ldk-server-cli** - CLI client using clap
1111
- **ldk-server-client** - Reqwest-based client library
12-
- **ldk-server-protos** - Protocol buffer definitions and generated Rust code
12+
- **ldk-server-json-models** - Shared JSON request/response types with serde
1313

1414
## Development Rules
1515

CONTRIBUTING.md

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -37,18 +37,11 @@ cargo clippy --all-features -- -D warnings -A clippy::drop_non_drop # Lint (CI
3737
- Hard tabs, max width 100 chars
3838
- Imports grouped: std, external crates, local crates
3939

40-
## Protocol Buffer Generation
41-
42-
```bash
43-
RUSTFLAGS="--cfg genproto" cargo build -p ldk-server-protos
44-
cargo fmt --all
45-
```
46-
4740
## Adding a New API Endpoint
4841

49-
1. Define request/response messages in `ldk-server-protos/src/proto/api.proto`
50-
2. Regenerate protos (see above)
51-
3. Create handler in `ldk-server/src/api/` (follow existing patterns)
42+
1. Define request/response types in `ldk-server-json-models/src/api.rs`
43+
2. Create handler in `ldk-server/src/api/` (follow existing patterns)
44+
3. Add endpoint constant in `ldk-server-json-models/src/endpoints.rs`
5245
4. Add route in `ldk-server/src/service.rs`
5346
5. Add CLI command in `ldk-server-cli/src/main.rs`
5447

Cargo.lock

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

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[workspace]
22
resolver = "2"
3-
members = ["ldk-server-cli", "ldk-server-client", "ldk-server-protos", "ldk-server"]
3+
members = ["ldk-server-cli", "ldk-server-client", "ldk-server-json-models", "ldk-server"]
44
exclude = ["e2e-tests"]
55

66
[profile.release]

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,15 @@
77

88
The primary goal of LDK Server is to provide an efficient, stable, and API-first solution for deploying and managing
99
a Lightning Network node. With its streamlined setup, LDK Server enables users to easily set up, configure, and run
10-
a Lightning node while exposing a robust, language-agnostic API via [Protocol Buffers (Protobuf)](https://protobuf.dev/).
10+
a Lightning node while exposing a robust, language-agnostic REST API with JSON.
1111

1212
### Features
1313

1414
- **Out-of-the-Box Lightning Node**:
1515
- Deploy a Lightning Network node with minimal configuration, no coding required.
1616

1717
- **API-First Design**:
18-
- Exposes a well-defined API using Protobuf, allowing seamless integration with HTTP-clients or applications.
18+
- Exposes a well-defined JSON REST API, allowing seamless integration with HTTP-clients or applications.
1919

2020
- **Powered by LDK**:
2121
- Built on top of LDK-Node, leveraging the modular, reliable, and high-performance architecture of LDK.

e2e-tests/Cargo.lock

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

e2e-tests/Cargo.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,9 @@ corepc-node = { version = "0.10", features = ["download", "29_0"] }
88
tempfile = "3"
99
tokio = { version = "1.38.0", features = ["rt-multi-thread", "macros", "time"] }
1010
ldk-server-client = { path = "../ldk-server-client" }
11-
ldk-server-protos = { path = "../ldk-server-protos", features = ["serde"] }
11+
ldk-server-json-models = { path = "../ldk-server-json-models" }
1212
serde_json = "1.0"
1313
hex-conservative = { version = "0.2", features = ["std"] }
1414
lapin = { version = "2.4.0", features = ["rustls"], default-features = false }
15-
prost = { version = "0.11.6", default-features = false, features = ["std"] }
1615
futures-util = "0.3"
1716
ldk-node = { git = "https://github.com/lightningdevkit/ldk-node", rev = "d1bbf978c8b7abe87ae2e40793556c1fe4e7ea49" }

e2e-tests/build.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,6 @@ fn main() {
4545
println!("cargo:rerun-if-changed=../ldk-server/Cargo.toml");
4646
println!("cargo:rerun-if-changed=../ldk-server-cli/src");
4747
println!("cargo:rerun-if-changed=../ldk-server-cli/Cargo.toml");
48-
println!("cargo:rerun-if-changed=../ldk-server-protos/src");
49-
println!("cargo:rerun-if-changed=../ldk-server-protos/Cargo.toml");
48+
println!("cargo:rerun-if-changed=../ldk-server-json-models/src");
49+
println!("cargo:rerun-if-changed=../ldk-server-json-models/Cargo.toml");
5050
}

e2e-tests/src/lib.rs

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ use std::time::Duration;
1616
use corepc_node::Node;
1717
use hex_conservative::DisplayHex;
1818
use ldk_server_client::client::LdkServerClient;
19-
use ldk_server_client::ldk_server_protos::api::{GetNodeInfoRequest, GetNodeInfoResponse};
20-
use ldk_server_protos::api::{
21-
GetBalancesRequest, ListChannelsRequest, OnchainReceiveRequest, OpenChannelRequest,
19+
use ldk_server_json_models::api::{
20+
GetBalancesRequest, GetNodeInfoRequest, GetNodeInfoResponse, ListChannelsRequest,
21+
OnchainReceiveRequest, OpenChannelRequest,
2222
};
2323

2424
/// Wrapper around a managed bitcoind process for regtest.
@@ -92,7 +92,7 @@ pub struct LdkServerHandle {
9292
pub storage_dir: PathBuf,
9393
pub api_key: String,
9494
pub tls_cert_path: PathBuf,
95-
pub node_id: String,
95+
pub node_id: [u8; 33],
9696
pub exchange_name: String,
9797
client: LdkServerClient,
9898
}
@@ -201,7 +201,7 @@ client_trusts_lsp = true
201201
storage_dir,
202202
api_key,
203203
tls_cert_path,
204-
node_id: String::new(),
204+
node_id: [0u8; 33],
205205
exchange_name,
206206
client,
207207
};
@@ -217,7 +217,7 @@ client_trusts_lsp = true
217217
&self.client
218218
}
219219

220-
pub fn node_id(&self) -> &str {
220+
pub fn node_id(&self) -> &[u8; 33] {
221221
&self.node_id
222222
}
223223

@@ -325,16 +325,14 @@ pub async fn mine_and_sync(
325325
let start = std::time::Instant::now();
326326
loop {
327327
if let Ok(info) = client.get_node_info(GetNodeInfoRequest {}).await {
328-
if info.current_best_block.as_ref().map(|b| b.height).unwrap_or(0)
329-
>= expected_height as u32
330-
{
328+
if info.current_best_block.height >= expected_height as u32 {
331329
break;
332330
}
333331
}
334332
if start.elapsed() > timeout {
335333
panic!(
336334
"Timed out waiting for server {} to sync to height {}",
337-
server.node_id(),
335+
server.node_id().to_lower_hex_string(),
338336
expected_height
339337
);
340338
}
@@ -409,7 +407,7 @@ pub async fn setup_funded_channel(
409407
let open_resp = server_a
410408
.client()
411409
.open_channel(OpenChannelRequest {
412-
node_pubkey: server_b.node_id().to_string(),
410+
node_pubkey: *server_b.node_id(),
413411
address: format!("127.0.0.1:{}", server_b.p2p_port),
414412
channel_amount_sats,
415413
push_to_counterparty_msat: None,
@@ -502,17 +500,16 @@ impl RabbitMqEventConsumer {
502500
/// Consume up to `count` events, waiting up to `timeout` for each.
503501
pub async fn consume_events(
504502
&mut self, count: usize, timeout: Duration,
505-
) -> Vec<ldk_server_protos::events::EventEnvelope> {
503+
) -> Vec<ldk_server_json_models::events::Event> {
506504
use futures_util::StreamExt;
507505
use lapin::options::BasicAckOptions;
508-
use prost::Message;
509506

510507
let mut events = Vec::new();
511508
for _ in 0..count {
512509
match tokio::time::timeout(timeout, self.consumer.next()).await {
513510
Ok(Some(Ok(delivery))) => {
514-
let event = ldk_server_protos::events::EventEnvelope::decode(&*delivery.data)
515-
.expect("Failed to decode event");
511+
let event: ldk_server_json_models::events::Event =
512+
serde_json::from_slice(&delivery.data).expect("Failed to decode event");
516513
self.channel
517514
.basic_ack(delivery.delivery_tag, BasicAckOptions::default())
518515
.await

0 commit comments

Comments
 (0)