diff --git a/evm/src/cpu/kernel/aggregator.rs b/evm/src/cpu/kernel/aggregator.rs index 67a0051b..5fb6ad08 100644 --- a/evm/src/cpu/kernel/aggregator.rs +++ b/evm/src/cpu/kernel/aggregator.rs @@ -45,7 +45,6 @@ pub(crate) fn combined_kernel() -> Kernel { include_str!("asm/sha2/ops.asm"), include_str!("asm/sha2/store_pad.asm"), include_str!("asm/sha2/temp_words.asm"), - include_str!("asm/sha2/util.asm"), include_str!("asm/sha2/write_length.asm"), include_str!("asm/rlp/encode.asm"), include_str!("asm/rlp/decode.asm"), diff --git a/evm/src/cpu/kernel/asm/sha2/compression.asm b/evm/src/cpu/kernel/asm/sha2/compression.asm index 5325e7d0..eb9b73b8 100644 --- a/evm/src/cpu/kernel/asm/sha2/compression.asm +++ b/evm/src/cpu/kernel/asm/sha2/compression.asm @@ -1,3 +1,11 @@ +// We use memory starting at 320 * num_blocks + 2 (after the message schedule +// space) as scratch space to store stack values. +%macro scratch_space_addr_from_num_blocks + // stack: num_blocks + %mul_const(320) + %add_const(2) +%endmacro + global sha2_compression: // stack: message_schedule_addr, retdest PUSH 0 diff --git a/evm/src/cpu/kernel/asm/sha2/message_schedule.asm b/evm/src/cpu/kernel/asm/sha2/message_schedule.asm index d3b5c6c1..78d98634 100644 --- a/evm/src/cpu/kernel/asm/sha2/message_schedule.asm +++ b/evm/src/cpu/kernel/asm/sha2/message_schedule.asm @@ -1,3 +1,10 @@ +// We put the message schedule in memory starting at 64 * num_blocks + 2. +%macro message_schedule_addr_from_num_blocks + // stack: num_blocks + %mul_const(64) + %add_const(2) +%endmacro + // Precodition: stack contains address of one message block, followed by output address // Postcondition: 256 bytes starting at given output address contain the 64 32-bit chunks // of message schedule (in four-byte increments) @@ -32,7 +39,7 @@ gen_message_schedule_from_block_0_loop: // stack: block[0] >> 32, block[0], output_addr, counter, block[1], retdest SWAP1 // stack: block[0], block[0] >> 32, output_addr, counter, block[1], retdest - %truncate_to_u32 + %as_u32 // stack: block[0] % (1 << 32), block[0] >> 32, output_addr, counter, block[1], retdest DUP3 // stack: output_addr, block[0] % (1 << 32), block[0] >> 32, output_addr, counter, block[1], retdest @@ -73,7 +80,7 @@ gen_message_schedule_from_block_1_loop: // stack: block[1] >> 32, block[1], output_addr, counter, block[0], retdest SWAP1 // stack: block[1], block[1] >> 32, output_addr, counter, block[0], retdest - %truncate_to_u32 + %as_u32 // stack: block[1] % (1 << 32), block[1] >> 32, output_addr, counter, block[0], retdest DUP3 // stack: output_addr, block[1] % (1 << 32), block[1] >> 32, output_addr, counter, block[0], retdest diff --git a/evm/src/cpu/kernel/asm/sha2/ops.asm b/evm/src/cpu/kernel/asm/sha2/ops.asm index f24455ef..7d8054ca 100644 --- a/evm/src/cpu/kernel/asm/sha2/ops.asm +++ b/evm/src/cpu/kernel/asm/sha2/ops.asm @@ -1,13 +1,3 @@ -// u32 addition (discarding 2^32 bit) -%macro add_u32 - // stack: x, y - ADD - // stack: x + y - %truncate_to_u32 - // stack: (x + y) & u32::MAX -%endmacro - - // 32-bit right rotation %macro rotr(rot) // stack: value @@ -25,7 +15,7 @@ // stack: 32 - rot, value, value >> rot SHL // stack: value << (32 - rot), value >> rot - %truncate_to_u32 + %as_u32 // stack: (value << (32 - rot)) % (1 << 32), value >> rot ADD %endmacro diff --git a/evm/src/cpu/kernel/asm/sha2/store_pad.asm b/evm/src/cpu/kernel/asm/sha2/store_pad.asm index ce935ec3..7594eb81 100644 --- a/evm/src/cpu/kernel/asm/sha2/store_pad.asm +++ b/evm/src/cpu/kernel/asm/sha2/store_pad.asm @@ -1,3 +1,6 @@ +global sha2: + %jump(sha2_store) + global sha2_store: // stack: num_bytes, x[0], x[1], ..., x[num_bytes - 1], retdest DUP1 @@ -84,6 +87,3 @@ global sha2_pad: // stack: num_blocks, retdest %message_schedule_addr_from_num_blocks %jump(sha2_gen_all_message_schedules) - -global sha2: - %jump(sha2_store) diff --git a/evm/src/cpu/kernel/asm/sha2/util.asm b/evm/src/cpu/kernel/asm/sha2/util.asm deleted file mode 100644 index e090df0a..00000000 --- a/evm/src/cpu/kernel/asm/sha2/util.asm +++ /dev/null @@ -1,18 +0,0 @@ -// We put the message schedule in memory starting at 64 * num_blocks + 2. -%macro message_schedule_addr_from_num_blocks - // stack: num_blocks - %mul_const(64) - %add_const(2) -%endmacro - -// We use memory starting at 320 * num_blocks + 2 (after the message schedule -// space) as scratch space to store stack values. -%macro scratch_space_addr_from_num_blocks - // stack: num_blocks - %mul_const(320) - %add_const(2) -%endmacro - -%macro truncate_to_u32 - %and_const(0xFFFFFFFF) -%endmacro diff --git a/evm/src/cpu/kernel/asm/util/basic_macros.asm b/evm/src/cpu/kernel/asm/util/basic_macros.asm index fb9e6d01..8ac92258 100644 --- a/evm/src/cpu/kernel/asm/util/basic_macros.asm +++ b/evm/src/cpu/kernel/asm/util/basic_macros.asm @@ -246,3 +246,16 @@ %mod_const(2) 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 +%endmacro diff --git a/evm/src/cpu/kernel/tests/sha2.rs b/evm/src/cpu/kernel/tests/hash.rs similarity index 63% rename from evm/src/cpu/kernel/tests/sha2.rs rename to evm/src/cpu/kernel/tests/hash.rs index cb6d580a..de707e71 100644 --- a/evm/src/cpu/kernel/tests/sha2.rs +++ b/evm/src/cpu/kernel/tests/hash.rs @@ -8,21 +8,23 @@ use sha2::{Digest, Sha256}; use crate::cpu::kernel::aggregator::combined_kernel; use crate::cpu::kernel::interpreter::run_with_kernel; -#[test] -fn test_sha2() -> Result<()> { - let kernel = combined_kernel(); - let sha2 = kernel.global_labels["sha2"]; +/// Standard Sha2 implementation. +fn sha2(input: Vec) -> U256 { + let mut hasher = Sha256::new(); + hasher.update(input.clone()); + U256::from(&hasher.finalize()[..]) +} +fn test_hash(hash_fn_label: &str, standard_implementation: &dyn Fn(Vec) -> U256) -> Result<()> { + let kernel = combined_kernel(); let mut rng = thread_rng(); // Generate a random message, between 0 and 9999 bytes. let num_bytes = rng.gen_range(0..10000); let message: Vec = (0..num_bytes).map(|_| rng.gen()).collect(); - // Hash the message using a standard Sha256 implementation. - let mut hasher = Sha256::new(); - hasher.update(message.clone()); - let expected = U256::from(&hasher.finalize()[..]); + // Hash the message using a standard implementation. + let expected = standard_implementation(message.clone()); // Load the message onto the stack. let mut initial_stack = vec![U256::from(num_bytes)]; @@ -31,8 +33,9 @@ fn test_sha2() -> Result<()> { initial_stack.push(U256::from_str("0xdeadbeef").unwrap()); initial_stack.reverse(); - // Run the sha2 kernel code. - let result = run_with_kernel(&kernel, sha2, initial_stack)?; + // Run the kernel code. + let kernel_function = kernel.global_labels[hash_fn_label]; + let result = run_with_kernel(&kernel, kernel_function, initial_stack)?; let actual = result.stack()[0]; // Check that the result is correct. @@ -40,3 +43,8 @@ fn test_sha2() -> Result<()> { Ok(()) } + +#[test] +fn test_sha2() -> Result<()> { + test_hash("sha2", &sha2) +} diff --git a/evm/src/cpu/kernel/tests/mod.rs b/evm/src/cpu/kernel/tests/mod.rs index 36471dc4..45feb238 100644 --- a/evm/src/cpu/kernel/tests/mod.rs +++ b/evm/src/cpu/kernel/tests/mod.rs @@ -2,10 +2,10 @@ mod core; mod curve_ops; mod ecrecover; mod exp; +mod hash; mod mpt; mod packing; mod rlp; -mod sha2; mod transaction_parsing; use std::str::FromStr;