Skip to content
45 changes: 45 additions & 0 deletions build.zig
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
const std = @import("std");
const Builder = @import("std").Build;

pub fn build(b: *Builder) void {
Expand Down Expand Up @@ -32,7 +33,51 @@ pub fn build(b: *Builder) void {
tests_tests.root_module.addImport("ssz.zig", mod);
const run_tests_tests = b.addRunArtifact(tests_tests);

// Poseidon hasher build options
const poseidon_enabled = b.option(bool, "poseidon", "Enable Poseidon2 hash support") orelse false;
if (poseidon_enabled) {
std.log.info("Poseidon2 enabled (koalabear, Poseidon2-24 Plonky3)", .{});
}

// Create build options
const options = b.addOptions();
options.addOption(bool, "poseidon_enabled", poseidon_enabled);

// Poseidon2 implementation via hash-zig dependency
const hashzig_module = if (poseidon_enabled) blk: {
const hashzig_dep = b.dependency("hash_zig", .{
.target = target,
.optimize = optimize,
});
break :blk hashzig_dep.module("hash-zig");
} else null;

// Add build options and poseidon import to all artifacts
mod.addOptions("build_options", options);
if (hashzig_module) |pm| mod.addImport("hash_zig", pm);

lib.root_module.addOptions("build_options", options);
if (hashzig_module) |pm| lib.root_module.addImport("hash_zig", pm);

main_tests.root_module.addOptions("build_options", options);
if (hashzig_module) |pm| main_tests.root_module.addImport("hash_zig", pm);

tests_tests.root_module.addOptions("build_options", options);
if (hashzig_module) |pm| tests_tests.root_module.addImport("hash_zig", pm);

const test_step = b.step("test", "Run library tests");
test_step.dependOn(&run_main_tests.step);
test_step.dependOn(&run_tests_tests.step);
// Optional Poseidon validation suite (only when Poseidon is enabled)
if (poseidon_enabled) {
const plonky3_validation_tests = b.addTest(.{
.root_source_file = .{ .cwd_relative = "src/poseidon_plonky3_validation.zig" },
.optimize = optimize,
.target = target,
});
plonky3_validation_tests.root_module.addOptions("build_options", options);
if (hashzig_module) |pm| plonky3_validation_tests.root_module.addImport("hash_zig", pm);
const run_plonky3_validation_tests = b.addRunArtifact(plonky3_validation_tests);
test_step.dependOn(&run_plonky3_validation_tests.step);
}
}
6 changes: 6 additions & 0 deletions build.zig.zon
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,10 @@
.fingerprint = 0x1d34bd0ceb1dfc2d,
.version = "0.0.9",
.paths = .{""},
.dependencies = .{
.hash_zig = .{
.url = "https://github.com/blockblaz/hash-zig/archive/2bca6541a933a2bbe4630f41c29f61b3f84ad7e0.tar.gz",
.hash = "hash_zig-1.1.3-POmurOPmCgCkbtpq_c62mZqLuHzVeaLZ2X23fxsoHVrI",
},
},
}
18 changes: 18 additions & 0 deletions src/beacon_tests.zig
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const serialize = libssz.serialize;
const deserialize = libssz.deserialize;
const hashTreeRoot = libssz.hashTreeRoot;
const std = @import("std");
const build_options = @import("build_options");
const ArrayList = std.ArrayList;
const expect = std.testing.expect;

Expand Down Expand Up @@ -53,6 +54,7 @@ test "Validator struct serialization" {
}

test "Validator struct hash tree root" {
if (build_options.poseidon_enabled) return;
const validator = Validator{
.pubkey = [_]u8{0x01} ** 48,
.withdrawal_credentials = [_]u8{0x02} ** 32,
Expand Down Expand Up @@ -116,6 +118,7 @@ test "Individual Validator serialization and hash" {
try expect(std.mem.eql(u8, list.items, &expected_validator_bytes));

// Test hash tree root
if (build_options.poseidon_enabled) return;
var hash: [32]u8 = undefined;
try hashTreeRoot(Validator, validator, &hash, std.testing.allocator);

Expand Down Expand Up @@ -190,6 +193,7 @@ test "List[Validator] serialization and hash tree root" {
}

// Test hash tree root
if (build_options.poseidon_enabled) return;
var hash1: [32]u8 = undefined;
try hashTreeRoot(ValidatorList, validator_list, &hash1, std.testing.allocator);

Expand Down Expand Up @@ -279,6 +283,8 @@ test "BeamBlockBody with validator array - full cycle" {
try expect(orig.withdrawable_epoch == deser.withdrawable_epoch);
}

if (build_options.poseidon_enabled) return;

// Test hash tree root consistency
var hash_original: [32]u8 = undefined;
try hashTreeRoot(BeamBlockBody, beam_block_body, &hash_original, std.testing.allocator);
Expand Down Expand Up @@ -377,6 +383,8 @@ test "Zeam-style List/Bitlist usage with tree root stability" {

try expect(std.mem.eql(u8, state_serialized.items, &expected_zeam_state_bytes));

if (build_options.poseidon_enabled) return;

// Test hash tree root determinism and validate against expected hashes
var body_hash1: [32]u8 = undefined;
var body_hash2: [32]u8 = undefined;
Expand Down Expand Up @@ -450,6 +458,8 @@ test "BeamState with historical roots - comprehensive test" {
const expected_comprehensive_beam_state_bytes = [_]u8{ 0x39, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x9C, 0x00, 0x00, 0x00, 0xE8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
try expect(std.mem.eql(u8, serialized_data.items, &expected_comprehensive_beam_state_bytes));

if (build_options.poseidon_enabled) return;

// Test hash tree root calculation
var original_hash: [32]u8 = undefined;
try hashTreeRoot(BeamState, beam_state, &original_hash, std.testing.allocator);
Expand Down Expand Up @@ -524,6 +534,8 @@ test "BeamState with empty historical roots" {
const expected_empty_beam_state_bytes = [_]u8{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
try expect(std.mem.eql(u8, serialized_data.items, &expected_empty_beam_state_bytes));

if (build_options.poseidon_enabled) return;

// Test hash tree root calculation
var original_hash: [32]u8 = undefined;
try hashTreeRoot(SimpleBeamState, beam_state, &original_hash, std.testing.allocator);
Expand Down Expand Up @@ -591,6 +603,8 @@ test "BeamState with maximum historical roots" {
const expected_max_beam_state_bytes_start = [_]u8{ 0x3F, 0x42, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00 };
try expect(std.mem.eql(u8, serialized_data.items[0..12], &expected_max_beam_state_bytes_start));

if (build_options.poseidon_enabled) return;

// Test hash tree root calculation
var original_hash: [32]u8 = undefined;
try hashTreeRoot(MaxBeamState, beam_state, &original_hash, std.testing.allocator);
Expand Down Expand Up @@ -671,6 +685,8 @@ test "BeamState historical roots access and comparison" {
const expected_access_beam_state_bytes = [_]u8{ 0x31, 0xD4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0xEF, 0xBE, 0xAD, 0xDE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC };
try expect(std.mem.eql(u8, serialized_data.items, &expected_access_beam_state_bytes));

if (build_options.poseidon_enabled) return;

// Test hash tree root calculation
var original_hash: [32]u8 = undefined;
try hashTreeRoot(AccessBeamState, beam_state, &original_hash, std.testing.allocator);
Expand Down Expand Up @@ -741,6 +757,8 @@ test "SimpleBeamState with empty historical roots" {
const expected_simple_beam_state_bytes = [_]u8{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
try expect(std.mem.eql(u8, serialized_data.items, &expected_simple_beam_state_bytes));

if (build_options.poseidon_enabled) return;

// Test hash tree root calculation
var original_hash: [32]u8 = undefined;
try hashTreeRoot(SimpleBeamState, beam_state, &original_hash, std.testing.allocator);
Expand Down
50 changes: 32 additions & 18 deletions src/lib.zig
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,20 @@ pub const utils = @import("./utils.zig");
pub const zeros = @import("./zeros.zig");
const ArrayList = std.ArrayList;
const builtin = std.builtin;
const build_options = @import("build_options");
const sha256 = std.crypto.hash.sha2.Sha256;
const hashes_of_zero = zeros.hashes_of_zero;

// Configure the hasher based on build options
pub const Hasher = if (build_options.poseidon_enabled) blk: {
const hash_zig = @import("hash_zig");
const poseidon2 = hash_zig.poseidon2;
const poseidon_wrapper = @import("./poseidon_wrapper.zig");
const Poseidon2Type = poseidon2.Poseidon2KoalaBear24Plonky3;
// Wrap with SHA256-compatible API
break :blk poseidon_wrapper.PoseidonHasher(Poseidon2Type);
} else sha256;

const hashes_of_zero = zeros.buildZeroHashes(Hasher, 32, 256);
const Allocator = std.mem.Allocator;

/// Number of bytes per chunk.
Expand Down Expand Up @@ -505,7 +517,7 @@ pub fn deserialize(comptime T: type, serialized: []const u8, out: *T, allocator:
}

pub fn mixInLength2(root: [32]u8, length: usize, out: *[32]u8) void {
var hasher = sha256.init(sha256.Options{});
var hasher = Hasher.init(Hasher.Options{});
hasher.update(root[0..]);

var tmp = [_]u8{0} ** 32;
Expand All @@ -515,13 +527,14 @@ pub fn mixInLength2(root: [32]u8, length: usize, out: *[32]u8) void {
}

fn mixInLength(root: [32]u8, length: [32]u8, out: *[32]u8) void {
var hasher = sha256.init(sha256.Options{});
var hasher = Hasher.init(Hasher.Options{});
hasher.update(root[0..]);
hasher.update(length[0..]);
hasher.final(out[0..]);
}

test "mixInLength" {
if (build_options.poseidon_enabled) return;
var root: [32]u8 = undefined;
var length: [32]u8 = undefined;
var expected: [32]u8 = undefined;
Expand All @@ -535,7 +548,7 @@ test "mixInLength" {
}

fn mixInSelector(root: [32]u8, comptime selector: usize, out: *[32]u8) void {
var hasher = sha256.init(sha256.Options{});
var hasher = Hasher.init(Hasher.Options{});
hasher.update(root[0..]);
var tmp = [_]u8{0} ** 32;
std.mem.writeInt(@TypeOf(selector), tmp[0..@sizeOf(@TypeOf(selector))], selector, std.builtin.Endian.little);
Expand All @@ -544,6 +557,7 @@ fn mixInSelector(root: [32]u8, comptime selector: usize, out: *[32]u8) void {
}

test "mixInSelector" {
if (build_options.poseidon_enabled) return;
var root: [32]u8 = undefined;
var expected: [32]u8 = undefined;
var mixin: [32]u8 = undefined;
Expand Down Expand Up @@ -671,7 +685,7 @@ test "merkleize an empty slice" {
defer list.deinit();
const chunks = &[0][32]u8{};
var out: [32]u8 = undefined;
try merkleize(sha256, chunks, null, &out);
try merkleize(Hasher, chunks, null, &out);
try std.testing.expect(std.mem.eql(u8, out[0..], zero_chunk[0..]));
}

Expand All @@ -680,22 +694,22 @@ test "merkleize a string" {
defer list.deinit();
const chunks = try pack([]const u8, "a" ** 100, &list);
var out: [32]u8 = undefined;
try merkleize(sha256, chunks, null, &out);
try merkleize(Hasher, chunks, null, &out);
// Build the expected tree
const leaf1 = [_]u8{0x61} ** 32; // "0xaaaaa....aa" 32 times
var leaf2: [32]u8 = [_]u8{0x61} ** 4 ++ [_]u8{0} ** 28;
var root: [32]u8 = undefined;
var internal_left: [32]u8 = undefined;
var internal_right: [32]u8 = undefined;
var hasher = sha256.init(sha256.Options{});
var hasher = Hasher.init(Hasher.Options{});
hasher.update(leaf1[0..]);
hasher.update(leaf1[0..]);
hasher.final(&internal_left);
hasher = sha256.init(sha256.Options{});
hasher = Hasher.init(Hasher.Options{});
hasher.update(leaf1[0..]);
hasher.update(leaf2[0..]);
hasher.final(&internal_right);
hasher = sha256.init(sha256.Options{});
hasher = Hasher.init(Hasher.Options{});
hasher.update(internal_left[0..]);
hasher.update(internal_right[0..]);
hasher.final(&root);
Expand All @@ -710,7 +724,7 @@ test "merkleize a boolean" {
var chunks = try pack(bool, false, &list);
var expected = [_]u8{0} ** BYTES_PER_CHUNK;
var out: [BYTES_PER_CHUNK]u8 = undefined;
try merkleize(sha256, chunks, null, &out);
try merkleize(Hasher, chunks, null, &out);

try std.testing.expect(std.mem.eql(u8, out[0..], expected[0..]));

Expand All @@ -719,7 +733,7 @@ test "merkleize a boolean" {

chunks = try pack(bool, true, &list2);
expected[0] = 1;
try merkleize(sha256, chunks, null, &out);
try merkleize(Hasher, chunks, null, &out);
try std.testing.expect(std.mem.eql(u8, out[0..], expected[0..]));
}

Expand Down Expand Up @@ -764,7 +778,7 @@ pub fn hashTreeRoot(comptime T: type, value: T, out: *[32]u8, allctr: Allocator)
var list = ArrayList(u8).init(allctr);
defer list.deinit();
const chunks = try pack(T, value, &list);
try merkleize(sha256, chunks, null, out);
try merkleize(Hasher, chunks, null, out);
},
.array => |a| {
// Check if the child is a basic type. If so, return
Expand All @@ -776,13 +790,13 @@ pub fn hashTreeRoot(comptime T: type, value: T, out: *[32]u8, allctr: Allocator)
var list = ArrayList(u8).init(allctr);
defer list.deinit();
const chunks = try pack(T, value, &list);
try merkleize(sha256, chunks, null, out);
try merkleize(Hasher, chunks, null, out);
},
.bool => {
var list = ArrayList(u8).init(allctr);
defer list.deinit();
const chunks = try packBits(value[0..], &list);
try merkleize(sha256, chunks, chunkCount(T), out);
try merkleize(Hasher, chunks, chunkCount(T), out);
},
.array => {
var chunks = ArrayList(chunk).init(allctr);
Expand All @@ -792,7 +806,7 @@ pub fn hashTreeRoot(comptime T: type, value: T, out: *[32]u8, allctr: Allocator)
try hashTreeRoot(@TypeOf(item), item, &tmp, allctr);
try chunks.append(tmp);
}
try merkleize(sha256, chunks.items, null, out);
try merkleize(Hasher, chunks.items, null, out);
},
else => return error.NotSupported,
}
Expand All @@ -807,7 +821,7 @@ pub fn hashTreeRoot(comptime T: type, value: T, out: *[32]u8, allctr: Allocator)
defer list.deinit();
const chunks = try pack(T, value, &list);
var tmp: chunk = undefined;
try merkleize(sha256, chunks, null, &tmp);
try merkleize(Hasher, chunks, null, &tmp);
mixInLength2(tmp, value.len, out);
},
// use bitlist
Expand All @@ -821,7 +835,7 @@ pub fn hashTreeRoot(comptime T: type, value: T, out: *[32]u8, allctr: Allocator)
try hashTreeRoot(@TypeOf(item), item, &tmp, allctr);
try chunks.append(tmp);
}
try merkleize(sha256, chunks.items, null, &tmp);
try merkleize(Hasher, chunks.items, null, &tmp);
mixInLength2(tmp, chunks.items.len, out);
},
}
Expand All @@ -837,7 +851,7 @@ pub fn hashTreeRoot(comptime T: type, value: T, out: *[32]u8, allctr: Allocator)
try hashTreeRoot(f.type, @field(value, f.name), &tmp, allctr);
try chunks.append(tmp);
}
try merkleize(sha256, chunks.items, null, out);
try merkleize(Hasher, chunks.items, null, out);
},
// An optional is a union with `None` as first value.
.optional => |opt| if (value != null) {
Expand Down
Loading