Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
c4120d9
shred: widen data-payload-size bound check to u32
yewman Jul 16, 2026
0bb12d3
shred: accept parent_offset == slot at any slot
yewman Jul 16, 2026
07fe616
shred/receiver: reject LAST_SHRED_IN_SLOT at misaligned data index
yewman Jul 16, 2026
a99b7b4
shred/receiver: drop data shreds with parent slot below current root
yewman Jul 16, 2026
2555c7b
shred/receiver: re-validate Reed-Solomon-recovered data shreds
yewman Jul 16, 2026
8a94b30
replay: extract MerkleForest into v2/lib/replay.zig
yewman Jul 22, 2026
fc3b26e
shred/receiver: pin chained_merkle_root within a FEC set
yewman Jul 22, 2026
d94c491
shred: add parent_offset to DeshreddedFecSet and MerkleNode
yewman Jul 22, 2026
ec28f0c
shred/receiver: id-secondary index for erasure-set routing
yewman Jul 22, 2026
d421469
conformance/shred_parse: cap future shred slot at half epoch
yewman Jul 16, 2026
78570b0
conformance/shred_parse: reject empty EntryBatch without valid BlockM…
yewman Jul 16, 2026
48ed094
conformance/shred_parse: derive block-parse verdict from replay state
yewman Jul 22, 2026
b6764dd
conformance(shred): mirror agave's LastIndexConflict admission check
yewman Jul 22, 2026
86d462f
improve comment and panic on insertFecSet failure in conformance harness
yewman Jul 29, 2026
060a521
add comment on merkle root per shred computation
yewman Jul 29, 2026
5c36b3d
Merge branch 'main' into harnew/v2-shred-parse-conformance
yewman Jul 29, 2026
e30360a
build: tighten components loop
yewman Jul 29, 2026
b871bdf
tidy up comments
yewman Jul 30, 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
75 changes: 49 additions & 26 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -317,53 +317,69 @@ const Sig = struct {
});
unit_tests.add("lib", lib);

// Components: one per subdir of v2/components/. Each gets lib, tracy, and build-options
// Components: one per subdir of v2/components/. Each gets lib, tracy, and build-options.
//
// A component's impl (component.zig + siblings) may opt into a sibling
// component's api via `extra_api_deps`. The `_api` module itself always
// stays isolated to lib/tracy/build-options so the public surface is
// guaranteed cycle-free.
const extra_api_deps = std.StaticStringMap([]const []const u8).initComptime(&.{
.{ "replay", &.{"shred_api"} },
});

const component_base_imports: []const Build.Module.Import = &.{
.{ .name = "lib", .module = lib },
.{ .name = "tracy", .module = deps.tracy },
.{ .name = "build-options", .module = build_options_mod },
};

const Pending = struct { name: []const u8, comp_dir: []const u8, api: *Build.Module };
var pending: std.ArrayList(Pending) = .empty;
var components: std.StringHashMapUnmanaged(Component) = .empty;
var api_import_list: std.ArrayList(Build.Module.Import) = .empty;

// Pass 1: build every api so pass 2's sibling lookups can't miss.
{
var dir = try b.build_root.handle.openDir(
"v2/components",
.{ .iterate = true },
);
var dir = try b.build_root.handle.openDir("v2/components", .{ .iterate = true });
defer dir.close();
var it = dir.iterate();
while (try it.next()) |entry| {
if (entry.kind != .directory) continue;
if (std.mem.eql(u8, entry.name, "runtime")) continue;
const name = b.dupe(entry.name);

const comp_dir = b.fmt("v2/components/{s}", .{name});
const imports: []const Build.Module.Import = &.{
.{ .name = "lib", .module = lib },
.{ .name = "tracy", .module = deps.tracy },
.{ .name = "build-options", .module = build_options_mod },
};

const api_name = b.fmt("{s}_api", .{name});
const api = b.addModule(api_name, .{
.root_source_file = b.path(b.fmt("{s}/api.zig", .{comp_dir})),
.target = config.target,
.optimize = config.optimize,
.imports = imports,
.imports = component_base_imports,
});
unit_tests.add(api_name, api);

const component = b.addModule(name, .{
.root_source_file = b.path(b.fmt("{s}/component.zig", .{comp_dir})),
.target = config.target,
.optimize = config.optimize,
.imports = concatImports(b, &.{
imports,
&.{.{ .name = "api", .module = api }},
}),
});
unit_tests.add(name, component);

try components.put(b.allocator, name, .{ .api = api, .component = component });
try api_import_list.append(b.allocator, .{ .name = api_name, .module = api });
try pending.append(b.allocator, .{ .name = name, .comp_dir = comp_dir, .api = api });
}
}

// Pass 2: build each component impl module.
for (pending.items) |p| {
var imports: std.ArrayList(Build.Module.Import) = .empty;
try imports.appendSlice(b.allocator, component_base_imports);
try imports.append(b.allocator, .{ .name = "api", .module = p.api });
for (extra_api_deps.get(p.name) orelse &.{}) |extra| {
try imports.append(b.allocator, findApi(api_import_list.items, extra));
}

const component = b.addModule(p.name, .{
.root_source_file = b.path(b.fmt("{s}/component.zig", .{p.comp_dir})),
.target = config.target,
.optimize = config.optimize,
.imports = imports.items,
});
unit_tests.add(p.name, component);
try components.put(b.allocator, p.name, .{ .api = p.api, .component = component });
}

// runtime is special cased because it needs codegen and a bunch of extra deps that
// no other component uses.
const runtime = addRuntime(b, config, deps, unit_tests, lib, features_zon, feature_set_id);
Expand Down Expand Up @@ -594,6 +610,13 @@ fn concatImports(
return out;
}

fn findApi(imports: []const Build.Module.Import, name: []const u8) Build.Module.Import {
for (imports) |imp| {
if (std.mem.eql(u8, imp.name, name)) return imp;
}
std.debug.panic("extra_api_deps references unknown api '{s}'", .{name});
}

/// Everything other than Sig itself: developer tools, ci scripts, docs,
/// integration tests, etc.
const Tools = struct {
Expand Down
4 changes: 4 additions & 0 deletions conformance/build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ pub fn build(b: *Build) void {
const sig_v2_mod = sig_v2_dep.module("lib");
const shred_api_mod = sig_v2_dep.module("shred_api");
const shred_mod = sig_v2_dep.module("shred");
const replay_api_mod = sig_v2_dep.module("replay_api");
const replay_mod = sig_v2_dep.module("replay");

const pb_dep = b.dependency("pb", .{
.target = target,
Expand All @@ -105,6 +107,8 @@ pub fn build(b: *Build) void {
.{ .name = "sig_v2", .module = sig_v2_mod },
.{ .name = "shred_api", .module = shred_api_mod },
.{ .name = "shred", .module = shred_mod },
.{ .name = "replay_api", .module = replay_api_mod },
.{ .name = "replay", .module = replay_mod },
.{ .name = "protobuf", .module = pb_mod },
.{ .name = "build-options", .module = build_options.createModule() },
};
Expand Down
Loading