diff --git a/evm/src/cpu/kernel/asm/core/precompiles/blake2_f.asm b/evm/src/cpu/kernel/asm/core/precompiles/blake2_f.asm index a10c9ba2..74c65610 100644 --- a/evm/src/cpu/kernel/asm/core/precompiles/blake2_f.asm +++ b/evm/src/cpu/kernel/asm/core/precompiles/blake2_f.asm @@ -1,3 +1,55 @@ global precompile_blake2_f: - // TODO - PANIC + // stack: address, retdest, new_ctx, kexit_info, ret_offset, ret_size + %pop2 + // stack: new_ctx, kexit_info, ret_offset, ret_size + DUP1 + SET_CONTEXT + // stack: (empty) + PUSH 0x100000000 // = 2^32 (is_kernel = true) + // stack: kexit_info + + // get various inputs out of SEGMENT_CALLDATA + + // charge gas (based on rounds) + + // Copy the call data to the kernel general segment (blake2b expects it there) and call blake2b. + %calldatasize + GET_CONTEXT + // stack: ctx, size + + // TODO: change + // The next block of code is equivalent to the following %stack macro call + // (unfortunately the macro call takes too long to expand dynamically). + // + // %stack (ctx, size) -> + // ( + // 0, @SEGMENT_KERNEL_GENERAL, 1, // DST + // ctx, @SEGMENT_CALLDATA, 0, // SRC + // size, blake2_f, // count, retdest + // 0, size, blake2_f_contd // blake2b input: virt, num_bytes, retdest + // ) + // + PUSH 0 + PUSH blake2_f + DUP4 + PUSH 0 + PUSH @SEGMENT_CALLDATA + PUSH blake2_f_contd + SWAP7 + SWAP6 + PUSH 1 + PUSH @SEGMENT_KERNEL_GENERAL + PUSH 0 + + %jump(memcpy) + +blake2_f_contd: + // stack: hash, kexit_info + // Store the result hash to the parent's return data using `mstore_unpacking`. + + + + %mstore_parent_context_metadata(@CTX_METADATA_RETURNDATA_SIZE, 32) + %mload_context_metadata(@CTX_METADATA_PARENT_CONTEXT) + %stack (parent_ctx, hash) -> (parent_ctx, @SEGMENT_RETURNDATA, 0, hash, 32, pop_and_return_success) + %jump(mstore_unpacking) diff --git a/evm/src/cpu/kernel/asm/core/precompiles/sha256.asm b/evm/src/cpu/kernel/asm/core/precompiles/sha256.asm index 86461a59..804c8a7e 100644 --- a/evm/src/cpu/kernel/asm/core/precompiles/sha256.asm +++ b/evm/src/cpu/kernel/asm/core/precompiles/sha256.asm @@ -23,6 +23,7 @@ global precompile_sha256: // Copy the call data to the kernel general segment (sha2 expects it there) and call sha2. %calldatasize GET_CONTEXT + // stack: ctx, size // The next block of code is equivalent to the following %stack macro call // (unfortunately the macro call takes too long to expand dynamically). diff --git a/evm/src/cpu/kernel/asm/hash/blake2b/blake2_f.asm b/evm/src/cpu/kernel/asm/hash/blake2b/blake2_f.asm new file mode 100644 index 00000000..6a433e23 --- /dev/null +++ b/evm/src/cpu/kernel/asm/hash/blake2b/blake2_f.asm @@ -0,0 +1,145 @@ +global blake2_f: + // stack: rounds, h0...h7, m0...m15, t0, t1, flag, retdest + + // Store the hash values. + %blake2b_hash_value_addr + // stack: addr, rounds, h0...h7, m0...m15, t0, t1, flag, retdest + %rep 8 + // stack: addr, rounds, h_i, ... + %stack (addr, rounds, h_i) -> (addr, h_i, addr, rounds) + // stack: addr, h_i, addr, rounds, ... + %mstore_kernel_general + %increment + %endrep + + // stack: addr, rounds, m0...m15, t0, t1, flag, retdest + POP + // stack: rounds, m0...m15, t0, t1, flag, retdest + + // Save the message to the message working space. + %blake2b_message_addr + // stack: message_addr, rounds, m0...m15, t0, t1, flag, retdest + %rep 16 + // stack: message_addr, rounds, m_i, ... + %stack (message_addr, rounds, m_i) -> (message_addr, m_i, message_addr, rounds) + // stack: message_addr, m_i, message_addr, rounds, ... + %mstore_kernel_general + %increment + %endrep + + // stack: message_addr, rounds, t0, t1, flag, retdest + POP + // stack: rounds, t0, t1, flag, retdest + + + + + %blake2b_hash_value_addr + %add_const(7) + %rep 8 + // stack: addr, ... + DUP1 + // stack: addr, addr, ... + %mload_kernel_general + // stack: val, addr, ... + SWAP1 + // stack: addr, val, ... + %decrement + %endrep + // stack: addr, h_0, ..., h_7, rounds, t0, t1, flag, retdest + POP + // stack: h_0, ..., h_7, rounds, t0, t1, flag, retdest + + // Store the initial 16 values of the internal state. + %blake2b_internal_state_addr + // stack: start, h_0, ..., h_7, rounds, t0, t1, flag, retdest + + // First eight words of the internal state: current hash value h_0, ..., h_7. + %rep 8 + SWAP1 + DUP2 + %mstore_kernel_general + %increment + %endrep + // stack: start + 8, rounds, t0, t1, flag, retdest + + // Next four values of the internal state: first four IV values. + PUSH 0 + // stack: 0, start + 8, rounds, t0, t1, flag, retdest + %rep 4 + // stack: i, loc, ... + DUP1 + // stack: i, i, loc, ... + %blake2b_iv + // stack: IV_i, i, loc, ... + DUP3 + // stack: loc, IV_i, i, loc, ... + %mstore_kernel_general + // stack: i, loc, ... + %increment + SWAP1 + %increment + SWAP1 + // stack: i + 1, loc + 1,... + %endrep + // stack: 4, start + 12, rounds, t0, t1, flag, retdest + POP + // stack: start + 12, rounds, t0, t1, flag, retdest + SWAP4 + // stack: flag, rounds, t0, t1, start + 12, retdest + %mul_const(0xFFFFFFFFFFFFFFFF) + // stack: invert_if_flag, rounds, t0, t1, start + 12, retdest + %stack (inv, r, t0, t1, s) -> (4, s, t0, t1, inv, 0, r) + // stack: 4, start + 12, t0, t1, invert_if_flag, 0, rounds, retdest + + + // Last four values of the internal state: last four IV values, XOR'd with + // the values (t0, t1, invert_if_flag, 0). + %rep 4 + // stack: i, loc, val, next_val,... + DUP1 + // stack: i, i, loc, val, next_val,... + %blake2b_iv + // stack: IV_i, i, loc, val, next_val,... + DUP4 + // stack: val, IV_i, i, loc, val, next_val,... + XOR + // stack: val ^ IV_i, i, loc, val, next_val,... + DUP3 + // stack: loc, val ^ IV_i, i, loc, val, next_val,... + %mstore_kernel_general + // stack: i, loc, val, next_val,... + %increment + // stack: i + 1, loc, val, next_val,... + SWAP2 + // stack: val, loc, i + 1, next_val,... + POP + // stack: loc, i + 1, next_val,... + %increment + // stack: loc + 1, i + 1, next_val,... + SWAP1 + // stack: i + 1, loc + 1, next_val,... + %endrep + // stack: 8, start + 16, rounds, retdest + %pop2 + // stack: rounds, retdest + + // Run rounds of G functions. + PUSH g_functions_return + // stack: g_functions_return, rounds, retdest + SWAP1 + // stack: rounds, g_functions_return, retdest + %blake2b_internal_state_addr + // stack: start, rounds, g_functions_return, retdest + %jump(run_rounds_g_function) +g_functions_return: + // Finalize hash value. + // stack: retdest + PUSH hash_generate_return + // stack: hash_generate_return, retdest + %jump(blake2b_generate_all_hash_values) +hash_generate_return: + // stack: h_0', h_1', h_2', h_3', h_4', h_5', h_6', h_7', retdest + %stack (h: 8, retdest) -> (retdest, h) + // stack: retdest, h_0', h_1', h_2', h_3', h_4', h_5', h_6', h_7' + JUMP diff --git a/evm/src/cpu/kernel/asm/hash/blake2b/compression.asm b/evm/src/cpu/kernel/asm/hash/blake2b/compression.asm index 6e8cdb0a..9ad6bba9 100644 --- a/evm/src/cpu/kernel/asm/hash/blake2b/compression.asm +++ b/evm/src/cpu/kernel/asm/hash/blake2b/compression.asm @@ -187,9 +187,10 @@ compression_loop: // Run 12 rounds of G functions. PUSH g_functions_return // stack: g_functions_return, cur_block, retdest + PUSH 12 %blake2b_internal_state_addr - // stack: start, g_functions_return, cur_block, retdest - %jump(run_12_rounds_g_function) + // stack: start, 12, g_functions_return, cur_block, retdest + %jump(run_rounds_g_function) g_functions_return: // Finalize hash value. // stack: cur_block, retdest diff --git a/evm/src/cpu/kernel/asm/hash/blake2b/g_functions.asm b/evm/src/cpu/kernel/asm/hash/blake2b/g_functions.asm index f2d3b1d2..0544fe98 100644 --- a/evm/src/cpu/kernel/asm/hash/blake2b/g_functions.asm +++ b/evm/src/cpu/kernel/asm/hash/blake2b/g_functions.asm @@ -149,27 +149,29 @@ run_g_function_round: // stack: retdest, round, start JUMP -global run_12_rounds_g_function: - // stack: start, retdest +global run_rounds_g_function: + // stack: start, rounds, retdest PUSH 0 - // stack: round=0, start, retdest + // stack: round=0, start, rounds, retdest run_next_round_g_function: - // stack: round, start, retdest + // stack: round, start, rounds, retdest PUSH run_next_round_g_function_return - // stack: run_next_round_g_function_return, round, start, retdest + // stack: run_next_round_g_function_return, round, start, rounds, retdest SWAP2 // stack: start, round, run_next_round_g_function_return, retdest SWAP1 // stack: round, start, run_next_round_g_function_return, retdest %jump(run_g_function_round) run_next_round_g_function_return: - // stack: round, start, retdest + // stack: round, start, rounds, retdest %increment - // stack: round+1, start, retdest + // stack: round+1, start, rounds, retdest DUP1 - // stack: round+1, round+1, start, retdest - %lt_const(12) - // stack: round+1 < 12, round+1, start, retdest + // stack: round+1, round+1, start, rounds, retdest + DUP4 + // stack: rounds, round+1, round+1, start, rounds, retdest + GT + // stack: round+1 < rounds, round+1, start, rounds, retdest %jumpi(run_next_round_g_function) // stack: round+1, start, retdest %pop2 diff --git a/evm/src/cpu/kernel/asm/hash/blake2b/hash.asm b/evm/src/cpu/kernel/asm/hash/blake2b/hash.asm index 654b51b3..afaaa548 100644 --- a/evm/src/cpu/kernel/asm/hash/blake2b/hash.asm +++ b/evm/src/cpu/kernel/asm/hash/blake2b/hash.asm @@ -1,3 +1,4 @@ +// Generate a new hash value from the previous hash value and two elements of the internal state. blake2b_generate_new_hash_value: // stack: i, retdest %blake2b_hash_value_addr diff --git a/evm/src/cpu/kernel/constants/mod.rs b/evm/src/cpu/kernel/constants/mod.rs index 75a96403..24f62fdf 100644 --- a/evm/src/cpu/kernel/constants/mod.rs +++ b/evm/src/cpu/kernel/constants/mod.rs @@ -225,5 +225,5 @@ const PRECOMPILES_GAS: [(&str, u16); 13] = [ ("BN_MUL_GAS", 6_000), ("SNARKV_STATIC_GAS", 45_000), ("SNARKV_DYNAMIC_GAS", 34_000), - ("BLAKE2_F_DYNAMIC_GAS", 1), + ("BLAKE2_F__GAS", 1), ];