Skip to content

Commit

Permalink
feat:Add merkle helper
Browse files Browse the repository at this point in the history
Signed-off-by: Chen Kai <[email protected]>
  • Loading branch information
GrapeBaBa committed Oct 17, 2024
1 parent 8e3227e commit d27f882
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 0 deletions.
61 changes: 61 additions & 0 deletions src/consensus/helpers/merkle.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
const std = @import("std");
const primitives = @import("../../primitives/types.zig");
const consensus = @import("../../consensus/types.zig");
const configs = @import("../../configs/config.zig");
const constants = @import("../../primitives/constants.zig");
const preset = @import("../../presets/preset.zig");
const sha256 = std.crypto.hash.sha2.Sha256;

/// verifyMerkleProof verifies a merkle proof.
/// @param leaf - The leaf value.
/// @param branch - The branch.
/// @param depth - The depth.
/// @param index - The index.
/// @param root - The root.
/// @returns True if the proof is valid, false otherwise.
/// Spec pseudocode definition:
/// def is_valid_merkle_branch(leaf: Bytes32, branch: Sequence[Bytes32], depth: uint64, index: uint64, root: Root) -> bool:
/// """
/// Check if ``leaf`` at ``index`` verifies against the Merkle ``root`` and ``branch``.
/// """
/// value = leaf
/// for i in range(depth):
/// if index // (2**i) % 2:
/// value = hash(branch[i] + value)
/// else:
/// value = hash(value + branch[i])
/// return value == root
pub fn verifyMerkleProof(leaf: primitives.Bytes32, branch: []const primitives.Bytes32, depth: u64, index: u64, root: primitives.Root) !bool {
var value: [32]u8 = leaf;
var i: u64 = 0;
while (i < depth) : (i += 1) {
var combined: [64]u8 = undefined;
if (@mod(try std.math.divFloor(u64, index, std.math.pow(u64, 2, i)), 2) != 0) {
@memcpy(combined[0..32], &branch[i]);
@memcpy(combined[32..64], &value);
} else {
@memcpy(combined[0..32], &value);
@memcpy(combined[32..64], &branch[i]);
}
sha256.hash(&combined, &value, .{});
}
return std.mem.eql(u8, &value, &root);
}

test "verifyMerkleProof" {
const leaf: primitives.Bytes32 = undefined;
const branch: [32]primitives.Bytes32 = undefined;
const root: primitives.Root = undefined;
const depth: u64 = 0;
const index: u64 = 0;
try std.testing.expect(try verifyMerkleProof(leaf, &branch, depth, index, root));
}

test "verifyMerkleProof with valid branch" {
const leaf: primitives.Bytes32 = [_]u8{1} ** 32;
const branch: [32]primitives.Bytes32 = [_]primitives.Bytes32{[_]u8{2} ** 32} ** 32;
const root: primitives.Root = [_]u8{ 228, 209, 245, 144, 152, 7, 227, 251, 129, 176, 248, 115, 30, 139, 1, 35, 21, 112, 168, 110, 176, 175, 25, 181, 52, 215, 85, 95, 22, 63, 166, 194 };
const depth: u64 = 5;
const index: u64 = 0;
try std.testing.expect(try verifyMerkleProof(leaf, &branch, depth, index, root));
}
1 change: 1 addition & 0 deletions src/root.zig
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ pub const shuffle_helper = @import("consensus/helpers/shuffle.zig");
pub const balance_helper = @import("consensus/helpers/balance.zig");
pub const ssz = @import("./ssz/ssz.zig");
pub const snappy = @import("./snappy/snappy.zig");
pub const merkle = @import("consensus/helpers/merkle.zig");

test {
@import("std").testing.refAllDeclsRecursive(@This());
Expand Down

0 comments on commit d27f882

Please sign in to comment.