Skip to content

Commit

Permalink
Feat/sha256 utils (keep-starknet-strange#513)
Browse files Browse the repository at this point in the history
* sha256 hints

* sha256 utils + blake2s fixes
  • Loading branch information
StringNick authored Apr 28, 2024
1 parent b7dce71 commit 793e199
Show file tree
Hide file tree
Showing 10 changed files with 783 additions and 42 deletions.
40 changes: 25 additions & 15 deletions src/hint_processor/blake2s_hash.zig
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const std = @import("std");
const testing = std.testing;
const Allocator = std.mem.Allocator;

pub const IV = [8]u32{
0x6A09E667,
0xBB67AE85,
Expand All @@ -11,6 +12,7 @@ pub const IV = [8]u32{
0x1F83D9AB,
0x5BE0CD19,
};

const SIGMA = [_][16]usize{
[_]usize{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
[_]usize{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 },
Expand All @@ -23,21 +25,24 @@ const SIGMA = [_][16]usize{
[_]usize{ 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 },
[_]usize{ 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 },
};
fn right_rot(value: u32, comptime n: u5) u32 {

fn rightRot(value: u32, comptime n: u5) u32 {
return (value >> n) | (value << (@as(u6, 32) - @as(u6, n)));
}

fn mix(a: u32, b: u32, c: u32, d: u32, m0: u32, m1: u32) struct { u32, u32, u32, u32 } {
var a1 = a +% b +% m0;
var d1 = right_rot(d ^ a1, 16);
var d1 = rightRot(d ^ a1, 16);
var c1 = c +% d1;
var b1 = right_rot(b ^ c1, 12);
var b1 = rightRot(b ^ c1, 12);
a1 = a1 +% b1 +% m1;
d1 = right_rot(d1 ^ a1, 8);
d1 = rightRot(d1 ^ a1, 8);
c1 = c1 +% d1;
b1 = right_rot(b1 ^ c1, 7);
b1 = rightRot(b1 ^ c1, 7);
return .{ a1, b1, c1, d1 };
}
fn blake_round(state: std.ArrayList(u32), message: [16]u32, sigma: [16]usize) void {

fn blakeRound(state: std.ArrayList(u32), message: [16]u32, sigma: [16]usize) void {
const state_items = state.items;
state_items[0], state_items[4], state_items[8], state_items[12] = mix(
state_items[0],
Expand Down Expand Up @@ -106,7 +111,8 @@ fn blake_round(state: std.ArrayList(u32), message: [16]u32, sigma: [16]usize) vo
message[sigma[15]],
);
}
pub fn blake2s_compress(

pub fn blake2sCompress(
allocator: Allocator,
h: [8]u32,
message: [16]u32,
Expand All @@ -117,16 +123,20 @@ pub fn blake2s_compress(
) !std.ArrayList(u32) {
var state = std.ArrayList(u32).init(allocator);
defer state.deinit();

try state.appendSlice(&h);
try state.appendSlice(&[8]u32{ IV[0], IV[1], IV[2], IV[3], IV[4] ^ t0, IV[5] ^ t1, IV[6] ^ f0, IV[7] ^ f1 });

for (SIGMA) |sigma| {
blake_round(state, message, sigma);
blakeRound(state, message, sigma);
}
var new_state = std.ArrayList(u32).init(allocator);
errdefer new_state.deinit();

for (0..8) |i| {
try new_state.append(h[i] ^ state.items[i] ^ state.items[8 + i]);
}

return new_state;
}

Expand All @@ -136,7 +146,7 @@ test "blake2s compress: test a" {
1541459225,
};
const message = [_]u32{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
const new_state = try blake2s_compress(testing.allocator, h, message, 2, 0, 4294967295, 0);
const new_state = try blake2sCompress(testing.allocator, h, message, 2, 0, 4294967295, 0);
defer new_state.deinit();
try std.testing.expectEqualSlices(u32, &[8]u32{ 412110711, 3234706100, 3894970767, 982912411, 937789635, 742982576, 3942558313, 1407547065 }, new_state.items);
}
Expand All @@ -147,7 +157,7 @@ test "blake2s compress: test b" {
1541459225,
};
const message = [_]u32{ 456710651, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
const new_state = try blake2s_compress(testing.allocator, h, message, 2, 0, 4294967295, 0);
const new_state = try blake2sCompress(testing.allocator, h, message, 2, 0, 4294967295, 0);
defer new_state.deinit();
try std.testing.expectEqualSlices(u32, &[8]u32{ 1061041453, 3663967611, 2158760218, 836165556, 3696892209, 3887053585, 2675134684, 2201582556 }, new_state.items);
}
Expand All @@ -160,7 +170,7 @@ test "blake2s compress: test c" {
const message = [_]u32{
1819043144, 1870078063, 6581362, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
const new_state = try blake2s_compress(testing.allocator, h, message, 9, 0, 4294967295, 0);
const new_state = try blake2sCompress(testing.allocator, h, message, 9, 0, 4294967295, 0);
defer new_state.deinit();
try std.testing.expectEqualSlices(u32, &[8]u32{ 939893662, 3935214984, 1704819782, 3912812968, 4211807320, 3760278243, 674188535, 2642110762 }, new_state.items);
}
Expand All @@ -174,7 +184,7 @@ test "blake2s compress: test d" {
1819043144, 1870078063, 6581362, 274628678, 715791845, 175498643, 871587583, 0, 0, 0,
0, 0, 0, 0, 0, 0,
};
const new_state = try blake2s_compress(testing.allocator, h, message, 28, 0, 4294967295, 0);
const new_state = try blake2sCompress(testing.allocator, h, message, 28, 0, 4294967295, 0);
defer new_state.deinit();
try std.testing.expectEqualSlices(u32, &[8]u32{ 3980510537, 3982966407, 1593299263, 2666882356, 3288094120, 2682988286, 1666615862, 378086837 }, new_state.items);
}
Expand All @@ -188,7 +198,7 @@ test "blake2s compress: test e" {
1819043144, 1870078063, 6581362, 274628678, 715791845, 175498643, 871587583, 635963558,
557369694, 1576875962, 215769785, 0, 0, 0, 0, 0,
};
const new_state = try blake2s_compress(testing.allocator, h, message, 44, 0, 4294967295, 0);
const new_state = try blake2sCompress(testing.allocator, h, message, 44, 0, 4294967295, 0);
defer new_state.deinit();
try std.testing.expectEqualSlices(u32, &[8]u32{ 3251785223, 1946079609, 2665255093, 3508191500, 3630835628, 3067307230, 3623370123, 656151356 }, new_state.items);
}
Expand All @@ -202,7 +212,7 @@ test "blake2s compress: test f" {
1819043144, 1870078063, 6581362, 274628678, 715791845, 175498643, 871587583, 635963558,
557369694, 1576875962, 215769785, 152379578, 585849303, 764739320, 437383930, 74833930,
};
const new_state = try blake2s_compress(testing.allocator, h, message, 64, 0, 4294967295, 0);
const new_state = try blake2sCompress(testing.allocator, h, message, 64, 0, 4294967295, 0);
defer new_state.deinit();
try std.testing.expectEqualSlices(u32, &[8]u32{ 2593218707, 3238077801, 914875393, 3462286058, 4028447058, 3174734057, 2001070146, 3741410512 }, new_state.items);
}
Expand All @@ -216,7 +226,7 @@ test "blake2s compress: test g" {
11563522, 43535528, 653255322, 274628678, 73471943, 17549868, 87158958, 635963558,
343656565, 1576875962, 215769785, 152379578, 585849303, 76473202, 437253230, 74833930,
};
const new_state = try blake2s_compress(testing.allocator, h, message, 64, 0, 4294967295, 0);
const new_state = try blake2sCompress(testing.allocator, h, message, 64, 0, 4294967295, 0);
defer new_state.deinit();
try std.testing.expectEqualSlices(u32, &[8]u32{ 3496615692, 3252241979, 3771521549, 2125493093, 3240605752, 2885407061, 3962009872, 3845288240 }, new_state.items);
}
52 changes: 34 additions & 18 deletions src/hint_processor/blake2s_utils.zig
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ const CairoVMError = @import("../vm/error.zig").CairoVMError;
const MemoryError = @import("../vm/error.zig").MemoryError;
const blake2s_hash = @import("blake2s_hash.zig");
const builtin_hints = @import("builtin_hint_codes.zig");
fn feltToU32(felt: Felt252) MathError!u32 {

pub fn feltToU32(felt: Felt252) MathError!u32 {
const u256_val = felt.toInteger();
if (u256_val > 0xFFFFFFFF) {
return MathError.Felt252ToU32Conversion;
Expand All @@ -35,14 +36,18 @@ fn getFixedSizeU32Array(comptime N: usize, h_range: std.ArrayList(Felt252)) ![N]
}
return result;
}

fn getMaybeRelocArrayFromU32Array(allocator: Allocator, h_range: std.ArrayList(u32)) !std.ArrayList(MaybeRelocatable) {
var result = std.ArrayList(MaybeRelocatable).init(allocator);
errdefer result.deinit();

for (h_range.items) |h| {
const felt = Felt252.fromInt(u32, h);
try result.append(MaybeRelocatable.fromFelt(felt));
try result.append(MaybeRelocatable.fromInt(u32, h));
}

return result;
}

fn computeBlake2sFunc(allocator: Allocator, vm: *CairoVM, output_ptr: Relocatable) !void {
const h_felt_range = try vm.getFeltRange(try output_ptr.subUint(26), 8);
defer h_felt_range.deinit();
Expand All @@ -55,7 +60,7 @@ fn computeBlake2sFunc(allocator: Allocator, vm: *CairoVM, output_ptr: Relocatabl
const t = try feltToU32(try vm.getFelt(try output_ptr.subUint(2)));
const f = try feltToU32(try vm.getFelt(try output_ptr.subUint(1)));

const h_range = try blake2s_hash.blake2s_compress(allocator, h, message, t, 0, f, 0);
const h_range = try blake2s_hash.blake2sCompress(allocator, h, message, t, 0, f, 0);
defer h_range.deinit();
var new_state = try getMaybeRelocArrayFromU32Array(allocator, h_range);
defer new_state.deinit();
Expand All @@ -71,7 +76,7 @@ pub fn blake2sCompute(allocator: Allocator, vm: *CairoVM, ids_data: std.StringHa
try computeBlake2sFunc(allocator, vm, output);
}

// /* Implements Hint:
// Implements Hint:
// # Add dummy pairs of input and output.
// from starkware.cairo.common.cairo_blake2s.blake2s_utils import IV, blake2s_compress

Expand Down Expand Up @@ -99,7 +104,7 @@ pub fn blake2sFinalize(allocator: Allocator, vm: *CairoVM, ids_data: std.StringH
const message: [16]u32 = .{0} ** 16;
var modified_iv = blake2s_hash.IV;
modified_iv[0] = blake2s_hash.IV[0] ^ 0x01010020;
const output = try blake2s_hash.blake2s_compress(allocator, modified_iv, message, 0, 0, 0xffffffff, 0);
const output = try blake2s_hash.blake2sCompress(allocator, modified_iv, message, 0, 0, 0xffffffff, 0);
defer output.deinit();
var full_padding = std.ArrayList(u32).init(allocator);
defer full_padding.deinit();
Expand All @@ -113,7 +118,7 @@ pub fn blake2sFinalize(allocator: Allocator, vm: *CairoVM, ids_data: std.StringH
defer data.deinit();
_ = try vm.loadData(blake2s_ptr_end, &data);
}
// /* Implements Hint:
// Implements Hint:
// # Add dummy pairs of input and output.
// from starkware.cairo.common.cairo_blake2s.blake2s_utils import IV, blake2s_compress

Expand All @@ -134,30 +139,34 @@ pub fn blake2sFinalize(allocator: Allocator, vm: *CairoVM, ids_data: std.StringH
// )
// padding = (message + modified_iv + [0, 0xffffffff] + output) * (_n_packed_instances - 1)
// segments.write_arg(ids.blake2s_ptr_end, padding)
// */
//
pub fn blake2sFinalizeV3(allocator: Allocator, vm: *CairoVM, ids_data: std.StringHashMap(HintReference), ap_tracking: ApTracking) !void {
const N_PACKED_INSTANCES = 7;
const blake2s_ptr_end = try hint_utils.getPtrFromVarName("blake2s_ptr_end", vm, ids_data, ap_tracking);
const message: [16]u32 = .{0} ** 16;
var modified_iv = blake2s_hash.IV;
modified_iv[0] = blake2s_hash.IV[0] ^ 0x01010020;
const output = try blake2s_hash.blake2s_compress(allocator, modified_iv, message, 0, 0, 0xffffffff, 0);
const output = try blake2s_hash.blake2sCompress(allocator, modified_iv, message, 0, 0, 0xffffffff, 0);
defer output.deinit();

var padding = std.ArrayList(u32).init(allocator);
defer padding.deinit();

try padding.appendSlice(&message);
try padding.appendSlice(&modified_iv);
try padding.appendSlice(&.{ 0, 0xffffffff });
try padding.appendSlice(output.items);

var full_padding = std.ArrayList(u32).init(allocator);
defer full_padding.deinit();

for (N_PACKED_INSTANCES - 1) |_| {
try full_padding.appendSlice(&padding);
try full_padding.appendSlice(padding.items);
}

var data = try getMaybeRelocArrayFromU32Array(allocator, full_padding);
defer data.deinit();

_ = try vm.loadData(blake2s_ptr_end, &data);
}
// /* Implements Hint:
Expand Down Expand Up @@ -197,12 +206,11 @@ pub fn blake2sAddUnit256(_: Allocator, vm: *CairoVM, ids_data: std.StringHashMap
_ = try vm.loadData(data_ptr, &data);
}

// /* Implements Hint:
// Implements Hint:
// B = 32
// MASK = 2 ** 32 - 1
// segments.write_arg(ids.data, [(ids.high >> (B * (3 - i))) & MASK for i in range(4)])
// segments.write_arg(ids.data + 4, [(ids.low >> (B * (3 - i))) & MASK for i in range(4)])
// */
pub fn blake2sAddUnit256BigEnd(_: Allocator, vm: *CairoVM, ids_data: std.StringHashMap(HintReference), ap_tracking: ApTracking) !void {
const data_ptr = try hint_utils.getPtrFromVarName("data", vm, ids_data, ap_tracking);
const low_addr = try hint_utils.getRelocatableFromVarName("low", vm, ids_data, ap_tracking);
Expand Down Expand Up @@ -238,7 +246,7 @@ pub fn blake2sAddUnit256BigEnd(_: Allocator, vm: *CairoVM, ids_data: std.StringH
_ = try vm.loadData(data_ptr, &bigend_data);
}

// /* Implements Hint:
// Implements Hint:
// %{
// from starkware.cairo.common.cairo_blake2s.blake2s_utils import IV, blake2s_compress

Expand All @@ -258,21 +266,29 @@ pub fn blake2sAddUnit256BigEnd(_: Allocator, vm: *CairoVM, ids_data: std.StringH
// %}

// Note: This hint belongs to the blake2s lib in cario_examples
// */

pub fn exampleBlake2SCompress(allocator: Allocator, vm: *CairoVM, ids_data: std.StringHashMap(HintReference), ap_tracking: ApTracking) !void {
//
pub fn exampleBlake2SCompress(
allocator: Allocator,
vm: *CairoVM,
ids_data: std.StringHashMap(HintReference),
ap_tracking: ApTracking,
) !void {
const blake2s_start = try hint_utils.getPtrFromVarName("blake2s_start", vm, ids_data, ap_tracking);
const output = try hint_utils.getPtrFromVarName("output", vm, ids_data, ap_tracking);
const n_bytes_felt = try hint_utils.getIntegerFromVarName("n_bytes", vm, ids_data, ap_tracking);
const n_bytes = try feltToU32(n_bytes_felt);

const message = try getFixedSizeU32Array(16, try vm.getFeltRange(blake2s_start, 16));

var modified_iv = blake2s_hash.IV;
modified_iv[0] = blake2s_hash.IV[0] ^ 0x01010020;
var new_state = try blake2s_hash.blake2s_compress(allocator, modified_iv, message, n_bytes, 0, 0xffffffff, 0);

var new_state = try blake2s_hash.blake2sCompress(allocator, modified_iv, message, n_bytes, 0, 0xffffffff, 0);
defer new_state.deinit();

var new_state_relocatable = try getMaybeRelocArrayFromU32Array(allocator, new_state);
new_state_relocatable.deinit();
defer new_state_relocatable.deinit();

_ = try vm.segments.writeArg(std.ArrayList(MaybeRelocatable), output, &new_state_relocatable);
}

Expand Down
47 changes: 47 additions & 0 deletions src/hint_processor/builtin_hint_codes.zig
Original file line number Diff line number Diff line change
Expand Up @@ -743,6 +743,7 @@ pub const EXAMPLE_BLAKE2S_COMPRESS =
pub const BLAKE2S_FINALIZE_V3 =
\\# Add dummy pairs of input and output.
\\from starkware.cairo.common.cairo_blake2s.blake2s_utils import IV, blake2s_compress
\\
\\_n_packed_instances = int(ids.N_PACKED_INSTANCES)
\\assert 0 <= _n_packed_instances < 20
\\_blake2s_input_chunk_size_felts = int(ids.BLAKE2S_INPUT_CHUNK_SIZE_FELTS)
Expand Down Expand Up @@ -1484,6 +1485,52 @@ pub const PACK_MODN_DIV_MODN =
\\value = res = div_mod(x, s, N)
;

pub const SHA256_INPUT = "ids.full_word = int(ids.n_bytes >= 4)";

pub const SHA256_MAIN_CONSTANT_INPUT_LENGTH =
\\from starkware.cairo.common.cairo_sha256.sha256_utils import (
\\ IV, compute_message_schedule, sha2_compress_function)
\\
\\_sha256_input_chunk_size_felts = int(ids.SHA256_INPUT_CHUNK_SIZE_FELTS)
\\assert 0 <= _sha256_input_chunk_size_felts < 100
\\
\\w = compute_message_schedule(memory.get_range(
\\ ids.sha256_start, _sha256_input_chunk_size_felts))
\\new_state = sha2_compress_function(IV, w)
\\segments.write_arg(ids.output, new_state)
;

pub const SHA256_MAIN_ARBITRARY_INPUT_LENGTH =
\\from starkware.cairo.common.cairo_sha256.sha256_utils import (
\\ compute_message_schedule, sha2_compress_function)
\\
\\_sha256_input_chunk_size_felts = int(ids.SHA256_INPUT_CHUNK_SIZE_FELTS)
\\assert 0 <= _sha256_input_chunk_size_felts < 100
\\_sha256_state_size_felts = int(ids.SHA256_STATE_SIZE_FELTS)
\\assert 0 <= _sha256_state_size_felts < 100
\\w = compute_message_schedule(memory.get_range(
\\ ids.sha256_start, _sha256_input_chunk_size_felts))
\\new_state = sha2_compress_function(memory.get_range(ids.state, _sha256_state_size_felts), w)
\\segments.write_arg(ids.output, new_state)
;

pub const SHA256_FINALIZE =
\\# Add dummy pairs of input and output.
\\from starkware.cairo.common.cairo_sha256.sha256_utils import (
\\ IV, compute_message_schedule, sha2_compress_function)
\\
\\_block_size = int(ids.BLOCK_SIZE)
\\assert 0 <= _block_size < 20
\\_sha256_input_chunk_size_felts = int(ids.SHA256_INPUT_CHUNK_SIZE_FELTS)
\\assert 0 <= _sha256_input_chunk_size_felts < 100
\\
\\message = [0] * _sha256_input_chunk_size_felts
\\w = compute_message_schedule(message)
\\output = sha2_compress_function(IV, w)
\\padding = (message + IV + output) * (_block_size - 1)
\\segments.write_arg(ids.sha256_ptr_end, padding)
;

pub const UINT384_GET_SQUARE_ROOT =
\\from starkware.python.math_utils import is_quad_residue, sqrt
\\
Expand Down
Loading

0 comments on commit 793e199

Please sign in to comment.