Skip to content

Commit 20694bb

Browse files
committed
refactor sha256 hash api
1 parent 4d50162 commit 20694bb

File tree

21 files changed

+116
-132
lines changed

21 files changed

+116
-132
lines changed

conformance/src/txn_execute.zig

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1397,25 +1397,22 @@ pub fn hashSlot(
13971397
var signature_count_bytes: [8]u8 = undefined;
13981398
std.mem.writeInt(u64, &signature_count_bytes, 0, .little);
13991399

1400-
const initial_hash =
1401-
if (feature_set.active(.remove_accounts_delta_hash, 0))
1402-
Hash.generateSha256(.{
1403-
Hash.ZEROES,
1404-
&signature_count_bytes,
1405-
blockhash,
1406-
})
1407-
else
1408-
Hash.generateSha256(.{
1409-
Hash.ZEROES,
1410-
try freeze.deltaMerkleHash(account_reader, allocator, 0),
1411-
&signature_count_bytes,
1412-
blockhash,
1413-
});
1400+
var hash = std.crypto.hash.sha2.Sha256.init(.{});
1401+
hash.update(&sig.core.Hash.ZEROES.data); // no parent lt hash, start with zeroes
1402+
if (!feature_set.active(.remove_accounts_delta_hash, 0)) {
1403+
const delta_hash = try freeze.deltaMerkleHash(account_reader, allocator, 0);
1404+
hash.update(&delta_hash.data);
1405+
}
1406+
hash.update(&blockhash.data);
1407+
const initial_hash = hash.finalResult();
14141408

14151409
return if (feature_set.active(.accounts_lt_hash, 0))
1416-
Hash.generateSha256(.{ initial_hash, sig.core.hash.LtHash.IDENTITY.constBytes() })
1410+
Hash.initMany(&.{
1411+
&initial_hash,
1412+
sig.core.hash.LtHash.IDENTITY.constBytes(),
1413+
})
14171414
else
1418-
initial_hash;
1415+
.{ .data = initial_hash };
14191416
}
14201417

14211418
const State = struct {

src/consensus/optimistic_vote_verifier.zig

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -306,9 +306,9 @@ test "OptimisticConfirmationVerifier.verifyForUnrootedOptimisticSlots: unrooted
306306
);
307307

308308
// Hashes for slots 1,3,5
309-
const h1 = Hash.generateSha256("1");
310-
const h3 = Hash.generateSha256("3");
311-
const h5 = Hash.generateSha256("5");
309+
const h1 = Hash.init("1");
310+
const h3 = Hash.init("3");
311+
const h5 = Hash.init("5");
312312

313313
var verifier = OptimisticConfirmationVerifier.init(
314314
sig.time.Instant.now(),
@@ -369,7 +369,7 @@ test "OptimisticConfirmationVerifier.verifyForUnrootedOptimisticSlots: unrooted
369369
const unrooted = try verifier.verifyForUnrootedOptimisticSlots(
370370
allocator,
371371
&ledger_reader,
372-
.{ .slot = 4, .hash = Hash.generateSha256("4"), .ancestors = &anc4 },
372+
.{ .slot = 4, .hash = Hash.init("4"), .ancestors = &anc4 },
373373
);
374374
defer allocator.free(unrooted);
375375
try std.testing.expectEqual(1, unrooted.len);
@@ -395,7 +395,7 @@ test "OptimisticConfirmationVerifier.verifyForUnrootedOptimisticSlots: unrooted
395395
const unrooted = try verifier.verifyForUnrootedOptimisticSlots(
396396
allocator,
397397
&ledger_reader,
398-
.{ .slot = 7, .hash = Hash.generateSha256("7"), .ancestors = &anc7 },
398+
.{ .slot = 7, .hash = Hash.init("7"), .ancestors = &anc7 },
399399
);
400400
defer allocator.free(unrooted);
401401
// Expect two entries (1 and 3), order by slot ascending due to set ordering
@@ -423,7 +423,7 @@ test "OptimisticConfirmationVerifier.verifyForUnrootedOptimisticSlots: unrooted
423423
const unrooted = try verifier.verifyForUnrootedOptimisticSlots(
424424
allocator,
425425
&ledger_reader,
426-
.{ .slot = 7, .hash = Hash.generateSha256("7"), .ancestors = &anc7 },
426+
.{ .slot = 7, .hash = Hash.init("7"), .ancestors = &anc7 },
427427
);
428428
defer allocator.free(unrooted);
429429
try std.testing.expectEqual(0, unrooted.len);

src/consensus/vote_listener.zig

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1601,14 +1601,14 @@ test "vote_parser.parseVoteTransaction" {
16011601
var prng = std.Random.DefaultPrng.init(42);
16021602
const random = prng.random();
16031603
try vote_parser.testParseVoteTransaction(null, random);
1604-
try vote_parser.testParseVoteTransaction(Hash.generateSha256(&[_]u8{42}), random);
1604+
try vote_parser.testParseVoteTransaction(Hash.init(&.{42}), random);
16051605
}
16061606

16071607
test "vote_parser.parseSanitizedVoteTransaction" {
16081608
var prng = std.Random.DefaultPrng.init(43);
16091609
const random = prng.random();
16101610
try vote_parser.testParseSanitizedVoteTransaction(null, random);
1611-
try vote_parser.testParseSanitizedVoteTransaction(Hash.generateSha256(&[_]u8{43}), random);
1611+
try vote_parser.testParseSanitizedVoteTransaction(Hash.init(&.{43}), random);
16121612
}
16131613

16141614
test verifyVoteTransaction {

src/core/blockhash_queue.zig

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -212,15 +212,15 @@ test "reject old last hash" {
212212
defer queue.deinit(allocator);
213213

214214
for (0..102) |i| {
215-
const last_hash_i = Hash.ZEROES.extendAndHash(&[_]u8{@intCast(i)});
215+
const last_hash_i = Hash.ZEROES.extend(&[_]u8{@intCast(i)});
216216
try queue.insertHash(allocator, last_hash_i, 0);
217217
}
218218

219-
const hash_0 = Hash.ZEROES.extendAndHash(&[_]u8{@intCast(0)});
219+
const hash_0 = Hash.ZEROES.extend(&[_]u8{@intCast(0)});
220220
try std.testing.expect(!queue.isHashValidForAge(hash_0, max_age));
221221
try std.testing.expect(!queue.isHashValidForAge(hash_0, 0));
222222

223-
const hash_1 = Hash.ZEROES.extendAndHash(&[_]u8{@intCast(1)});
223+
const hash_1 = Hash.ZEROES.extend(&[_]u8{@intCast(1)});
224224
try std.testing.expect(queue.isHashValidForAge(hash_1, max_age));
225225
try std.testing.expect(!queue.isHashValidForAge(hash_1, 0));
226226
}

src/core/entry.zig

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -110,20 +110,19 @@ pub fn verifyPoh(
110110
if (entry.num_hashes == 0) continue;
111111

112112
for (1..entry.num_hashes) |_| {
113-
current_hash = Hash.generateSha256(&current_hash.data);
113+
current_hash = Hash.init(&current_hash.data);
114114
}
115115

116116
if (entry.transactions.len > 0) {
117-
const mixin =
118-
try hashTransactions(allocator, optional.preallocated_nodes, entry.transactions);
119-
current_hash = current_hash.extendAndHash(&mixin.data);
120-
} else {
121-
current_hash = Hash.generateSha256(&current_hash.data);
122-
}
123-
124-
if (!current_hash.eql(entry.hash)) {
125-
return false;
126-
}
117+
const mixin = try hashTransactions(
118+
allocator,
119+
optional.preallocated_nodes,
120+
entry.transactions,
121+
);
122+
current_hash = current_hash.extend(&mixin.data);
123+
} else current_hash = Hash.init(&current_hash.data);
124+
125+
if (!current_hash.eql(entry.hash)) return false;
127126
}
128127

129128
return true;
@@ -159,7 +158,7 @@ pub fn hashTransactions(
159158
try nodes.ensureTotalCapacity(allocator, capacity);
160159

161160
for (transactions) |tx| for (tx.signatures) |signature| {
162-
const hash = Hash.generateSha256(.{ LEAF_PREFIX, &signature.data });
161+
const hash = Hash.initMany(&.{ LEAF_PREFIX, &signature.data });
163162
nodes.appendAssumeCapacity(hash);
164163
};
165164

@@ -177,7 +176,7 @@ pub fn hashTransactions(
177176
// Duplicate last entry if the level length is odd
178177
&nodes.items[prev_level_start + prev_level_idx];
179178

180-
const hash = Hash.generateSha256(.{ INTERMEDIATE_PREFIX, &lsib.data, &rsib.data });
179+
const hash = Hash.initMany(&.{ INTERMEDIATE_PREFIX, &lsib.data, &rsib.data });
181180
nodes.appendAssumeCapacity(hash);
182181
}
183182
prev_level_start = level_start;

src/core/hash.zig

Lines changed: 20 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -36,54 +36,33 @@ pub const Hash = extern struct {
3636

3737
pub const SIZE = 32;
3838

39-
pub const ZEROES: Hash = .{ .data = .{0} ** SIZE };
40-
41-
/// Hashes the input byte slice(s) using SHA 256.
42-
///
43-
/// If the passed-in type contains multiple byte slices, it will
44-
/// iterate/recurse over them in order, updating the hasher for all of them
45-
/// before finalizing at the end.
46-
pub fn generateSha256(
47-
/// May be a slice or array of bytes, or a slice, array, or tuple
48-
/// containing slices or arrays of bytes nested with arbitrary depth.
49-
///
50-
/// for example:
51-
/// - []const u8
52-
/// - []const []const u8
53-
/// - [2]u8
54-
/// - *[13]u8
55-
/// - struct { [128]u8, []const []const u8, struct { []const u8 }, ... }
56-
data: anytype,
57-
) Hash {
58-
var hasher = Sha256.init(.{});
59-
update(&hasher, data);
60-
return .{ .data = hasher.finalResult() };
39+
pub const ZEROES: Hash = .{ .data = @splat(0) };
40+
41+
/// Creates a `Hash` by applying SHA256 to the input `data` and using
42+
/// the result of that as the output.
43+
pub fn init(data: []const u8) Hash {
44+
var out: [32]u8 = undefined;
45+
Sha256.hash(data, &out, .{});
46+
return .{ .data = out };
6147
}
6248

63-
/// re-hashes the current hash with the mixed-in byte slice(s).
64-
pub fn extendAndHash(self: Hash, data: anytype) Hash {
65-
return generateSha256(.{ self.data, data });
49+
/// Does the same thing as `init`, but updates the hash with each
50+
/// input slice from the `data` list.
51+
pub fn initMany(data: []const []const u8) Hash {
52+
var new = Sha256.init(.{});
53+
for (data) |d| new.update(d);
54+
return .{ .data = new.finalResult() };
6655
}
6756

68-
fn update(hasher: *Sha256, data: anytype) void {
69-
const T = @TypeOf(data);
70-
71-
if (T == Hash or T == *const Hash or T == *Hash) {
72-
hasher.update(&data.data);
73-
} else if (@typeInfo(T) == .@"struct") {
74-
inline for (data) |val| update(hasher, val);
75-
} else if (std.meta.Elem(T) == u8) switch (@typeInfo(T)) {
76-
.array => hasher.update(&data),
77-
else => hasher.update(data),
78-
} else {
79-
for (data) |val| update(hasher, val);
80-
}
57+
/// re-hashes the current hash with the mixed-in byte slice(s).
58+
pub fn extend(self: Hash, data: []const u8) Hash {
59+
return .initMany(&.{ &self.data, data });
8160
}
8261

8362
pub fn eql(self: Hash, other: Hash) bool {
84-
const xx: @Vector(SIZE, u8) = self.data;
85-
const yy: @Vector(SIZE, u8) = other.data;
86-
return @reduce(.And, xx == yy);
63+
const x: @Vector(SIZE, u8) = self.data;
64+
const y: @Vector(SIZE, u8) = other.data;
65+
return @reduce(.And, x == y);
8766
}
8867

8968
pub fn order(self: *const Hash, other: *const Hash) std.math.Order {

src/core/poh.zig

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ pub const Poh = struct {
3636
pub fn hash(self: *Poh, max_num_hashes: u64) bool {
3737
const num_hashes = @min(self.remaining_hashes -| 1, max_num_hashes);
3838
for (0..num_hashes) |_| {
39-
self.latest_hash = self.latest_hash.extendAndHash(.{});
39+
self.latest_hash = .init(&self.latest_hash.data);
4040
}
4141
self.num_hashes += num_hashes;
4242
self.remaining_hashes -= num_hashes;
@@ -70,12 +70,12 @@ pub const Poh = struct {
7070
return null; // needs a tick first
7171
}
7272

73-
self.latest_hash = self.latest_hash.extendAndHash(mixin.data);
73+
self.latest_hash = self.latest_hash.extend(&mixin.data);
7474
const num_hashes = self.num_hashes + 1;
7575
self.num_hashes = 0;
7676
self.remaining_hashes -= 1;
7777

78-
return PohEntry{
78+
return .{
7979
.num_hashes = num_hashes,
8080
.hash = self.latest_hash,
8181
};
@@ -84,7 +84,7 @@ pub const Poh = struct {
8484
/// Calculate the hash for a tick entry, without a mixin hash, and increment
8585
/// the tick counter
8686
pub fn tick(self: *Poh) ?PohEntry {
87-
self.latest_hash = self.latest_hash.extendAndHash(.{});
87+
self.latest_hash = .init(&self.latest_hash.data);
8888
self.num_hashes += 1;
8989
self.remaining_hashes -= 1;
9090

@@ -98,7 +98,7 @@ pub const Poh = struct {
9898
self.num_hashes = 0;
9999
self.tick_count += 1;
100100

101-
return PohEntry{
101+
return .{
102102
.num_hashes = num_hashes,
103103
.hash = self.latest_hash,
104104
};

src/core/shred.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ pub const ShredVersion = struct {
2525
var hash = genesis_hash;
2626
if (maybe_hard_forks) |hard_forks| {
2727
for (hard_forks.entries.items) |*hard_fork| {
28-
hash = Hash.extendAndHash(
28+
hash = Hash.extend(
2929
hash,
3030
std.mem.asBytes(hard_fork),
3131
);

src/gossip/fuzz_service.zig

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -448,9 +448,9 @@ pub fn randomPullRequestWithContactInfo(
448448
// add more random hashes
449449
for (0..5) |_| {
450450
const rand_value = try randomSignedGossipData(allocator, random, true);
451-
var buf: [PACKET_DATA_SIZE]u8 = undefined;
452-
const bytes = try bincode.writeToSlice(&buf, rand_value, bincode.Params.standard);
453-
const value_hash = Hash.generateSha256(bytes);
451+
var buffer: [PACKET_DATA_SIZE]u8 = undefined;
452+
const bytes = try bincode.writeToSlice(&buffer, rand_value, bincode.Params.standard);
453+
const value_hash = Hash.init(bytes);
454454
filter.filter.add(&value_hash.data);
455455
}
456456
} else {
@@ -459,9 +459,9 @@ pub fn randomPullRequestWithContactInfo(
459459

460460
for (0..5) |_| {
461461
const rand_value = try randomSignedGossipData(allocator, random, true);
462-
var buf: [PACKET_DATA_SIZE]u8 = undefined;
463-
const bytes = try bincode.writeToSlice(&buf, rand_value, bincode.Params.standard);
464-
const value_hash = Hash.generateSha256(bytes);
462+
var buffer: [PACKET_DATA_SIZE]u8 = undefined;
463+
const bytes = try bincode.writeToSlice(&buffer, rand_value, bincode.Params.standard);
464+
const value_hash = Hash.init(bytes);
465465
filter_set.add(&value_hash);
466466
}
467467

src/gossip/ping_pong.zig

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ pub const Pong = struct {
6060

6161
pub fn init(ping: *const Ping, keypair: *const KeyPair) !Pong {
6262
const token_with_prefix = PING_PONG_HASH_PREFIX ++ ping.token;
63-
const hash = Hash.generateSha256(token_with_prefix);
63+
const hash = Hash.init(&token_with_prefix);
6464
const signature = keypair.sign(&hash.data, null) catch return error.SignatureError;
6565

6666
return .{
@@ -172,7 +172,7 @@ pub const PingCache = struct {
172172
var prng = DefaultPrng.init(0);
173173
const ping = Ping.initRandom(prng.random(), keypair) catch return null;
174174
var token_with_prefix = PING_PONG_HASH_PREFIX ++ ping.token;
175-
const hash = Hash.generateSha256(token_with_prefix[0..]);
175+
const hash = Hash.init(&token_with_prefix);
176176
_ = self.pending_cache.put(hash, peer_and_addr);
177177
_ = self.pings.put(peer_and_addr, now);
178178
return ping;

0 commit comments

Comments
 (0)