From eb6095cd047de85e6c24706aabae1a056a5a2ec0 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Mon, 1 Aug 2022 16:36:36 -0700 Subject: [PATCH] message schedule progress --- evm/src/cpu/kernel/aggregator.rs | 196 +------------------- evm/src/cpu/kernel/asm/helper_functions.asm | 135 -------------- evm/src/cpu/kernel/asm/sha2.asm | 76 +++++--- evm/src/cpu/kernel/tests/mod.rs | 1 + 4 files changed, 52 insertions(+), 356 deletions(-) delete mode 100644 evm/src/cpu/kernel/asm/helper_functions.asm diff --git a/evm/src/cpu/kernel/aggregator.rs b/evm/src/cpu/kernel/aggregator.rs index 65cfbe28..85ebd11a 100644 --- a/evm/src/cpu/kernel/aggregator.rs +++ b/evm/src/cpu/kernel/aggregator.rs @@ -41,7 +41,7 @@ pub(crate) fn combined_kernel() -> Kernel { include_str!("asm/memory/packing.asm"), include_str!("asm/memory/txn_fields.asm"), include_str!("asm/exp.asm"), - include_str!("asm/helper_functions.asm"), + include_str!("asm/memory.asm"), include_str!("asm/moddiv.asm"), include_str!("asm/secp256k1/curve_mul.asm"), include_str!("asm/secp256k1/curve_add.asm"), @@ -81,9 +81,8 @@ mod tests { use anyhow::Result; use ethereum_types::U256; use log::debug; - use rand::thread_rng; - use crate::cpu::kernel::{aggregator::combined_kernel, interpreter::run}; + use crate::cpu::kernel::aggregator::combined_kernel; #[test] fn make_kernel() { @@ -93,195 +92,4 @@ mod tests { let kernel = combined_kernel(); debug!("Total kernel size: {} bytes", kernel.code.len()); } - - fn u256ify<'a>(hexes: impl IntoIterator) -> Result> { - Ok(hexes - .into_iter() - .map(U256::from_str) - .collect::, _>>()?) - } - - #[test] - fn test_insert() -> Result<()> { - // Make sure we can parse and assemble the entire kernel. - let kernel = combined_kernel(); - let exp = kernel.global_labels["swapn"]; - let mut rng = thread_rng(); - let a = U256([0; 4].map(|_| rng.gen())); - let b = U256([0; 4].map(|_| rng.gen())); - let n = rng.gen_range(0..16); - let n_u256 = U256([n, 0, 0, 0]); - - let mut initial_stack = vec![U256::from_str("0xdeadbeef")?, n_u256, b]; - initial_stack.extend([a; 16]); - let stack_with_kernel = run(&kernel.code, exp, initial_stack); - - dbg!(stack_with_kernel); - let expected_stack = todo!(); - - // assert_eq!(stack_with_kernel, expected_stack); - - Ok(()) - } - - #[test] - fn test_exp() -> Result<()> { - // Make sure we can parse and assemble the entire kernel. - let kernel = combined_kernel(); - let exp = kernel.global_labels["exp"]; - let mut rng = thread_rng(); - let a = U256([0; 4].map(|_| rng.gen())); - let b = U256([0; 4].map(|_| rng.gen())); - - // Random input - let initial_stack = vec![U256::from_str("0xdeadbeef")?, b, a]; - let stack_with_kernel = run(&kernel.code, exp, initial_stack); - let initial_stack = vec![b, a]; - let code = [0xa, 0x63, 0xde, 0xad, 0xbe, 0xef, 0x56]; // EXP, PUSH4 deadbeef, JUMP - let stack_with_opcode = run(&code, 0, initial_stack); - assert_eq!(stack_with_kernel, stack_with_opcode); - - // 0 base - let initial_stack = vec![U256::from_str("0xdeadbeef")?, b, U256::zero()]; - let stack_with_kernel = run(&kernel.code, exp, initial_stack); - let initial_stack = vec![b, U256::zero()]; - let code = [0xa, 0x63, 0xde, 0xad, 0xbe, 0xef, 0x56]; // EXP, PUSH4 deadbeef, JUMP - let stack_with_opcode = run(&code, 0, initial_stack); - assert_eq!(stack_with_kernel, stack_with_opcode); - - // 0 exponent - let initial_stack = vec![U256::from_str("0xdeadbeef")?, U256::zero(), a]; - let stack_with_kernel = run(&kernel.code, exp, initial_stack); - let initial_stack = vec![U256::zero(), a]; - let code = [0xa, 0x63, 0xde, 0xad, 0xbe, 0xef, 0x56]; // EXP, PUSH4 deadbeef, JUMP - let stack_with_opcode = run(&code, 0, initial_stack); - assert_eq!(stack_with_kernel, stack_with_opcode); - - Ok(()) - } - - #[test] - fn test_ec_ops() -> Result<()> { - // Make sure we can parse and assemble the entire kernel. - let kernel = combined_kernel(); - let ec_add = kernel.global_labels["ec_add"]; - let ec_double = kernel.global_labels["ec_double"]; - let ec_mul = kernel.global_labels["ec_mul"]; - let identity = ("0x0", "0x0"); - let invalid = ("0x0", "0x3"); // Not on curve - let point0 = ( - "0x1feee7ec986e198890cb83be8b8ba09ee953b3f149db6d9bfdaa5c308a33e58d", - "0x2051cc9a9edd46231604fd88f351e95ec72a285be93e289ac59cb48561efb2c6", - ); - let point1 = ( - "0x15b64d0a5f329fb672029298be8050f444626e6de11903caffa74b388075be1b", - "0x2d9e07340bd5cd7b70687b98f2500ff930a89a30d7b6a3e04b1b4d345319d234", - ); - // point2 = point0 + point1 - let point2 = ( - "0x18659c0e0a8fedcb8747cf463fc7cfa05f667d84e771d0a9521fc1a550688f0c", - "0x283ed10b42703e187e7a808aeb45c6b457bc4cc7d704e53b3348a1e3b0bfa55b", - ); - // point3 = 2 * point0 - let point3 = ( - "0x17da2b7b1a01c8dfdf0f5a6415833c7d755d219aa7e2c4cd0ac83d87d0ca4217", - "0xc9ace9de14aac8114541b50c19320eb40f0eeac3621526d9e34dbcf4c3a6c0f", - ); - let s = "0xabb2a34c0e7956cfe6cef9ddb7e810c45ea19a6ebadd79c21959af09f5ba480a"; - // point4 = s * point0 - let point4 = ( - "0xe519344959cc17021fe98878f947f5c1b1675325533a620c1684cfa6367e6c0", - "0x7496a7575b0b6a821e19ce780ecc3e0b156e605327798693defeb9f265b7a6f", - ); - - // Standard addition #1 - let initial_stack = u256ify(["0xdeadbeef", point0.1, point0.0, point1.1, point1.0])?; - let stack = run(&kernel.code, ec_add, initial_stack); - assert_eq!(stack, u256ify([point2.1, point2.0])?); - // Standard addition #2 - let initial_stack = u256ify(["0xdeadbeef", point1.1, point1.0, point0.1, point0.0])?; - let stack = run(&kernel.code, ec_add, initial_stack); - assert_eq!(stack, u256ify([point2.1, point2.0])?); - - // Standard doubling #1 - let initial_stack = u256ify(["0xdeadbeef", point0.1, point0.0, point0.1, point0.0])?; - let stack = run(&kernel.code, ec_add, initial_stack); - assert_eq!(stack, u256ify([point3.1, point3.0])?); - // Standard doubling #2 - let initial_stack = u256ify(["0xdeadbeef", point0.1, point0.0])?; - let stack = run(&kernel.code, ec_double, initial_stack); - assert_eq!(stack, u256ify([point3.1, point3.0])?); - // Standard doubling #3 - let initial_stack = u256ify(["0xdeadbeef", "0x2", point0.1, point0.0])?; - let stack = run(&kernel.code, ec_mul, initial_stack); - assert_eq!(stack, u256ify([point3.1, point3.0])?); - - // Addition with identity #1 - let initial_stack = u256ify(["0xdeadbeef", identity.1, identity.0, point1.1, point1.0])?; - let stack = run(&kernel.code, ec_add, initial_stack); - assert_eq!(stack, u256ify([point1.1, point1.0])?); - // Addition with identity #2 - let initial_stack = u256ify(["0xdeadbeef", point1.1, point1.0, identity.1, identity.0])?; - let stack = run(&kernel.code, ec_add, initial_stack); - assert_eq!(stack, u256ify([point1.1, point1.0])?); - // Addition with identity #3 - let initial_stack = - u256ify(["0xdeadbeef", identity.1, identity.0, identity.1, identity.0])?; - let stack = run(&kernel.code, ec_add, initial_stack); - assert_eq!(stack, u256ify([identity.1, identity.0])?); - - // Addition with invalid point(s) #1 - let initial_stack = u256ify(["0xdeadbeef", point0.1, point0.0, invalid.1, invalid.0])?; - let stack = run(&kernel.code, ec_add, initial_stack); - assert_eq!(stack, vec![U256::MAX, U256::MAX]); - // Addition with invalid point(s) #2 - let initial_stack = u256ify(["0xdeadbeef", invalid.1, invalid.0, point0.1, point0.0])?; - let stack = run(&kernel.code, ec_add, initial_stack); - assert_eq!(stack, vec![U256::MAX, U256::MAX]); - // Addition with invalid point(s) #3 - let initial_stack = u256ify(["0xdeadbeef", invalid.1, invalid.0, identity.1, identity.0])?; - let stack = run(&kernel.code, ec_add, initial_stack); - assert_eq!(stack, vec![U256::MAX, U256::MAX]); - // Addition with invalid point(s) #4 - let initial_stack = u256ify(["0xdeadbeef", invalid.1, invalid.0, invalid.1, invalid.0])?; - let stack = run(&kernel.code, ec_add, initial_stack); - assert_eq!(stack, vec![U256::MAX, U256::MAX]); - - // Scalar multiplication #1 - let initial_stack = u256ify(["0xdeadbeef", s, point0.1, point0.0])?; - let stack = run(&kernel.code, ec_mul, initial_stack); - assert_eq!(stack, u256ify([point4.1, point4.0])?); - // Scalar multiplication #2 - let initial_stack = u256ify(["0xdeadbeef", "0x0", point0.1, point0.0])?; - let stack = run(&kernel.code, ec_mul, initial_stack); - assert_eq!(stack, u256ify([identity.1, identity.0])?); - // Scalar multiplication #3 - let initial_stack = u256ify(["0xdeadbeef", "0x1", point0.1, point0.0])?; - let stack = run(&kernel.code, ec_mul, initial_stack); - assert_eq!(stack, u256ify([point0.1, point0.0])?); - // Scalar multiplication #4 - let initial_stack = u256ify(["0xdeadbeef", s, identity.1, identity.0])?; - let stack = run(&kernel.code, ec_mul, initial_stack); - assert_eq!(stack, u256ify([identity.1, identity.0])?); - // Scalar multiplication #5 - let initial_stack = u256ify(["0xdeadbeef", s, invalid.1, invalid.0])?; - let stack = run(&kernel.code, ec_mul, initial_stack); - assert_eq!(stack, vec![U256::MAX, U256::MAX]); - - // Multiple calls - let ec_mul_hex = format!("0x{:x}", ec_mul); - let initial_stack = u256ify([ - "0xdeadbeef", - s, - &ec_mul_hex, - identity.1, - identity.0, - point0.1, - point0.0, - ])?; - let stack = run(&kernel.code, ec_add, initial_stack); - assert_eq!(stack, u256ify([point4.1, point4.0])?); - - Ok(()) - } } diff --git a/evm/src/cpu/kernel/asm/helper_functions.asm b/evm/src/cpu/kernel/asm/helper_functions.asm deleted file mode 100644 index c628916c..00000000 --- a/evm/src/cpu/kernel/asm/helper_functions.asm +++ /dev/null @@ -1,135 +0,0 @@ -global swapn: - JUMPDEST - - // stack: n, ... - %eq(1) - %jumpi(case1) - %eq(2) - %jumpi(case2) - %eq(3) - %jumpi(case3) - %eq(4) - %jumpi(case4) - %eq(5) - %jumpi(case5) - %eq(6) - %jumpi(case6) - %eq(7) - %jumpi(case7) - %eq(8) - %jumpi(case8) - %eq(9) - %jumpi(case9) - %eq(10) - %jumpi(case10) - %eq(11) - %jumpi(case11) - %eq(12) - %jumpi(case12) - %eq(13) - %jumpi(case13) - %eq(14) - %jumpi(case14) - %eq(15) - %jumpi(case15) - %eq(16) - %jumpi(case16) -case1: - JUMPDEST - swap1 - %jump(swapn_end) -case2: - JUMPDEST - swap2 - %jump(swapn_end) -case3: - JUMPDEST - swap3 - %jump(swapn_end) -case4: - JUMPDEST - swap4 - %jump(swapn_end) -case5: - JUMPDEST - swap5 - %jump(swapn_end) -case6: - JUMPDEST - swap6 - %jump(swapn_end) -case7: - JUMPDEST - swap7 - %jump(swapn_end) -case8: - JUMPDEST - swap8 - %jump(swapn_end) -case9: - JUMPDEST - swap9 - %jump(swapn_end) -case10: - JUMPDEST - swap10 - %jump(swapn_end) -case11: - JUMPDEST - swap11 - %jump(swapn_end) -case12: - JUMPDEST - swap12 - %jump(swapn_end) -case13: - JUMPDEST - swap13 - %jump(swapn_end) -case14: - JUMPDEST - swap14 - %jump(swapn_end) -case15: - JUMPDEST - swap15 - %jump(swapn_end) -case16: - JUMPDEST - swap16 - %jump(swapn_end) -swapn_end: - JUMPDEST - - -global insertn: - JUMPDEST - - // stack: n, val, ... - dup1 - // stack: n, n, val, ... - swap2 - // stack: val, n, n, ... - swap1 - // stack: n, val, n, ... - %jump(swapn) - // stack: [nth], n, ..., val - swap1 - // stack: n, [nth], ..., val -swap_back_loop: - // stack: k, [kth], ..., [k-1st] - dup1 - // stack: k, k, [kth], ..., [k-1st] - swap2 - // stack: [kth], k, k, ..., [k-1st] - swap1 - // stack: k, [kth], k, ..., [k-1st] - %jump(swapn) - // stack: [k-1st], k, ..., [k-2nd], [kth] - swap1 - // stack: k, [k-1st], ..., [k-2nd], [kth] - %decrement - // stack: k-1, [k-1st], ..., [k-2nd], [kth] - iszero - not - %jumpi(swap_back_loop) diff --git a/evm/src/cpu/kernel/asm/sha2.asm b/evm/src/cpu/kernel/asm/sha2.asm index b13abb38..33b4e11d 100644 --- a/evm/src/cpu/kernel/asm/sha2.asm +++ b/evm/src/cpu/kernel/asm/sha2.asm @@ -1,3 +1,8 @@ +sha2_test_input: + BYTES 0x4 + BYTES 0x1, 0x2, 0x3, 0x4 + + // Precodition: input is in memory, starting at [TODO: fix] 0, of the form @@ -5,7 +10,7 @@ // Postcodition: output is in memory, starting at [TODO: fix] 0, of the form // num_blocks, block0[0], block0[1], block1[0], ..., blocklast[1] global sha2_pad: - // TODO: use kernel memory, and start address not at 0 + // TODO: use kernel memory (SEGMENT_KERNEL_MISC or SEGMENT_KERNEL_SHA2), and instead of 0 // stack: retdest push 0 mload @@ -217,65 +222,82 @@ sha2_gen_message_schedule_from_block_1_end: // stack: output_addr, block[0], block[1], retdest push 48 // stack: counter=48, output_addr, block[0], block[1], retdest - - -global sha2_message_schedule_next_word: +sha2_gen_message_schedule_remaining_loop: JUMPDEST - // stack: addr, retdest + // stack: counter, output_addr, block[0], block[1], retdest + swap1 + // stack: output_addr, counter, block[0], block[1], retdest dup1 - // stack: addr, addr, retdest + // stack: output_addr, output_addr, counter, block[0], block[1], retdest push 2 swap1 sub - // stack: addr - 2, addr, retdest + // stack: output_addr - 2, output_addr, counter, block[0], block[1], retdest mload - // stack: x[addr - 2], addr, retdest + // stack: x[output_addr - 2], output_addr, counter, block[0], block[1], retdest %sha2_sigma_1 - // stack: sigma_1(x[addr - 2]), addr, retdest + // stack: sigma_1(x[output_addr - 2]), output_addr, counter, block[0], block[1], retdest swap1 - // stack: addr, sigma_1(x[addr - 2]), retdest + // stack: output_addr, sigma_1(x[output_addr - 2]), counter, block[0], block[1], retdest dup1 - // stack: addr, addr, sigma_1(x[addr - 2]), retdest + // stack: output_addr, output_addr, sigma_1(x[output_addr - 2]), counter, block[0], block[1], retdest push 7 swap1 sub - // stack: addr - 7, addr, sigma_1(x[addr - 2]), retdest + // stack: output_addr - 7, output_addr, sigma_1(x[output_addr - 2]), counter, block[0], block[1], retdest mload - // stack: x[addr - 7], addr, sigma_1(x[addr - 2]), retdest + // stack: x[output_addr - 7], output_addr, sigma_1(x[output_addr - 2]), counter, block[0], block[1], retdest swap1 - // stack: addr, x[addr - 7], sigma_1(x[addr - 2]), retdest + // stack: output_addr, x[output_addr - 7], sigma_1(x[output_addr - 2]), counter, block[0], block[1], retdest dup1 - // stack: addr, addr, x[addr - 7], sigma_1(x[addr - 2]), retdest + // stack: output_addr, output_addr, x[output_addr - 7], sigma_1(x[output_addr - 2]), counter, block[0], block[1], retdest push 15 swap1 sub - // stack: addr - 15, addr, x[addr - 7], sigma_1(x[addr - 2]), retdest + // stack: output_addr - 15, output_addr, x[output_addr - 7], sigma_1(x[output_addr - 2]), counter, block[0], block[1], retdest mload - // stack: x[addr - 15], addr, x[addr - 7], sigma_1(x[addr - 2]), retdest + // stack: x[output_addr - 15], output_addr, x[output_addr - 7], sigma_1(x[output_addr - 2]), counter, block[0], block[1], retdest %sha2_sigma_0 - // stack: sigma_0(x[addr - 15]), addr, x[addr - 7], sigma_1(x[addr - 2]), retdest + // stack: sigma_0(x[output_addr - 15]), output_addr, x[output_addr - 7], sigma_1(x[output_addr - 2]), counter, block[0], block[1], retdest swap1 - // stack: addr, sigma_0(x[addr - 15]), x[addr - 7], sigma_1(x[addr - 2]), retdest + // stack: output_addr, sigma_0(x[output_addr - 15]), x[output_addr - 7], sigma_1(x[output_addr - 2]), counter, block[0], block[1], retdest dup1 - // stack: addr, addr, sigma_0(x[addr - 15]), x[addr - 7], sigma_1(x[addr - 2]), retdest + // stack: output_addr, output_addr, sigma_0(x[output_addr - 15]), x[output_addr - 7], sigma_1(x[output_addr - 2]), counter, block[0], block[1], retdest push 16 swap1 sub - // stack: addr - 16, addr, sigma_0(x[addr - 15]), x[addr - 7], sigma_1(x[addr - 2]), retdest + // stack: output_addr - 16, output_addr, sigma_0(x[output_addr - 15]), x[output_addr - 7], sigma_1(x[output_addr - 2]), counter, block[0], block[1], retdest mload - // stack: x[addr - 16], addr, sigma_0(x[addr - 15]), x[addr - 7], sigma_1(x[addr - 2]), retdest + // stack: x[output_addr - 16], output_addr, sigma_0(x[output_addr - 15]), x[output_addr - 7], sigma_1(x[output_addr - 2]), counter, block[0], block[1], retdest swap1 - // stack: addr, x[addr - 16], sigma_0(x[addr - 15]), x[addr - 7], sigma_1(x[addr - 2]), retdest + // stack: output_addr, x[output_addr - 16], sigma_0(x[output_addr - 15]), x[output_addr - 7], sigma_1(x[output_addr - 2]), counter, block[0], block[1], retdest swap4 - // stack: sigma_1(x[addr - 2]), x[addr - 16], sigma_0(x[addr - 15]), x[addr - 7], addr, retdest + // stack: sigma_1(x[output_addr - 2]), x[output_addr - 16], sigma_0(x[output_addr - 15]), x[output_addr - 7], output_addr, counter, block[0], block[1], retdest add add add - // stack: sigma_1(x[addr - 2]) + x[addr - 16] + sigma_0(x[addr - 15]) + x[addr - 7], addr, retdest + // stack: sigma_1(x[output_addr - 2]) + x[output_addr - 16] + sigma_0(x[output_addr - 15]) + x[output_addr - 7], output_addr, counter, block[0], block[1], retdest swap1 + // stack: output_addr, sigma_1(x[output_addr - 2]) + x[output_addr - 16] + sigma_0(x[output_addr - 15]) + x[output_addr - 7], counter, block[0], block[1], retdest + dup1 + // stack: output_addr, output_addr, sigma_1(x[output_addr - 2]) + x[output_addr - 16] + sigma_0(x[output_addr - 15]) + x[output_addr - 7], counter, block[0], block[1], retdest + swap2 + // stack: sigma_1(x[output_addr - 2]) + x[output_addr - 16] + sigma_0(x[output_addr - 15]) + x[output_addr - 7], output_addr, output_addr, counter, block[0], block[1], retdest + swap1 + // stack: output_addr, sigma_1(x[output_addr - 2]) + x[output_addr - 16] + sigma_0(x[output_addr - 15]) + x[output_addr - 7], output_addr, counter, block[0], block[1], retdest mstore - // stack: retdest - JUMP + // stack: output_addr, counter, block[0], block[1], retdest + %increment + // stack: output_addr + 1, counter, block[0], block[1], retdest + swap1 + // stack: counter, output_addr + 1, block[0], block[1], retdest + %decrement + // stack: counter - 1, output_addr + 1, block[0], block[1], retdest + iszero + %jumpi(sha2_gen_message_schedule_remaining_end) + %jump(sha2_gen_message_schedule_remaining_loop) +sha2_gen_message_schedule_remaining_end: + JUMPDEST global sha2_gen_all_message_schedules: JUMPDEST diff --git a/evm/src/cpu/kernel/tests/mod.rs b/evm/src/cpu/kernel/tests/mod.rs index a9c8c08c..d1fa616b 100644 --- a/evm/src/cpu/kernel/tests/mod.rs +++ b/evm/src/cpu/kernel/tests/mod.rs @@ -6,6 +6,7 @@ mod mpt; mod packing; mod rlp; mod transaction_parsing; +mod sha2; use std::str::FromStr;