From e151be552214117543fd01bcd97db8d2f30fd367 Mon Sep 17 00:00:00 2001 From: Dmitry Vagner Date: Mon, 19 Sep 2022 12:09:57 -0700 Subject: [PATCH] ripemd storage --- evm/src/cpu/kernel/asm/memory/core.asm | 26 ---- evm/src/cpu/kernel/asm/ripemd/compression.asm | 90 ++++++------ evm/src/cpu/kernel/asm/ripemd/constants.asm | 9 +- evm/src/cpu/kernel/asm/ripemd/memory.asm | 138 ++++++++++++++++++ .../cpu/kernel/asm/ripemd/memory_macros.asm | 22 --- evm/src/cpu/kernel/asm/ripemd/ripemd.asm | 24 +-- 6 files changed, 200 insertions(+), 109 deletions(-) create mode 100644 evm/src/cpu/kernel/asm/ripemd/memory.asm delete mode 100644 evm/src/cpu/kernel/asm/ripemd/memory_macros.asm diff --git a/evm/src/cpu/kernel/asm/memory/core.asm b/evm/src/cpu/kernel/asm/memory/core.asm index ac02fb12..2c896345 100644 --- a/evm/src/cpu/kernel/asm/memory/core.asm +++ b/evm/src/cpu/kernel/asm/memory/core.asm @@ -85,32 +85,6 @@ // stack: (((((c_3 << 8) | c_2) << 8) | c_1) << 8) | c_0 %endmacro - -// Load a little-endian u32, consisting of 4 bytes (c_0, c_1, c_2, c_3), -// from kernel code. -%macro mload_kernel_code_u32_LE - // stack: offset - DUP1 - %mload_kernel_code - // stack: c_0, offset - DUP2 - %add_const(1) - %mload_kernel_code - %shl_const(8) - // stack: c0 | (c1 << 8), offset - DUP2 - %add_const(2) - %mload_kernel_code - %shl_const(16) - // stack: c0 | (c1 << 8) | (c2 << 16), offset - SWAP1 - %add_const(3) - %mload_kernel_code - %shl_const(24) - // stack: c0 | (c1 << 8) | (c2 << 16) | (c3 << 24) -%endmacro - - // Store a single byte to kernel code. %macro mstore_kernel_code // stack: offset, value diff --git a/evm/src/cpu/kernel/asm/ripemd/compression.asm b/evm/src/cpu/kernel/asm/ripemd/compression.asm index b14b0e72..544d417c 100644 --- a/evm/src/cpu/kernel/asm/ripemd/compression.asm +++ b/evm/src/cpu/kernel/asm/ripemd/compression.asm @@ -1,8 +1,8 @@ -/// _block is stored in memory and its address block remains on the stack +/// _offset is stored in memory and its address offset remains on the stack /// Note that state takes up 5 stack slots -/// def compression(state, _block): +/// def compression(state, _offset): /// /// stateL = state /// stateL = loop(stateL) @@ -22,10 +22,10 @@ /// u32(s0 + l1 + r2) /// /// where si, li, ri, oi, BL, RD respectively denote -/// state[i], stateL[i], stateR[i], output[i], block, retdest +/// state[i], stateL[i], stateR[i], output[i], offset, retdest global compression: - // stack: *state, block, retdest + // stack: *state, offset, retdest PUSH switch DUP7 PUSH 1 @@ -33,16 +33,16 @@ global compression: PUSH 16 PUSH 0 PUSH 0 - // stack: 0, 0, 16, 5, 1, block, switch, *state, block, retdest + // stack: 0, 0, 16, 5, 1, offset, switch, *state, offset, retdest DUP12 DUP12 DUP12 DUP12 DUP12 - // stack: *state, 0, 0, 16, 5, 1, block, switch, *state, block, retdest + // stack: *state, 0, 0, 16, 5, 1, offset, switch, *state, offset, retdest %jump(loop) switch: - // stack: *stateL, *state, block, retdest + // stack: *stateL, *state, offset, retdest PUSH mix DUP12 PUSH 0 @@ -50,13 +50,13 @@ switch: PUSH 16 PUSH 0 PUSH 0 - // stack: 0, 0, 16, 5, 0, block, mix, *stateL, *state, block, retdest + // stack: 0, 0, 16, 5, 0, offset, mix, *stateL, *state, offset, retdest DUP17 DUP17 DUP17 DUP17 DUP17 - // stack: *state, 0, 0, 16, 5, 0, block, mix, *stateL, *state, block, retdest + // stack: *state, 0, 0, 16, 5, 0, offset, mix, *stateL, *state, offset, retdest %jump(loop) mix: // stack: r0, r1, r2, r3, r4, l0, l1, l2, l3, l4, s0, s1, s2, s3, s4, BL, RD @@ -123,50 +123,50 @@ mix: loop: - // stack: *state, F, K, 16, rounds, sides, block, retdest + // stack: *state, F, K, 16, rounds, sides, offset, retdest DUP9 - // stack: round, *state, F, K, 16, rounds, sides, block, retdest + // stack: round, *state, F, K, 16, rounds, sides, offset, retdest %jumpi(update_round_vars) - // stack: *state, F, K, 16, 0, sides, block, retdest - %stack (a, b, c, d, e, F, K, boxes, rounds, sides, block, retdest) -> (retdest, a, b, c, d, e) + // stack: *state, F, K, 16, 0, sides, offset, retdest + %stack (a, b, c, d, e, F, K, boxes, rounds, sides, offset, retdest) -> (retdest, a, b, c, d, e) // stack: retdest, *state JUMP update_round_vars: - // stack: *state, F , K , 16, rounds, sides, block, retdest + // stack: *state, F , K , 16, rounds, sides, offset, retdest DUP9 DUP11 %get_round DUP1 - // stack: rnd, rnd, *state, F , K , 16, rounds, sides, block, retdest + // stack: rnd, rnd, *state, F , K , 16, rounds, sides, offset, retdest SWAP7 POP %push_F SWAP7 - // stack: rnd, rnd, *state, F', K , 16, rounds, sides, block, retdest + // stack: rnd, rnd, *state, F', K , 16, rounds, sides, offset, retdest SWAP8 POP - %load_u32(K_data) + %load_K SWAP7 POP - // stack: *state, F', K', 16, rounds, sides, block, retdest + // stack: *state, F', K', 16, rounds, sides, offset, retdest %jump(round) round: - // stack: *state, F, K, boxes, rounds , sides, block, retdest + // stack: *state, F, K, boxes, rounds , sides, offset, retdest DUP8 - // stack: boxes, *state, F, K, boxes, rounds , sides, block, retdest + // stack: boxes, *state, F, K, boxes, rounds , sides, offset, retdest %jumpi(box) - // stack: *state, F, K, 0, rounds , sides, block, retdest + // stack: *state, F, K, 0, rounds , sides, offset, retdest SWAP7 POP PUSH 16 SWAP7 - // stack: *state, F, K, 16, rounds , sides, block, retdest + // stack: *state, F, K, 16, rounds , sides, offset, retdest PUSH 1 DUP10 SUB SWAP9 POP - // stack: *state, F, K, 16, rounds-1, sides, block, retdest + // stack: *state, F, K, 16, rounds-1, sides, offset, retdest %jump(loop) @@ -178,7 +178,7 @@ round: /// box = get_box(sides, rounds, boxes) /// a += F(b, c, d) /// r = load_byte(r)(box) -/// x = load_block(r) +/// x = load_offset(r) /// a += x + K /// s = load_byte(s)(box) /// a = rol(s, a) @@ -189,66 +189,67 @@ round: box: - // stack: a, b, c, d, e, F, K, boxes, rounds, sides, block + // stack: a, b, c, d, e, F, K, boxes, rounds, sides, offset PUSH pre_rol DUP5 DUP5 DUP5 DUP10 - // stack: F, b, c, d, pre_rol, a, b, c, d, e, F, K, boxes, rounds, sides, block + // stack: F, b, c, d, pre_rol, a, b, c, d, e, F, K, boxes, rounds, sides, offset JUMP pre_rol: - // stack: F(b, c, d), a, b, c, d, e, F, K, boxes, rounds, sides, block + // stack: F(b, c, d), a, b, c, d, e, F, K, boxes, rounds, sides, offset ADD - // stack: a, b, c, d, e, F, K, boxes, rounds, sides, block + // stack: a, b, c, d, e, F, K, boxes, rounds, sides, offset %get_box - // stack: box, a, b, c, d, e, F, K, boxes, rounds, sides, block + // stack: box, a, b, c, d, e, F, K, boxes, rounds, sides, offset DUP1 %load_byte(R_data) DUP13 - // stack: block, r, box, a, b, c, d, e, F, K, boxes, rounds, sides, block - %load_from_block - // stack: x, box, a, b, c, d, e, F, K, boxes, rounds, sides, block + ADD + // stack: offset + r, box, a, b, c, d, e, F, K, boxes, rounds, sides, offset + %load_u32_from_block + // stack: x, box, a, b, c, d, e, F, K, boxes, rounds, sides, offset SWAP1 SWAP2 - // stack: a, x, box, b, c, d, e, F, K, boxes, rounds, sides, block + // stack: a, x, box, b, c, d, e, F, K, boxes, rounds, sides, offset ADD DUP8 ADD %u32 - // stack: a, box, b, c, d, e, F, K, boxes, rounds, sides, block + // stack: a, box, b, c, d, e, F, K, boxes, rounds, sides, offset PUSH mid_rol SWAP2 - // stack: box, a, mid_rol, b, c, d, e, F, K, boxes, rounds, sides, block + // stack: box, a, mid_rol, b, c, d, e, F, K, boxes, rounds, sides, offset %load_byte(S_data) - // stack: s, a, mid_rol, b, c, d, e, F, K, boxes, rounds, sides, block + // stack: s, a, mid_rol, b, c, d, e, F, K, boxes, rounds, sides, offset %jump(rol) mid_rol: - // stack: a, b, c, d, e, F, K, boxes, rounds, sides, block + // stack: a, b, c, d, e, F, K, boxes, rounds, sides, offset DUP5 - // stack: e, a, b, c, d, e, F, K, boxes, rounds, sides, block + // stack: e, a, b, c, d, e, F, K, boxes, rounds, sides, offset ADD %u32 - // stack: a, b, c, d, e, F, K, boxes, rounds, sides, block + // stack: a, b, c, d, e, F, K, boxes, rounds, sides, offset SWAP1 SWAP2 PUSH post_rol SWAP1 PUSH 10 - // stack: 10, c, post_rol, b, a, d, e, F, K, boxes, rounds, sides, block + // stack: 10, c, post_rol, b, a, d, e, F, K, boxes, rounds, sides, offset %jump(rol) post_rol: - // stack: c, a, b, d, e, F, K, boxes , rounds, sides, block + // stack: c, a, b, d, e, F, K, boxes , rounds, sides, offset SWAP3 - // stack: d, a, b, c, e, F, K, boxes , rounds, sides, block + // stack: d, a, b, c, e, F, K, boxes , rounds, sides, offset SWAP4 - // stack: e, a, b, c, d, F, K, boxes , rounds, sides, block + // stack: e, a, b, c, d, F, K, boxes , rounds, sides, offset SWAP7 PUSH 1 SWAP1 SUB SWAP7 - // stack: e, a, b, c, d, F, K, boxes-1, rounds, sides, block + // stack: e, a, b, c, d, F, K, boxes-1, rounds, sides, offset %jump(round) @@ -258,7 +259,6 @@ post_rol: // stack: 10 - 5*sides - rounds %endmacro - %macro get_box // stack: *7_args, boxes, rounds, sides DUP10 diff --git a/evm/src/cpu/kernel/asm/ripemd/constants.asm b/evm/src/cpu/kernel/asm/ripemd/constants.asm index 6d0c5b0e..69b75e86 100644 --- a/evm/src/cpu/kernel/asm/ripemd/constants.asm +++ b/evm/src/cpu/kernel/asm/ripemd/constants.asm @@ -1,11 +1,10 @@ -%macro load_u32(loc) +%macro load_K // stack: rnd %mul_const(4) - push $loc - ADD - // stack: loc + 4*rnd + %add_const(K_data) + // stack: K_data + 4*rnd %mload_kernel_code_u32 - // stack: u32 + // stack: K %end_macro K_data: diff --git a/evm/src/cpu/kernel/asm/ripemd/memory.asm b/evm/src/cpu/kernel/asm/ripemd/memory.asm new file mode 100644 index 00000000..0a170eb0 --- /dev/null +++ b/evm/src/cpu/kernel/asm/ripemd/memory.asm @@ -0,0 +1,138 @@ +ripemd_storage: // starts by initializing buffer + // stack: i (init 64) + %store_zeros(64, ripemd_storage) + // stack: + %jump(store_size) + +store_size: + // stack: length + %shl_const(3) + // stack: abcdefgh + %extract_and_store_byte(64) + // stack: abcdefg + %extract_and_store_byte(65) + // stack: abcdef + %extract_and_store_byte(66) + // stack: abcde + %extract_and_store_byte(67) + // stack: abcd + %extract_and_store_byte(68) + // stack: abc + %extract_and_store_byte(69) + // stack: ab + %extract_and_store_byte(70) + // stack: a + %mstore_ripemd(71) + // stack: 0x80 // padding has 0x80 in first position and zeros elsewhere + %mstore_ripemd(72) // store first padding term here so as to avoid extra label + %jump(store_padding) + +store_padding: + // stack: i (init 63) + %store_zeros(136, store_padding) + %jump(store_input) + +store_input: + // stack: ADDR , rem , length + DUP3 + DUP3 + DUP3 + MLOAD_GENERAL + // stack: byte, ADDR , rem , length + DUP5 + DUP7 + SUB + %add_const(136) + // stack: offset, byte, ADDR , rem , length + %mstore_ripemd + // stack: ADDR , rem , length + SWAP2 + %add_const(1) + SWAP2 + // stack: ADDR + 1, rem , length + SWAP3 + %sub_const(1) + SWAP3 + // stack: ADDR + 1, rem - 1, length + DUP4 + %jumpi(store_input) + // stack: ADDR , 0 , length + %pop4 + // stack: length + %jump(ripemd_init) + + +%macro store_zeros(N, label) + // stack: i + %stack (i) -> ($N, i, 0, i) + SUB + // stack: offset = N-i, 0, i + %mstore_ripemd + // stack: i + %sub_const(1) + DUP1 + // stack: i-1, i-1 + %jumpi($label) + // stack: 0 + POP +%endmacro + +%macro extract_and_store_byte(offset) + // stack: xsy + PUSH 0x100 + DUP2 + MOD + // stack: y, xsy + %stack (y, xsy) -> (xsy, y, 0x100, y) + // stack: xsy, y, 0x100, y + SUB + DIV + SWAP1 + // stack: y, xs + %mstore_ripemd($offset) + // stack: xs +%endmacro + +%macro mstore_ripemd_offset($offset) + // stack: value + PUSH $offset + // stack: offset, value + %mstore_kernel(RipeMD) + // stack: +%endmacro + +%macro mstore_ripemd + // stack: offset, value + %mstore_kernel(RipeMD) + // stack: +%endmacro + +%macro mload_ripemd + %mload_kernel(RipeMD) +%endmacro + +// Load LE u32 from 4 contiguous bytes a, b, c, d in RipeMD segment +%macro load_u32_from_block + // stack: offset + DUP1 + %mload_ripemd + // stack: a, offset + DUP2 + %add_const(1) + %mload_ripemd + %shl_const(8) + OR + // stack: a | (b << 8), offset + DUP2 + %add_const(2) + %mload_ripemd + %shl_const(16) + OR + // stack: a | (b << 8) | (c << 16), offset + SWAP1 + %add_const(3) + %mload_ripemd + %shl_const(24) + OR + // stack: a | (b << 8) | (c << 16) | (d << 24) +%endmacro diff --git a/evm/src/cpu/kernel/asm/ripemd/memory_macros.asm b/evm/src/cpu/kernel/asm/ripemd/memory_macros.asm deleted file mode 100644 index 1c35506b..00000000 --- a/evm/src/cpu/kernel/asm/ripemd/memory_macros.asm +++ /dev/null @@ -1,22 +0,0 @@ -%macro load_from_block - // stack: block, r - ADD - // stack: offset = block + r -%endmacro - -%macro init_buffer - -%endmacro - -%macro store_input - // stack: ADDR -%endmacro - -%macro store_padding -%endmacro - -%macro store_size - // stack: length - %shl_const(3) - // stack: length -%endmacro diff --git a/evm/src/cpu/kernel/asm/ripemd/ripemd.asm b/evm/src/cpu/kernel/asm/ripemd/ripemd.asm index 58a51224..46db0c2d 100644 --- a/evm/src/cpu/kernel/asm/ripemd/ripemd.asm +++ b/evm/src/cpu/kernel/asm/ripemd/ripemd.asm @@ -2,24 +2,26 @@ /// /// def ripemd160(_input): /// state, count, _buffer = [0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0], 0, [0]*64 -/// state, count, _buffer = ripemd_update(state, count, _buffer, len(input) , _input ) -/// state, count, _buffer = ripemd_update(state, count, _buffer, padlength(len(input)), [0x80]+[0]*63) -/// state, count, _buffer = ripemd_update(state, count, _buffer, 8, size(len(_input))) +/// state, count, _buffer = ripemd_update(state, count, _buffer, len(input) , bytes = _input ) +/// state, count, _buffer = ripemd_update(state, count, _buffer, padlength(len(input)), bytes = [0x80]+[0]*63) +/// state, count, _buffer = ripemd_update(state, count, _buffer, 8, bytes = size(len(_input))) /// return process(state) - +/// /// ripemd is called on a stack with ADDR and length /// ripemd_update will receive and return the stack in the form: /// stack: *state, count, length, offset -/// where offset is the virtual address of its final positional argument +/// where offset is the virtual address of the bytes argument global ripemd: // stack: ADDR, length - DUP4 - // stack: length, ADDR, length - %init_buffer // init _buffer at offset 0 - %store_size // store _size at offset 64 [consumes length] - %store_padding // store _padding at offset 72 - %store_input // store _input at offset 136 [consumes ADDR] + $stack (a, b, c, length) -> (64, length, 0x80, 63, a, b, c, length, length) + // stack: 64, length, 0x80, 63, a, b, c, length, length + %jump(ripemd_storage) // stores the following into memory + // init _buffer at offset 0 [consumes 64] + // store _size at offset 64 [consumes length] + // store _padding at offset 72 [consumes 0x80, 63] + // store _input at offset 136 [consumes ADDR, length] +ripemd_init: // stack: length %stack (length) -> ( 0, length, 136, ripemd_1, ripemd_2, process) // stack: count = 0, length, offset = 136, ripemd_1, ripemd_2, process