Skip to content
Open
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
4924e83
feat: impl sig spec test
GrapeBaBa Dec 22, 2025
0233f7d
feat: add signature spec test
GrapeBaBa Dec 27, 2025
a27a789
fix: fix signature test
GrapeBaBa Jan 3, 2026
5e56317
fix: bootstrap spectest:run when missing generated index
Jan 14, 2026
ff26975
fix(spectest): support verify_signatures attestations + proofs
Jan 15, 2026
71c50b4
chore: fix zig fmt step and rust lint
Jan 15, 2026
164aca4
Apply suggestion from @Copilot
GrapeBaBa Jan 15, 2026
ffe61b6
fix(spectest): stop using ctx allocator in signature parsing
Jan 16, 2026
c45ec58
Merge branch 'main' of github.com:blockblaz/zeam into sig_spec_test
Jan 22, 2026
ebb40d1
refactor: align latest spec test
Jan 22, 2026
f6abf9c
Merge branch 'main' into sig_spec_test
GrapeBaBa Jan 22, 2026
9fe4b7b
refactor: hashsig test scheme
Jan 23, 2026
cf0df8f
fix: fix test
Jan 23, 2026
1a33798
fix: fix lint
Jan 23, 2026
9b24b2b
fix: fix review comments
Jan 23, 2026
961ee03
fix: fix review comments
Jan 23, 2026
fc8eb66
Merge remote-tracking branch 'origin/main' into sig_spec_test
Jan 23, 2026
4e7046f
Merge branch 'main' into sig_spec_test
GrapeBaBa Jan 23, 2026
51f2ff4
feat: add API endpoint versioning (#514)
ch4r10t33r Jan 24, 2026
074c1c6
refactor: rename justified endpoint to /lean/v0/checkpoints/justified…
ch4r10t33r Jan 24, 2026
bdb711a
fix snappy frame decoding boundaries for req/resp (#515)
shariqnaiyer Jan 25, 2026
5c6b6f1
add OCI labels for git commit and branch to docker images (#493)
KatyaRyazantseva Jan 25, 2026
97e2760
update to use SSZ hasher agnostic hashTreeRoot API (#474)
chetanyb Jan 25, 2026
28f4bca
Merge remote-tracking branch 'origin/main' into sig_spec_test
Jan 25, 2026
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
3 changes: 3 additions & 0 deletions .github/workflows/auto-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,9 @@ jobs:
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-args: |
GIT_COMMIT=${{ github.sha }}
GIT_BRANCH=${{ github.ref_name }}
cache-from: type=gha
cache-to: type=gha,mode=max
provenance: false
Expand Down
6 changes: 6 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,12 @@ RUN mkdir -p /runtime-libs && \
# Runtime stage - using scratch for absolute minimal size
FROM scratch AS runtime

ARG GIT_COMMIT=unknown
ARG GIT_BRANCH=unknown

LABEL org.opencontainers.image.revision=$GIT_COMMIT
LABEL org.opencontainers.image.ref.name=$GIT_BRANCH

# Copy the architecture-specific libraries and loader
COPY --from=runtime-prep /runtime-libs/ /

Expand Down
6 changes: 6 additions & 0 deletions Dockerfile.prebuilt
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ RUN mkdir -p /runtime-libs && \
# Runtime stage - using scratch for minimal size
FROM scratch AS runtime

ARG GIT_COMMIT=unknown
ARG GIT_BRANCH=unknown

LABEL org.opencontainers.image.revision=$GIT_COMMIT
LABEL org.opencontainers.image.ref.name=$GIT_BRANCH

# Copy the architecture-specific libraries and loader
COPY --from=runtime-prep /runtime-libs/ /

Expand Down
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,14 @@ zig build -Doptimize=ReleaseFast -Dgit_version="$(git rev-parse --short HEAD)"
docker build -f Dockerfile.prebuilt -t zeam:local .
```

For publishing to a public registry, add OCI labels for better traceability:
```bash
docker build -f Dockerfile.prebuilt \
--build-arg GIT_COMMIT=$(git rev-parse HEAD) \
--build-arg GIT_BRANCH=$(git rev-parse --abbrev-ref HEAD) \
-t blockblaz/zeam:latest .
```

#### Prerequisites

- Zeam requires zig version 0.14.1 to build.
Expand Down
8 changes: 8 additions & 0 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ pub fn build(b: *Builder) !void {
});
zeam_utils.addImport("datetime", datetime);
zeam_utils.addImport("yaml", yaml);
zeam_utils.addImport("ssz", ssz);

// add zeam-params
const zeam_params = b.addModule("@zeam/params", .{
Expand Down Expand Up @@ -221,6 +222,7 @@ pub fn build(b: *Builder) !void {
});
zeam_key_manager.addImport("@zeam/xmss", zeam_xmss);
zeam_key_manager.addImport("@zeam/types", zeam_types);
zeam_key_manager.addImport("@zeam/utils", zeam_utils);
zeam_key_manager.addImport("@zeam/metrics", zeam_metrics);
zeam_key_manager.addImport("ssz", ssz);

Expand Down Expand Up @@ -319,6 +321,7 @@ pub fn build(b: *Builder) !void {
zeam_spectests.addImport("build_options", build_options_module);
zeam_spectests.addImport("@zeam/state-transition", zeam_state_transition);
zeam_spectests.addImport("@zeam/node", zeam_beam_node);
zeam_spectests.addImport("@zeam/xmss", zeam_xmss);

// Add the cli executable
const cli_exe = b.addExecutable(.{
Expand Down Expand Up @@ -570,6 +573,10 @@ pub fn build(b: *Builder) !void {
spectests.root_module.addImport("@zeam/metrics", zeam_metrics);
spectests.root_module.addImport("@zeam/state-transition", zeam_state_transition);
spectests.root_module.addImport("ssz", ssz);
spectests.root_module.addImport("@zeam/xmss", zeam_xmss);

spectests.step.dependOn(&build_rust_lib_steps.step);
addRustGlueLib(b, spectests, target, prover);

manager_tests.step.dependOn(&build_rust_lib_steps.step);

Expand Down Expand Up @@ -728,6 +735,7 @@ fn build_zkvm_targets(b: *Builder, main_exe: *Builder.Step, host_target: std.Bui
.optimize = optimize,
.root_source_file = b.path("pkgs/utils/src/lib.zig"),
});
zeam_utils.addImport("ssz", ssz);

// add zeam-metrics (core metrics definitions for ZKVM)
const zeam_metrics = b.addModule("@zeam/metrics", .{
Expand Down
4 changes: 2 additions & 2 deletions build.zig.zon
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
.version = "0.0.0",
.dependencies = .{
.ssz = .{
.url = "git+https://github.com/blockblaz/ssz.zig#5ce7322fc45cab4f215021cae2579d1343e05d55",
.hash = "ssz-0.0.9-Lfwd61PEAgAUPJfUQiK4R5gRX_lTWOd_qYwNT-KAhRLA",
.url = "https://github.com/blockblaz/ssz.zig/archive/0ce92a8f093a321b0d0815eec6c90bd4e745d8e1.tar.gz",

Copilot AI Jan 25, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The dependency changed from a git URL with fragment to a tarball archive URL. While valid, ensure this commit (0ce92a8) is stable and won't be force-pushed, as tarballs don't have the same ref protection as git tags.

Suggested change
.url = "https://github.com/blockblaz/ssz.zig/archive/0ce92a8f093a321b0d0815eec6c90bd4e745d8e1.tar.gz",
.url = "https://github.com/blockblaz/ssz.zig/archive/v0.0.9.tar.gz",

Copilot uses AI. Check for mistakes.
.hash = "ssz-0.0.9-Lfwd6wvKAgA3JZjtfbeXeQG6zle1K_K2j6HPmQJJF4an",
},
.zigcli = .{
.url = "git+https://github.com/jiacai2050/zigcli?ref=main#dcbc59d70b4787671c8a4e484ffd2b725aa17af5",
Expand Down
2 changes: 1 addition & 1 deletion leanSpec
Submodule leanSpec updated 82 files
+65 −0 .dockerignore
+1 −1 .github/workflows/prod-vectors.yml
+3 −0 .gitignore
+1 −1 CONTRIBUTING.md
+203 −0 DOCKER_QUICKSTART.md
+145 −0 Dockerfile
+85 −12 README.md
+2 −0 VERSIONS.md
+ lean_consensus.pdf
+6 −4 pyproject.toml
+238 −21 src/lean_spec/__main__.py
+2 −2 src/lean_spec/subspecs/api/__init__.py
+4 −4 src/lean_spec/subspecs/api/client.py
+34 −5 src/lean_spec/subspecs/api/server.py
+0 −2 src/lean_spec/subspecs/chain/__init__.py
+28 −3 src/lean_spec/subspecs/chain/clock.py
+1 −31 src/lean_spec/subspecs/chain/config.py
+85 −35 src/lean_spec/subspecs/chain/service.py
+35 −22 src/lean_spec/subspecs/containers/state/state.py
+6 −6 src/lean_spec/subspecs/containers/state/types.py
+24 −11 src/lean_spec/subspecs/forkchoice/store.py
+67 −62 src/lean_spec/subspecs/genesis/config.py
+511 −58 src/lean_spec/subspecs/networking/client/event_source.py
+59 −8 src/lean_spec/subspecs/networking/client/reqresp_client.py
+15 −0 src/lean_spec/subspecs/networking/config.py
+64 −0 src/lean_spec/subspecs/networking/gossipsub/__init__.py
+875 −0 src/lean_spec/subspecs/networking/gossipsub/behavior.py
+2 −4 src/lean_spec/subspecs/networking/gossipsub/parameters.py
+720 −0 src/lean_spec/subspecs/networking/gossipsub/rpc.py
+1 −3 src/lean_spec/subspecs/networking/reqresp/codec.py
+73 −38 src/lean_spec/subspecs/networking/reqresp/handler.py
+5 −0 src/lean_spec/subspecs/networking/transport/connection/manager.py
+1 −2 src/lean_spec/subspecs/networking/transport/multistream/negotiation.py
+9 −5 src/lean_spec/subspecs/networking/transport/noise/payload.py
+4 −2 src/lean_spec/subspecs/networking/transport/peer_id.py
+22 −0 src/lean_spec/subspecs/networking/transport/quic/__init__.py
+696 −0 src/lean_spec/subspecs/networking/transport/quic/connection.py
+408 −0 src/lean_spec/subspecs/networking/transport/quic/tls.py
+2 −2 src/lean_spec/subspecs/networking/varint.py
+11 −3 src/lean_spec/subspecs/node/node.py
+3 −0 src/lean_spec/subspecs/ssz/constants.py
+17 −15 src/lean_spec/subspecs/ssz/hash.py
+42 −16 src/lean_spec/subspecs/ssz/merkleization.py
+7 −22 src/lean_spec/subspecs/ssz/pack.py
+13 −1 src/lean_spec/subspecs/sync/service.py
+147 −50 src/lean_spec/subspecs/validator/registry.py
+36 −5 src/lean_spec/subspecs/validator/service.py
+12 −7 src/lean_spec/subspecs/xmss/aggregation.py
+5 −2 src/lean_spec/subspecs/xmss/interface.py
+7 −6 src/lean_spec/subspecs/xmss/subtree.py
+1 −2 src/lean_spec/types/__init__.py
+6 −10 src/lean_spec/types/bitfields.py
+0 −6 src/lean_spec/types/byte_arrays.py
+48 −86 src/lean_spec/types/collections.py
+32 −1 src/lean_spec/types/exceptions.py
+10 −44 src/lean_spec/types/union.py
+65 −5 tests/lean_spec/subspecs/api/test_server.py
+100 −10 tests/lean_spec/subspecs/chain/test_clock.py
+293 −62 tests/lean_spec/subspecs/chain/test_service.py
+270 −52 tests/lean_spec/subspecs/containers/test_state_aggregation.py
+6 −30 tests/lean_spec/subspecs/containers/test_state_justified_slots.py
+32 −64 tests/lean_spec/subspecs/forkchoice/test_time_management.py
+37 −8 tests/lean_spec/subspecs/forkchoice/test_validator.py
+96 −46 tests/lean_spec/subspecs/genesis/test_config.py
+21 −25 tests/lean_spec/subspecs/networking/client/test_gossip_reception.py
+368 −0 tests/lean_spec/subspecs/networking/test_gossipsub.py
+1 −1 tests/lean_spec/subspecs/networking/test_network_service.py
+5 −3 tests/lean_spec/subspecs/networking/test_reqresp.py
+2 −2 tests/lean_spec/subspecs/networking/transport/multistream/test_negotiation.py
+18 −14 tests/lean_spec/subspecs/networking/transport/noise/test_payload.py
+7 −7 tests/lean_spec/subspecs/networking/transport/test_peer_id.py
+78 −1 tests/lean_spec/subspecs/node/test_node.py
+388 −0 tests/lean_spec/subspecs/ssz/test_boundary_values.py
+457 −0 tests/lean_spec/subspecs/ssz/test_edge_cases.py
+369 −0 tests/lean_spec/subspecs/ssz/test_malformed_data.py
+402 −0 tests/lean_spec/subspecs/ssz/test_nested_structures.py
+1 −1 tests/lean_spec/subspecs/sync/test_service.py
+84 −28 tests/lean_spec/subspecs/validator/test_registry.py
+2 −2 tests/lean_spec/subspecs/validator/test_service.py
+44 −0 tests/lean_spec/subspecs/xmss/test_interface.py
+87 −1 tests/lean_spec/subspecs/xmss/test_merkle_tree.py
+103 −5 uv.lock
51 changes: 44 additions & 7 deletions pkgs/api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@

## Overview

This package provides the HTTP API server for the Zeam node with three main endpoints:
This package provides the HTTP API server for the Zeam node with five main endpoints:

- Server-Sent Events (SSE) stream for real-time chain events at `/events`
- Prometheus metrics endpoint at `/metrics`
- Health check at `/health`
- Health check at `/lean/v0/health`
- Finalized checkpoint state at `/lean/v0/states/finalized` (for checkpoint sync)
- Justified checkpoint information at `/lean/v0/checkpoints/justified`

## Package Components

Expand All @@ -31,7 +33,7 @@ Provides real-time chain event streaming via Server-Sent Events:

### 2. Health Checks

Simple health check endpoint at `/health`.
Simple health check endpoint at `/lean/v0/health`.

## Event System

Expand Down Expand Up @@ -97,14 +99,41 @@ Streams real-time chain events (head, justification, finalization).
curl -N http://localhost:9667/events
```

### `/health`
### `/lean/v0/health`

Returns node health status.

```sh
curl http://localhost:9667/health
curl http://localhost:9667/lean/v0/health
```

### `/lean/v0/states/finalized`

Returns the finalized checkpoint state as SSZ-encoded binary for checkpoint sync.

```sh
curl http://localhost:9667/lean/v0/states/finalized -o finalized_state.ssz
```

Returns:
- **Content-Type**: `application/octet-stream`
- **Body**: SSZ-encoded `BeamState`
- **Status 503**: Returned if no finalized state is available yet

### `/lean/v0/checkpoints/justified`

Returns the latest justified checkpoint information as JSON.

```sh
curl http://localhost:9667/lean/v0/checkpoints/justified
```

Returns:
- **Content-Type**: `application/json`
- **Body**: JSON object with `slot` and `root` fields
- **Status 503**: Returned if chain is not initialized
- **Example response**: `{"root":"0x1234...","slot":42}`

## Usage

### Initialization
Expand All @@ -122,7 +151,9 @@ try api_server.startAPIServer(allocator, apiPort);
The server exposes:
- SSE at `/events`
- Metrics at `/metrics`
- Health at `/health`
- Health at `/lean/v0/health`
- Checkpoint state at `/lean/v0/states/finalized`
- Justified checkpoint at `/lean/v0/checkpoints/justified`

**Note**: On freestanding targets (ZKVM), the HTTP server is automatically disabled.

Expand Down Expand Up @@ -179,7 +210,13 @@ curl -N http://localhost:9668/events
curl http://localhost:9668/metrics

# Health
curl http://localhost:9668/health
curl http://localhost:9668/lean/v0/health

# Checkpoint state
curl http://localhost:9668/lean/v0/states/finalized -o state.ssz

# Justified checkpoint
curl http://localhost:9668/lean/v0/checkpoints/justified
```

## Visualization with Prometheus & Grafana
Expand Down
48 changes: 43 additions & 5 deletions pkgs/cli/src/api_server.zig
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ const node_lib = @import("@zeam/node");
const BeamChain = node_lib.chainFactory.BeamChain;

/// API server that runs in a background thread
/// Handles metrics, SSE events, health checks, and checkpoint state endpoints
/// chain is optional - if null, the finalized state endpoint will return 503
/// Handles metrics, SSE events, health checks, checkpoint endpoints, and finalized state
/// chain is optional - if null, endpoints will return 503
/// (API server starts before chain initialization, so chain may not be available yet)
pub fn startAPIServer(allocator: std.mem.Allocator, port: u16, logger_config: *LoggerConfig, chain: ?*BeamChain) !void {
// Initialize the global event broadcaster for SSE events
Expand Down Expand Up @@ -98,15 +98,21 @@ const ApiServer = struct {
} else if (std.mem.eql(u8, request.head.target, "/metrics")) {
// Handle metrics request
self.handleMetrics(&request);
} else if (std.mem.eql(u8, request.head.target, "/health")) {
} else if (std.mem.eql(u8, request.head.target, "/lean/v0/health")) {
// Handle health check
self.handleHealth(&request);
} else if (std.mem.eql(u8, request.head.target, "/lean/states/finalized")) {
} else if (std.mem.eql(u8, request.head.target, "/lean/v0/states/finalized")) {
// Handle finalized checkpoint state endpoint
self.handleFinalizedCheckpointState(&request) catch |err| {
self.logger.warn("failed to handle finalized checkpoint state request: {}", .{err});
_ = request.respond("Internal Server Error\n", .{ .status = .internal_server_error }) catch {};
};
} else if (std.mem.eql(u8, request.head.target, "/lean/v0/checkpoints/justified")) {
// Handle justified checkpoint endpoint
self.handleJustifiedCheckpoint(&request) catch |err| {
self.logger.warn("failed to handle justified checkpoint request: {}", .{err});
_ = request.respond("Internal Server Error\n", .{ .status = .internal_server_error }) catch {};
};
} else {
_ = request.respond("Not Found\n", .{ .status = .not_found }) catch {};
}
Expand Down Expand Up @@ -140,7 +146,7 @@ const ApiServer = struct {
}

/// Handle finalized checkpoint state endpoint
/// Serves the finalized checkpoint lean state (BeamState) as SSZ octet-stream at /lean/states/finalized
/// Serves the finalized checkpoint lean state (BeamState) as SSZ octet-stream at /lean/v0/states/finalized
fn handleFinalizedCheckpointState(self: *const Self, request: *std.http.Server.Request) !void {
// Get the chain (may be null if API server started before chain initialization)
const chain = self.chain orelse {
Expand Down Expand Up @@ -180,6 +186,38 @@ const ApiServer = struct {
};
}

/// Handle justified checkpoint endpoint
/// Returns checkpoint info as JSON at /lean/v0/checkpoints/justified
/// Useful for monitoring consensus progress and fork choice state
fn handleJustifiedCheckpoint(self: *const Self, request: *std.http.Server.Request) !void {
// Get the chain (may be null if API server started before chain initialization)
const chain = self.chain orelse {
_ = request.respond("Service Unavailable: Chain not initialized\n", .{ .status = .service_unavailable }) catch {};
return;
};

// Get justified checkpoint from chain (chain handles its own locking internally)
const justified_checkpoint = chain.getJustifiedCheckpoint();

// Convert checkpoint to JSON string
const json_string = justified_checkpoint.toJsonString(self.allocator) catch |err| {
self.logger.err("failed to serialize justified checkpoint to JSON: {}", .{err});
_ = request.respond("Internal Server Error: Serialization failed\n", .{ .status = .internal_server_error }) catch {};
return;
};
defer self.allocator.free(json_string);

// Respond with JSON
_ = request.respond(json_string, .{
.extra_headers = &.{
.{ .name = "content-type", .value = "application/json; charset=utf-8" },
},
}) catch |err| {
self.logger.warn("failed to respond with justified checkpoint: {}", .{err});
return err;
};
}

/// Handle SSE events endpoint
fn handleSSEEvents(self: *const Self, stream: std.net.Stream) !void {
// Set SSE headers manually by writing HTTP response
Expand Down
2 changes: 1 addition & 1 deletion pkgs/cli/src/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ pub const NodeCommand = struct {
.override_genesis_time = "Override genesis time in the config.yaml",
.@"sig-keys-dir" = "Relative path of custom genesis to signature key directory",
.@"data-dir" = "Path to the data directory",
.@"checkpoint-sync-url" = "URL to fetch finalized checkpoint state from for checkpoint sync (e.g., http://localhost:5052/lean/states/finalized)",
.@"checkpoint-sync-url" = "URL to fetch finalized checkpoint state from for checkpoint sync (e.g., http://localhost:5052/lean/v0/states/finalized)",
.help = "Show help information for the node command",
};
};
Expand Down
10 changes: 5 additions & 5 deletions pkgs/cli/src/node.zig
Original file line number Diff line number Diff line change
Expand Up @@ -656,7 +656,7 @@ fn verifyCheckpointState(

// Calculate the block root from the properly constructed block header
var block_root: types.Root = undefined;
try ssz.hashTreeRoot(types.BeamBlockHeader, state_block_header, &block_root, allocator);
try zeam_utils.hashTreeRoot(types.BeamBlockHeader, state_block_header, &block_root, allocator);

logger.info("checkpoint state verified: slot={d}, genesis_time={d}, validators={d}, state_root=0x{s}, block_root=0x{s}", .{
state.slot,
Expand Down Expand Up @@ -1201,7 +1201,7 @@ test "compare roots from genGensisBlock and genGenesisState and genStateBlockHea

// Get state root by hashing the state directly
var state_root_from_genesis: [32]u8 = undefined;
try ssz.hashTreeRoot(types.BeamState, genesis_state, &state_root_from_genesis, allocator);
try zeam_utils.hashTreeRoot(types.BeamState, genesis_state, &state_root_from_genesis, allocator);

// Generate block header using genStateBlockHeader
const state_block_header = try genesis_state.genStateBlockHeader(allocator);
Expand Down Expand Up @@ -1265,11 +1265,11 @@ test "checkpoint-sync-url parameter is optional" {
.@"node-id" = "test",
.validator_config = "test",
.override_genesis_time = null,
.@"checkpoint-sync-url" = "http://localhost:5052/lean/states/finalized",
.@"checkpoint-sync-url" = "http://localhost:5052/lean/v0/states/finalized",
};

try std.testing.expect(node_cmd_with_url.@"checkpoint-sync-url" != null);
try std.testing.expectEqualStrings(node_cmd_with_url.@"checkpoint-sync-url".?, "http://localhost:5052/lean/states/finalized");
try std.testing.expectEqualStrings(node_cmd_with_url.@"checkpoint-sync-url".?, "http://localhost:5052/lean/v0/states/finalized");
}

test "NodeOptions checkpoint_sync_url field is optional" {
Expand Down Expand Up @@ -1314,6 +1314,6 @@ test "NodeOptions checkpoint_sync_url field is optional" {
try std.testing.expect(node_options.checkpoint_sync_url == null);

// Test with a URL
node_options.checkpoint_sync_url = "http://localhost:5052/lean/states/finalized";
node_options.checkpoint_sync_url = "http://localhost:5052/lean/v0/states/finalized";
try std.testing.expect(node_options.checkpoint_sync_url != null);
}
8 changes: 4 additions & 4 deletions pkgs/cli/test/fixtures/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -272,10 +272,10 @@ To enable checkpoint sync, add the `--checkpoint-sync-url` parameter:
--validator_config genesis_bootnode \
--override_genesis_time $GENESIS_TIME \
--data-dir ./data/test_node1 \
--checkpoint-sync-url http://localhost:5052/lean/states/finalized
--checkpoint-sync-url http://localhost:5052/lean/v0/states/finalized
```

The URL should point to a zeam node's checkpoint state endpoint (e.g., `http://localhost:5052/lean/states/finalized` if the source node has metrics enabled on port 5052).
The URL should point to a zeam node's checkpoint state endpoint (e.g., `http://localhost:5052/lean/v0/states/finalized` if the source node has metrics enabled on port 5052).

### Checkpoint Sync Server

Expand All @@ -292,7 +292,7 @@ To serve checkpoint state from a zeam node, enable the metrics server:
--api-port 5052
```

This node will serve the finalized checkpoint state at `http://localhost:5052/lean/states/finalized`.
This node will serve the finalized checkpoint state at `http://localhost:5052/lean/v0/states/finalized`.

### Checkpoint Sync Example

Expand All @@ -318,7 +318,7 @@ This node will serve the finalized checkpoint state at `http://localhost:5052/le
--validator_config genesis_bootnode \
--override_genesis_time 1759210782 \
--data-dir ./data/test_node1 \
--checkpoint-sync-url http://localhost:5052/lean/states/finalized
--checkpoint-sync-url http://localhost:5052/lean/v0/states/finalized
```

**Note:** The `--checkpoint-sync-url` parameter is optional. If not provided, the node will start from genesis as usual.
Expand Down
4 changes: 2 additions & 2 deletions pkgs/cli/test/integration.zig
Original file line number Diff line number Diff line change
Expand Up @@ -159,9 +159,9 @@ const ZeamRequest = struct {
return self.makeRequest("/metrics");
}

/// Make a request to the /health endpoint and return the response
/// Make a request to the /lean/v0/health endpoint and return the response
fn getHealth(self: ZeamRequest) ![]u8 {
return self.makeRequest("/health");
return self.makeRequest("/lean/v0/health");
}

/// Internal helper to make HTTP requests to any endpoint
Expand Down
Loading
Loading