-
Notifications
You must be signed in to change notification settings - Fork 38
/
Copy pathhash.zig
100 lines (82 loc) · 2.88 KB
/
hash.zig
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
const std = @import("std");
const sig = @import("../sig.zig");
const Sha256 = std.crypto.hash.sha2.Sha256;
const Slot = sig.core.time.Slot;
const Allocator = std.mem.Allocator;
pub const SlotAndHash = struct {
slot: Slot,
hash: Hash,
pub fn order(a: *const SlotAndHash, b: *const SlotAndHash) std.math.Order {
if (a.slot == b.slot and a.hash.order(&b.hash) == .eq) {
return .eq;
} else if (a.slot < b.slot or a.slot == b.slot and (a.hash.order(&b.hash) == .lt)) {
return .lt;
} else if (a.slot > b.slot or a.slot == b.slot and (a.hash.order(&b.hash) == .gt)) {
return .gt;
} else {
unreachable;
}
}
pub fn equals(a: *const SlotAndHash, b: *const SlotAndHash) bool {
return order(a, b) == .eq;
}
};
pub const Hash = extern struct {
data: [size]u8,
pub const size = 32;
pub const ZEROES: Hash = .{ .data = .{0} ** size };
const base58 = sig.crypto.base58.Base58Sized(size);
pub fn fromSizedSlice(data: *const [size]u8) Hash {
var hash: Hash = undefined;
@memcpy(&hash.data, data);
return hash;
}
pub fn generateSha256Hash(bytes: []const u8) Hash {
var data: [size]u8 = undefined;
Sha256.hash(bytes, &data, .{});
return .{ .data = data };
}
pub fn extendAndHash(id: Hash, val: []const u8) Hash {
var hasher = Sha256.init(.{});
hasher.update(&id.data);
hasher.update(val);
return .{ .data = hasher.finalResult() };
}
pub fn eql(self: Hash, other: Hash) bool {
const xx: @Vector(size, u8) = self.data;
const yy: @Vector(size, u8) = other.data;
return @reduce(.And, xx == yy);
}
pub fn order(a: *const Hash, b: *const Hash) std.math.Order {
for (a.data, b.data) |a_byte, b_byte| {
if (a_byte > b_byte) return .gt;
if (a_byte < b_byte) return .lt;
}
return .eq;
}
pub fn parseBase58String(str: []const u8) error{InvalidHash}!Hash {
return .{ .data = base58.decode(str) catch return error.InvalidHash };
}
pub const base58_max_encoded_size = base58.max_encoded_size;
pub const Base58String = std.BoundedArray(u8, base58_max_encoded_size);
pub fn base58String(self: Hash) Base58String {
return base58.encode(self.data);
}
pub fn format(
self: Hash,
comptime _: []const u8,
_: std.fmt.FormatOptions,
writer: anytype,
) !void {
return base58.format(self.data, writer);
}
pub fn base58EncodeAlloc(self: Hash, allocator: Allocator) Allocator.Error![]const u8 {
return base58.encodeAlloc(self.data, allocator);
}
/// Intended to be used in tests.
pub fn initRandom(random: std.Random) Hash {
var data: [size]u8 = undefined;
random.bytes(&data);
return .{ .data = data };
}
};