From 1ffbcf93b676bad73708a5a7de1454f414667230 Mon Sep 17 00:00:00 2001 From: fearlessfe <505380967@qq.com> Date: Thu, 31 Oct 2024 23:10:29 +0800 Subject: [PATCH 1/3] feat: add ssz test for more types --- src/spec_tests/ssz_static/root.zig | 111 +++++++++++++++++++++-------- src/yaml/yaml.zig | 28 ++++++-- 2 files changed, 105 insertions(+), 34 deletions(-) diff --git a/src/spec_tests/ssz_static/root.zig b/src/spec_tests/ssz_static/root.zig index b74f5ef..4e625ed 100644 --- a/src/spec_tests/ssz_static/root.zig +++ b/src/spec_tests/ssz_static/root.zig @@ -9,10 +9,6 @@ const Yaml = @import("../../yaml/yaml.zig").Yaml; const gpa = testing.allocator; /// Loads and parses a YAML file into a Yaml object -/// Parameters: -/// file_path: Path to the YAML file to load -/// Returns: -/// Parsed Yaml object or error fn loadFromFile(file_path: []const u8) !Yaml { const file = try std.fs.cwd().openFile(file_path, .{}); defer file.close(); @@ -26,42 +22,105 @@ fn loadFromFile(file_path: []const u8) !Yaml { const Roots = struct { root: [32]u8, }; + +const structMultiPhase = union { + Attestation: types.Attestation, + BeaconBlockBody: types.BeaconBlockBody, + BeaconState: types.BeaconState, + BlobIdentifier: types.BlobIdentifier, + BlobSidecar: types.BlobSidecar, + BLSToExecutionChange: types.BLSToExecutionChange, + ConsolidationRequest: types.ConsolidationRequest, + ContributionAndProof: types.ContributionAndProof, + DepositRequest: types.DepositRequest, + ExecutionPayload: types.ExecutionPayload, + ExecutionPayloadHeader: types.ExecutionPayloadHeader, + HistoricalSummary: types.HistoricalSummary, + LightClientBootstrap: types.LightClientBootstrap, + LightClientFinalityUpdate: types.LightClientFinalityUpdate, + LightClientHeader: types.LightClientHeader, + LightClientOptimisticUpdate: types.LightClientOptimisticUpdate, + LightClientUpdate: types.LightClientUpdate, + PendingBalanceDeposit: types.PendingBalanceDeposit, + PendingConsolidation: types.PendingConsolidation, + PendingPartialWithdrawal: types.PendingPartialWithdrawal, + PowBlock: types.PowBlock, + SignedBLSToExecutionChange: types.SignedBLSToExecutionChange, + SignedContributionAndProof: types.SignedContributionAndProof, + SignedVoluntaryExit: types.SignedVoluntaryExit, + SyncAggregate: types.SyncAggregate, + SyncCommittee: types.SyncCommittee, + SyncCommitteeContribution: types.SyncCommitteeContribution, + SyncCommitteeMessage: types.SyncCommitteeMessage, + Withdrawal: types.Withdrawal, + WithdrawalRequest: types.WithdrawalRequest, +}; + +const altair = union { + SyncAggregatorSelectionData: types.SyncAggregatorSelectionData, +}; + // test cases for all phases -const CommonUnion = union { +const commonUnion = union { + // AggregateAndProof: types.AggregateAndProof, + // AttestationData: types.AttestationData, + // AttesterSlashing: types.AttesterSlashing, + // BeaconBlock: types.BeaconBlock, + // BeaconBlockHeader: types.BeaconBlockHeader, + Checkpoint: types.Checkpoint, + // Deposit: types.Deposit, + // DepositData: types.DepositData, + // DepositMessage: types.DepositMessage, + // Eth1Block: types.Eth1Block, + // Eth1Data: types.Eth1Data, Fork: types.Fork, + ForkData: types.ForkData, + // HistoricalBatch: types.HistoricalBatch, + // IndexedAttestation: types.IndexedAttestation, + // PendingAttestation: types.PendingAttestation, + // ProposerSlashing: types.ProposerSlashing, + // SignedBeaconBlock: types.SignedBeaconBlock, + // SignedBeaconBlockHeader: types.SignedBeaconBlockHeader, + // SigningData: types.SigningData, + SyncAggregatorSelectionData: types.SyncAggregatorSelectionData, // only exist in altair or later + // Validator: types.Validator, + VoluntaryExit: types.VoluntaryExit, }; +const forks = [_][]const u8{ "phase0", "altair", "bellatrix", "capella", "deneb", "electra" }; + test "ssz static" { const testPath = "consensus-spec-tests/tests/mainnet"; const gpa1 = testing.allocator; - const fields = @typeInfo(CommonUnion).@"union".fields; + const fields = @typeInfo(commonUnion).@"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); + for (forks) |fork| { + const ssz_type_path = try std.fmt.allocPrint(gpa1, "{s}/{s}/ssz_static/{s}", .{ testPath, fork, fieldName }); + + var dirs = getLeafDirs(gpa1, ssz_type_path) catch |err| { + if (err == error.FileNotFound) { + continue; + } + return err; + }; + // deinit the dirs array + defer { + for (dirs.items) |item| { + gpa1.free(item); + } + dirs.deinit(); } - dirs.deinit(); - } - for (dirs.items) |dir| { - try testSSZStatic(dir, fieldType); + for (dirs.items) |dir| { + try testSSZStatic(dir, fieldType); + } } } } /// Recursively finds all leaf directories (directories with no subdirectories) starting from the given path -/// Parameters: -/// allocator: Memory allocator for dynamic allocations -/// path: Starting directory path to search from -/// Returns: -/// ArrayList containing paths to all leaf directories fn getLeafDirs(allocator: std.mem.Allocator, path: []const u8) !std.ArrayList([]const u8) { var leafDirs = std.ArrayList([]const u8).init(allocator); // defer leafDirs.deinit(); @@ -101,12 +160,6 @@ fn getLeafDirs(allocator: std.mem.Allocator, path: []const u8) !std.ArrayList([] } /// Tests SSZ (Simple Serialize) static functionality by performing: -/// 1. YAML parsing -/// 2. Hash tree root verification -/// 3. SSZ encoding/decoding with snappy compression -/// Parameters: -/// path: Directory path containing test files -/// t: Type to test SSZ operations against fn testSSZStatic(path: []const u8, t: type) !void { // parse from yaml const valueFile = try std.fmt.allocPrint(testing.allocator, "{s}/value.yaml", .{path}); diff --git a/src/yaml/yaml.zig b/src/yaml/yaml.zig index ea2934c..ffcfa77 100644 --- a/src/yaml/yaml.zig +++ b/src/yaml/yaml.zig @@ -1,5 +1,3 @@ -//! The code bellow is essentially a port of https://github.com/kubkon/zig-yaml - const std = @import("std"); const assert = std.debug.assert; const math = std.math; @@ -29,6 +27,7 @@ pub const Map = std.StringArrayHashMap(Value); pub const Value = union(enum) { empty, int: i64, + uint: u64, float: f64, string: []const u8, list: List, @@ -39,6 +38,11 @@ pub const Value = union(enum) { return self.int; } + pub fn asUint(self: Value) !u64 { + if (self != .uint) return error.TypeMismatch; + return self.uint; + } + pub fn asFloat(self: Value) !f64 { if (self != .float) return error.TypeMismatch; return self.float; @@ -90,6 +94,7 @@ pub const Value = union(enum) { switch (self) { .empty => return, .int => |int| return writer.print("{}", .{int}), + .uint => |uint| return writer.print("{}", .{uint}), .float => |float| return writer.print("{d}", .{float}), .string => |string| return writer.print("{s}", .{string}), .list => |list| { @@ -205,8 +210,15 @@ pub const Value = union(enum) { const raw = tree.getRaw(node.start, node.end); try_int: { - const int = std.fmt.parseInt(i64, raw, 0) catch break :try_int; - return Value{ .int = int }; + if (std.fmt.parseUnsigned(u64, raw, 0)) |uint| { + if (uint > math.maxInt(i64)) { + return Value{ .uint = uint }; + } + return Value{ .int = @intCast(uint) }; + } else |_| { + const int = std.fmt.parseInt(i64, raw, 0) catch break :try_int; + return Value{ .int = int }; + } } try_float: { @@ -393,7 +405,13 @@ pub const Yaml = struct { fn parseValue(self: *Yaml, comptime T: type, value: Value) Error!T { return switch (@typeInfo(T)) { - .int => math.cast(T, try value.asInt()) orelse return error.Overflow, + .int => { + return switch (value) { + .int => math.cast(T, try value.asInt()) orelse return error.Overflow, + .uint => math.cast(T, try value.asUint()) orelse return error.Overflow, + else => return error.TypeMismatch, + }; + }, .float => if (value.asFloat()) |float| { return math.lossyCast(T, float); } else |_| { From 84063e70384fec82baf86d3cfde2cdb28bd9d064 Mon Sep 17 00:00:00 2001 From: PengZhen Date: Fri, 1 Nov 2024 13:20:20 +0800 Subject: [PATCH 2/3] fix: typ err --- clib/libyaml | 1 + src/spec_tests/ssz_static/root.zig | 14 +++++--------- 2 files changed, 6 insertions(+), 9 deletions(-) create mode 160000 clib/libyaml diff --git a/clib/libyaml b/clib/libyaml new file mode 160000 index 0000000..840b65c --- /dev/null +++ b/clib/libyaml @@ -0,0 +1 @@ +Subproject commit 840b65c40675e2d06bf40405ad3f12dec7f35923 diff --git a/src/spec_tests/ssz_static/root.zig b/src/spec_tests/ssz_static/root.zig index 4e625ed..ec57b0b 100644 --- a/src/spec_tests/ssz_static/root.zig +++ b/src/spec_tests/ssz_static/root.zig @@ -23,7 +23,7 @@ const Roots = struct { root: [32]u8, }; -const structMultiPhase = union { +const StructMultiPhase = union { Attestation: types.Attestation, BeaconBlockBody: types.BeaconBlockBody, BeaconState: types.BeaconState, @@ -56,12 +56,8 @@ const structMultiPhase = union { WithdrawalRequest: types.WithdrawalRequest, }; -const altair = union { - SyncAggregatorSelectionData: types.SyncAggregatorSelectionData, -}; - // test cases for all phases -const commonUnion = union { +const CommonUnion = union { // AggregateAndProof: types.AggregateAndProof, // AttestationData: types.AttestationData, // AttesterSlashing: types.AttesterSlashing, @@ -87,16 +83,16 @@ const commonUnion = union { VoluntaryExit: types.VoluntaryExit, }; -const forks = [_][]const u8{ "phase0", "altair", "bellatrix", "capella", "deneb", "electra" }; +const forkDirs = [_][]const u8{ "phase0", "altair", "bellatrix", "capella", "deneb", "electra" }; test "ssz static" { const testPath = "consensus-spec-tests/tests/mainnet"; const gpa1 = testing.allocator; - const fields = @typeInfo(commonUnion).@"union".fields; + const fields = @typeInfo(CommonUnion).@"union".fields; inline for (fields) |field| { const fieldType = field.type; const fieldName = field.name; - for (forks) |fork| { + for (forkDirs) |fork| { const ssz_type_path = try std.fmt.allocPrint(gpa1, "{s}/{s}/ssz_static/{s}", .{ testPath, fork, fieldName }); var dirs = getLeafDirs(gpa1, ssz_type_path) catch |err| { From f72568ee93178f897b366edf59346eea3ccefdb3 Mon Sep 17 00:00:00 2001 From: PengZhen Date: Fri, 1 Nov 2024 17:36:46 +0800 Subject: [PATCH 3/3] fix: remove unused dir --- clib/libyaml | 1 - 1 file changed, 1 deletion(-) delete mode 160000 clib/libyaml diff --git a/clib/libyaml b/clib/libyaml deleted file mode 160000 index 840b65c..0000000 --- a/clib/libyaml +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 840b65c40675e2d06bf40405ad3f12dec7f35923