Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ssz spec test #11

Merged
merged 5 commits into from
Oct 29, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
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: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@

.zig-cache
zig-out
.vscode
.vscode
consensus-spec-tests/
7 changes: 7 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,15 @@ check_nasm:
fi \
fi

SPEC_VERSION ?= v1.5.0-alpha.8

# Update deps target to include nasm check
deps: check_nasm
@echo "Installing dependencies"
@git submodule update --init --recursive
@cd bls && make -f Makefile.onelib ETH_CFLAGS=-DBLS_ETH LIB_DIR=lib

mkdir -p consensus-spec-tests
Copy link
Member

Choose a reason for hiding this comment

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

Use a separate the task would be better such as if someone want to build it in local but don't want to do spec tests.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

wget https://github.com/ethereum/consensus-spec-tests/releases/download/$(SPEC_VERSION)/general.tar.gz -O - | tar -xz -C consensus-spec-tests
wget https://github.com/ethereum/consensus-spec-tests/releases/download/$(SPEC_VERSION)/minimal.tar.gz -O - | tar -xz -C consensus-spec-tests
wget https://github.com/ethereum/consensus-spec-tests/releases/download/$(SPEC_VERSION)/mainnet.tar.gz -O - | tar -xz -C consensus-spec-tests
7 changes: 7 additions & 0 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,13 @@ pub fn build(b: *std.Build) void {
lib_unit_tests.root_module.addImport("bls", bls);
lib_unit_tests.addIncludePath(b.path("bls/include/"));
lib_unit_tests.addIncludePath(b.path("bls/mcl/include/"));
const yaml = b.dependency("yaml", .{
.target = target,
.optimize = optimize,
});

lib_unit_tests.root_module.addImport("yaml", yaml.module("yaml"));

const run_lib_unit_tests = b.addRunArtifact(lib_unit_tests);

const exe_unit_tests = b.addTest(.{
Expand Down
5 changes: 1 addition & 4 deletions build.zig.zon
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,7 @@
// `zig build --fetch` can be used to fetch all dependencies of a package, recursively.
// Once all dependencies are fetched, `zig build` no longer requires
// internet connectivity.
// .dependencies = .{ .zabi = .{
// .url = "https://github.com/Raiden1411/zabi/archive/79c77aa4a39d41ed50033fd922f4d37c0f0638bb.tar.gz",
// .hash = "122095aaf2d09e3286bf8b00b773b65c1632639de6c5005de881754df7c04efc7e98",
// } },
.dependencies = .{ .yaml = .{ .url = "git+https://github.com/optimism-java/zig-yaml.git#7a7c5162230bb08f73ec22a063010ed7c76ccded", .hash = "1220a6d7148f7777d997ee663e0efe0fb9c57a38658ea164bcd267e8391c3ce0aa87" } },
Copy link
Member

Choose a reason for hiding this comment

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

Why snappy/ssz directly imported but this lib outside, should we unify them?

.paths = .{
"build.zig",
"build.zig.zon",
Expand Down
Binary file removed serialized.ssz_snappy
Binary file not shown.
2 changes: 2 additions & 0 deletions src/snappy/snappy.zig
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//! The code bellow is essentially a port of https://github.com/gsquire/zig-snappy

const std = @import("std");
const Allocator = std.mem.Allocator;
const crc32 = std.hash.crc.Crc32Iscsi;
Expand Down
121 changes: 109 additions & 12 deletions src/spec_tests/ssz_static/root.zig
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,123 @@ const ssz = @import("../../ssz/ssz.zig");
const types = @import("../../consensus/types.zig");
const snappy = @import("../../snappy/snappy.zig");

test "hash tree root" {
const fork = types.Fork{
.previous_version = [4]u8{ 0x75, 0xeb, 0x7f, 0x25 },
.current_version = [4]u8{ 0x10, 0xd4, 0xe2, 0x7f },
.epoch = 8876772290899440384,
};
const Yaml = @import("yaml").Yaml;

const gpa = testing.allocator;

Copy link
Member

Choose a reason for hiding this comment

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

Add comment for functions

Copy link
Contributor Author

@fearlessfe fearlessfe Oct 29, 2024

Choose a reason for hiding this comment

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

done

fn loadFromFile(file_path: []const u8) !Yaml {
const file = try std.fs.cwd().openFile(file_path, .{});
defer file.close();

const source = try file.readToEndAlloc(gpa, std.math.maxInt(u32));
defer gpa.free(source);

return Yaml.load(gpa, source);
}

const Roots = struct {
root: [32]u8,
};

const TestCasesUnion = union {
Fork: types.Fork,
};

fn getLeafDirs(allocator: std.mem.Allocator, path: []const u8) !std.ArrayList([]const u8) {
var leafDirs = std.ArrayList([]const u8).init(allocator);
// defer leafDirs.deinit();
var list = std.ArrayList([]const u8).init(allocator);
defer {
for (list.items) |item| {
allocator.free(item);
}
list.deinit();
}
try list.append(path);

var index: u32 = 0;

while (index < list.items.len) {
var hasSubDir = false;
const currentPath = list.items[index];
var dir = try std.fs.cwd().openDir(currentPath, .{ .iterate = true });
defer dir.close();

var iter = dir.iterate();

while (try iter.next()) |entry| {
if (entry.kind == .directory) {
hasSubDir = true;
const fullPath = try std.fs.path.join(allocator, &[_][]const u8{ currentPath, entry.name });
try list.append(fullPath);
}
}
if (!hasSubDir) {
// std.debug.print("currentPath: {s}\n", .{currentPath});
Copy link
Member

Choose a reason for hiding this comment

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

remove comment out code

try leafDirs.append(try allocator.dupe(u8, currentPath));
// try leafDirs.append(currentPath);
// defer allocator.free(currentPath);
}
index += 1;
}

return leafDirs;
}

fn testSSZStatic(path: []const u8, t: type) !void {
// parse from yaml
const valueFile = try std.fmt.allocPrint(testing.allocator, "{s}/value.yaml", .{path});
defer testing.allocator.free(valueFile);
var parsed = try loadFromFile(valueFile);
defer parsed.deinit();
const fork = try parsed.parse(t);
// test hash tree root
var out: [32]u8 = [_]u8{0} ** 32;
try ssz.hashTreeRoot(fork, &out, testing.allocator);
const expect: [32]u8 = [_]u8{ 0x98, 0x2a, 0x69, 0x96, 0xc9, 0x2f, 0x86, 0xf6, 0x37, 0x68, 0x3c, 0x72, 0xd9, 0x09, 0xc7, 0xa8, 0x68, 0x11, 0x0e, 0x3b, 0x05, 0xf7, 0xb4, 0x48, 0x44, 0xbc, 0x53, 0x96, 0x0d, 0x89, 0x56, 0xf5 };
const rootFile = try std.fmt.allocPrint(testing.allocator, "{s}/roots.yaml", .{path});
defer testing.allocator.free(rootFile);
var rootData = try loadFromFile(rootFile);
defer rootData.deinit();
const root = try rootData.parse(Roots);
const expect: [32]u8 = root.root;
try std.testing.expect(std.mem.eql(u8, out[0..], expect[0..]));
const file_path = "serialized.ssz_snappy";
// test ssz encode
const file_path = try std.fmt.allocPrint(testing.allocator, "{s}/serialized.ssz_snappy", .{path});
defer testing.allocator.free(file_path);
const file_contents = try std.fs.cwd().readFileAlloc(testing.allocator, file_path, std.math.maxInt(usize));
defer testing.allocator.free(file_contents);
// std.debug.print("Hex: {any}\n", .{std.fmt.fmtSliceHexLower(file_contents)});

const decoded_data = try snappy.decode(testing.allocator, file_contents);
defer testing.allocator.free(decoded_data);

const encode = try ssz.encodeSSZ(testing.allocator, fork);
defer testing.allocator.free(encode);

try std.testing.expect(std.mem.eql(u8, encode, decoded_data));

// test ssz decode
const decode = try ssz.decodeSSZ(t, decoded_data);
try std.testing.expectEqualDeep(decode, fork);
}

test "ssz static" {
const testPath = "consensus-spec-tests/tests/mainnet";
const gpa1 = testing.allocator;
const fields = @typeInfo(TestCasesUnion).@"union".fields;
inline for (fields) |field| {
const fieldType = field.type;
const fieldName = field.name;
const ssz_type_path = try std.fmt.allocPrint(gpa1, "{s}/phase0/ssz_static/{s}", .{ testPath, fieldName });

var dirs = try getLeafDirs(gpa1, ssz_type_path);

// deinit the dirs array
defer {
for (dirs.items) |item| {
gpa1.free(item);
}
dirs.deinit();
}

for (dirs.items) |dir| {
try testSSZStatic(dir, fieldType);
}
}
}
2 changes: 1 addition & 1 deletion src/ssz/ssz.zig
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//! The code bellow is essentially a port of https://github.com/Raiden1411/zabi
//! The code bellow is essentially a combination of https://github.com/Raiden1411/zabi and https://github.com/gballet/ssz.zig
//! to the most recent version of zig with a couple of stylistic changes and support for
//! other zig types.

Expand Down
3 changes: 2 additions & 1 deletion src/ssz/zeros.zig
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// List of root hashes of zero-subtries, up to depth 255.
//! The code bellow is essentially a port of https://github.com/gballet/ssz.zig
//! // List of root hashes of zero-subtries, up to depth 255.
const std = @import("std");

const strs = [_][]const u8{
Expand Down
Loading