This commit is contained in:
Dmitry Vagner 2022-12-13 16:32:13 -08:00
commit 8c064b8624
31 changed files with 838 additions and 38 deletions

View File

@ -6,7 +6,8 @@ edition = "2021"
[dependencies]
anyhow = "1.0.40"
env_logger = "0.9.0"
blake2 = "0.10.5"
env_logger = "0.10.0"
eth_trie_utils = "0.4.0"
ethereum-types = "0.14.0"
hex = { version = "0.4.3", optional = true }
@ -23,11 +24,9 @@ plonky2 = { path = "../plonky2", default-features = false, features = ["timing"]
plonky2_util = { path = "../util" }
rand = "0.8.5"
rand_chacha = "0.3.1"
ripemd = "0.1.3"
rlp = "0.5.1"
rlp-derive = "0.1.0"
serde = { version = "1.0.144", features = ["derive"] }
sha2 = "0.10.2"
static_assertions = "1.1.0"
tiny-keccak = "2.0.2"
@ -37,6 +36,8 @@ jemallocator = "0.5.0"
[dev-dependencies]
criterion = "0.4.0"
hex = "0.4.3"
ripemd = "0.1.3"
sha2 = "0.10.6"
[features]
default = ["parallel"]

View File

@ -43,6 +43,28 @@ pub(crate) fn combined_kernel() -> Kernel {
include_str!("asm/curve/secp256k1/moddiv.asm"),
include_str!("asm/exp.asm"),
include_str!("asm/halt.asm"),
include_str!("asm/hash/blake2b/addresses.asm"),
include_str!("asm/hash/blake2b/compression.asm"),
include_str!("asm/hash/blake2b/g_functions.asm"),
include_str!("asm/hash/blake2b/hash.asm"),
include_str!("asm/hash/blake2b/iv.asm"),
include_str!("asm/hash/blake2b/ops.asm"),
include_str!("asm/hash/blake2b/permutations.asm"),
include_str!("asm/hash/blake2b/store.asm"),
include_str!("asm/hash/ripemd/box.asm"),
include_str!("asm/hash/ripemd/compression.asm"),
include_str!("asm/hash/ripemd/constants.asm"),
include_str!("asm/hash/ripemd/functions.asm"),
include_str!("asm/hash/ripemd/main.asm"),
include_str!("asm/hash/ripemd/memory.asm"),
include_str!("asm/hash/ripemd/update.asm"),
include_str!("asm/hash/sha2/compression.asm"),
include_str!("asm/hash/sha2/constants.asm"),
include_str!("asm/hash/sha2/message_schedule.asm"),
include_str!("asm/hash/sha2/ops.asm"),
include_str!("asm/hash/sha2/store_pad.asm"),
include_str!("asm/hash/sha2/temp_words.asm"),
include_str!("asm/hash/sha2/write_length.asm"),
include_str!("asm/main.asm"),
include_str!("asm/memory/core.asm"),
include_str!("asm/memory/memcpy.asm"),
@ -65,25 +87,11 @@ pub(crate) fn combined_kernel() -> Kernel {
include_str!("asm/mpt/storage/storage_read.asm"),
include_str!("asm/mpt/storage/storage_write.asm"),
include_str!("asm/mpt/util.asm"),
include_str!("asm/ripemd/box.asm"),
include_str!("asm/ripemd/compression.asm"),
include_str!("asm/ripemd/constants.asm"),
include_str!("asm/ripemd/functions.asm"),
include_str!("asm/ripemd/main.asm"),
include_str!("asm/ripemd/memory.asm"),
include_str!("asm/ripemd/update.asm"),
include_str!("asm/rlp/decode.asm"),
include_str!("asm/rlp/encode.asm"),
include_str!("asm/rlp/encode_rlp_string.asm"),
include_str!("asm/rlp/num_bytes.asm"),
include_str!("asm/rlp/read_to_memory.asm"),
include_str!("asm/sha2/compression.asm"),
include_str!("asm/sha2/constants.asm"),
include_str!("asm/sha2/message_schedule.asm"),
include_str!("asm/sha2/ops.asm"),
include_str!("asm/sha2/store_pad.asm"),
include_str!("asm/sha2/temp_words.asm"),
include_str!("asm/sha2/write_length.asm"),
include_str!("asm/shift.asm"),
include_str!("asm/transactions/router.asm"),
include_str!("asm/transactions/type_0.asm"),

View File

@ -0,0 +1,43 @@
// Load the initial hash value (the IV, but with params XOR'd into the first word).
%macro blake2b_initial_hash_value
%blake2b_iv_i(7)
%blake2b_iv_i(6)
%blake2b_iv_i(5)
%blake2b_iv_i(4)
%blake2b_iv_i(3)
%blake2b_iv_i(2)
%blake2b_iv_i(1)
// stack: IV_1, IV_2, IV_3, IV_4, IV_5, IV_6, IV_7
PUSH 0x01010040 // params: key = 00, digest_size = 64 = 0x40
%blake2b_iv_i(0)
XOR
// stack: IV_0 ^ params, IV_1, IV_2, IV_3, IV_4, IV_5, IV_6, IV_7
%endmacro
// Address where the working version of the hash value is stored.
%macro blake2b_hash_value_addr
PUSH 0
// stack: 0
%mload_kernel_general
// stack: num_blocks
%block_size
%add_const(2)
// stack: num_bytes+2
%endmacro
// Address where the working version of the compression internal state is stored.
%macro blake2b_internal_state_addr
%blake2b_hash_value_addr
%add_const(8)
%endmacro
// Address where the current message block is stored.
%macro blake2b_message_addr
%blake2b_internal_state_addr
%add_const(16)
%endmacro
// Block size is 128 bytes.
%macro block_size
%mul_const(128)
%endmacro

View File

@ -0,0 +1,280 @@
global blake2b_compression:
// stack: retdest
PUSH 0
// stack: cur_block = 0, retdest
%blake2b_initial_hash_value
compression_loop:
// stack: h_0, ..., h_7, cur_block, retdest
// Store the hash values.
%blake2b_hash_value_addr
// stack: addr, h_0, ..., h_7, cur_block, retdest
%rep 8
SWAP1
DUP2
%mstore_kernel_general
%increment
%endrep
// stack: addr, cur_block, retdest
POP
// stack: cur_block, retdest
PUSH 0
%mload_kernel_general
// stack: num_blocks, cur_block, retdest
%decrement
// stack: num_blocks - 1, cur_block, retdest
DUP2
// stack: cur_block, num_blocks - 1, cur_block, retdest
EQ
// stack: is_last_block, cur_block, retdest
SWAP1
// stack: cur_block, is_last_block, retdest
PUSH 1
%mload_kernel_general
// stack: num_bytes, cur_block, is_last_block, retdest
// Calculate t counter value.
DUP3
// stack: is_last_block, num_bytes, cur_block, is_last_block, retdest
MUL
// stack: is_last_block * num_bytes, cur_block, is_last_block, retdest
DUP2
// stack: cur_block, is_last_block * num_bytes, cur_block, is_last_block, retdest
%increment
%block_size
// stack: (cur_block + 1) * 128, is_last_block * num_bytes, cur_block, is_last_block, retdest
DUP4
// stack: is_last_block, (cur_block + 1) * 128, is_last_block * num_bytes, cur_block, is_last_block, retdest
ISZERO
// stack: not_last_block, (cur_block + 1) * 128, is_last_block * num_bytes, cur_block, is_last_block, retdest
MUL
// stack: not_last_block * ((cur_block + 1) * 128), is_last_block * num_bytes, cur_block, is_last_block, retdest
ADD
// stack: t = not_last_block * ((cur_block + 1) * 128) + is_last_block * num_bytes, cur_block, is_last_block, retdest
SWAP1
// stack: cur_block, t, is_last_block, retdest
DUP1
// stack: cur_block, cur_block, t, is_last_block, retdest
%block_size
%add_const(2)
// stack: cur_block_start_byte, t, cur_block, is_last_block, retdest
// Copy the message from the input space to the message working space.
%blake2b_message_addr
// stack: message_addr, cur_block_start_byte, t, cur_block, is_last_block, retdest
%rep 16
// stack: cur_message_addr, cur_block_byte, ...
DUP2
// stack: cur_block_byte, cur_message_addr, cur_block_byte, ...
%mload_kernel_general_u64_LE
// stack: m_i, cur_message_addr, cur_block_byte, ...
DUP2
// stack: cur_message_addr, m_i, cur_message_addr, cur_block_byte, ...
%mstore_kernel_general
// stack: cur_message_addr, cur_block_byte, ...
%increment
// stack: cur_message_addr + 1, cur_block_byte, ...
SWAP1
// stack: cur_block_byte, cur_message_addr + 1, ...
%add_const(8)
// stack: cur_block_byte + 8, cur_message_addr + 1, ...
SWAP1
// stack: cur_message_addr + 1, cur_block_byte + 8, ...
%endrep
// stack: end_message_addr, end_block_start_byte, t, cur_block, is_last_block, retdest
POP
POP
// stack: t, cur_block, is_last_block, retdest
SWAP1
// stack: cur_block, t, is_last_block, retdest
SWAP2
// stack: is_last_block, t, cur_block, retdest
%mul_const(0xFFFFFFFFFFFFFFFF)
// stack: invert_if_last_block, t, cur_block, 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, invert_if_last_block, t, cur_block, retdest
POP
// stack: h_0, ..., h_7, invert_if_last_block, t, cur_block, retdest
// Store the initial 16 values of the internal state.
%blake2b_internal_state_addr
// stack: start, h_0, ..., h_7, invert_if_last_block, t, cur_block, 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, invert_if_last_block, t, cur_block, retdest
// Next four values of the internal state: first four IV values.
PUSH 0
// stack: 0, start + 8, invert_if_last_block, t, cur_block, retdest
%rep 4
// stack: i, loc, ...
DUP2
DUP2
// stack: i, loc, i, loc,...
%blake2b_iv
// stack: IV_i, loc, i, loc,...
SWAP1
// 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, invert_if_last_block, t, cur_block, retdest
%stack (i, loc, inv, last, t) -> (t, t, i, loc, inv, last)
// stack: t, t, 4, start + 12, invert_if_last_block, cur_block, retdest
%shr_const(64)
// stack: t >> 64, t, 4, start + 12, invert_if_last_block, cur_block, retdest
SWAP1
// stack: t, t >> 64, 4, start + 12, invert_if_last_block, cur_block, retdest
PUSH 1
%shl_const(64)
// stack: 1 << 64, t, t >> 64, 4, start + 12, invert_if_last_block, cur_block, retdest
SWAP1
MOD
// stack: t_lo = t % (1 << 64), t_hi = t >> 64, 4, start + 12, invert_if_last_block, cur_block, retdest
%stack (t_lo, t_hi, i, loc, inv) -> (i, loc, t_lo, t_hi, inv, 0)
// stack: 4, start + 12, t_lo, t_hi, invert_if_last_block, 0, cur_block, retdest
// Last four values of the internal state: last four IV values, XOR'd with
// the values (t % 2**64, t >> 64, invert_if, 0).
%rep 4
// stack: i, loc, val, next_val,...
%stack (i, loc, val) -> (i, val, loc, i, loc)
// stack: i, val, loc, i, loc, next_val,...
%blake2b_iv
// stack: IV_i, val, loc, i, loc, next_val,...
XOR
// stack: val ^ IV_i, loc, i, loc, next_val,...
SWAP1
// stack: loc, val ^ IV_i, i, loc, next_val,...
%mstore_kernel_general
// stack: i, loc, next_val,...
%increment
SWAP1
%increment
SWAP1
// stack: i + 1, loc + 1, next_val,...
%endrep
// stack: 8, loc + 16, cur_block, retdest
POP
POP
// stack: cur_block, retdest
%blake2b_internal_state_addr
// stack: start, cur_block, retdest
PUSH 0
// stack: round=0, start, cur_block, retdest
// Run 12 rounds of G functions.
%rep 12
// stack: round, start, cur_block, retdest
%call_blake2b_g_function(0, 4, 8, 12, 0, 1)
%call_blake2b_g_function(1, 5, 9, 13, 2, 3)
%call_blake2b_g_function(2, 6, 10, 14, 4, 5)
%call_blake2b_g_function(3, 7, 11, 15, 6, 7)
%call_blake2b_g_function(0, 5, 10, 15, 8, 9)
%call_blake2b_g_function(1, 6, 11, 12, 10, 11)
%call_blake2b_g_function(2, 7, 8, 13, 12, 13)
%call_blake2b_g_function(3, 4, 9, 14, 14, 15)
// stack: round, start, cur_block, retdest
%increment
// stack: round + 1, start, cur_block, retdest
%endrep
// stack: 12, start, cur_block, retdest
POP
POP
// Finalize hash value.
// stack: cur_block, retdest
%blake2b_generate_new_hash_value(7)
%blake2b_generate_new_hash_value(6)
%blake2b_generate_new_hash_value(5)
%blake2b_generate_new_hash_value(4)
%blake2b_generate_new_hash_value(3)
%blake2b_generate_new_hash_value(2)
%blake2b_generate_new_hash_value(1)
%blake2b_generate_new_hash_value(0)
// stack: h_0', h_1', h_2', h_3', h_4', h_5', h_6', h_7', cur_block, retdest
DUP9
// stack: cur_block, h_0', h_1', h_2', h_3', h_4', h_5', h_6', h_7', cur_block, retdest
%increment
// stack: cur_block + 1, h_0', h_1', h_2', h_3', h_4', h_5', h_6', h_7', cur_block, retdest
SWAP9
// stack: cur_block, h_0', h_1', h_2', h_3', h_4', h_5', h_6', h_7', cur_block + 1, retdest
%increment
// stack: cur_block + 1, h_0', h_1', h_2', h_3', h_4', h_5', h_6', h_7', cur_block + 1, retdest
PUSH 0
%mload_kernel_general
// stack: num_blocks, cur_block + 1, h_0', h_1', h_2', h_3', h_4', h_5', h_6', h_7', cur_block + 1, retdest
EQ
// stack: last_block, h_0', h_1', h_2', h_3', h_4', h_5', h_6', h_7', cur_block + 1, retdest
%jumpi(compression_end)
%jump(compression_loop)
compression_end:
// stack: h_0', h_1', h_2', h_3', h_4', h_5', h_6', h_7', cur_block + 1, retdest
// Invert the bytes of each hash value.
%reverse_bytes_u64
// stack: h_0'', h_1', h_2', h_3', h_4', h_5', h_6', h_7', cur_block + 1, retdest
SWAP1
// stack: h_1', h_0'', h_2', h_3', h_4', h_5', h_6', h_7', cur_block + 1, retdest
%reverse_bytes_u64
// stack: h_1'', h_0'', h_2', h_3', h_4', h_5', h_6', h_7', cur_block + 1, retdest
SWAP2
// stack: h_2', h_0'', h_1'', h_3', h_4', h_5', h_6', h_7', cur_block + 1, retdest
%reverse_bytes_u64
// stack: h_2'', h_0'', h_1'', h_3', h_4', h_5', h_6', h_7', cur_block + 1, retdest
SWAP3
// stack: h_3', h_0'', h_1'', h_2'', h_4', h_5', h_6', h_7', cur_block + 1, retdest
%reverse_bytes_u64
// stack: h_3'', h_0'', h_1'', h_2'', h_4', h_5', h_6', h_7', cur_block + 1, retdest
SWAP4
// stack: h_4', h_0'', h_1'', h_2'', h_3'', h_5', h_6', h_7', cur_block + 1, retdest
%reverse_bytes_u64
// stack: h_4'', h_0'', h_1'', h_2'', h_3'', h_5', h_6', h_7', cur_block + 1, retdest
SWAP5
// stack: h_5', h_0'', h_1'', h_2'', h_3'', h_4'', h_6', h_7', cur_block + 1, retdest
%reverse_bytes_u64
// stack: h_5'', h_0'', h_1'', h_2'', h_3'', h_4'', h_6', h_7', cur_block + 1, retdest
SWAP6
// stack: h_6', h_0'', h_1'', h_2'', h_3'', h_4'', h_5'', h_7', cur_block + 1, retdest
%reverse_bytes_u64
// stack: h_6'', h_0'', h_1'', h_2'', h_3'', h_4'', h_5'', h_7', cur_block + 1, retdest
SWAP7
// stack: h_7', h_0'', h_1'', h_2'', h_3'', h_4'', h_5'', h_6'', cur_block + 1, retdest
%reverse_bytes_u64
// stack: h_7'', h_0'', h_1'', h_2'', h_3'', h_4'', h_5'', h_6'', cur_block + 1, retdest
%stack (h_7, h_s: 7) -> (h_s, h_7)
// stack: h_0'', h_1'', h_2'', h_3'', h_4'', h_5'', h_6'', h_7'', cur_block + 1, retdest
// Combine hash values.
%u64s_to_u256
// stack: h_0'' || h_1'' || h_2'' || h_3'', h_4'', h_5'', h_6'', h_7'', cur_block + 1, retdest
%stack (first, second: 4, cur) -> (second, first)
// stack: h_4'', h_5'', h_6'', h_7'', h_0'' || h_1'' || h_2'' || h_3'', retdest
%u64s_to_u256
// stack: hash_second = h_4'' || h_5'' || h_6'' || h_7'', hash_first = h_0'' || h_1'' || h_2'' || h_3'', retdest
%stack (second, first, ret) -> (ret, second, first)
// stack: retdest, hash_first, hash_second
JUMP

View File

@ -0,0 +1,126 @@
%macro blake2b_g_function
// Function to mix two input words, x and y, into the four words indexed by a, b, c, d (which
// are in the range 0..16) in the internal state.
// The internal state is stored in memory starting at the address start.
// stack: a, b, c, d, x, y, start
%stack (indices: 4) -> (indices, indices)
// stack: a, b, c, d, a, b, c, d, x, y, start
DUP11
// stack: start, a, b, c, d, a, b, c, d, x, y, start
%stack (start, a, b, c, d) -> (d, start, c, start, b, start, a, start)
// stack: d, start, c, start, b, start, a, start, a, b, c, d, x, y, start
ADD
%mload_kernel_general
// stack: v[d], c, start, b, start, a, start, a, b, c, d, x, y, start
%stack (vd, remaining: 6) -> (remaining, vd)
// stack: c, start, b, start, a, start, v[d], a, b, c, d, x, y, start
ADD
%mload_kernel_general
%stack (vc, remaining: 4) -> (remaining, vc)
// stack: b, start, a, start, v[c], v[d], a, b, c, d, x, y, start
ADD
%mload_kernel_general
// stack: v[b], a, start, v[c], v[d], a, b, c, d, x, y, start
%stack (vb, remaining: 2) -> (remaining, vb)
// stack: a, start, v[b], v[c], v[d], a, b, c, d, x, y, start
ADD
%mload_kernel_general
// stack: v[a], v[b], v[c], v[d], a, b, c, d, x, y, start
DUP2
// stack: v[b], v[a], v[b], v[c], v[d], a, b, c, d, x, y, start
DUP10
// stack: x, v[b], v[a], v[b], v[c], v[d], a, b, c, d, x, y, start
ADD
ADD
%as_u64
// stack: v[a]' = (v[a] + v[b] + x) % 2^64, v[b], v[c], v[d], a, b, c, d, x, y, start
%stack (a, b, c, d) -> (a, d, a, b, c, d)
// stack: v[a]', v[d], v[a]', v[b], v[c], v[d], a, b, c, d, x, y, start
XOR
%rotr_64(32)
// stack: v[d]' = (v[d] ^ v[a]') >>> 32, v[a]', v[b], v[c], v[d], a, b, c, d, x, y, start
%stack (top: 4, vd) -> (top)
// stack: v[d]', v[a]', v[b], v[c], a, b, c, d, x, y, start
%stack (d, a, b, c) -> (c, d, a, b, d)
// stack: v[c], v[d]', v[a]', v[b], v[d]', a, b, c, d, x, y, start
ADD
%as_u64
// stack: v[c]' = (v[c] + v[d]') % 2^64, v[a]', v[b], v[d]', a, b, c, d, x, y, start
%stack (c, a, b, d) -> (b, c, a, c, d)
// stack: v[b], v[c]', v[a]', v[c]', v[d]', a, b, c, d, x, y, start
XOR
%rotr_64(24)
// stack: v[b]' = (v[b] ^ v[c]') >>> 24, v[a]', v[c]', v[d]', a, b, c, d, x, y, start
SWAP1
// stack: v[a]', v[b]', v[c]', v[d]', a, b, c, d, x, y, start
DUP2
// stack: v[b]', v[a]', v[b]', v[c]', v[d]', a, b, c, d, x, y, start
DUP11
// stack: y, v[b]', v[a]', v[b]', v[c]', v[d]', a, b, c, d, x, y, start
ADD
ADD
%as_u64
// stack: v[a]'' = (v[a]' + v[b]' + y) % 2^64, v[b]', v[c]', v[d]', a, b, c, d, x, y, start
SWAP3
// stack: v[d]', v[b]', v[c]', v[a]'', a, b, c, d, x, y, start
DUP4
// stack: v[a]'', v[d]', v[b]', v[c]', v[a]'', a, b, c, d, x, y, start
XOR
%rotr_64(16)
// stack: v[d]'' = (v[a]'' ^ v[d]') >>> 8, v[b]', v[c]', v[a]'', a, b, c, d, x, y, start
SWAP2
// stack: v[c]', v[b]', v[d]'', v[a]'', a, b, c, d, x, y, start
DUP3
// stack: v[d]'', v[c]', v[b]', v[d]'', v[a]'', a, b, c, d, x, y, start
ADD
%as_u64
// stack: v[c]'' = (v[c]' + v[d]'') % 2^64, v[b]', v[d]'', v[a]'', a, b, c, d, x, y, start
DUP1
// stack: v[c]'', v[c]'', v[b]', v[d]'', v[a]'', a, b, c, d, x, y, start
SWAP2
// stack: v[b]', v[c]'', v[c]'', v[d]'', v[a]'', a, b, c, d, x, y, start
XOR
%rotr_64(63)
// stack: v[b]'' = (v[b]' ^ v[c]'') >>> 7, v[c]'', v[d]'', v[a]'', a, b, c, d, x, y, start
%stack (vb, vc, vd, va, a, b, c, d, x, y, start) -> (start, a, va, start, b, vb, start, c, vc, start, d, vd)
// stack: start, a, v[a]'', start, b, v[b]'', start, c, v[c]'', start, d, v[d]''
ADD
%mstore_kernel_general
ADD
%mstore_kernel_general
ADD
%mstore_kernel_general
ADD
%mstore_kernel_general
%endmacro
%macro call_blake2b_g_function(a, b, c, d, x_idx, y_idx)
// stack: round, start
PUSH $y_idx
DUP2
// stack: round, y_idx, round, start
%blake2b_permutation
// stack: s[y_idx], round, start
%blake2b_message_addr
ADD
%mload_kernel_general
// stack: m[s[y_idx]], round, start
PUSH $x_idx
DUP3
// stack: round, 2, m[s[y_idx]], round, start
%blake2b_permutation
// stack: s[x_idx], m[s[y_idx]], round, start
%blake2b_message_addr
ADD
%mload_kernel_general
// stack: m[s[x_idx]], m[s[y_idx]], round, start
%stack (ss: 2, r, s) -> (ss, s, r, s)
// stack: m[s[x_idx]], m[s[y_idx]], start, round, start
PUSH $d
PUSH $c
PUSH $b
PUSH $a
// stack: a, b, c, d, m[s[x_idx]], m[s[y_idx]], start, round, start
%blake2b_g_function
// stack: round, start
%endmacro

View File

@ -0,0 +1,18 @@
%macro blake2b_generate_new_hash_value(i)
%blake2b_hash_value_addr
%add_const($i)
%mload_kernel_general
// stack: h_i, ...
%blake2b_internal_state_addr
%add_const($i)
%mload_kernel_general
// stack: v_i, h_i, ...
%blake2b_internal_state_addr
%add_const($i)
%add_const(8)
%mload_kernel_general
// stack: v_(i+8), v_i, h_i, ...
XOR
XOR
// stack: h_i' = v_(i+8) ^ v_i ^ h_i, ...
%endmacro

View File

@ -0,0 +1,62 @@
global blake2b_iv_const:
// IV constants (big-endian)
// IV_0
BYTES 106, 9, 230, 103
BYTES 243, 188, 201, 8
// IV_1
BYTES 187, 103, 174, 133
BYTES 132, 202, 167, 59
// IV_2
BYTES 60, 110, 243, 114
BYTES 254, 148, 248, 43
// IV_3
BYTES 165, 79, 245, 58
BYTES 95, 29, 54, 241
// IV_4
BYTES 81, 14, 82, 127
BYTES 173, 230, 130, 209
// IV_5
BYTES 155, 5, 104, 140
BYTES 43, 62, 108, 31
// IV_6
BYTES 31, 131, 217, 171
BYTES 251, 65, 189, 107
// IV_7
BYTES 91, 224, 205, 25
BYTES 19, 126, 33, 121
%macro blake2b_iv
// stack: i, ...
PUSH blake2b_iv_const
// stack: blake2b_iv_const, i, ...
SWAP1
// stack: i, blake2b_iv_const, ...
%mul_const(8)
ADD
// stack: blake2b_iv_const + 2 * i, ...
DUP1
// stack: blake2b_iv_const + 2 * i, blake2b_iv_const + 2 * i, ...
%add_const(4)
// stack: blake2b_iv_const + 2 * i + 1, blake2b_iv_const + 2 * i, ...
%mload_kernel_code_u32
SWAP1
%mload_kernel_code_u32
// stack: IV_i[32:], IV_i[:32], ...
%shl_const(32)
// stack: IV_i[32:] << 32, IV_i[:32], ...
OR
// stack: IV_i, ...
%endmacro
%macro blake2b_iv_i(i)
PUSH $i
%blake2b_iv
%endmacro

View File

@ -0,0 +1,21 @@
// 64-bit right rotation
%macro rotr_64(rot)
// stack: value
PUSH $rot
// stack: rot, value
DUP2
DUP2
// stack: rot, value, rot, value
SHR
// stack: value >> rot, rot, value
%stack (shifted, rot, value) -> (rot, value, shifted)
// stack: rot, value, value >> rot
PUSH 64
SUB
// stack: 64 - rot, value, value >> rot
SHL
// stack: value << (64 - rot), value >> rot
%as_u64
// stack: (value << (64 - rot)) % (1 << 64), value >> rot
ADD
%endmacro

View File

@ -0,0 +1,74 @@
global permutation_0_constants:
BYTES 0, 1, 2, 3
BYTES 4, 5, 6, 7
BYTES 8, 9, 10, 11
BYTES 12, 13, 14, 15
global permutation_1_constants:
BYTES 14, 10, 4, 8
BYTES 9, 15, 13, 6
BYTES 1, 12, 0, 2
BYTES 11, 7, 5, 3
global permutation_2_constants:
BYTES 11, 8, 12, 0
BYTES 5, 2, 15, 13
BYTES 10, 14, 3, 6
BYTES 7, 1, 9, 4
global permutation_3_constants:
BYTES 7, 9, 3, 1
BYTES 13, 12, 11, 14
BYTES 2, 6, 5, 10
BYTES 4, 0, 15, 8
global permutation_4_constants:
BYTES 9, 0, 5, 7
BYTES 2, 4, 10, 15
BYTES 14, 1, 11, 12
BYTES 6, 8, 3, 13
global permutation_5_constants:
BYTES 2, 12, 6, 10
BYTES 0, 11, 8, 3
BYTES 4, 13, 7, 5
BYTES 15, 14, 1, 9
global permutation_6_constants:
BYTES 12, 5, 1, 15
BYTES 14, 13, 4, 10
BYTES 0, 7, 6, 3
BYTES 9, 2, 8, 11
global permutation_7_constants:
BYTES 13, 11, 7, 14
BYTES 12, 1, 3, 9
BYTES 5, 0, 15, 4
BYTES 8, 6, 2, 10
global permutation_8_constants:
BYTES 6, 15, 14, 9
BYTES 11, 3, 0, 8
BYTES 12, 2, 13, 7
BYTES 1, 4, 10, 5
global permutation_9_constants:
BYTES 10, 2, 8, 4
BYTES 7, 6, 1, 5
BYTES 15, 11, 9, 14
BYTES 3, 12, 13, 0
%macro blake2b_permutation
// stack: round, i
PUSH permutation_0_constants
// stack: permutation_0_constants, round, i
SWAP1
// stack: round, permutation_1_constants, i
%mod_const(10)
// stack: round % 10, permutation_1_constants, i
%mul_const(16)
ADD
// stack: permutation_(round)_constants, i
ADD
%mload_kernel_code
%endmacro

View File

@ -0,0 +1,45 @@
global blake2b:
%jump(blake2b_store)
global blake2b_store:
// stack: num_bytes, x[0], x[1], ..., x[num_bytes - 1], retdest
DUP1
// stack: num_bytes, num_bytes, x[0], x[1], ..., x[num_bytes - 1], retdest
%add_const(127)
%div_const(128)
// stack: num_blocks = ceil(num_bytes / 128), num_bytes, x[0], x[1], ..., x[num_bytes - 1], retdest
PUSH 0
// stack: addr=0, num_blocks, num_bytes, x[0], x[1], ..., x[num_bytes - 1], retdest
%mstore_kernel_general
// stack: num_bytes, x[0], x[1], ..., x[num_bytes - 1], retdest
DUP1
// stack: num_bytes, num_bytes, x[0], x[1], ..., x[num_bytes - 1], retdest
PUSH 1
// stack: 1, num_bytes, num_bytes, x[0], x[1], ..., x[num_bytes - 1], retdest
%mstore_kernel_general
// stack: num_bytes, x[0], x[1], ..., x[num_bytes - 1], retdest
PUSH 2
// stack: addr=2, counter=num_bytes, x[0], x[1], x[2], ... , x[num_bytes-1], retdest
store_loop:
// stack: addr, counter, x[num_bytes-counter], ... , x[num_bytes-1], retdest
DUP2
// stack: counter, addr, counter, x[num_bytes-counter], ... , x[num_bytes-1], retdest
ISZERO
%jumpi(store_end)
// stack: addr, counter, x[num_bytes-counter], ... , x[num_bytes-1], retdest
%stack (addr, counter, val) -> (addr, val, counter, addr)
// stack: addr, x[num_bytes-counter], counter, addr, ... , x[num_bytes-1], retdest
%mstore_kernel_general
// stack: counter, addr, ... , x[num_bytes-1], retdest
%decrement
// stack: counter-1, addr, ... , x[num_bytes-1], retdest
SWAP1
// stack: addr, counter-1, ... , x[num_bytes-1], retdest
%increment
// stack: addr+1, counter-1, ... , x[num_bytes-1], retdest
%jump(store_loop)
store_end:
// stack: addr, counter, retdest
%pop2
// stack: retdest
%jump(blake2b_compression)

View File

@ -97,7 +97,7 @@
// stack: (((((c_3 << 8) | c_2) << 8) | c_1) << 8) | c_0
%endmacro
// Load from the kernel a little-endian u32, consisting of 4 bytes (c_0, c_1, c_2, c_3)
// Load from the kernel a little-endian u32, consisting of 4 bytes (c_0, c_1, c_2, c_3).
%macro mload_kernel_u32_LE(segment)
// stack: offset
DUP1
@ -123,6 +123,24 @@
// stack: c0 | (c1 << 8) | (c2 << 16) | (c3 << 24)
%endmacro
// Load from the kernel a little-endian u64, consisting of 8 bytes
// (c_0, c_1, c_2, c_3, c_4, c_5, c_6, c_7).
%macro mload_kernel_u64_LE(segment)
// stack: offset
DUP1
%mload_kernel_u32_LE($segment)
// stack: lo, offset
SWAP1
// stack: offset, lo
%add_const(4)
%mload_kernel_u32_LE($segment)
// stack: hi, lo
%shl_const(32)
// stack: hi << 32, lo
OR
// stack: (hi << 32) | lo
%endmacro
// Load a u256 (big-endian) from the kernel.
%macro mload_kernel_u256(segment)
// stack: offset
@ -292,7 +310,7 @@
// stack: value
%endmacro
// Load a little-endian u32, consisting of 4 bytes (c_3, c_2, c_1, c_0),
// Load a little-endian u32, consisting of 4 bytes (c_0, c_1, c_2, c_3),
// from kernel general memory.
%macro mload_kernel_general_u32_LE
// stack: offset
@ -300,6 +318,14 @@
// stack: value
%endmacro
// Load a little-endian u64, consisting of 8 bytes
// (c_0, c_1, c_2, c_3, c_4, c_5, c_6, c_7), from kernel general memory.
%macro mload_kernel_general_u64_LE
// stack: offset
%mload_kernel_u64_LE(@SEGMENT_KERNEL_GENERAL)
// stack: value
%endmacro
// Load a u256 (big-endian) from kernel code.
%macro mload_kernel_code_u256
// stack: offset

View File

@ -240,6 +240,10 @@
%and_const(0xffffffff)
%endmacro
%macro as_u64
%and_const(0xffffffffffffffff)
%endmacro
%macro not_u32
// stack: x
PUSH 0xffffffff
@ -311,6 +315,33 @@
// stack: dcba
%endmacro
01 00 00 00 01 00 00 00 01 00
ff 00 00 ff 00 ff 00 00 00 00 ff 00 00
ff ff ff ff ff ff
%macro reverse_bytes_u64
// stack: word
DUP1
// stack: word, word
%and_const(0xffffffff)
// stack: word_lo, word
SWAP1
// stack: word, word_lo
%shr_const(32)
// stack: word_hi, word_lo
%reverse_bytes_u32
// stack: word_hi_inverted, word_lo
SWAP1
// stack: word_lo, word_hi_inverted
%reverse_bytes_u32
// stack: word_lo_inverted, word_hi_inverted
%shl_const(32)
OR
// stack: word_inverted
%endmacro
// Combine four big-endian u64s into a u256.
%macro u64s_to_u256
// stack: a, b, c, d
%rep 3
%shl_const(64)
OR
%endrep
// stack: a || b || c || d
%endmacro

View File

@ -18,15 +18,16 @@ pub(crate) mod txn_fields;
/// Constants that are accessible to our kernel assembly code.
pub fn evm_constants() -> HashMap<String, U256> {
let mut c = HashMap::new();
for (name, value) in EC_CONSTANTS {
c.insert(name.into(), U256::from_big_endian(&value));
}
for (name, value) in HASH_CONSTANTS {
let hex_constants = EC_CONSTANTS.iter().chain(HASH_CONSTANTS.iter()).cloned();
for (name, value) in hex_constants {
c.insert(name.into(), U256::from_big_endian(&value));
}
for (name, value) in GAS_CONSTANTS {
c.insert(name.into(), U256::from(value));
}
for segment in Segment::all() {
c.insert(segment.var_name().into(), (segment as u32).into());
}

View File

@ -163,17 +163,25 @@ impl<'a> Interpreter<'a> {
&mut self.generation_state.memory.contexts[0].segments[Segment::TrieData as usize].content
}
pub(crate) fn get_rlp_memory(&self) -> Vec<u8> {
self.generation_state.memory.contexts[0].segments[Segment::RlpRaw as usize]
pub(crate) fn get_memory_segment_bytes(&self, segment: Segment) -> Vec<u8> {
self.generation_state.memory.contexts[0].segments[segment as usize]
.content
.iter()
.map(|x| x.as_u32() as u8)
.collect()
}
pub(crate) fn get_rlp_memory(&self) -> Vec<u8> {
self.get_memory_segment_bytes(Segment::RlpRaw)
}
pub(crate) fn set_memory_segment_bytes(&mut self, segment: Segment, memory: Vec<u8>) {
self.generation_state.memory.contexts[0].segments[segment as usize].content =
memory.into_iter().map(U256::from).collect();
}
pub(crate) fn set_rlp_memory(&mut self, rlp: Vec<u8>) {
self.generation_state.memory.contexts[0].segments[Segment::RlpRaw as usize].content =
rlp.into_iter().map(U256::from).collect();
self.set_memory_segment_bytes(Segment::RlpRaw, rlp)
}
pub(crate) fn set_code(&mut self, context: usize, code: Vec<u8>) {

View File

@ -1,7 +1,8 @@
use std::str::FromStr;
use anyhow::Result;
use ethereum_types::U256;
use blake2::Blake2b512;
use ethereum_types::{U256, U512};
use rand::{thread_rng, Rng};
use ripemd::{Digest, Ripemd160};
use sha2::Sha256;
@ -23,6 +24,13 @@ fn ripemd(input: Vec<u8>) -> U256 {
U256::from(&hasher.finalize()[..])
}
/// Standard Blake2b implementation.
fn blake2b(input: Vec<u8>) -> U512 {
let mut hasher = Blake2b512::new();
hasher.update(input);
U512::from(&hasher.finalize()[..])
}
fn make_random_input() -> Vec<u8> {
// Generate a random message, between 0 and 9999 bytes.
let mut rng = thread_rng();
@ -48,7 +56,17 @@ fn make_input_stack(message: Vec<u8>) -> Vec<U256> {
initial_stack
}
fn test_hash(hash_fn_label: &str, standard_implementation: &dyn Fn(Vec<u8>) -> U256) -> Result<()> {
fn combine_u256s(hi: U256, lo: U256) -> U512 {
let mut result = U512::from(hi);
result <<= 256;
result += U512::from(lo);
result
}
fn prepare_test<T>(
hash_fn_label: &str,
standard_implementation: &dyn Fn(Vec<u8>) -> T,
) -> Result<(T, T, Vec<U256>, Vec<U256>)> {
// Make the input.
let message_random = make_random_input();
let message_custom = make_custom_input();
@ -68,9 +86,42 @@ fn test_hash(hash_fn_label: &str, standard_implementation: &dyn Fn(Vec<u8>) -> U
let result_random = run_interpreter(kernel_function, initial_stack_random)?;
let result_custom = run_interpreter(kernel_function, initial_stack_custom)?;
Ok((
expected_random,
expected_custom,
result_random.stack().to_vec(),
result_custom.stack().to_vec(),
))
}
fn test_hash_256(
hash_fn_label: &str,
standard_implementation: &dyn Fn(Vec<u8>) -> U256,
) -> Result<()> {
let (expected_random, expected_custom, random_stack, custom_stack) =
prepare_test(hash_fn_label, standard_implementation).unwrap();
// Extract the final output.
let actual_random = result_random.stack()[0];
let actual_custom = result_custom.stack()[0];
let actual_random = random_stack[0];
let actual_custom = custom_stack[0];
// Check that the result is correct.
assert_eq!(expected_random, actual_random);
assert_eq!(expected_custom, actual_custom);
Ok(())
}
fn test_hash_512(
hash_fn_label: &str,
standard_implementation: &dyn Fn(Vec<u8>) -> U512,
) -> Result<()> {
let (expected_random, expected_custom, random_stack, custom_stack) =
prepare_test(hash_fn_label, standard_implementation).unwrap();
// Extract the final output.
let actual_random = combine_u256s(random_stack[0], random_stack[1]);
let actual_custom = combine_u256s(custom_stack[0], custom_stack[1]);
// Check that the result is correct.
assert_eq!(expected_random, actual_random);
@ -81,10 +132,15 @@ fn test_hash(hash_fn_label: &str, standard_implementation: &dyn Fn(Vec<u8>) -> U
#[test]
fn test_sha2() -> Result<()> {
test_hash("sha2", &sha2)
test_hash_256("sha2", &sha2)
}
#[test]
fn test_ripemd() -> Result<()> {
test_hash("ripemd_stack", &ripemd)
test_hash_256("ripemd_stack", &ripemd)
}
#[test]
fn test_blake2b() -> Result<()> {
test_hash_512("blake2b", &blake2b)
}

View File

@ -6,7 +6,6 @@ edition = "2021"
[dependencies]
anyhow = "1.0.40"
env_logger = "0.9.0"
itertools = "0.10.0"
log = "0.4.14"
plonky2 = { path = "../plonky2" }
@ -17,6 +16,7 @@ starky = { path = "../starky" }
[dev-dependencies]
criterion = "0.4.0"
env_logger = "0.10.0"
[[bench]]
name = "lookup_permuted_cols"

View File

@ -4,5 +4,5 @@ description = "Utilities used by Plonky2"
version = "0.1.0"
edition = "2021"
[dependencies]
[dev-dependencies]
rand = { version = "0.8.5", default-features = false, features = ["getrandom"] }