mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-05 23:33:07 +00:00
commit
dd6c5a0d1a
@ -22,6 +22,7 @@ pest = "2.1.3"
|
||||
pest_derive = "2.1.0"
|
||||
rand = "0.8.5"
|
||||
rand_chacha = "0.3.1"
|
||||
ripemd = "0.1.3"
|
||||
rlp = "0.5.1"
|
||||
serde = { version = "1.0.144", features = ["derive"] }
|
||||
sha2 = "0.10.2"
|
||||
|
||||
@ -48,6 +48,13 @@ pub(crate) fn combined_kernel() -> Kernel {
|
||||
include_str!("asm/mpt/storage_write.asm"),
|
||||
include_str!("asm/mpt/util.asm"),
|
||||
include_str!("asm/mpt/write.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/encode.asm"),
|
||||
include_str!("asm/rlp/decode.asm"),
|
||||
include_str!("asm/rlp/num_bytes.asm"),
|
||||
|
||||
@ -55,8 +55,7 @@
|
||||
// stack: (empty)
|
||||
%endmacro
|
||||
|
||||
// Load a big-endian u32, consisting of 4 bytes (c_3, c_2, c_1, c_0),
|
||||
// from the kernel.
|
||||
// Load from the kernel a big-endian u32, consisting of 4 bytes (c_3, c_2, c_1, c_0)
|
||||
%macro mload_kernel_u32(segment)
|
||||
// stack: offset
|
||||
DUP1
|
||||
@ -85,6 +84,32 @@
|
||||
// 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)
|
||||
%macro mload_kernel_u32_LE(segment)
|
||||
// stack: offset
|
||||
DUP1
|
||||
%mload_kernel($segment)
|
||||
// stack: c0 , offset
|
||||
DUP2
|
||||
%add_const(1)
|
||||
%mload_kernel($segment)
|
||||
%shl_const(8)
|
||||
OR
|
||||
// stack: c0 | (c1 << 8) , offset
|
||||
DUP2
|
||||
%add_const(2)
|
||||
%mload_kernel($segment)
|
||||
%shl_const(16)
|
||||
OR
|
||||
// stack: c0 | (c1 << 8) | (c2 << 16), offset
|
||||
SWAP1
|
||||
%add_const(3)
|
||||
%mload_kernel($segment)
|
||||
%shl_const(24)
|
||||
OR
|
||||
// stack: c0 | (c1 << 8) | (c2 << 16) | (c3 << 24)
|
||||
%endmacro
|
||||
|
||||
// Load a u256 (big-endian) from the kernel.
|
||||
%macro mload_kernel_u256(segment)
|
||||
// stack: offset
|
||||
@ -204,11 +229,13 @@
|
||||
// stack: value
|
||||
%endmacro
|
||||
|
||||
// Load a single byte from kernel general memory.
|
||||
%macro mload_kernel_general
|
||||
// stack: offset
|
||||
%mload_kernel(@SEGMENT_KERNEL_GENERAL)
|
||||
// stack: value
|
||||
%macro mload_kernel_code(label)
|
||||
// stack: shift
|
||||
PUSH $label
|
||||
ADD
|
||||
// stack: label + shift
|
||||
%mload_kernel_code
|
||||
// stack: byte
|
||||
%endmacro
|
||||
|
||||
// Load a big-endian u32, consisting of 4 bytes (c_3, c_2, c_1, c_0),
|
||||
@ -219,6 +246,24 @@
|
||||
// stack: value
|
||||
%endmacro
|
||||
|
||||
%macro mload_kernel_code_u32(label)
|
||||
// stack: u32_shift
|
||||
%mul_const(4)
|
||||
// stack: byte_shift
|
||||
PUSH $label
|
||||
ADD
|
||||
// stack: offset
|
||||
%mload_kernel_u32(@SEGMENT_CODE)
|
||||
// stack: value
|
||||
%endmacro
|
||||
|
||||
// Load a single byte from kernel general memory.
|
||||
%macro mload_kernel_general
|
||||
// stack: offset
|
||||
%mload_kernel(@SEGMENT_KERNEL_GENERAL)
|
||||
// stack: value
|
||||
%endmacro
|
||||
|
||||
// Load a big-endian u32, consisting of 4 bytes (c_3, c_2, c_1, c_0),
|
||||
// from kernel general memory.
|
||||
%macro mload_kernel_general_u32
|
||||
@ -227,6 +272,14 @@
|
||||
// stack: value
|
||||
%endmacro
|
||||
|
||||
// Load a little-endian u32, consisting of 4 bytes (c_3, c_2, c_1, c_0),
|
||||
// from kernel general memory.
|
||||
%macro mload_kernel_general_u32_LE
|
||||
// stack: offset
|
||||
%mload_kernel_u32_LE(@SEGMENT_KERNEL_GENERAL)
|
||||
// stack: value
|
||||
%endmacro
|
||||
|
||||
// Load a u256 (big-endian) from kernel code.
|
||||
%macro mload_kernel_code_u256
|
||||
// stack: offset
|
||||
@ -248,13 +301,6 @@
|
||||
// stack: (empty)
|
||||
%endmacro
|
||||
|
||||
// Store a single byte to kernel general memory.
|
||||
%macro mstore_kernel_general
|
||||
// stack: offset, value
|
||||
%mstore_kernel(@SEGMENT_KERNEL_GENERAL)
|
||||
// stack: (empty)
|
||||
%endmacro
|
||||
|
||||
// Store a big-endian u32, consisting of 4 bytes (c_3, c_2, c_1, c_0),
|
||||
// to kernel code.
|
||||
%macro mstore_kernel_code_u32
|
||||
@ -262,6 +308,27 @@
|
||||
%mstore_kernel_u32(@SEGMENT_CODE)
|
||||
%endmacro
|
||||
|
||||
// Store a single byte to @SEGMENT_RLP_RAW.
|
||||
%macro mstore_rlp
|
||||
// stack: offset, value
|
||||
%mstore_kernel(@SEGMENT_RLP_RAW)
|
||||
// stack: (empty)
|
||||
%endmacro
|
||||
|
||||
%macro mstore_kernel_general
|
||||
// stack: offset, value
|
||||
%mstore_kernel(@SEGMENT_KERNEL_GENERAL)
|
||||
// stack:
|
||||
%endmacro
|
||||
|
||||
%macro mstore_kernel_general(offset)
|
||||
// stack: value
|
||||
PUSH $offset
|
||||
// stack: offset, value
|
||||
%mstore_kernel_general
|
||||
// stack:
|
||||
%endmacro
|
||||
|
||||
// Store a big-endian u32, consisting of 4 bytes (c_3, c_2, c_1, c_0),
|
||||
// to kernel general memory.
|
||||
%macro mstore_kernel_general_u32
|
||||
@ -269,9 +336,12 @@
|
||||
%mstore_kernel_u32(@SEGMENT_KERNEL_GENERAL)
|
||||
%endmacro
|
||||
|
||||
// Store a single byte to @SEGMENT_RLP_RAW.
|
||||
%macro mstore_rlp
|
||||
// stack: offset, value
|
||||
%mstore_kernel(@SEGMENT_RLP_RAW)
|
||||
// stack: (empty)
|
||||
// set offset i to offset j in kernel general
|
||||
%macro mupdate_kernel_general
|
||||
// stack: j, i
|
||||
%mload_kernel_general
|
||||
// stack: x, i
|
||||
SWAP1
|
||||
%mstore_kernel_general
|
||||
// stack:
|
||||
%endmacro
|
||||
|
||||
96
evm/src/cpu/kernel/asm/ripemd/box.asm
Normal file
96
evm/src/cpu/kernel/asm/ripemd/box.asm
Normal file
@ -0,0 +1,96 @@
|
||||
/// Note that we unpack STATE: 5 to a, b, c, d, e
|
||||
/// All additions are u32
|
||||
///
|
||||
/// def box(a, b, c, d, e, F, K):
|
||||
///
|
||||
/// box = get_box(sides, rounds, boxes)
|
||||
/// a += F(b, c, d)
|
||||
/// r = load(r)(box)
|
||||
/// x = load_offset(r)
|
||||
/// a += x + K
|
||||
/// s = load(s)(box)
|
||||
/// a = rol(s, a)
|
||||
/// a += e
|
||||
/// c = rol(10, c)
|
||||
///
|
||||
/// return e, a, b, c, d, F, K
|
||||
|
||||
global box:
|
||||
// stack: a, b, c, d, e, F, K, boxes, rounds, sides, virt
|
||||
PUSH pre_rol
|
||||
DUP5
|
||||
DUP5
|
||||
DUP5
|
||||
DUP10
|
||||
// stack: F, b, c, d, pre_rol, a, b, c, d, e, F, K, boxes, rounds, sides, virt
|
||||
JUMP
|
||||
pre_rol:
|
||||
// stack: F(b, c, d), a, b, c, d, e, F, K, boxes, rounds, sides, virt
|
||||
ADD
|
||||
// stack: a, b, c, d, e, F, K, boxes, rounds, sides, virt
|
||||
%get_box
|
||||
// stack: box, a, b, c, d, e, F, K, boxes, rounds, sides, virt
|
||||
DUP12
|
||||
DUP2
|
||||
%mload_kernel_code(r_data)
|
||||
ADD
|
||||
// stack: virt + r, box, a, b, c, d, e, F, K, boxes, rounds, sides, virt
|
||||
%mload_kernel_general_u32_LE
|
||||
// stack: x, box, a, b, c, d, e, F, K, boxes, rounds, sides, virt
|
||||
SWAP1
|
||||
SWAP2
|
||||
// stack: a, x, box, b, c, d, e, F, K, boxes, rounds, sides, virt
|
||||
ADD
|
||||
DUP8
|
||||
ADD
|
||||
%as_u32
|
||||
// stack: a, box, b, c, d, e, F, K, boxes, rounds, sides, virt
|
||||
PUSH mid_rol
|
||||
SWAP2
|
||||
// stack: box, a, mid_rol, b, c, d, e, F, K, boxes, rounds, sides, virt
|
||||
%mload_kernel_code(s_data)
|
||||
// stack: s, a, mid_rol, b, c, d, e, F, K, boxes, rounds, sides, virt
|
||||
%jump(rol)
|
||||
mid_rol:
|
||||
// stack: a, b, c, d, e, F, K, boxes, rounds, sides, virt
|
||||
DUP5
|
||||
// stack: e, a, b, c, d, e, F, K, boxes, rounds, sides, virt
|
||||
ADD
|
||||
%as_u32
|
||||
// stack: a, b, c, d, e, F, K, boxes, rounds, sides, virt
|
||||
%stack (a, b, c) -> (10, c, post_rol, a, b)
|
||||
// stack: 10, c, post_rol, a, b, d, e, F, K, boxes, rounds, sides, virt
|
||||
%jump(rol)
|
||||
post_rol:
|
||||
// stack: c, a, b, d, e, F, K, boxes , rounds, sides, virt
|
||||
%stack (c, a, b, d, e, F, K, boxes) -> (boxes, 1, a, b, c, d, F, K, e)
|
||||
// stack: boxes, 1, a, b, c, d, F, K, e, rounds, sides, virt
|
||||
SUB
|
||||
SWAP7
|
||||
// stack: e, a, b, c, d, F, K, boxes-1, rounds, sides, virt
|
||||
%jump(round)
|
||||
|
||||
|
||||
%macro get_round
|
||||
// stack: sides, rounds
|
||||
%mul_const(5)
|
||||
PUSH 10
|
||||
SUB
|
||||
SUB
|
||||
// stack: 10 - 5*sides - rounds
|
||||
%endmacro
|
||||
|
||||
%macro get_box
|
||||
// stack: ARGS: 7, boxes, rounds, sides
|
||||
DUP10
|
||||
%mul_const(80)
|
||||
DUP10
|
||||
%mul_const(16)
|
||||
DUP10
|
||||
// stack: boxes , 16*rounds , 80*sides, ARGS: 7, boxes, rounds, sides
|
||||
PUSH 176
|
||||
SUB
|
||||
SUB
|
||||
SUB
|
||||
// stack: 176 - boxes - 16*rounds - 80*sides, ARGS: 7, boxes, rounds, sides
|
||||
%endmacro
|
||||
160
evm/src/cpu/kernel/asm/ripemd/compression.asm
Normal file
160
evm/src/cpu/kernel/asm/ripemd/compression.asm
Normal file
@ -0,0 +1,160 @@
|
||||
/// _block is stored in memory: its address virt stays on the stack
|
||||
/// def compress(STATE: 5, _block):
|
||||
///
|
||||
/// STATEL = STATE
|
||||
/// STATEL = loop(STATEL)
|
||||
///
|
||||
/// STATER = state
|
||||
/// STATER = loop(STATER)
|
||||
///
|
||||
/// return mix(STATER, STATEL, STATE)
|
||||
///
|
||||
///
|
||||
/// def mix(STATER, STATEL, STATE):
|
||||
/// return
|
||||
/// u32(s1 + l2 + r3),
|
||||
/// u32(s2 + l3 + r4),
|
||||
/// u32(s3 + l4 + r0),
|
||||
/// u32(s4 + l0 + r1),
|
||||
/// u32(s0 + l1 + r2)
|
||||
///
|
||||
/// where si, li, ri, oi, VR, RD respectively denote
|
||||
/// STATE[i], STATEL[i], STATER[i], OUTPUT[i], virt, retdest
|
||||
|
||||
global compress:
|
||||
// stack: STATE, virt, retdest
|
||||
PUSH switch
|
||||
DUP7
|
||||
%stack () -> (0, 0, 16, 5, 1)
|
||||
// stack: 0, 0, 16, 5, 1, virt, switch, STATE, virt, retdest
|
||||
DUP12
|
||||
DUP12
|
||||
DUP12
|
||||
DUP12
|
||||
DUP12
|
||||
// stack: STATE, 0, 0, 16, 5, 1, virt, switch, STATE, virt, retdest
|
||||
%jump(loop)
|
||||
switch:
|
||||
// stack: STATEL, STATE, virt, retdest
|
||||
PUSH mix
|
||||
DUP12
|
||||
%stack () -> (16, 5, 0)
|
||||
// stack: 16, 5, 0, virt, mix, STATEL, STATE, virt, retdest
|
||||
DUP15
|
||||
DUP15
|
||||
DUP15
|
||||
DUP15
|
||||
DUP15
|
||||
// stack: STATE, 16, 5, 0, virt, mix, STATEL, STATE, virt, retdest
|
||||
%stack (STATE: 5) -> (STATE, 0, 0)
|
||||
// stack: STATE, 0, 0, 16, 5, 0, virt, mix, STATEL, STATE, virt, retdest
|
||||
%jump(loop)
|
||||
mix:
|
||||
// stack: r0, r1, r2, r3, r4, l0, l1, l2, l3, l4, s0, s1, s2, s3, s4, VR, RD
|
||||
SWAP10
|
||||
// stack: s0, r1, r2, r3, r4, l0, l1, l2, l3, l4, r0, s1, s2, s3, s4, VR, RD
|
||||
SWAP1
|
||||
// stack: r1, s0, r2, r3, r4, l0, l1, l2, l3, l4, r0, s1, s2, s3, s4, VR, RD
|
||||
SWAP6
|
||||
// stack: l1, s0, r2, r3, r4, l0, r1, l2, l3, l4, r0, s1, s2, s3, s4, VR, RD
|
||||
%add3_u32
|
||||
// stack: o4, r3, r4, l0, r1, l2, l3, l4, r0, s1, s2, s3, s4, VR, RD
|
||||
SWAP14
|
||||
// stack: RD, r3, r4, l0, r1, l2, l3, l4, r0, s1, s2, s3, s4, VR, o4
|
||||
SWAP11
|
||||
// stack: s3, r3, r4, l0, r1, l2, l3, l4, r0, s1, s2, RD, s4, VR, o4
|
||||
SWAP10
|
||||
// stack: s2, r3, r4, l0, r1, l2, l3, l4, r0, s1, s3, RD, s4, VR, o4
|
||||
SWAP1
|
||||
// stack: r3, s2, r4, l0, r1, l2, l3, l4, r0, s1, s3, RD, s4, VR, o4
|
||||
SWAP6
|
||||
// stack: l3, s2, r4, l0, r1, l2, r3, l4, r0, s1, s3, RD, s4, VR, o4
|
||||
%add3_u32
|
||||
// stack: o1, l0, r1, l2, r3, l4, r0, s1, s3, RD, s4, VR, o4
|
||||
SWAP9
|
||||
// stack: RD, l0, r1, l2, r3, l4, r0, s1, s3, o1, s4, VR, o4
|
||||
SWAP10
|
||||
// stack: s4, l0, r1, l2, r3, l4, r0, s1, s3, o1, RD, VR, o4
|
||||
%add3_u32
|
||||
// stack: o3, l2, r3, l4, r0, s1, s3, o1, RD, VR, o4
|
||||
SWAP9
|
||||
// stack: VR, l2, r3, l4, r0, s1, s3, o1, RD, o3, o4
|
||||
SWAP5
|
||||
// stack: s1, l2, r3, l4, r0, VR, s3, o1, RD, o3, o4
|
||||
%add3_u32
|
||||
// stack: o0, l4, r0, VR, s3, o1, RD, o3, o4
|
||||
SWAP4
|
||||
// stack: s3, l4, r0, VR, o0, o1, RD, o3, o4
|
||||
%add3_u32
|
||||
// stack: o2, VR, o0, o1, RD, o3, o4
|
||||
SWAP4
|
||||
// stack: RD, VR, o0, o1, o2, o3, o4
|
||||
SWAP1
|
||||
// stack: VR, RD, o0, o1, o2, o3, o4
|
||||
POP
|
||||
// stack: RD, o0, o1, o2, o3, o4
|
||||
JUMP
|
||||
|
||||
|
||||
/// def loop(STATE: 5):
|
||||
/// while rounds:
|
||||
/// update_round_vars()
|
||||
/// round(STATE: 5, F, K, rounds, sides)
|
||||
///
|
||||
/// def update_round_vars():
|
||||
/// F = load(F)(sides, rounds)
|
||||
/// K = load(K)(sides, rounds)
|
||||
///
|
||||
/// def round(STATE, rounds, sides):
|
||||
/// while boxes:
|
||||
/// box(STATE, F, K)
|
||||
/// boxes -= 1
|
||||
/// boxes = 16
|
||||
/// rounds -= 1
|
||||
|
||||
loop:
|
||||
// stack: STATE, F, K, 16, rounds, sides, virt, retdest
|
||||
DUP9
|
||||
// stack: round, STATE, F, K, 16, rounds, sides, virt, retdest
|
||||
%jumpi(update_round_vars)
|
||||
// stack: STATE, F, K, 16, 0, sides, virt, retdest
|
||||
%stack (STATE: 5, F, K, boxes, rounds, sides, virt, retdest) -> (retdest, STATE)
|
||||
// stack: retdest, STATE
|
||||
JUMP
|
||||
update_round_vars:
|
||||
// stack: STATE, F , K , 16, rounds, sides, virt, retdest
|
||||
DUP9
|
||||
DUP11
|
||||
%get_round
|
||||
DUP1
|
||||
// stack: rnd, rnd, STATE, F , K , 16, rounds, sides, virt, retdest
|
||||
SWAP7
|
||||
POP
|
||||
%push_f
|
||||
SWAP7
|
||||
// stack: rnd, rnd, STATE, F', K , 16, rounds, sides, virt, retdest
|
||||
SWAP8
|
||||
POP
|
||||
%mload_kernel_code_u32(k_data)
|
||||
SWAP7
|
||||
POP
|
||||
// stack: STATE, F', K', 16, rounds, sides, virt, retdest
|
||||
%jump(round)
|
||||
global round:
|
||||
// stack: STATE, F, K, boxes, rounds , sides, virt, retdest
|
||||
DUP8
|
||||
// stack: boxes, STATE, F, K, boxes, rounds , sides, virt, retdest
|
||||
%jumpi(box)
|
||||
// stack: STATE, F, K, 0, rounds , sides, virt, retdest
|
||||
SWAP7
|
||||
POP
|
||||
PUSH 16
|
||||
SWAP7
|
||||
// stack: STATE, F, K, 16, rounds , sides, virt, retdest
|
||||
PUSH 1
|
||||
DUP10
|
||||
SUB
|
||||
SWAP9
|
||||
POP
|
||||
// stack: STATE, F, K, 16, rounds-1, sides, virt, retdest
|
||||
%jump(loop)
|
||||
117
evm/src/cpu/kernel/asm/ripemd/constants.asm
Normal file
117
evm/src/cpu/kernel/asm/ripemd/constants.asm
Normal file
@ -0,0 +1,117 @@
|
||||
global k_data:
|
||||
// Left
|
||||
BYTES 0x00, 0x00, 0x00, 0x00
|
||||
BYTES 0x5A, 0x82, 0x79, 0x99
|
||||
BYTES 0x6E, 0xD9, 0xEB, 0xA1
|
||||
BYTES 0x8F, 0x1B, 0xBC, 0xDC
|
||||
BYTES 0xA9, 0x53, 0xFD, 0x4E
|
||||
// Right
|
||||
BYTES 0x50, 0xA2, 0x8B, 0xE6
|
||||
BYTES 0x5C, 0x4D, 0xD1, 0x24
|
||||
BYTES 0x6D, 0x70, 0x3E, 0xF3
|
||||
BYTES 0x7A, 0x6D, 0x76, 0xE9
|
||||
BYTES 0x00, 0x00, 0x00, 0x00
|
||||
|
||||
global s_data:
|
||||
// Left Round 0
|
||||
BYTES 11, 14, 15, 12
|
||||
BYTES 05, 08, 07, 09
|
||||
BYTES 11, 13, 14, 15
|
||||
BYTES 06, 07, 09, 08
|
||||
// Left Round 1
|
||||
BYTES 07, 06, 08, 13
|
||||
BYTES 11, 09, 07, 15
|
||||
BYTES 07, 12, 15, 09
|
||||
BYTES 11, 07, 13, 12
|
||||
// Left Round 2
|
||||
BYTES 11, 13, 06, 07
|
||||
BYTES 14, 09, 13, 15
|
||||
BYTES 14, 08, 13, 06
|
||||
BYTES 05, 12, 07, 05
|
||||
// Left Round 3
|
||||
BYTES 11, 12, 14, 15
|
||||
BYTES 14, 15, 09, 08
|
||||
BYTES 09, 14, 05, 06
|
||||
BYTES 08, 06, 05, 12
|
||||
// Left Round 4
|
||||
BYTES 09, 15, 05, 11
|
||||
BYTES 06, 08, 13, 12
|
||||
BYTES 05, 12, 13, 14
|
||||
BYTES 11, 08, 05, 06
|
||||
// Right Round 0
|
||||
BYTES 08, 09, 09, 11
|
||||
BYTES 13, 15, 15, 05
|
||||
BYTES 07, 07, 08, 11
|
||||
BYTES 14, 14, 12, 06
|
||||
// Right Round 1
|
||||
BYTES 09, 13, 15, 07
|
||||
BYTES 12, 08, 09, 11
|
||||
BYTES 07, 07, 12, 07
|
||||
BYTES 06, 15, 13, 11
|
||||
// Right Round 2
|
||||
BYTES 09, 07, 15, 11
|
||||
BYTES 08, 06, 06, 14
|
||||
BYTES 12, 13, 05, 14
|
||||
BYTES 13, 13, 07, 05
|
||||
// Right Round 3
|
||||
BYTES 15, 05, 08, 11
|
||||
BYTES 14, 14, 06, 14
|
||||
BYTES 06, 09, 12, 09
|
||||
BYTES 12, 05, 15, 08
|
||||
// Right Round 4
|
||||
BYTES 08, 05, 12, 09
|
||||
BYTES 12, 05, 14, 06
|
||||
BYTES 08, 13, 06, 05
|
||||
BYTES 15, 13, 11, 11
|
||||
|
||||
global r_data:
|
||||
// Left Round 0
|
||||
BYTES 00, 04, 08, 12
|
||||
BYTES 16, 20, 24, 28
|
||||
BYTES 32, 36, 40, 44
|
||||
BYTES 48, 52, 56, 60
|
||||
// Left Round 1
|
||||
BYTES 28, 16, 52, 04
|
||||
BYTES 40, 24, 60, 12
|
||||
BYTES 48, 00, 36, 20
|
||||
BYTES 08, 56, 44, 32
|
||||
// Left Round 2
|
||||
BYTES 12, 40, 56, 16
|
||||
BYTES 36, 60, 32, 04
|
||||
BYTES 08, 28, 00, 24
|
||||
BYTES 52, 44, 20, 48
|
||||
// Left Round 3
|
||||
BYTES 04, 36, 44, 40
|
||||
BYTES 00, 32, 48, 16
|
||||
BYTES 52, 12, 28, 60
|
||||
BYTES 56, 20, 24, 08
|
||||
// Left Round 4
|
||||
BYTES 16, 00, 20, 36
|
||||
BYTES 28, 48, 08, 40
|
||||
BYTES 56, 04, 12, 32
|
||||
BYTES 44, 24, 60, 52
|
||||
// Right Round 0
|
||||
BYTES 20, 56, 28, 00
|
||||
BYTES 36, 08, 44, 16
|
||||
BYTES 52, 24, 60, 32
|
||||
BYTES 04, 40, 12, 48
|
||||
// Right Round 1
|
||||
BYTES 24, 44, 12, 28
|
||||
BYTES 00, 52, 20, 40
|
||||
BYTES 56, 60, 32, 48
|
||||
BYTES 16, 36, 04, 08
|
||||
// Right Round 2
|
||||
BYTES 60, 20, 04, 12
|
||||
BYTES 28, 56, 24, 36
|
||||
BYTES 44, 32, 48, 08
|
||||
BYTES 40, 00, 16, 52
|
||||
// Right Round 3
|
||||
BYTES 32, 24, 16, 04
|
||||
BYTES 12, 44, 60, 00
|
||||
BYTES 20, 48, 08, 52
|
||||
BYTES 36, 28, 40, 56
|
||||
// Right Round 4
|
||||
BYTES 48, 60, 40, 16
|
||||
BYTES 04, 20, 32, 28
|
||||
BYTES 24, 08, 52, 56
|
||||
BYTES 00, 12, 36, 44
|
||||
150
evm/src/cpu/kernel/asm/ripemd/functions.asm
Normal file
150
evm/src/cpu/kernel/asm/ripemd/functions.asm
Normal file
@ -0,0 +1,150 @@
|
||||
/// def rol(n, x):
|
||||
/// return (u32(x << n)) | (x >> (32 - n))
|
||||
|
||||
global rol:
|
||||
// stack: n, x, retdest
|
||||
SWAP1
|
||||
DUP1
|
||||
DUP3
|
||||
// stack: n, x, x, n, retdest
|
||||
PUSH 32
|
||||
SUB
|
||||
// stack: 32-n, x, x, n, retdest
|
||||
SHR
|
||||
// stack: x >> (32-n), x, n, retdest
|
||||
SWAP2
|
||||
// stack: n, x, x >> (32-n), retdest
|
||||
SHL
|
||||
// stack: x << n, x >> (32-n), retdest
|
||||
%as_u32
|
||||
// stack: u32(x << n), x >> (32-n), retdest
|
||||
OR
|
||||
// stack: u32(x << n) | (x >> (32-n)), retdest
|
||||
SWAP1
|
||||
JUMP
|
||||
|
||||
// def push_f(rnd):
|
||||
// Fs = [F0, F1, F2, F3, F4, F4, F3, F2, F1, F0]
|
||||
// acc = 0
|
||||
// for i, F in enumerate(Fs):
|
||||
// acc += (i==rnd)*F
|
||||
// return acc, rnd
|
||||
//
|
||||
// %this_f(i,F) enacts
|
||||
// acc += (i==rnd)*F
|
||||
|
||||
%macro push_f
|
||||
// stack: rnd
|
||||
PUSH 0
|
||||
%this_f(0,F0)
|
||||
%this_f(1,F1)
|
||||
%this_f(2,F2)
|
||||
%this_f(3,F3)
|
||||
%this_f(4,F4)
|
||||
%this_f(5,F4)
|
||||
%this_f(6,F3)
|
||||
%this_f(7,F2)
|
||||
%this_f(8,F1)
|
||||
%this_f(9,F0)
|
||||
// stack: F, rnd
|
||||
%endmacro
|
||||
|
||||
%macro this_f(i, F)
|
||||
// stack: acc, rnd
|
||||
DUP2
|
||||
// stack: rnd , acc, rnd
|
||||
%eq_const($i)
|
||||
// stack: rnd==i , acc, rnd
|
||||
%mul_const($F)
|
||||
// stack: (rnd==i)*F , acc, rnd
|
||||
ADD
|
||||
// stack: (rnd==j)*F + acc, rnd
|
||||
%endmacro
|
||||
|
||||
/// def F0(x, y, z):
|
||||
/// return x ^ y ^ z
|
||||
|
||||
global F0:
|
||||
// stack: x , y , z, retdest
|
||||
XOR
|
||||
// stack: x ^ y , z, retdest
|
||||
XOR
|
||||
// stack: x ^ y ^ z, retdest
|
||||
SWAP1
|
||||
JUMP
|
||||
|
||||
/// def F1(x, y, z):
|
||||
/// return (x & y) | (u32(~x) & z)
|
||||
|
||||
global F1:
|
||||
// stack: x, y, z, retdest
|
||||
DUP1
|
||||
// stack: x, x, y, z, retdest
|
||||
SWAP2
|
||||
// stack: y, x, x, z, retdest
|
||||
AND
|
||||
// stack: y & x, x, z, retdest
|
||||
SWAP2
|
||||
// stack: z, x, y & x , retdest
|
||||
SWAP1
|
||||
// stack: x, z, y & x , retdest
|
||||
%not_u32
|
||||
// stack: ~x, z, y & x , retdest
|
||||
AND
|
||||
// stack: ~x & z , y & x , retdest
|
||||
OR
|
||||
// stack: (~x & z) | (y & x), retdest
|
||||
SWAP1
|
||||
JUMP
|
||||
|
||||
/// def F2(x, y, z):
|
||||
/// return (x | u32(~y)) ^ z
|
||||
|
||||
global F2:
|
||||
// stack: x , y, z, retdest
|
||||
SWAP1
|
||||
// stack: y , x, z, retdest
|
||||
%not_u32
|
||||
// stack: ~y , x , z, retdest
|
||||
OR
|
||||
// stack: ~y | x , z, retdest
|
||||
XOR
|
||||
// stack: (~y | x) ^ z, retdest
|
||||
SWAP1
|
||||
JUMP
|
||||
|
||||
/// def F3(x, y, z):
|
||||
/// return (x & z) | (u32(~z) & y)
|
||||
|
||||
global F3:
|
||||
// stack: x, y , z , retdest
|
||||
DUP3
|
||||
// stack: z , x, y , z , retdest
|
||||
AND
|
||||
// stack: z & x, y , z , retdest
|
||||
SWAP2
|
||||
// stack: z, y, z & x , retdest
|
||||
%not_u32
|
||||
// stack: ~z , y, z & x , retdest
|
||||
AND
|
||||
// stack: ~z & y, z & x , retdest
|
||||
OR
|
||||
// stack: (~z & y) | (z & x), retdest
|
||||
SWAP1
|
||||
JUMP
|
||||
|
||||
/// def F4(x, y, z):
|
||||
/// return x ^ (y | u32(~z))
|
||||
|
||||
global F4:
|
||||
// stack: x, y, z, retdest
|
||||
SWAP2
|
||||
// stack: z, y, x, retdest
|
||||
%not_u32
|
||||
// stack: ~z, y, x, retdest
|
||||
OR
|
||||
// stack: ~z | y, x, retdest
|
||||
XOR
|
||||
// stack: (~z | y) ^ x, retdest
|
||||
SWAP1
|
||||
JUMP
|
||||
107
evm/src/cpu/kernel/asm/ripemd/main.asm
Normal file
107
evm/src/cpu/kernel/asm/ripemd/main.asm
Normal file
@ -0,0 +1,107 @@
|
||||
/// Variables beginning with _ are in memory
|
||||
///
|
||||
/// def ripemd160(_input):
|
||||
/// STATE, count, _buffer = [0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0], 0, [0]*64
|
||||
/// 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_stack is called on a stack with length, followed by the input bytes
|
||||
///
|
||||
/// ripemd_update receives and return the stack in the form:
|
||||
/// stack: STATE, count, length, virt
|
||||
/// where virt is the virtual address of the bytes argument
|
||||
|
||||
global ripemd_stack:
|
||||
// stack: length, INPUT
|
||||
%stack (length) -> (64, length, 0x80, 63, length, length)
|
||||
// stack: 64, length, 0x80, 63, length, length, INPUT
|
||||
%jump(ripemd_storage) // stores the following into memory
|
||||
// init _buffer at virt 0 [consumes 64]
|
||||
// store _size at virt 64 [consumes length]
|
||||
// store _padding at virt 72 [consumes 0x80, 63]
|
||||
// store _input at virt 136 [consumes length]
|
||||
|
||||
global ripemd:
|
||||
// stack: ADDR, length
|
||||
%stack (ADDR: 3, length) -> (64, length, 0x80, 63, length, ADDR, length)
|
||||
// stack: 64, length, 0x80, 63, length, ADDR, length
|
||||
%jump(ripemd_storage) // stores the following into memory
|
||||
// init _buffer at virt 0 [consumes 64]
|
||||
// store _size at virt 64 [consumes length]
|
||||
// store _padding at virt 72 [consumes 0x80, 63]
|
||||
// store _input at virt 136 [consumes ADDR, length]
|
||||
|
||||
global ripemd_init:
|
||||
// stack: length
|
||||
%stack (length) -> ( 0, length, 136, ripemd_1, ripemd_2, process)
|
||||
// stack: count = 0, length, virt = 136, ripemd_1, ripemd_2, process
|
||||
%stack () -> (0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0)
|
||||
// stack: 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0, count, length, virt, LABELS
|
||||
%jump(ripemd_update)
|
||||
ripemd_1:
|
||||
// stack: STATE, count, length , virt , LABELS
|
||||
DUP7
|
||||
// stack: length, STATE, count, length , virt , LABELS
|
||||
%padlength
|
||||
// stack: padlength, STATE, count, length , virt , LABELS
|
||||
SWAP7
|
||||
POP
|
||||
// stack: STATE, count, length = padlength, virt , LABELS
|
||||
%stack (STATE: 5, count, length, virt) -> (STATE, count, length, 72)
|
||||
// STATE, count, length , virt = 72, LABELS
|
||||
%jump(ripemd_update)
|
||||
ripemd_2:
|
||||
// stack: STATE, count, length , virt , LABELS
|
||||
%stack (STATE: 5, count, length, virt) -> (STATE, count, 8, 64)
|
||||
// stack: STATE, count, length = 8, virt = 64, LABELS
|
||||
%jump(ripemd_update)
|
||||
global process:
|
||||
// stack: a , b, c, d, e, count, length, virt
|
||||
%reverse_bytes_u32
|
||||
%shl_const(128)
|
||||
// stack: a', b, c, d, e, VARS
|
||||
SWAP1
|
||||
%reverse_bytes_u32
|
||||
%shl_const(96)
|
||||
OR
|
||||
// stack: b' a', c, d, e, VARS
|
||||
SWAP1
|
||||
%reverse_bytes_u32
|
||||
%shl_const(64)
|
||||
OR
|
||||
// stack: c' b' a', d, e, VARS
|
||||
SWAP1
|
||||
%reverse_bytes_u32
|
||||
%shl_const(32)
|
||||
OR
|
||||
// stack: d' c' b' a', e, VARS
|
||||
SWAP1
|
||||
%reverse_bytes_u32
|
||||
OR
|
||||
// stack: e' d' c' b' a', VARS
|
||||
%stack (result, VARS: 3, retdest) -> (retdest, result)
|
||||
// stack: 0xdeadbeef, result
|
||||
JUMP
|
||||
|
||||
|
||||
/// def padlength(length):
|
||||
/// t = length % 64
|
||||
/// return 56 + 64*(t > 47) - t
|
||||
|
||||
%macro padlength
|
||||
// stack: count
|
||||
%mod_const(64)
|
||||
// stack: t = count % 64
|
||||
PUSH 47
|
||||
DUP2
|
||||
// stack: t , 47 , t
|
||||
GT
|
||||
// stack: t > 47 , t
|
||||
%mul_const(64)
|
||||
%add_const(56)
|
||||
// stack: 56 + 64*(t > 47), t
|
||||
SUB
|
||||
%endmacro
|
||||
137
evm/src/cpu/kernel/asm/ripemd/memory.asm
Normal file
137
evm/src/cpu/kernel/asm/ripemd/memory.asm
Normal file
@ -0,0 +1,137 @@
|
||||
global 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_kernel_general(71)
|
||||
// stack: 0x80 // padding has 0x80 in first position and zeros elsewhere
|
||||
%mstore_kernel_general(72) // store first padding term here so as to avoid extra label
|
||||
%jump(store_padding)
|
||||
|
||||
store_padding:
|
||||
// stack: i [init 63], length
|
||||
%store_zeros(136, store_padding)
|
||||
// stack: length
|
||||
DUP1
|
||||
%jumpi(store_input_stack)
|
||||
POP
|
||||
%jump(ripemd_init)
|
||||
|
||||
store_input_stack:
|
||||
// stack: rem, length, REM_INP
|
||||
%stack (rem, length, head) -> (length, rem, 136, head, rem, length)
|
||||
SUB
|
||||
ADD
|
||||
// stack: offset, byte, rem, length, REM_INP
|
||||
%mstore_kernel_general
|
||||
// stack: rem, length, REM_INP
|
||||
%sub_const(1)
|
||||
DUP1
|
||||
// stack: rem - 1, rem - 1, length, REM_INP
|
||||
%jumpi(store_input_stack)
|
||||
// stack: 0, length
|
||||
POP
|
||||
%jump(ripemd_init)
|
||||
|
||||
store_input:
|
||||
// stack: rem , ADDR , length
|
||||
DUP4
|
||||
DUP4
|
||||
DUP4
|
||||
MLOAD_GENERAL
|
||||
// stack: byte, rem , ADDR , length
|
||||
DUP2
|
||||
DUP7
|
||||
SUB
|
||||
%add_const(136)
|
||||
// stack: offset, byte, rem , ADDR , length
|
||||
%mstore_kernel_general
|
||||
// stack: rem , ADDR , length
|
||||
%sub_const(1)
|
||||
// stack: rem-1, ADDR , length
|
||||
SWAP3
|
||||
%add_const(1)
|
||||
SWAP3
|
||||
// stack: rem-1, ADDR+1, length
|
||||
DUP1
|
||||
%jumpi(store_input)
|
||||
// stack: 0 , ADDR , length
|
||||
%pop4
|
||||
// stack: length
|
||||
%jump(ripemd_init)
|
||||
|
||||
/// def buffer_update(get, set, times):
|
||||
/// for i in range(times):
|
||||
/// buffer[set+i] = bytestring[get+i]
|
||||
|
||||
global buffer_update:
|
||||
// stack: get , set , times , retdest
|
||||
DUP2
|
||||
DUP2
|
||||
// stack: get, set, get , set , times , retdest
|
||||
%mupdate_kernel_general
|
||||
// stack: get , set , times , retdest
|
||||
%add_const(1)
|
||||
SWAP1
|
||||
%add_const(1)
|
||||
SWAP1
|
||||
SWAP2
|
||||
%sub_const(1)
|
||||
SWAP2
|
||||
// stack: get+1, set+1, times-1, retdest
|
||||
DUP3
|
||||
%jumpi(buffer_update)
|
||||
// stack: get , set , 0 , retdest
|
||||
%pop3
|
||||
JUMP
|
||||
|
||||
|
||||
%macro store_zeros(N, label)
|
||||
// stack: i
|
||||
%stack (i) -> ($N, i, 0, i)
|
||||
SUB
|
||||
// stack: offset = N-i, 0, i
|
||||
%mstore_kernel_general
|
||||
// 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_kernel_general($offset)
|
||||
// stack: xs
|
||||
%endmacro
|
||||
108
evm/src/cpu/kernel/asm/ripemd/update.asm
Normal file
108
evm/src/cpu/kernel/asm/ripemd/update.asm
Normal file
@ -0,0 +1,108 @@
|
||||
/// ripemd_update will receive and return the stack in the form:
|
||||
/// stack: STATE, count, length, virt
|
||||
///
|
||||
/// def ripemd_update(state, count, buffer, length, bytestring):
|
||||
/// have = (count // 8) % 64
|
||||
/// need = 64 - have
|
||||
/// shift = 0
|
||||
/// P = length >= need and have
|
||||
/// Q = length >= need
|
||||
/// if P:
|
||||
/// update_1()
|
||||
/// if Q:
|
||||
/// update_2()
|
||||
/// R = length > shift
|
||||
/// if R:
|
||||
/// buffer_update(virt + shift, have, length - shift)
|
||||
///
|
||||
/// return state, count + 8*length, buffer
|
||||
|
||||
global ripemd_update:
|
||||
// stack: STATE, count, length, virt, retdest
|
||||
%stack (STATE: 5, count, length, virt) -> (count, 8, 64, STATE, count, length, virt)
|
||||
DIV
|
||||
MOD
|
||||
// stack: have, STATE, count, length, virt, retdest
|
||||
DUP1
|
||||
PUSH 64
|
||||
SUB
|
||||
PUSH 0
|
||||
// stack: shift, need, have, STATE, count, length, virt, retdest
|
||||
%stack (shift, need, have, STATE: 5, count, length) -> (length, need, STATE, shift, need, have, count, length)
|
||||
// stack: length, need, STATE, shift, need, have, count, length, virt, retdest
|
||||
LT
|
||||
ISZERO
|
||||
// stack: Q, STATE, shift, need, have, count, length, virt, retdest
|
||||
%stack (Q, STATE: 5, shift, need, have) -> (have, Q, Q, STATE, shift, need, have)
|
||||
%gt_const(0)
|
||||
AND
|
||||
// stack: P, Q, STATE, shift, need, have, count, length, virt, retdest
|
||||
%jumpi(update_1)
|
||||
// stack: Q, STATE, shift, need, have, count, length, virt, retdest
|
||||
%jumpi(update_2)
|
||||
final_update:
|
||||
// stack: STATE, shift, need, have, count, length, virt, retdest
|
||||
%stack (STATE: 5, shift, need, have, count, length) -> (length, shift, return_step, STATE, shift, need, have, count, length)
|
||||
SUB
|
||||
// stack: ARGS: 2, STATE, shift, need, have, count, length, virt, retdest
|
||||
%stack (ARGS: 2, STATE: 5, shift, need, have, count, length, virt) -> (shift, virt, have, ARGS, STATE, shift, need, have, count, length, virt)
|
||||
ADD
|
||||
// stack: ARGS: 4, STATE, shift, need, have, count, length, virt, retdest
|
||||
%stack (ARGS: 4, STATE: 5, shift, need, have, count, length) -> (length, shift, ARGS, STATE, shift, need, have, count, length)
|
||||
GT
|
||||
// stack: R, ARGS: 4, STATE, shift, need, have, count, length, virt, retdest
|
||||
%jumpi(buffer_update)
|
||||
// stack: ARGS: 4, STATE, shift, need, have, count, length, virt, retdest
|
||||
%pop3
|
||||
JUMP
|
||||
return_step:
|
||||
// stack: STATE, shift, need, have, count, length, virt, retdest
|
||||
SWAP8
|
||||
DUP10
|
||||
%mul_const(8)
|
||||
ADD
|
||||
SWAP8
|
||||
// stack: STATE, shift, need, have, count, length, virt, retdest
|
||||
%stack (STATE: 5, shift, need, have, count, length, virt, retdest) -> (retdest, STATE, count, length, virt)
|
||||
JUMP
|
||||
|
||||
|
||||
/// def update_1():
|
||||
/// buffer_update(virt, have, need)
|
||||
/// shift = need
|
||||
/// have = 0
|
||||
/// state = compress(state, buffer)
|
||||
|
||||
update_1:
|
||||
// stack: Q, STATE, shift, need, have, count, length, virt, retdest
|
||||
%stack (Q, STATE: 5, shift, need, have, count, length, virt) -> (virt, have, need, update_1a, STATE, shift, need, have, count, length, virt)
|
||||
%jump(buffer_update)
|
||||
update_1a:
|
||||
// stack: STATE, shift, need, have, count, length, virt, retdest
|
||||
%stack (STATE: 5, shift, need, have) -> (STATE, 0, update_2, need, need, 0)
|
||||
// stack: STATE, 0, update_2, shift = need, need, have = 0, count, length, virt, retdest
|
||||
%jump(compress)
|
||||
|
||||
/// def update_2():
|
||||
/// while length >= shift + 64:
|
||||
/// shift += 64
|
||||
/// state = compress(state, bytestring[shift-64:])
|
||||
|
||||
update_2:
|
||||
// stack: STATE, shift, need, have, count, length, virt, retdest
|
||||
%stack (STATE: 5, shift, need, have, count, length) -> (64, shift, length, STATE, shift, need, have, count, length)
|
||||
ADD
|
||||
GT
|
||||
// stack: cond, STATE, shift, need, have, count, length, virt, retdest
|
||||
%jumpi(final_update)
|
||||
SWAP5
|
||||
%add_const(64)
|
||||
SWAP5
|
||||
%stack (STATE: 5, shift) -> (shift, 64, STATE, shift)
|
||||
DUP13
|
||||
ADD
|
||||
SUB
|
||||
// stack: offset, STATE, shift, need, have, count, length, virt, retdest
|
||||
%stack (offset, STATE: 5) -> (STATE, offset, update_2)
|
||||
// stack: STATE, offset, update_2, shift, need, have, count, length, virt, retdest
|
||||
%jump(compress)
|
||||
@ -230,6 +230,36 @@
|
||||
// stack: max
|
||||
%endmacro
|
||||
|
||||
%macro as_u32
|
||||
%and_const(0xffffffff)
|
||||
%endmacro
|
||||
|
||||
%macro not_u32
|
||||
// stack: x
|
||||
PUSH 0xffffffff
|
||||
// stack: 0xffffffff, x
|
||||
SUB
|
||||
// stack: 0xffffffff - x
|
||||
%endmacro
|
||||
|
||||
// u32 addition (discarding 2^32 bit)
|
||||
%macro add_u32
|
||||
// stack: x, y
|
||||
ADD
|
||||
// stack: x + y
|
||||
%as_u32
|
||||
// stack: (x + y) & u32::MAX
|
||||
%endmacro
|
||||
|
||||
%macro add3_u32
|
||||
// stack: x , y , z
|
||||
ADD
|
||||
// stack: x + y , z
|
||||
ADD
|
||||
// stack: x + y + z
|
||||
%as_u32
|
||||
%endmacro
|
||||
|
||||
%macro increment
|
||||
%add_const(1)
|
||||
%endmacro
|
||||
@ -247,15 +277,30 @@
|
||||
ISZERO
|
||||
%endmacro
|
||||
|
||||
%macro as_u32
|
||||
%and_const(0xFFFFFFFF)
|
||||
%endmacro
|
||||
|
||||
// u32 addition (discarding 2^32 bit)
|
||||
%macro add_u32
|
||||
// stack: x, y
|
||||
ADD
|
||||
// stack: x + y
|
||||
%as_u32
|
||||
// stack: (x + y) & u32::MAX
|
||||
// given u32 bytestring abcd return dcba
|
||||
%macro reverse_bytes_u32
|
||||
// stack: abcd
|
||||
DUP1
|
||||
PUSH 28
|
||||
BYTE
|
||||
// stack: a, abcd
|
||||
DUP2
|
||||
PUSH 29
|
||||
BYTE
|
||||
%shl_const(8)
|
||||
// stack: b0, a, abcd
|
||||
DUP3
|
||||
PUSH 30
|
||||
BYTE
|
||||
%shl_const(16)
|
||||
// stack: c00, b0, a, abcd
|
||||
SWAP3
|
||||
PUSH 31
|
||||
BYTE
|
||||
%shl_const(24)
|
||||
// stack: d000, b0, a, c00
|
||||
OR
|
||||
OR
|
||||
OR
|
||||
// stack: dcba
|
||||
%endmacro
|
||||
|
||||
@ -3,7 +3,8 @@ use std::str::FromStr;
|
||||
use anyhow::Result;
|
||||
use ethereum_types::U256;
|
||||
use rand::{thread_rng, Rng};
|
||||
use sha2::{Digest, Sha256};
|
||||
use ripemd::{Digest, Ripemd160};
|
||||
use sha2::Sha256;
|
||||
|
||||
use crate::cpu::kernel::aggregator::combined_kernel;
|
||||
use crate::cpu::kernel::interpreter::run_with_kernel;
|
||||
@ -15,6 +16,13 @@ fn sha2(input: Vec<u8>) -> U256 {
|
||||
U256::from(&hasher.finalize()[..])
|
||||
}
|
||||
|
||||
/// Standard RipeMD implementation.
|
||||
fn ripemd(input: Vec<u8>) -> U256 {
|
||||
let mut hasher = Ripemd160::new();
|
||||
hasher.update(input);
|
||||
U256::from(&hasher.finalize()[..])
|
||||
}
|
||||
|
||||
fn test_hash(hash_fn_label: &str, standard_implementation: &dyn Fn(Vec<u8>) -> U256) -> Result<()> {
|
||||
let kernel = combined_kernel();
|
||||
let mut rng = thread_rng();
|
||||
@ -48,3 +56,8 @@ fn test_hash(hash_fn_label: &str, standard_implementation: &dyn Fn(Vec<u8>) -> U
|
||||
fn test_sha2() -> Result<()> {
|
||||
test_hash("sha2", &sha2)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ripemd() -> Result<()> {
|
||||
test_hash("ripemd_stack", &ripemd)
|
||||
}
|
||||
|
||||
@ -5,6 +5,7 @@ mod exp;
|
||||
mod hash;
|
||||
mod mpt;
|
||||
mod packing;
|
||||
mod ripemd;
|
||||
mod rlp;
|
||||
mod transaction_parsing;
|
||||
|
||||
|
||||
57
evm/src/cpu/kernel/tests/ripemd.rs
Normal file
57
evm/src/cpu/kernel/tests/ripemd.rs
Normal file
@ -0,0 +1,57 @@
|
||||
use anyhow::Result;
|
||||
use ethereum_types::U256;
|
||||
use itertools::Itertools;
|
||||
|
||||
use crate::cpu::kernel::aggregator::combined_kernel;
|
||||
use crate::cpu::kernel::interpreter::run_with_kernel;
|
||||
|
||||
fn make_input(word: &str) -> Vec<u32> {
|
||||
let mut input: Vec<u32> = vec![word.len().try_into().unwrap()];
|
||||
input.append(&mut word.as_bytes().iter().map(|&x| x as u32).collect_vec());
|
||||
input.push(u32::from_str_radix("deadbeef", 16).unwrap());
|
||||
input
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ripemd_reference() -> Result<()> {
|
||||
let reference = vec![
|
||||
("", "0x9c1185a5c5e9fc54612808977ee8f548b2258d31"),
|
||||
("a", "0x0bdc9d2d256b3ee9daae347be6f4dc835a467ffe"),
|
||||
("abc", "0x8eb208f7e05d987a9b044a8e98c6b087f15a0bfc"),
|
||||
(
|
||||
"message digest",
|
||||
"0x5d0689ef49d2fae572b881b123a85ffa21595f36",
|
||||
),
|
||||
(
|
||||
"abcdefghijklmnopqrstuvwxyz",
|
||||
"0xf71c27109c692c1b56bbdceb5b9d2865b3708dbc",
|
||||
),
|
||||
(
|
||||
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
|
||||
"0x12a053384a9c0c88e405a06c27dcf49ada62eb2b",
|
||||
),
|
||||
(
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
|
||||
"0xb0e20b6e3116640286ed3a87a5713079b21f5189",
|
||||
),
|
||||
(
|
||||
"12345678901234567890123456789012345678901234567890123456789012345678901234567890",
|
||||
"0x9b752e45573d4b39f4dbd3323cab82bf63326bfb",
|
||||
),
|
||||
];
|
||||
|
||||
for (x, y) in reference {
|
||||
let input: Vec<u32> = make_input(x);
|
||||
let expected = U256::from(y);
|
||||
|
||||
let kernel = combined_kernel();
|
||||
let initial_offset = kernel.global_labels["ripemd_stack"];
|
||||
let initial_stack: Vec<U256> = input.iter().map(|&x| U256::from(x as u32)).rev().collect();
|
||||
let final_stack: Vec<U256> = run_with_kernel(&kernel, initial_offset, initial_stack)?
|
||||
.stack()
|
||||
.to_vec();
|
||||
let actual = final_stack[0];
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user