Skip to content

Commit 4715850

Browse files
committed
feat: add SSZ binary format support for finalized endpoint
Update lean_api.zig to parse SSZ-encoded state data from /lean/states/finalized endpoint. The slot is extracted from the first 8 bytes (little-endian u64) of the SSZ-encoded BeaconState structure. Since /lean/states/justified returns 404, use finalized slot for both justified and finalized until correct endpoint is found.
1 parent afaaa57 commit 4715850

1 file changed

Lines changed: 35 additions & 33 deletions

File tree

src/lean_api.zig

Lines changed: 35 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -5,36 +5,36 @@ pub const Slots = struct {
55
finalized_slot: u64,
66
};
77

8-
/// Fetch finalized and justified slots from separate endpoints
8+
/// Fetch finalized and justified slots from lean node endpoints
9+
/// The finalized endpoint returns SSZ-encoded state data
910
pub fn fetchSlots(
1011
allocator: std.mem.Allocator,
1112
client: *std.http.Client,
1213
base_url: []const u8,
1314
_: []const u8, // path parameter not used anymore
1415
) !Slots {
15-
// Fetch finalized slot
16-
const finalized_slot = try fetchSlotFromEndpoint(
16+
// Fetch finalized slot from SSZ-encoded endpoint
17+
const finalized_slot = try fetchSlotFromSSZEndpoint(
1718
allocator,
1819
client,
1920
base_url,
2021
"/lean/states/finalized",
2122
);
2223

23-
// Fetch justified slot
24-
const justified_slot = try fetchSlotFromEndpoint(
25-
allocator,
26-
client,
27-
base_url,
28-
"/lean/states/justified",
29-
);
24+
// For now, use finalized slot as justified slot since /lean/states/justified returns 404
25+
// TODO: Find the correct endpoint for justified slot
26+
const justified_slot = finalized_slot;
3027

3128
return Slots{
3229
.justified_slot = justified_slot,
3330
.finalized_slot = finalized_slot,
3431
};
3532
}
3633

37-
fn fetchSlotFromEndpoint(
34+
/// Fetch slot from SSZ-encoded endpoint
35+
/// The lean nodes return SSZ-encoded BeaconState data
36+
/// The slot is the first field (first 8 bytes as little-endian u64)
37+
fn fetchSlotFromSSZEndpoint(
3838
allocator: std.mem.Allocator,
3939
client: *std.http.Client,
4040
base_url: []const u8,
@@ -63,40 +63,42 @@ fn fetchSlotFromEndpoint(
6363
return error.BadStatus;
6464
}
6565

66-
// Read response body
66+
// Read response body (SSZ binary data)
6767
var body_buf = std.ArrayList(u8).init(allocator);
6868
defer body_buf.deinit();
6969

70-
const max_bytes = 1024 * 1024; // 1 MB limit
70+
const max_bytes = 10 * 1024 * 1024; // 10 MB limit for state data
7171
try req.reader().readAllArrayList(&body_buf, max_bytes);
7272

73-
// Parse JSON - expecting just a number
7473
const body = body_buf.items;
7574

76-
// Try to parse as direct number first
77-
const slot = std.fmt.parseInt(u64, std.mem.trim(u8, body, " \t\n\r\""), 10) catch {
78-
// If that fails, try parsing as JSON object with "slot" field
79-
const parsed = try std.json.parseFromSlice(
80-
struct { slot: u64 },
81-
allocator,
82-
body,
83-
.{},
84-
);
85-
defer parsed.deinit();
86-
return parsed.value.slot;
87-
};
75+
// SSZ-encoded BeaconState: slot is the first field (8 bytes, little-endian u64)
76+
if (body.len < 8) {
77+
return error.InvalidSSZData;
78+
}
79+
80+
// Read first 8 bytes as little-endian u64
81+
const slot = std.mem.readInt(u64, body[0..8], .little);
8882

8983
return slot;
9084
}
9185

92-
test "parse slot from plain number" {
93-
const body = "12345";
94-
const slot = try std.fmt.parseInt(u64, std.mem.trim(u8, body, " \t\n\r\""), 10);
86+
test "parse SSZ slot from binary data" {
87+
// Simulate SSZ data where first 8 bytes represent slot
88+
var data: [8]u8 = undefined;
89+
std.mem.writeInt(u64, &data, 12345, .little);
90+
91+
const slot = std.mem.readInt(u64, data[0..8], .little);
9592
try std.testing.expectEqual(@as(u64, 12345), slot);
9693
}
9794

98-
test "parse slot from quoted number" {
99-
const body = "\"12345\"";
100-
const slot = try std.fmt.parseInt(u64, std.mem.trim(u8, body, " \t\n\r\""), 10);
101-
try std.testing.expectEqual(@as(u64, 12345), slot);
95+
test "parse SSZ slot with additional data" {
96+
// Simulate SSZ data with slot + other fields
97+
var data: [100]u8 = undefined;
98+
std.mem.writeInt(u64, data[0..8], 99999, .little);
99+
// Fill rest with dummy data
100+
@memset(data[8..], 0xFF);
101+
102+
const slot = std.mem.readInt(u64, data[0..8], .little);
103+
try std.testing.expectEqual(@as(u64, 99999), slot);
102104
}

0 commit comments

Comments
 (0)