From 93abd35ffb0abea517f93646955ca0dabde75f63 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Tue, 7 Mar 2023 11:06:49 -0800 Subject: [PATCH 001/121] optimizations --- .../kernel/asm/hash/blake2b/compression.asm | 29 +-- .../kernel/asm/hash/blake2b/g_functions.asm | 205 +++++++++++++----- 2 files changed, 154 insertions(+), 80 deletions(-) diff --git a/evm/src/cpu/kernel/asm/hash/blake2b/compression.asm b/evm/src/cpu/kernel/asm/hash/blake2b/compression.asm index a25158d9..840d8c54 100644 --- a/evm/src/cpu/kernel/asm/hash/blake2b/compression.asm +++ b/evm/src/cpu/kernel/asm/hash/blake2b/compression.asm @@ -181,30 +181,15 @@ compression_loop: 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 - + PUSH g_functions_return + // stack: g_functions_return, cur_block, retdest + %blake2b_internal_state_addr + // stack: start, g_functions_return, cur_block, retdest + %jump(run_12_rounds_g_function) +g_functions_return: + // Finalize hash value. // stack: cur_block, retdest %blake2b_generate_new_hash_value(7) diff --git a/evm/src/cpu/kernel/asm/hash/blake2b/g_functions.asm b/evm/src/cpu/kernel/asm/hash/blake2b/g_functions.asm index 11e879fc..831841c5 100644 --- a/evm/src/cpu/kernel/asm/hash/blake2b/g_functions.asm +++ b/evm/src/cpu/kernel/asm/hash/blake2b/g_functions.asm @@ -1,89 +1,89 @@ -%macro blake2b_g_function +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: a, b, c, d, x, y, start, retdest %stack (indices: 4) -> (indices, indices) - // stack: a, b, c, d, a, b, c, d, x, y, start + // stack: a, b, c, d, a, b, c, d, x, y, start, retdest DUP11 - // stack: start, a, b, c, d, a, b, c, d, x, y, start + // stack: start, a, b, c, d, a, b, c, d, x, y, start, retdest %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 + // stack: d, start, c, start, b, start, a, start, a, b, c, d, x, y, start, retdest ADD %mload_kernel_general - // stack: v[d], c, start, b, start, a, start, a, b, c, d, x, y, start + // stack: v[d], c, start, b, start, a, start, a, b, c, d, x, y, start, retdest %stack (vd, remaining: 6) -> (remaining, vd) - // stack: c, start, b, start, a, start, v[d], a, b, c, d, x, y, start + // stack: c, start, b, start, a, start, v[d], a, b, c, d, x, y, start, retdest 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 + // stack: b, start, a, start, v[c], v[d], a, b, c, d, x, y, start, retdest ADD %mload_kernel_general - // stack: v[b], a, start, v[c], v[d], a, b, c, d, x, y, start + // stack: v[b], a, start, v[c], v[d], a, b, c, d, x, y, start, retdest %stack (vb, remaining: 2) -> (remaining, vb) - // stack: a, start, v[b], v[c], v[d], a, b, c, d, x, y, start + // stack: a, start, v[b], v[c], v[d], a, b, c, d, x, y, start, retdest ADD %mload_kernel_general - // stack: v[a], v[b], v[c], v[d], a, b, c, d, x, y, start + // stack: v[a], v[b], v[c], v[d], a, b, c, d, x, y, start, retdest DUP2 - // stack: v[b], v[a], v[b], v[c], v[d], a, b, c, d, x, y, start + // stack: v[b], v[a], v[b], v[c], v[d], a, b, c, d, x, y, start, retdest DUP10 - // stack: x, v[b], v[a], v[b], v[c], v[d], a, b, c, d, x, y, start + // stack: x, v[b], v[a], v[b], v[c], v[d], a, b, c, d, x, y, start, retdest 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: v[a]' = (v[a] + v[b] + x) % 2^64, v[b], v[c], v[d], a, b, c, d, x, y, start, retdest %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 + // stack: v[a]', v[d], v[a]', v[b], v[c], v[d], a, b, c, d, x, y, start, retdest 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: v[d]' = (v[d] ^ v[a]') >>> 32, v[a]', v[b], v[c], v[d], a, b, c, d, x, y, start, retdest %stack (top: 4, vd) -> (top) - // stack: v[d]', v[a]', v[b], v[c], a, b, c, d, x, y, start + // stack: v[d]', v[a]', v[b], v[c], a, b, c, d, x, y, start, retdest %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 + // stack: v[c], v[d]', v[a]', v[b], v[d]', a, b, c, d, x, y, start, retdest 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: v[c]' = (v[c] + v[d]') % 2^64, v[a]', v[b], v[d]', a, b, c, d, x, y, start, retdest %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 + // stack: v[b], v[c]', v[a]', v[c]', v[d]', a, b, c, d, x, y, start, retdest 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 + // stack: v[b]' = (v[b] ^ v[c]') >>> 24, v[a]', v[c]', v[d]', a, b, c, d, x, y, start, retdest SWAP1 - // stack: v[a]', v[b]', v[c]', v[d]', a, b, c, d, x, y, start + // stack: v[a]', v[b]', v[c]', v[d]', a, b, c, d, x, y, start, retdest DUP2 - // stack: v[b]', v[a]', v[b]', v[c]', v[d]', a, b, c, d, x, y, start + // stack: v[b]', v[a]', v[b]', v[c]', v[d]', a, b, c, d, x, y, start, retdest DUP11 - // stack: y, v[b]', v[a]', v[b]', v[c]', v[d]', a, b, c, d, x, y, start + // stack: y, v[b]', v[a]', v[b]', v[c]', v[d]', a, b, c, d, x, y, start, retdest 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 + // stack: v[a]'' = (v[a]' + v[b]' + y) % 2^64, v[b]', v[c]', v[d]', a, b, c, d, x, y, start, retdest SWAP3 - // stack: v[d]', v[b]', v[c]', v[a]'', a, b, c, d, x, y, start + // stack: v[d]', v[b]', v[c]', v[a]'', a, b, c, d, x, y, start, retdest DUP4 - // stack: v[a]'', v[d]', v[b]', v[c]', v[a]'', a, b, c, d, x, y, start + // stack: v[a]'', v[d]', v[b]', v[c]', v[a]'', a, b, c, d, x, y, start, retdest 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 + // stack: v[d]'' = (v[a]'' ^ v[d]') >>> 8, v[b]', v[c]', v[a]'', a, b, c, d, x, y, start, retdest SWAP2 - // stack: v[c]', v[b]', v[d]'', v[a]'', a, b, c, d, x, y, start + // stack: v[c]', v[b]', v[d]'', v[a]'', a, b, c, d, x, y, start, retdest DUP3 - // stack: v[d]'', v[c]', v[b]', v[d]'', v[a]'', a, b, c, d, x, y, start + // stack: v[d]'', v[c]', v[b]', v[d]'', v[a]'', a, b, c, d, x, y, start, retdest 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 + // stack: v[c]'' = (v[c]' + v[d]'') % 2^64, v[b]', v[d]'', v[a]'', a, b, c, d, x, y, start, retdest DUP1 - // stack: v[c]'', v[c]'', v[b]', v[d]'', v[a]'', a, b, c, d, x, y, start + // stack: v[c]'', v[c]'', v[b]', v[d]'', v[a]'', a, b, c, d, x, y, start, retdest SWAP2 - // stack: v[b]', v[c]'', v[c]'', v[d]'', v[a]'', a, b, c, d, x, y, start + // stack: v[b]', v[c]'', v[c]'', v[d]'', v[a]'', a, b, c, d, x, y, start, retdest 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: v[b]'' = (v[b]' ^ v[c]'') >>> 7, v[c]'', v[d]'', v[a]'', a, b, c, d, x, y, start, retdest %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]'' + // stack: start, a, v[a]'', start, b, v[b]'', start, c, v[c]'', start, d, v[d]'', retdest ADD %mstore_kernel_general ADD @@ -92,35 +92,124 @@ %mstore_kernel_general ADD %mstore_kernel_general -%endmacro + // stack: retdest + JUMP -%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 +call_blake2b_g_function: + // stack: a, b, c, d, x_idx, y_idx, round, start, retdest + DUP6 + // stack: y_idx, a, b, c, d, x_idx, y_idx, round, start, retdest + DUP8 + // stack: round, y_idx, a, b, c, d, x_idx, y_idx, round, start, retdest %blake2b_permutation - // stack: s[y_idx], round, start + // stack: s[y_idx], a, b, c, d, x_idx, y_idx, round, start, retdest %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 + // stack: m[s[y_idx]], a, b, c, d, x_idx, y_idx, round, start, retdest + DUP6 + // stack: x_idx, m[s[y_idx]], a, b, c, d, x_idx, y_idx, round, start, retdest + DUP9 + // stack: round, x_idx, m[s[y_idx]], a, b, c, d, x_idx, y_idx, round, start, retdest %blake2b_permutation - // stack: s[x_idx], m[s[y_idx]], round, start + // stack: s[x_idx], m[s[y_idx]], a, b, c, d, x_idx, y_idx, round, start, retdest %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 + // stack: m[s[x_idx]], m[s[y_idx]], a, b, c, d, x_idx, y_idx, round, start, retdest + %stack (mm: 2, abcd: 4, xy: 2, r, s) -> (abcd, mm, s, r, s) + // stack: a, b, c, d, m[s[x_idx]], m[s[y_idx]], start, round, start, retdest + %jump(blake2b_g_function) + +global run_g_function_round: + // stack: round, start, retdest + PUSH g_function_return_1 + // stack: g_function_return_1, round, start, retdest + %stack (ret, r, s) -> (0, 4, 8, 12, 0, 1, r, s, ret, r, s) + // stack: a=0, b=4, c=8, d=12, x_idx=0, y_idx=1, round, start, g_function_return_1, round, start, retdest + %jump(call_blake2b_g_function) +g_function_return_1: + // stack: round, start, retdest + PUSH g_function_return_2 + // stack: g_function_return_2, round, start, retdest + %stack (ret, r, s) -> (1, 5, 9, 13, 2, 3, r, s, ret, r, s) + // stack: a=1, b=5, c=9, d=13, x_idx=2, y_idx=3, round, start, g_function_return_2, round, start, retdest + %jump(call_blake2b_g_function) +g_function_return_2: + // stack: round, start, retdest + PUSH g_function_return_3 + // stack: g_function_return_3, round, start, retdest + %stack (ret, r, s) -> (2, 6, 10, 14, 4, 5, r, s, ret, r, s) + // stack: a=2, b=6, c=10, d=14, x_idx=4, y_idx=5, round, start, g_function_return_3, round, start, retdest + %jump(call_blake2b_g_function) +g_function_return_3: + // stack: round, start, retdest + PUSH g_function_return_4 + // stack: g_function_return_4, round, start, retdest + %stack (ret, r, s) -> (3, 7, 11, 15, 6, 7, r, s, ret, r, s) + // stack: a=3, b=7, c=11, d=15, x_idx=6, y_idx=7, round, start, g_function_return_4, round, start, retdest + %jump(call_blake2b_g_function) +g_function_return_4: + // stack: round, start, retdest + PUSH g_function_return_5 + // stack: g_function_return_5, round, start, retdest + %stack (ret, r, s) -> (0, 5, 10, 15, 8, 9, r, s, ret, r, s) + // stack: a=0, b=5, c=10, d=15, x_idx=8, y_idx=9, round, start, g_function_return_5, round, start, retdest + %jump(call_blake2b_g_function) +g_function_return_5: + // stack: round, start, retdest + PUSH g_function_return_6 + // stack: g_function_return_6, round, start, retdest + %stack (ret, r, s) -> (1, 6, 11, 12, 10, 11, r, s, ret, r, s) + // stack: a=1, b=6, c=11, d=12, x_idx=10, y_idx=11, round, start, g_function_return_6, round, start, retdest + %jump(call_blake2b_g_function) +g_function_return_6: + // stack: round, start, retdest + PUSH g_function_return_7 + // stack: g_function_return_7, round, start, retdest + %stack (ret, r, s) -> (2, 7, 8, 13, 12, 13, r, s, ret, r, s) + // stack: a=2, b=7, c=8, d=13, x_idx=12, y_idx=13, round, start, g_function_return_7, round, start, retdest + %jump(call_blake2b_g_function) +g_function_return_7: + // stack: round, start, retdest + PUSH g_function_return_8 + // stack: g_function_return_8, round, start, retdest + %stack (ret, r, s) -> (3, 4, 9, 14, 14, 15, r, s, ret, r, s) + // stack: a=3, b=4, c=9, d=14, x_idx=14, y_idx=15, round, start, g_function_return_8, round, start, retdest + %jump(call_blake2b_g_function) +g_function_return_8: + // stack: round, start, retdest + SWAP1 + // stack: start, round, retdest + SWAP2 + // stack: retdest, round, start + JUMP + + +global run_12_rounds_g_function: + // stack: start, retdest + PUSH 0 + // stack: round=0, start, retdest +run_next_round_g_function: + // stack: round, start, retdest + PUSH run_g_function_round_return + // stack: run_g_function_round_return, round, start, retdest + SWAP2 + // stack: start, round, run_g_function_round_return, retdest + SWAP1 + // stack: round, start, run_g_function_round_return, retdest + %jump(run_g_function_round) +run_next_round_g_function_return: + // stack: round, start, retdest + %increment + // stack: round+1, start, retdest + DUP1 + // stack: round+1, round+1, start, retdest + %lt_const(12) + // stack: round+1 < 12, round+1, start, retdest + %jumpi(run_next_round_g_function) + // stack: round+1, start, retdest + %pop2 + // stack: retdest + JUMP + From 5f592e60dc1248a80d54ed39139800eb97e9f95a Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Tue, 7 Mar 2023 12:25:34 -0800 Subject: [PATCH 002/121] fixes --- evm/src/cpu/kernel/asm/hash/blake2b/g_functions.asm | 12 ++++++------ evm/src/cpu/kernel/tests/hash.rs | 2 ++ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/evm/src/cpu/kernel/asm/hash/blake2b/g_functions.asm b/evm/src/cpu/kernel/asm/hash/blake2b/g_functions.asm index 831841c5..ff3ee43a 100644 --- a/evm/src/cpu/kernel/asm/hash/blake2b/g_functions.asm +++ b/evm/src/cpu/kernel/asm/hash/blake2b/g_functions.asm @@ -117,8 +117,8 @@ call_blake2b_g_function: ADD %mload_kernel_general // stack: m[s[x_idx]], m[s[y_idx]], a, b, c, d, x_idx, y_idx, round, start, retdest - %stack (mm: 2, abcd: 4, xy: 2, r, s) -> (abcd, mm, s, r, s) - // stack: a, b, c, d, m[s[x_idx]], m[s[y_idx]], start, round, start, retdest + %stack (mm: 2, abcd: 4, xy: 2, r, s) -> (abcd, mm, s) + // stack: a, b, c, d, m[s[x_idx]], m[s[y_idx]], start, retdest %jump(blake2b_g_function) global run_g_function_round: @@ -192,12 +192,12 @@ global run_12_rounds_g_function: // stack: round=0, start, retdest run_next_round_g_function: // stack: round, start, retdest - PUSH run_g_function_round_return - // stack: run_g_function_round_return, round, start, retdest + PUSH run_next_round_g_function_return + // stack: run_next_round_g_function_return, round, start, retdest SWAP2 - // stack: start, round, run_g_function_round_return, retdest + // stack: start, round, run_next_round_g_function_return, retdest SWAP1 - // stack: round, start, run_g_function_round_return, retdest + // stack: round, start, run_next_round_g_function_return, retdest %jump(run_g_function_round) run_next_round_g_function_return: // stack: round, start, retdest diff --git a/evm/src/cpu/kernel/tests/hash.rs b/evm/src/cpu/kernel/tests/hash.rs index bc73ecd5..cc2c96eb 100644 --- a/evm/src/cpu/kernel/tests/hash.rs +++ b/evm/src/cpu/kernel/tests/hash.rs @@ -79,6 +79,8 @@ fn prepare_test( // Run the interpeter let result = run_interpreter_with_memory(interpreter_setup).unwrap(); + dbg!(result.stack().to_vec()); + Ok((expected, result.stack().to_vec())) } From 70475a5a87bc3b2d9611bb4b66617dc636a43a1d Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Tue, 7 Mar 2023 12:27:08 -0800 Subject: [PATCH 003/121] cleanup --- evm/src/cpu/kernel/tests/hash.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/evm/src/cpu/kernel/tests/hash.rs b/evm/src/cpu/kernel/tests/hash.rs index cc2c96eb..bc73ecd5 100644 --- a/evm/src/cpu/kernel/tests/hash.rs +++ b/evm/src/cpu/kernel/tests/hash.rs @@ -79,8 +79,6 @@ fn prepare_test( // Run the interpeter let result = run_interpreter_with_memory(interpreter_setup).unwrap(); - dbg!(result.stack().to_vec()); - Ok((expected, result.stack().to_vec())) } From 40f90d8312f51e81407c48d7e464924b71d8f0d1 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Tue, 7 Mar 2023 15:45:20 -0800 Subject: [PATCH 004/121] hash function optimization --- .../kernel/asm/hash/blake2b/compression.asm | 12 +-- evm/src/cpu/kernel/asm/hash/blake2b/hash.asm | 91 +++++++++++++++++-- 2 files changed, 86 insertions(+), 17 deletions(-) diff --git a/evm/src/cpu/kernel/asm/hash/blake2b/compression.asm b/evm/src/cpu/kernel/asm/hash/blake2b/compression.asm index 840d8c54..fdf02d69 100644 --- a/evm/src/cpu/kernel/asm/hash/blake2b/compression.asm +++ b/evm/src/cpu/kernel/asm/hash/blake2b/compression.asm @@ -192,14 +192,10 @@ g_functions_return: // 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) + PUSH hash_generate_return + // stack: hash_generate_return, cur_block, retdest + %jump(blake2b_generate_all_hash_values) +hash_generate_return: // 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 diff --git a/evm/src/cpu/kernel/asm/hash/blake2b/hash.asm b/evm/src/cpu/kernel/asm/hash/blake2b/hash.asm index 712a97c0..91a5530e 100644 --- a/evm/src/cpu/kernel/asm/hash/blake2b/hash.asm +++ b/evm/src/cpu/kernel/asm/hash/blake2b/hash.asm @@ -1,18 +1,91 @@ -%macro blake2b_generate_new_hash_value(i) +blake2b_generate_new_hash_value: + // stack: i, retdest %blake2b_hash_value_addr - %add_const($i) + // stack: addr, i, retdest + DUP2 + ADD %mload_kernel_general - // stack: h_i, ... + // stack: h_i, i, retdest %blake2b_internal_state_addr - %add_const($i) + // stack: addr, h_i, i, retdest + DUP3 + ADD %mload_kernel_general - // stack: v_i, h_i, ... + // stack: v_i, h_i, i, retdest %blake2b_internal_state_addr - %add_const($i) + // stack: addr, v_i, h_i, i, retdest + DUP4 + ADD %add_const(8) %mload_kernel_general - // stack: v_(i+8), v_i, h_i, ... + // stack: v_(i+8), v_i, h_i, i, retdest XOR XOR - // stack: h_i' = v_(i+8) ^ v_i ^ h_i, ... -%endmacro + // stack: h_i' = v_(i+8) ^ v_i ^ h_i, i, retdest + SWAP1 + POP + // stack: h_i', retdest + SWAP1 + JUMP + +global blake2b_generate_all_hash_values: + // stack: retdest + PUSH blake2b_generate_hash_return_7 + // stack: blake2b_generate_hash_return_7, retdest + PUSH 7 + // stack: 7, blake2b_generate_hash_return_7, retdest + %jump(blake2b_generate_new_hash_value) +blake2b_generate_hash_return_7: + // stack: h_7', retdest + PUSH blake2b_generate_hash_return_6 + // stack: blake2b_generate_hash_return_6, h_7', retdest + PUSH 6 + // stack: 6, blake2b_generate_hash_return_6, h_7', retdest + %jump(blake2b_generate_new_hash_value) +blake2b_generate_hash_return_6: + // stack: h_6', h_7', retdest + PUSH blake2b_generate_hash_return_5 + // stack: blake2b_generate_hash_return_5, h_6', h_7', retdest + PUSH 5 + // stack: 5, blake2b_generate_hash_return_5, h_6', h_7', retdest + %jump(blake2b_generate_new_hash_value) +blake2b_generate_hash_return_5: + // stack: h_5', h_6', h_7', retdest + PUSH blake2b_generate_hash_return_4 + // stack: blake2b_generate_hash_return_4, h_5', h_6', h_7', retdest + PUSH 4 + // stack: 4, blake2b_generate_hash_return_4, h_5', h_6', h_7', retdest + %jump(blake2b_generate_new_hash_value) +blake2b_generate_hash_return_4: + // stack: h_4', h_5', h_6', h_7', retdest + PUSH blake2b_generate_hash_return_3 + // stack: blake2b_generate_hash_return_3, h_4', h_5', h_6', h_7', retdest + PUSH 3 + // stack: 3, blake2b_generate_hash_return_3, h_4', h_5', h_6', h_7', retdest + %jump(blake2b_generate_new_hash_value) +blake2b_generate_hash_return_3: + // stack: h_3', h_4', h_5', h_6', h_7', retdest + PUSH blake2b_generate_hash_return_2 + // stack: blake2b_generate_hash_return_2, h_3', h_4', h_5', h_6', h_7', retdest + PUSH 2 + // stack: 2, blake2b_generate_hash_return_2, h_3', h_4', h_5', h_6', h_7', retdest + %jump(blake2b_generate_new_hash_value) +blake2b_generate_hash_return_2: + // stack: h_2', h_3', h_4', h_5', h_6', h_7', retdest + PUSH blake2b_generate_hash_return_1 + // stack: blake2b_generate_hash_return_1, h_2', h_3', h_4', h_5', h_6', h_7', retdest + PUSH 1 + // stack: 1, blake2b_generate_hash_return_1, h_2', h_3', h_4', h_5', h_6', h_7', retdest + %jump(blake2b_generate_new_hash_value) +blake2b_generate_hash_return_1: + // stack: h_1', h_2', h_3', h_4', h_5', h_6', h_7', retdest + PUSH blake2b_generate_hash_return_0 + // stack: blake2b_generate_hash_return_0, h_1', h_2', h_3', h_4', h_5', h_6', h_7', retdest + PUSH 0 + // stack: 0, blake2b_generate_hash_return_0, h_1', h_2', h_3', h_4', h_5', h_6', h_7', retdest + %jump(blake2b_generate_new_hash_value) +blake2b_generate_hash_return_0: + // stack: h_0', h_1', h_2', h_3', h_4', h_5', h_6', h_7', retdest + %stack (h: 8, ret) -> (ret, h) + // stack: retdest, h_0', h_1', h_2', h_3', h_4', h_5', h_6', h_7' + JUMP \ No newline at end of file From c37d1e25fcf4697c5ef3033b7a7390b37b3043b1 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Tue, 7 Mar 2023 15:45:52 -0800 Subject: [PATCH 005/121] optimize hash generation further --- evm/src/cpu/kernel/asm/hash/blake2b/hash.asm | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/evm/src/cpu/kernel/asm/hash/blake2b/hash.asm b/evm/src/cpu/kernel/asm/hash/blake2b/hash.asm index 91a5530e..945c7fb0 100644 --- a/evm/src/cpu/kernel/asm/hash/blake2b/hash.asm +++ b/evm/src/cpu/kernel/asm/hash/blake2b/hash.asm @@ -14,17 +14,17 @@ blake2b_generate_new_hash_value: // stack: v_i, h_i, i, retdest %blake2b_internal_state_addr // stack: addr, v_i, h_i, i, retdest - DUP4 + SWAP1 + // stack: v_i, addr, h_i, i, retdest + SWAP3 + // stack: i, addr, h_i, v_i, retdest ADD %add_const(8) %mload_kernel_general - // stack: v_(i+8), v_i, h_i, i, retdest + // stack: v_(i+8), h_i, v_i, retdest XOR XOR - // stack: h_i' = v_(i+8) ^ v_i ^ h_i, i, retdest - SWAP1 - POP - // stack: h_i', retdest + // stack: h_i' = v_(i+8) ^ v_i ^ h_i, retdest SWAP1 JUMP @@ -88,4 +88,4 @@ blake2b_generate_hash_return_0: // stack: h_0', h_1', h_2', h_3', h_4', h_5', h_6', h_7', retdest %stack (h: 8, ret) -> (ret, h) // stack: retdest, h_0', h_1', h_2', h_3', h_4', h_5', h_6', h_7' - JUMP \ No newline at end of file + JUMP From 9d8d81b4b0e4f5570edbda8414d13b4fa14d07b5 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Tue, 7 Mar 2023 16:19:15 -0800 Subject: [PATCH 006/121] optimize hash generation further further --- evm/src/cpu/kernel/asm/hash/blake2b/hash.asm | 77 +++++--------------- evm/src/cpu/kernel/tests/hash.rs | 2 + 2 files changed, 22 insertions(+), 57 deletions(-) diff --git a/evm/src/cpu/kernel/asm/hash/blake2b/hash.asm b/evm/src/cpu/kernel/asm/hash/blake2b/hash.asm index 945c7fb0..654b51b3 100644 --- a/evm/src/cpu/kernel/asm/hash/blake2b/hash.asm +++ b/evm/src/cpu/kernel/asm/hash/blake2b/hash.asm @@ -30,62 +30,25 @@ blake2b_generate_new_hash_value: global blake2b_generate_all_hash_values: // stack: retdest - PUSH blake2b_generate_hash_return_7 - // stack: blake2b_generate_hash_return_7, retdest - PUSH 7 - // stack: 7, blake2b_generate_hash_return_7, retdest + PUSH 8 + // stack: i=8, retdest +blake2b_generate_hash_loop: + // stack: i, h_i', ..., h_7', retdest + %decrement + // stack: i-1, h_i', ..., h_7', retdest + PUSH blake2b_generate_hash_return + // stack: blake2b_generate_hash_return, i-1, h_i', ..., h_7', retdest + DUP2 + // stack: i-1, blake2b_generate_hash_return, i-1, h_i', ..., h_7', retdest %jump(blake2b_generate_new_hash_value) -blake2b_generate_hash_return_7: - // stack: h_7', retdest - PUSH blake2b_generate_hash_return_6 - // stack: blake2b_generate_hash_return_6, h_7', retdest - PUSH 6 - // stack: 6, blake2b_generate_hash_return_6, h_7', retdest - %jump(blake2b_generate_new_hash_value) -blake2b_generate_hash_return_6: - // stack: h_6', h_7', retdest - PUSH blake2b_generate_hash_return_5 - // stack: blake2b_generate_hash_return_5, h_6', h_7', retdest - PUSH 5 - // stack: 5, blake2b_generate_hash_return_5, h_6', h_7', retdest - %jump(blake2b_generate_new_hash_value) -blake2b_generate_hash_return_5: - // stack: h_5', h_6', h_7', retdest - PUSH blake2b_generate_hash_return_4 - // stack: blake2b_generate_hash_return_4, h_5', h_6', h_7', retdest - PUSH 4 - // stack: 4, blake2b_generate_hash_return_4, h_5', h_6', h_7', retdest - %jump(blake2b_generate_new_hash_value) -blake2b_generate_hash_return_4: - // stack: h_4', h_5', h_6', h_7', retdest - PUSH blake2b_generate_hash_return_3 - // stack: blake2b_generate_hash_return_3, h_4', h_5', h_6', h_7', retdest - PUSH 3 - // stack: 3, blake2b_generate_hash_return_3, h_4', h_5', h_6', h_7', retdest - %jump(blake2b_generate_new_hash_value) -blake2b_generate_hash_return_3: - // stack: h_3', h_4', h_5', h_6', h_7', retdest - PUSH blake2b_generate_hash_return_2 - // stack: blake2b_generate_hash_return_2, h_3', h_4', h_5', h_6', h_7', retdest - PUSH 2 - // stack: 2, blake2b_generate_hash_return_2, h_3', h_4', h_5', h_6', h_7', retdest - %jump(blake2b_generate_new_hash_value) -blake2b_generate_hash_return_2: - // stack: h_2', h_3', h_4', h_5', h_6', h_7', retdest - PUSH blake2b_generate_hash_return_1 - // stack: blake2b_generate_hash_return_1, h_2', h_3', h_4', h_5', h_6', h_7', retdest - PUSH 1 - // stack: 1, blake2b_generate_hash_return_1, h_2', h_3', h_4', h_5', h_6', h_7', retdest - %jump(blake2b_generate_new_hash_value) -blake2b_generate_hash_return_1: - // stack: h_1', h_2', h_3', h_4', h_5', h_6', h_7', retdest - PUSH blake2b_generate_hash_return_0 - // stack: blake2b_generate_hash_return_0, h_1', h_2', h_3', h_4', h_5', h_6', h_7', retdest - PUSH 0 - // stack: 0, blake2b_generate_hash_return_0, h_1', h_2', h_3', h_4', h_5', h_6', h_7', retdest - %jump(blake2b_generate_new_hash_value) -blake2b_generate_hash_return_0: - // stack: h_0', h_1', h_2', h_3', h_4', h_5', h_6', h_7', retdest - %stack (h: 8, ret) -> (ret, h) - // stack: retdest, h_0', h_1', h_2', h_3', h_4', h_5', h_6', h_7' +blake2b_generate_hash_return: + // stack: h_(i-1)', i-1, h_i', ..., h_7', retdest + SWAP1 + // stack: i-1, h_(i-1)', h_i', ..., h_7', retdest + DUP1 + // stack: i-1, i-1, h_(i-1)', ..., h_7', retdest + %jumpi(blake2b_generate_hash_loop) + // stack: i-1=0, h_0', ..., h_7', retdest + %stack (i, h: 8, ret) -> (ret, h) + // stack: retdest, h_0'...h_7' JUMP diff --git a/evm/src/cpu/kernel/tests/hash.rs b/evm/src/cpu/kernel/tests/hash.rs index bc73ecd5..cc2c96eb 100644 --- a/evm/src/cpu/kernel/tests/hash.rs +++ b/evm/src/cpu/kernel/tests/hash.rs @@ -79,6 +79,8 @@ fn prepare_test( // Run the interpeter let result = run_interpreter_with_memory(interpreter_setup).unwrap(); + dbg!(result.stack().to_vec()); + Ok((expected, result.stack().to_vec())) } From 5994f4d932e538f69cd5904b07e22b4c66456614 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Tue, 7 Mar 2023 16:49:28 -0800 Subject: [PATCH 007/121] cleanup --- evm/src/cpu/kernel/asm/hash/blake2b/compression.asm | 1 - 1 file changed, 1 deletion(-) diff --git a/evm/src/cpu/kernel/asm/hash/blake2b/compression.asm b/evm/src/cpu/kernel/asm/hash/blake2b/compression.asm index fdf02d69..11e5389b 100644 --- a/evm/src/cpu/kernel/asm/hash/blake2b/compression.asm +++ b/evm/src/cpu/kernel/asm/hash/blake2b/compression.asm @@ -189,7 +189,6 @@ compression_loop: // stack: start, g_functions_return, cur_block, retdest %jump(run_12_rounds_g_function) g_functions_return: - // Finalize hash value. // stack: cur_block, retdest PUSH hash_generate_return From 0f55956ade0ef43f99dd07daf6807e5791f7eb20 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Tue, 7 Mar 2023 17:17:23 -0800 Subject: [PATCH 008/121] optimized initial hash value generation --- .../cpu/kernel/asm/hash/blake2b/addresses.asm | 16 ----- .../kernel/asm/hash/blake2b/compression.asm | 4 +- evm/src/cpu/kernel/asm/hash/blake2b/iv.asm | 61 ++++++++++++++----- evm/src/cpu/kernel/tests/hash.rs | 2 - 4 files changed, 50 insertions(+), 33 deletions(-) diff --git a/evm/src/cpu/kernel/asm/hash/blake2b/addresses.asm b/evm/src/cpu/kernel/asm/hash/blake2b/addresses.asm index 9d65b9ed..f1d7c3e9 100644 --- a/evm/src/cpu/kernel/asm/hash/blake2b/addresses.asm +++ b/evm/src/cpu/kernel/asm/hash/blake2b/addresses.asm @@ -1,19 +1,3 @@ -// 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 diff --git a/evm/src/cpu/kernel/asm/hash/blake2b/compression.asm b/evm/src/cpu/kernel/asm/hash/blake2b/compression.asm index 11e5389b..cd1f6a80 100644 --- a/evm/src/cpu/kernel/asm/hash/blake2b/compression.asm +++ b/evm/src/cpu/kernel/asm/hash/blake2b/compression.asm @@ -2,7 +2,9 @@ global blake2b_compression: // stack: retdest PUSH 0 // stack: cur_block = 0, retdest - %blake2b_initial_hash_value + PUSH compression_loop + // stack: compression_loop, cur_block, retdest + %jump(blake2b_initial_hash_value) compression_loop: // stack: h_0, ..., h_7, cur_block, retdest diff --git a/evm/src/cpu/kernel/asm/hash/blake2b/iv.asm b/evm/src/cpu/kernel/asm/hash/blake2b/iv.asm index 174afd33..6236fbef 100644 --- a/evm/src/cpu/kernel/asm/hash/blake2b/iv.asm +++ b/evm/src/cpu/kernel/asm/hash/blake2b/iv.asm @@ -33,30 +33,63 @@ global blake2b_iv_const: BYTES 91, 224, 205, 25 BYTES 19, 126, 33, 121 -%macro blake2b_iv - // stack: i, ... +global blake2b_iv: + // stack: i, retdest PUSH blake2b_iv_const - // stack: blake2b_iv_const, i, ... + // stack: blake2b_iv_const, i, retdest SWAP1 - // stack: i, blake2b_iv_const, ... + // stack: i, blake2b_iv_const, retdest %mul_const(8) ADD - // stack: blake2b_iv_const + 2 * i, ... + // stack: blake2b_iv_const + 2 * i, retdest DUP1 - // stack: blake2b_iv_const + 2 * i, blake2b_iv_const + 2 * i, ... + // stack: blake2b_iv_const + 2 * i, blake2b_iv_const + 2 * i, retdest %add_const(4) - // stack: blake2b_iv_const + 2 * i + 1, blake2b_iv_const + 2 * i, ... + // stack: blake2b_iv_const + 2 * i + 1, blake2b_iv_const + 2 * i, retdest %mload_kernel_code_u32 SWAP1 %mload_kernel_code_u32 - // stack: IV_i[32:], IV_i[:32], ... + // stack: IV_i[32:], IV_i[:32], retdest %shl_const(32) - // stack: IV_i[32:] << 32, IV_i[:32], ... + // stack: IV_i[32:] << 32, IV_i[:32], retdest OR - // stack: IV_i, ... + // stack: IV_i, retdest + SWAP1 + JUMP + +%macro blake2b_iv + %stack (i) -> (i, %%after) + %jump(blake2b_iv) +%%after: %endmacro -%macro blake2b_iv_i(i) - PUSH $i - %blake2b_iv -%endmacro +// Load the initial hash value (the IV, but with params XOR'd into the first word). +global blake2b_initial_hash_value: + // stack: retdest + PUSH 8 + // stack: i=8, retdest +blake2b_initial_hash_loop: + // stack: i, IV_i, ..., IV_7, retdest + %decrement + // stack: i-1, IV_i, ..., IV_7, retdest + PUSH blake2b_initial_hash_return + // stack: blake2b_initial_hash_return, i-1, IV_i, ..., IV_7, retdest + DUP2 + // stack: i-1, blake2b_initial_hash_return, i-1, IV_i, ..., IV_7, retdest + %jump(blake2b_iv) +blake2b_initial_hash_return: + // stack: IV_(i-1), i-1, IV_i, ..., IV_7, retdest + SWAP1 + // stack: i-1, IV_(i-1), IV_i, ..., IV_7, retdest + DUP1 + // stack: i-1, i-1, IV_(i-1), ..., IV_7, retdest + %jumpi(blake2b_initial_hash_loop) + // stack: i-1=0, IV_0, ..., IV_7, retdest + POP + // stack: IV_0, ..., IV_7, retdest + PUSH 0x01010040 // params: key = 00, digest_size = 64 = 0x40 + XOR + // stack: IV_0 ^ params, IV_1, IV_2, IV_3, IV_4, IV_5, IV_6, IV_7, retdest + %stack(iv: 8, ret) -> (ret, iv) + JUMP + diff --git a/evm/src/cpu/kernel/tests/hash.rs b/evm/src/cpu/kernel/tests/hash.rs index cc2c96eb..bc73ecd5 100644 --- a/evm/src/cpu/kernel/tests/hash.rs +++ b/evm/src/cpu/kernel/tests/hash.rs @@ -79,8 +79,6 @@ fn prepare_test( // Run the interpeter let result = run_interpreter_with_memory(interpreter_setup).unwrap(); - dbg!(result.stack().to_vec()); - Ok((expected, result.stack().to_vec())) } From fa605d7b221414fae2e8ca8399592c74e2372901 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Fri, 10 Feb 2023 16:31:35 -0800 Subject: [PATCH 009/121] basic bignum --- evm/Cargo.toml | 1 + evm/src/cpu/kernel/aggregator.rs | 7 + evm/src/cpu/kernel/asm/bignum/add.asm | 56 +++++ evm/src/cpu/kernel/asm/bignum/ge.asm | 80 +++++++ evm/src/cpu/kernel/asm/bignum/iszero.asm | 36 +++ evm/src/cpu/kernel/asm/bignum/mul.asm | 202 +++++++++++++++++ evm/src/cpu/kernel/asm/bignum/shr.asm | 56 +++++ evm/src/cpu/kernel/asm/bignum/util.asm | 13 ++ evm/src/cpu/kernel/asm/memory/memset.asm | 38 ++++ evm/src/cpu/kernel/asm/util/basic_macros.asm | 8 + evm/src/cpu/kernel/constants/mod.rs | 14 +- evm/src/cpu/kernel/evm_asm.pest | 2 +- evm/src/cpu/kernel/interpreter.rs | 18 ++ evm/src/cpu/kernel/tests/bignum.rs | 222 +++++++++++++++++++ evm/src/cpu/kernel/tests/mod.rs | 1 + evm/src/keccak/keccak_stark.rs | 2 +- evm/src/util.rs | 38 ++++ plonky2/src/fri/recursive_verifier.rs | 8 +- plonky2/src/gadgets/split_base.rs | 3 +- plonky2/src/gates/random_access.rs | 4 +- plonky2/src/hash/merkle_tree.rs | 4 +- plonky2/src/iop/generator.rs | 3 +- plonky2/src/iop/witness.rs | 6 +- 23 files changed, 799 insertions(+), 23 deletions(-) create mode 100644 evm/src/cpu/kernel/asm/bignum/add.asm create mode 100644 evm/src/cpu/kernel/asm/bignum/ge.asm create mode 100644 evm/src/cpu/kernel/asm/bignum/iszero.asm create mode 100644 evm/src/cpu/kernel/asm/bignum/mul.asm create mode 100644 evm/src/cpu/kernel/asm/bignum/shr.asm create mode 100644 evm/src/cpu/kernel/asm/bignum/util.asm create mode 100644 evm/src/cpu/kernel/asm/memory/memset.asm create mode 100644 evm/src/cpu/kernel/tests/bignum.rs diff --git a/evm/Cargo.toml b/evm/Cargo.toml index d9de1d16..f2fb889d 100644 --- a/evm/Cargo.toml +++ b/evm/Cargo.toml @@ -22,6 +22,7 @@ keccak-hash = "0.10.0" log = "0.4.14" plonky2_maybe_rayon = "0.1.0" num = "0.4.0" +num-bigint = "0.4.3" once_cell = "1.13.0" pest = "2.1.3" pest_derive = "2.1.0" diff --git a/evm/src/cpu/kernel/aggregator.rs b/evm/src/cpu/kernel/aggregator.rs index 1d8f11a0..53787e48 100644 --- a/evm/src/cpu/kernel/aggregator.rs +++ b/evm/src/cpu/kernel/aggregator.rs @@ -11,6 +11,12 @@ pub static KERNEL: Lazy = Lazy::new(combined_kernel); pub(crate) fn combined_kernel() -> Kernel { let files = vec![ + include_str!("asm/bignum/add.asm"), + include_str!("asm/bignum/ge.asm"), + include_str!("asm/bignum/iszero.asm"), + include_str!("asm/bignum/mul.asm"), + include_str!("asm/bignum/shr.asm"), + include_str!("asm/bignum/util.asm"), include_str!("asm/core/bootloader.asm"), include_str!("asm/core/call.asm"), include_str!("asm/core/create.asm"), @@ -69,6 +75,7 @@ pub(crate) fn combined_kernel() -> Kernel { include_str!("asm/main.asm"), include_str!("asm/memory/core.asm"), include_str!("asm/memory/memcpy.asm"), + include_str!("asm/memory/memset.asm"), include_str!("asm/memory/metadata.asm"), include_str!("asm/memory/packing.asm"), include_str!("asm/memory/syscalls.asm"), diff --git a/evm/src/cpu/kernel/asm/bignum/add.asm b/evm/src/cpu/kernel/asm/bignum/add.asm new file mode 100644 index 00000000..508078ce --- /dev/null +++ b/evm/src/cpu/kernel/asm/bignum/add.asm @@ -0,0 +1,56 @@ +// Arithmetic on little-endian integers represented with 128-bit limbs. +// All integers must be under a given length bound, and are padded with leading zeroes. + +// Replaces a with a + b, leaving b unchanged. +global add_bignum: + // stack: len, a_start_loc, b_start_loc, retdest + PUSH 0 + // stack: carry=0, i=len, a_start_loc, b_start_loc, retdest +add_loop: + // stack: carry, i, a_cur_loc, b_cur_loc, retdest + DUP4 + %mload_kernel_general + // stack: b[cur], carry, i, a_cur_loc, b_cur_loc, retdest + DUP4 + %mload_kernel_general + // stack: a[cur], b[cur], carry, i, a_cur_loc, b_cur_loc, retdest + ADD + ADD + // stack: a[cur] + b[cur] + carry, i, a_cur_loc, b_cur_loc, retdest + DUP1 + // stack: a[cur] + b[cur] + carry, a[cur] + b[cur] + carry, i, a_cur_loc, b_cur_loc, retdest + %shr_const(128) + // stack: (a[cur] + b[cur] + carry) // 2^128, a[cur] + b[cur] + carry, i, a_cur_loc, b_cur_loc, retdest + SWAP1 + // stack: a[cur] + b[cur] + carry, (a[cur] + b[cur] + carry) // 2^128, i, a_cur_loc, b_cur_loc, retdest + %shl_const(128) + %shr_const(128) + // stack: c[cur] = (a[cur] + b[cur] + carry) % 2^128, carry_new = (a[cur] + b[cur] + carry) // 2^128, i, a_cur_loc, b_cur_loc, retdest + DUP4 + // stack: a_cur_loc, c[cur], carry_new, i, a_cur_loc, b_cur_loc, retdest + %mstore_kernel_general + // stack: carry_new, i, a_cur_loc, b_cur_loc, retdest + %stack (c, i, a, b) -> (a, b, c, i) + // stack: a_cur_loc, b_cur_loc, carry_new, i, retdest + %increment + // stack: a_cur_loc + 1, b_cur_loc, carry_new, i, retdest + SWAP1 + // stack: b_cur_loc, a_cur_loc + 1, carry_new, i, retdest + %increment + // stack: b_cur_loc + 1, a_cur_loc + 1, carry_new, i, retdest + %stack (b, a, c, i) -> (i, c, a, b) + // stack: i, carry_new, a_cur_loc + 1, b_cur_loc + 1, retdest + %decrement + // stack: i - 1, carry_new, a_cur_loc + 1, b_cur_loc + 1, retdest + SWAP1 + // stack: carry_new, i - 1, a_cur_loc + 1, b_cur_loc + 1, retdest + DUP2 + // stack: i - 1, carry_new, i - 1, a_cur_loc + 1, b_cur_loc + 1, retdest + %jumpi(add_loop) +add_end: + // stack: carry_new, i - 1, a_cur_loc + 1, b_cur_loc + 1, retdest + %stack (c, i, a, b) -> (c) + // stack: carry_new, retdest + SWAP1 + // stack: retdest, carry_new + JUMP diff --git a/evm/src/cpu/kernel/asm/bignum/ge.asm b/evm/src/cpu/kernel/asm/bignum/ge.asm new file mode 100644 index 00000000..cdd7712f --- /dev/null +++ b/evm/src/cpu/kernel/asm/bignum/ge.asm @@ -0,0 +1,80 @@ +// Arithmetic on little-endian integers represented with 128-bit limbs. +// All integers must be under a given length bound, and are padded with leading zeroes. + +// Returns a >= b. +global ge_bignum: + // stack: len, a_start_loc, b_start_loc, retdest + SWAP1 + // stack: a_start_loc, len, b_start_loc, retdest + DUP2 + // stack: len, a_start_loc, len, b_start_loc, retdest + ADD + %decrement + // stack: a_end_loc, len, b_start_loc, retdest + SWAP2 + // stack: b_start_loc, len, a_end_loc, retdest + DUP2 + // stack: len, b_start_loc, len, a_end_loc, retdest + ADD + %decrement + // stack: b_end_loc, len, a_end_loc, retdest + %stack (b, l, a) -> (l, a, b) + // stack: len, a_end_loc, b_end_loc, retdest + %decrement +ge_loop: + // stack: i, a_i_loc, b_i_loc, retdest + DUP3 + DUP3 + // stack: a_i_loc, b_i_loc, i, a_i_loc, b_i_loc, retdest + %mload_kernel_general + SWAP1 + %mload_kernel_general + SWAP1 + // stack: a[i], b[i], i, a_i_loc, b_i_loc, retdest + %stack (vals: 2) -> (vals, vals) + GT + %jumpi(greater) + // stack: a[i], b[i], i, a_i_loc, b_i_loc, retdest + LT + %jumpi(less) + // stack: i, a_i_loc, b_i_loc, retdest + DUP1 + ISZERO + %jumpi(equal) + %decrement + // stack: i-1, a_i_loc, b_i_loc, retdest + SWAP1 + // stack: a_i_loc, i-1, b_i_loc, retdest + %decrement + // stack: a_i_loc_new, i-1, b_i_loc, retdest + SWAP2 + // stack: b_i_loc, i-1, a_i_loc_new, retdest + %decrement + // stack: b_i_loc_new, i-1, a_i_loc_new, retdest + %stack (b, i, a) -> (i, a, b) + // stack: i-1, a_i_loc_new, b_i_loc_new, retdest + %jump(ge_loop) +equal: + // stack: i, a_i_loc, b_i_loc, retdest + %pop3 + // stack: retdest + PUSH 3 + // stack: 3, retdest + SWAP1 + JUMP +greater: + // stack: a[i], b[i], i, a_i_loc, b_i_loc, retdest + %pop5 + // stack: retdest + PUSH 1 + // stack: 1, retdest + SWAP1 + JUMP +less: + // stack: i, a_i_loc, b_i_loc, retdest + %pop3 + // stack: retdest + PUSH 0 + // stack: 0, retdest + SWAP1 + JUMP diff --git a/evm/src/cpu/kernel/asm/bignum/iszero.asm b/evm/src/cpu/kernel/asm/bignum/iszero.asm new file mode 100644 index 00000000..ff755270 --- /dev/null +++ b/evm/src/cpu/kernel/asm/bignum/iszero.asm @@ -0,0 +1,36 @@ +// Arithmetic on little-endian integers represented with 128-bit limbs. +// All integers must be under a given length bound, and are padded with leading zeroes. + +global iszero_bignum: + // stack: len, start_loc, retdest + DUP2 + // stack: start_loc, len, start_loc, retdest + ADD + // stack: end_loc, start_loc, retdest + SWAP1 + // stack: cur_loc=start_loc, end_loc, retdest +iszero_loop: + // stack: cur_loc, end_loc, retdest + DUP1 + // stack: cur_loc, cur_loc, end_loc, retdest + %mload_kernel_general + // stack: cur_val, cur_loc, end_loc, retdest + %jumpi(neqzero) + // stack: cur_loc, end_loc, retdest + %increment + // stack: cur_loc + 1, end_loc, retdest + %stack (vals: 2) -> (vals, vals) + // stack: cur_loc + 1, end_loc, cur_loc + 1, end_loc, retdest + EQ + %jumpi(eqzero) + %jump(iszero_loop) +neqzero: + // stack: cur_loc, end_loc, retdest + %stack (vals: 2, retdest) -> (retdest, 0) + // stack: retdest, 0 + JUMP +eqzero: + // stack: cur_loc, end_loc, retdest + %stack (vals: 2, retdest) -> (retdest, 1) + // stack: retdest, 1 + JUMP diff --git a/evm/src/cpu/kernel/asm/bignum/mul.asm b/evm/src/cpu/kernel/asm/bignum/mul.asm new file mode 100644 index 00000000..d96518fe --- /dev/null +++ b/evm/src/cpu/kernel/asm/bignum/mul.asm @@ -0,0 +1,202 @@ +// Arithmetic on little-endian integers represented with 128-bit limbs. +// All integers must be under a given length bound, and are padded with leading zeroes. + +// Multiplies a bignum by a single-limb value. Resulting limbs may be larger than 128 bits. +// This is a naive multiplication algorithm (BasecaseMultiply from Modern Computer Arithmetic). +mul_bignum_helper: + // stack: len, start_loc, val, retdest + DUP2 + // stack: start_loc, len, start_loc, val, retdest + ADD + // stack: end_loc, start_loc, val, retdest + SWAP2 + SWAP1 + // stack: i=start_loc, val, end_loc, retdest +mul_helper_loop: + // stack: i, val, end_loc, retdest + DUP1 + // stack: i, i, val, end_loc, retdest + %mload_kernel_general + // stack: bignum[i], i, val, end_loc, retdest + DUP3 + // stack: val, bignum[i], i, val, end_loc, retdest + MUL + // stack: val * bignum[i], i, val, end_loc, retdest + DUP2 + // stack: i, val * bignum[i], i, val, end_loc, retdest + %mstore_kernel_general + // stack: i, val, end_loc, retdest + %increment + // stack: i + 1, val, end_loc, retdest + DUP1 + // stack: i + 1, i + 1, val, end_loc, retdest + DUP4 + // stack: end_loc, i + 1, i + 1, val, end_loc, retdest + GT + %jumpi(mul_helper_loop) + // stack: n = 0, i, val, retdest + %pop3 + // stack: retdest + JUMP + +// Reduces a bignum with limbs possibly greater than 128 bits to a normalized bignum with length len + 1. +// Used after `mul_bignum_helper` to complete the process of multiplying a bignum by a constant value. +mul_bignum_reduce_helper: + // stack: len, start_loc, retdest + DUP2 + // stack: start_loc, len, start_loc, retdest + ADD + // stack: end_loc, start_loc, retdest + SWAP1 + // stack: i=start_loc, end_loc, retdest +reduce_loop: + // stack: i, end_loc, retdest + DUP1 + // stack: i, i, end_loc, retdest + %mload_kernel_general + // stack: bignum[i], i, end_loc, retdest + DUP1 + // stack: bignum[i], bignum[i], i, end_loc, retdest + %shl_const(128) + %shr_const(128) + // stack: bignum[i] % 2^128, bignum[i], i, end_loc, retdest + SWAP1 + // stack: bignum[i], bignum[i] % 2^128, i, end_loc, retdest + %shr_const(128) + // stack: bignum[i] // 2^128, bignum[i] % 2^128, i, end_loc, retdest + DUP3 + // stack: i, bignum[i] // 2^128, bignum[i] % 2^128, i, end_loc, retdest + %increment + // stack: i+1, bignum[i] // 2^128, bignum[i] % 2^128, i, end_loc, retdest + SWAP1 + // stack: bignum[i] // 2^128, i+1, bignum[i] % 2^128, i, end_loc, retdest + DUP2 + // stack: i+1, bignum[i] // 2^128, i+1, bignum[i] % 2^128, i, end_loc, retdest + %mload_kernel_general + // stack: bignum[i+1], bignum[i] // 2^128, i+1, bignum[i] % 2^128, i, end_loc, retdest + ADD + // stack: bignum[i+1] + bignum[i] // 2^128, i+1, bignum[i] % 2^128, i, end_loc, retdest + SWAP1 + // stack: i+1, bignum[i+1] + bignum[i] // 2^128, bignum[i] % 2^128, i, end_loc, retdest + %mstore_kernel_general + // stack: bignum[i] % 2^128, i, end_loc, retdest + DUP2 + // stack: i, bignum[i] % 2^128, i, end_loc, retdest + %mstore_kernel_general + // stack: i, end_loc, retdest + %increment + // stack: i + 1, end_loc, retdest + %stack (vals: 2) -> (vals, vals) + // stack: i + 1, end_loc, i + 1, end_loc, retdest + EQ + %jumpi(reduce_loop) +reduce_end: + // stack: n = 0, i, retdest + %pop2 + // stack: retdest + JUMP + +// Stores a * b in output_loc, leaving a and b unchanged. +// Both a and b have length len; a * b will have length 2 * len. +// Both output_loc and scratch_space must be initialized as zeroes (2 * len of them in the case +// of output_loc, and len + 1 of them in the case of scratch_space). +global mul_bignum: + // stack: len, a_start_loc, b_start_loc, output_loc, scratch_space, retdest + DUP1 + // stack: len, n=len, a_start_loc, bi=b_start_loc, output_cur=output_loc, scratch_space, retdest +mul_loop: + // stack: len, n, a_start_loc, bi, output_cur, scratch_space, retdest + + // Copy a from a_start_loc into scratch_space. + DUP1 + // stack: len, len, n, a_start_loc, bi, output_cur, scratch_space, retdest + DUP4 + // stack: a_start_loc, len, len, n, a_start_loc, bi, output_cur, scratch_space, retdest + DUP8 + // stack: scratch_space, a_start_loc, len, len, n, a_start_loc, bi, output_cur, scratch_space, retdest + %memcpy_kernel_general + // stack: len, n, a_start_loc, bi, output_cur, scratch_space, retdest + + // Insert a zero into scratch_space[len]. + DUP6 + // stack: scratch_space, len, n, a_start_loc, bi, output_cur, scratch_space, retdest + DUP2 + // stack: len, scratch_space, len, n, a_start_loc, bi, output_cur, scratch_space, retdest + ADD + // stack: scratch_space + len, len, n, a_start_loc, bi, output_cur, scratch_space, retdest + PUSH 0 + SWAP1 + // stack: scratch_space + len, 0, len, n, a_start_loc, bi, output_cur, scratch_space, retdest + %mstore_kernel_general + // stack: len, n, a_start_loc, bi, output_cur, scratch_space, retdest + + // Use scratch_space to multiply a by b[i]. + PUSH mul_return_1 + // stack: mul_return_1, len, n, a_start_loc, bi, output_cur, scratch_space, retdest + DUP5 + // stack: bi, mul_return_1, len, n, a_start_loc, bi, output_cur, scratch_space, retdest + %mload_kernel_general + // stack: b[i], mul_return_1, len, n, a_start_loc, bi, output_cur, scratch_space, retdest + DUP8 + // stack: scratch_space, b[i], mul_return_1, len, n, a_start_loc, bi, output_cur, scratch_space, retdest + DUP4 + // stack: len, scratch_space, b[i], mul_return_1, len, n, a_start_loc, bi, output_cur, scratch_space, retdest + %jump(mul_bignum_helper) +mul_return_1: + // stack: len, n, a_start_loc, bi, output_cur, scratch_space, retdest + PUSH mul_return_2 + // stack: mul_return_2, len, n, a_start_loc, bi, output_cur, scratch_space, retdest + DUP7 + // stack: scratch_space, mul_return_2, len, n, a_start_loc, bi, output_cur, scratch_space, retdest + DUP3 + // stack: len, scratch_space, mul_return_2, len, n, a_start_loc, bi, output_cur, scratch_space, retdest + %jump(mul_bignum_reduce_helper) +mul_return_2: + // stack: len, n, a_start_loc, bi, output_cur, scratch_space, retdest + + // Add the multiplication result into output_cur = output_len[i]. + PUSH mul_return_3 + // stack: mul_return_3, len, n, a_start_loc, bi, output_cur, scratch_space, retdest + DUP7 + // stack: scratch_space, mul_return_3, len, n, a_start_loc, bi, output_cur, scratch_space, retdest + DUP7 + // stack: output_cur, scratch_space, mul_return_3, len, n, a_start_loc, bi, output_cur, scratch_space, retdest + DUP4 + // stack: len, output_cur, scratch_space, mul_return_3, len, n, a_start_loc, bi, output_cur, scratch_space, retdest + %increment + // stack: len + 1, output_cur, scratch_space, mul_return_3, len, n, a_start_loc, bi, output_cur, scratch_space, retdest + %jump(add_bignum) +mul_return_3: + // stack: carry, len, n, a_start_loc, bi, output_cur, scratch_space, retdest + DUP6 + // stack: output_cur, carry, len, n, a_start_loc, bi, output_cur, scratch_space, retdest + DUP3 + // stack: len, output_cur, carry, len, n, a_start_loc, bi, output_cur, scratch_space, retdest + ADD + // stack: output_cur + len, carry, len, n, a_start_loc, bi, output_cur, scratch_space, retdest + %increment + // stack: output_cur + len + 1, carry, len, n, a_start_loc, bi, output_cur, scratch_space, retdest + %mstore_kernel_general + // stack: len, n, a_start_loc, bi, output_cur, scratch_space, retdest + + // Increment output_cur and b[i], decrement n, and check if we're done. + DUP5 + // stack: output_cur, len, n, a_start_loc, bi, output_cur, scratch_space, retdest + %increment + // stack: output_cur+1, len, n, a_start_loc, bi, output_cur, scratch_space, retdest + DUP5 + %increment + // stack: bi+1, output_cur+1, len, n, a_start_loc, bi, output_cur, scratch_space, retdest + DUP5 + // stack: a_start_loc, bi+1, output_cur+1, len, n, a_start_loc, bi, output_cur, scratch_space, retdest + DUP5 + %decrement + // stack: n-1, a_start_loc, bi+1, output_cur+1, len, n, a_start_loc, bi, output_cur, scratch_space, retdest + %stack (new: 4, len, old: 4) -> (len, new) + // stack: len, n-1, a_start_loc, bi+1, output_cur+1, scratch_space, retdest + DUP2 + // stack: n-1, len, n-1, a_start_loc, bi+1, output_cur+1, scratch_space, retdest + %jumpi(mul_loop) + // stack: len, n, a_start_loc, bi, output_cur, scratch_space, retdest + %pop6 + JUMP diff --git a/evm/src/cpu/kernel/asm/bignum/shr.asm b/evm/src/cpu/kernel/asm/bignum/shr.asm new file mode 100644 index 00000000..69d32b07 --- /dev/null +++ b/evm/src/cpu/kernel/asm/bignum/shr.asm @@ -0,0 +1,56 @@ +// Arithmetic on little-endian integers represented with 128-bit limbs. +// All integers must be under a given length bound, and are padded with leading zeroes. + +// Shifts a given bignum right by one bit (in place). +global shr_bignum: + // stack: len, start_loc, retdest + DUP2 + // stack: start_loc, len, start_loc, retdest + ADD + // stack: start_loc + len, start_loc, retdest + %decrement + // stack: end_loc, start_loc, retdest + %stack (e) -> (e, 0) + // stack: i=end_loc, carry=0, start_loc, retdest +shr_loop: + // stack: i, carry, start_loc, retdest + DUP1 + // stack: i, i, carry, start_loc, retdest + %mload_kernel_general + // stack: a[i], i, carry, start_loc, retdest + DUP1 + // stack: a[i], a[i], i, carry, start_loc, retdest + %shr_const(1) + // stack: a[i] >> 1, a[i], i, carry, start_loc, retdest + SWAP1 + // stack: a[i], a[i] >> 1, i, carry, start_loc, retdest + %mod_const(2) + // stack: new_carry = a[i] % 2, a[i] >> 1, i, carry, start_loc, retdest + SWAP3 + // stack: carry, a[i] >> 1, i, new_carry, start_loc, retdest + %shl_const(127) + // stack: carry << 127, a[i] >> 1, i, new_carry, start_loc, retdest + OR + // stack: carry << 127 | a[i] >> 1, i, new_carry, start_loc, retdest + DUP2 + // stack: i, carry << 127 | a[i] >> 1, i, new_carry, start_loc, retdest + %mstore_kernel_general + // stack: i, new_carry, start_loc, retdest + DUP1 + // stack: i, i, new_carry, start_loc, retdest + %decrement + // stack: i-1, i, new_carry, start_loc, retdest + SWAP1 + // stack: i, i-1, new_carry, start_loc, retdest + DUP4 + // stack: start_loc, i, i-1, new_carry, start_loc, retdest + EQ + // stack: i == start_loc, i-1, new_carry, start_loc, retdest + ISZERO + // stack: i != start_loc, i-1, new_carry, start_loc, retdest + %jumpi(shr_loop) +shr_end: + // stack: i, new_carry, start_loc, retdest + %pop3 + // stack: retdest + JUMP diff --git a/evm/src/cpu/kernel/asm/bignum/util.asm b/evm/src/cpu/kernel/asm/bignum/util.asm new file mode 100644 index 00000000..2c6b2185 --- /dev/null +++ b/evm/src/cpu/kernel/asm/bignum/util.asm @@ -0,0 +1,13 @@ +%macro memcpy_kernel_general + // stack: dst, src, len + %stack (dst, src, len) -> (0, @SEGMENT_KERNEL_GENERAL, dst, 0, @SEGMENT_KERNEL_GENERAL, src, len, %%after) + %jump(memcpy) +%%after: +%endmacro + +%macro clear_kernel_general + // stack: dst, len + %stack (dst, len) -> (0, @SEGMENT_KERNEL_GENERAL, dst, 0, len, %%after) + %jump(memset) +%%after: +%endmacro diff --git a/evm/src/cpu/kernel/asm/memory/memset.asm b/evm/src/cpu/kernel/asm/memory/memset.asm new file mode 100644 index 00000000..77b37f64 --- /dev/null +++ b/evm/src/cpu/kernel/asm/memory/memset.asm @@ -0,0 +1,38 @@ +// Sets `count` values to `value` at +// DST = (dst_ctx, dst_segment, dst_addr). +// This tuple definition is used for brevity in the stack comments below. +global memset: + // stack: DST, value, count, retdest + DUP5 + // stack: count, DST, value, count, retdest + ISZERO + // stack: count == 0, DST, value, count, retdest + %jumpi(memset_finish) + // stack: DST, value, count, retdest + + DUP4 + // stack: value, DST, value, count, retdest + DUP4 + DUP4 + DUP4 + // stack: DST, value, DST, value, count, retdest + MSTORE_GENERAL + // stack: DST, value, count, retdest + + // Increment dst_addr. + SWAP2 + %increment + SWAP2 + // Decrement count. + SWAP4 + %decrement + SWAP4 + + // Continue the loop. + %jump(memset) + +memset_finish: + // stack: DST, value, count, retdest + %pop5 + // stack: retdest + JUMP diff --git a/evm/src/cpu/kernel/asm/util/basic_macros.asm b/evm/src/cpu/kernel/asm/util/basic_macros.asm index a68d832d..2c27efa3 100644 --- a/evm/src/cpu/kernel/asm/util/basic_macros.asm +++ b/evm/src/cpu/kernel/asm/util/basic_macros.asm @@ -50,6 +50,14 @@ %endrep %endmacro +%macro neq + // stack: x, y + EQ + // stack: x == y + ISZERO + // stack: x != y +%endmacro + %macro and_const(c) // stack: input, ... PUSH $c diff --git a/evm/src/cpu/kernel/constants/mod.rs b/evm/src/cpu/kernel/constants/mod.rs index afabd955..d0a079b8 100644 --- a/evm/src/cpu/kernel/constants/mod.rs +++ b/evm/src/cpu/kernel/constants/mod.rs @@ -19,7 +19,11 @@ pub(crate) mod txn_fields; pub fn evm_constants() -> HashMap { let mut c = HashMap::new(); - let hex_constants = EC_CONSTANTS.iter().chain(HASH_CONSTANTS.iter()).cloned(); + let hex_constants = MISC_CONSTANTS + .iter() + .chain(EC_CONSTANTS.iter()) + .chain(HASH_CONSTANTS.iter()) + .cloned(); for (name, value) in hex_constants { c.insert(name.into(), U256::from_big_endian(&value)); } @@ -50,6 +54,14 @@ pub fn evm_constants() -> HashMap { c } +const MISC_CONSTANTS: [(&str, [u8; 32]); 1] = [ + // Base for limbs used in bignum arithmetic. + ( + "BIGNUM_LIMB_BASE", + hex!("0000000000000000000000000000000100000000000000000000000000000000"), + ), +]; + const HASH_CONSTANTS: [(&str, [u8; 32]); 2] = [ // Hash of an empty string: keccak(b'').hex() ( diff --git a/evm/src/cpu/kernel/evm_asm.pest b/evm/src/cpu/kernel/evm_asm.pest index e7337430..3243aecc 100644 --- a/evm/src/cpu/kernel/evm_asm.pest +++ b/evm/src/cpu/kernel/evm_asm.pest @@ -26,7 +26,7 @@ stack = { ^"%stack" ~ stack_placeholders ~ "->" ~ stack_replacements } stack_placeholders = { "(" ~ (stack_placeholder ~ ("," ~ stack_placeholder)*)? ~ ")" } stack_placeholder = { stack_block | identifier } stack_block = { identifier ~ ":" ~ literal_decimal } -stack_replacements = { "(" ~ stack_replacement ~ ("," ~ stack_replacement)* ~ ")" } +stack_replacements = { "(" ~ (stack_replacement ~ ("," ~ stack_replacement)*)? ~ ")" } stack_replacement = { literal | identifier | constant | macro_label | variable } global_label_decl = ${ ^"GLOBAL " ~ identifier ~ ":" } diff --git a/evm/src/cpu/kernel/interpreter.rs b/evm/src/cpu/kernel/interpreter.rs index 843f0a0d..b0d3a784 100644 --- a/evm/src/cpu/kernel/interpreter.rs +++ b/evm/src/cpu/kernel/interpreter.rs @@ -194,6 +194,12 @@ impl<'a> Interpreter<'a> { &mut self.generation_state.memory.contexts[0].segments[Segment::TrieData as usize].content } + pub(crate) fn get_memory_segment(&self, segment: Segment) -> Vec { + self.generation_state.memory.contexts[0].segments[segment as usize] + .content + .clone() + } + pub(crate) fn get_memory_segment_bytes(&self, segment: Segment) -> Vec { self.generation_state.memory.contexts[0].segments[segment as usize] .content @@ -202,10 +208,22 @@ impl<'a> Interpreter<'a> { .collect() } + pub(crate) fn get_kernel_general_memory(&self) -> Vec { + self.get_memory_segment(Segment::KernelGeneral) + } + pub(crate) fn get_rlp_memory(&self) -> Vec { self.get_memory_segment_bytes(Segment::RlpRaw) } + pub(crate) fn set_memory_segment(&mut self, segment: Segment, memory: Vec) { + self.generation_state.memory.contexts[0].segments[segment as usize].content = memory; + } + + pub(crate) fn set_kernel_general_memory(&mut self, memory: Vec) { + self.set_memory_segment(Segment::KernelGeneral, memory) + } + pub(crate) fn set_memory_segment_bytes(&mut self, segment: Segment, memory: Vec) { self.generation_state.memory.contexts[0].segments[segment as usize].content = memory.into_iter().map(U256::from).collect(); diff --git a/evm/src/cpu/kernel/tests/bignum.rs b/evm/src/cpu/kernel/tests/bignum.rs new file mode 100644 index 00000000..f866caad --- /dev/null +++ b/evm/src/cpu/kernel/tests/bignum.rs @@ -0,0 +1,222 @@ +use anyhow::Result; +use ethereum_types::U256; +use itertools::Itertools; +use num::{BigUint, Signed}; +use num_bigint::RandBigInt; + +use crate::cpu::kernel::aggregator::KERNEL; +use crate::cpu::kernel::interpreter::Interpreter; +use crate::util::{biguint_to_mem_vec, mem_vec_to_biguint}; + +fn pack_bignums(biguints: &[BigUint], length: usize) -> Vec { + biguints + .iter() + .flat_map(|biguint| { + biguint_to_mem_vec(biguint.clone()) + .into_iter() + .pad_using(length, |_| U256::zero()) + }) + .collect() +} + +fn gen_bignum(bit_size: usize) -> BigUint { + let mut rng = rand::thread_rng(); + rng.gen_bigint(bit_size as u64).abs().to_biguint().unwrap() +} + +fn bignum_len(a: &BigUint) -> usize { + (a.bits() as usize) / 128 + 1 +} + +fn gen_two_bignums_ordered(bit_size: usize) -> (BigUint, BigUint) { + let mut rng = rand::thread_rng(); + let (a, b) = { + let a = rng.gen_bigint(bit_size as u64).abs().to_biguint().unwrap(); + let b = rng.gen_bigint(bit_size as u64).abs().to_biguint().unwrap(); + (a.clone().max(b.clone()), a.min(b)) + }; + + (a, b) +} + +fn prepare_bignum(bit_size: usize) -> (BigUint, U256, Vec) { + let a = gen_bignum(bit_size); + let length: U256 = bignum_len(&a).into(); + let a_limbs = biguint_to_mem_vec(a.clone()); + + (a, length, a_limbs) +} + +fn prepare_two_bignums(bit_size: usize) -> (BigUint, BigUint, U256, Vec) { + let (a, b) = gen_two_bignums_ordered(bit_size); + let length: U256 = bignum_len(&a).into(); + let memory = pack_bignums(&[a.clone(), b.clone()], length.try_into().unwrap()); + + (a, b, length, memory) +} + +#[test] +fn test_shr_bignum() -> Result<()> { + let (a, length, memory) = prepare_bignum(1000); + + let halved = a >> 1; + + let retdest = 0xDEADBEEFu32.into(); + let shr_bignum = KERNEL.global_labels["shr_bignum"]; + + let a_start_loc = 0.into(); + + let mut initial_stack: Vec = vec![length, a_start_loc, retdest]; + initial_stack.reverse(); + let mut interpreter = Interpreter::new_with_kernel(shr_bignum, initial_stack); + interpreter.set_kernel_general_memory(memory); + interpreter.run()?; + + let new_memory = interpreter.get_kernel_general_memory(); + let new_a = mem_vec_to_biguint(&new_memory[0..length.as_usize()]); + assert_eq!(new_a, halved); + + Ok(()) +} + +#[test] +fn test_iszero_bignum() -> Result<()> { + let (_a, length, memory) = prepare_bignum(1000); + + let retdest = 0xDEADBEEFu32.into(); + let iszero_bignum = KERNEL.global_labels["iszero_bignum"]; + + let a_start_loc = 0.into(); + + // Test with a > 0. + let mut initial_stack: Vec = vec![length, a_start_loc, retdest]; + initial_stack.reverse(); + let mut interpreter = Interpreter::new_with_kernel(iszero_bignum, initial_stack); + interpreter.set_kernel_general_memory(memory.clone()); + interpreter.run()?; + let result = interpreter.stack()[0]; + assert_eq!(result, 0.into()); + + let memory = vec![0.into(); memory.len()]; + + // Test with a == 0. + let mut initial_stack: Vec = vec![length, a_start_loc, retdest]; + initial_stack.reverse(); + let mut interpreter = Interpreter::new_with_kernel(iszero_bignum, initial_stack); + interpreter.set_kernel_general_memory(memory); + interpreter.run()?; + let result = interpreter.stack()[0]; + assert_eq!(result, U256::one()); + + Ok(()) +} + +#[test] +fn test_ge_bignum() -> Result<()> { + let (_a, _b, length, memory) = prepare_two_bignums(1000); + + let retdest = 0xDEADBEEFu32.into(); + let ge_bignum = KERNEL.global_labels["ge_bignum"]; + + let a_start_loc = 0.into(); + let b_start_loc = length; + + // Test with a > b. + let mut initial_stack: Vec = vec![length, a_start_loc, b_start_loc, retdest]; + initial_stack.reverse(); + let mut interpreter = Interpreter::new_with_kernel(ge_bignum, initial_stack); + interpreter.set_kernel_general_memory(memory.clone()); + interpreter.run()?; + let result = interpreter.stack()[0]; + assert_eq!(result, U256::one()); + + // Swap a and b, to test the less-than case. + let mut initial_stack: Vec = vec![length, b_start_loc, a_start_loc, retdest]; + initial_stack.reverse(); + let mut interpreter = Interpreter::new_with_kernel(ge_bignum, initial_stack); + interpreter.set_kernel_general_memory(memory); + interpreter.run()?; + let result = interpreter.stack()[0]; + assert_eq!(result, 0.into()); + + Ok(()) +} + +#[test] +fn test_add_bignum() -> Result<()> { + let (a, b, length, memory) = prepare_two_bignums(1000); + + // Determine expected sum. + let sum = a + b; + let expected_sum: Vec = biguint_to_mem_vec(sum); + + let a_start_loc = 0.into(); + let b_start_loc = length; + + // Prepare stack. + let retdest = 0xDEADBEEFu32.into(); + let mut initial_stack: Vec = vec![length, a_start_loc, b_start_loc, retdest]; + initial_stack.reverse(); + + // Prepare interpreter. + let add_bignum = KERNEL.global_labels["add_bignum"]; + let mut interpreter = Interpreter::new_with_kernel(add_bignum, initial_stack); + interpreter.set_kernel_general_memory(memory); + + // Run add function. + interpreter.run()?; + + // Determine actual sum. + let new_memory = interpreter.get_kernel_general_memory(); + let actual_sum: Vec<_> = new_memory[..expected_sum.len()].into(); + + // Compare. + assert_eq!(actual_sum, expected_sum); + + Ok(()) +} + +#[test] +fn test_mul_bignum() -> Result<()> { + let (a, b, length, memory) = prepare_two_bignums(1000); + + // Determine expected product. + let product = a * b; + let expected_product: Vec = biguint_to_mem_vec(product); + + // Output and scratch space locations (initialized as zeroes) follow a and b in memory. + let a_start_loc = 0.into(); + let b_start_loc = length; + let output_loc = length * 2; + let scratch_space = length * 4; + + // Prepare stack. + let retdest = 0xDEADBEEFu32.into(); + let mut initial_stack: Vec = vec![ + length, + a_start_loc, + b_start_loc, + output_loc, + scratch_space, + retdest, + ]; + initial_stack.reverse(); + + // Prepare interpreter. + let mul_bignum = KERNEL.global_labels["mul_bignum"]; + let mut interpreter = Interpreter::new_with_kernel(mul_bignum, initial_stack); + interpreter.set_kernel_general_memory(memory); + + // Run mul function. + interpreter.run()?; + + // Determine actual product. + let new_memory = interpreter.get_kernel_general_memory(); + let output_location: usize = output_loc.try_into().unwrap(); + let actual_product: Vec<_> = + new_memory[output_location..output_location + expected_product.len()].into(); + + assert_eq!(actual_product, expected_product); + + Ok(()) +} diff --git a/evm/src/cpu/kernel/tests/mod.rs b/evm/src/cpu/kernel/tests/mod.rs index acf90230..6fb9ee4a 100644 --- a/evm/src/cpu/kernel/tests/mod.rs +++ b/evm/src/cpu/kernel/tests/mod.rs @@ -1,5 +1,6 @@ mod account_code; mod balance; +mod bignum; mod core; mod ecc; mod exp; diff --git a/evm/src/keccak/keccak_stark.rs b/evm/src/keccak/keccak_stark.rs index c8fe8086..61651dd5 100644 --- a/evm/src/keccak/keccak_stark.rs +++ b/evm/src/keccak/keccak_stark.rs @@ -68,7 +68,7 @@ impl, const D: usize> KeccakStark { let pad_rows = self.generate_trace_rows_for_perm([0; NUM_INPUTS]); while rows.len() < num_rows { - rows.extend(&pad_rows); + rows.extend(pad_rows.clone()); } rows.drain(num_rows..); rows diff --git a/evm/src/util.rs b/evm/src/util.rs index dcb0a8ef..55344dcb 100644 --- a/evm/src/util.rs +++ b/evm/src/util.rs @@ -144,3 +144,41 @@ pub(crate) fn biguint_to_u256(x: BigUint) -> U256 { let bytes = x.to_bytes_le(); U256::from_little_endian(&bytes) } + +pub(crate) fn le_limbs_to_biguint(x: &[u128]) -> BigUint { + BigUint::from_slice( + &x.iter() + .flat_map(|&a| { + [ + (a % (1 << 32)) as u32, + ((a >> 32) % (1 << 32)) as u32, + ((a >> 64) % (1 << 32)) as u32, + ((a >> 96) % (1 << 32)) as u32, + ] + }) + .collect::>(), + ) +} + +pub(crate) fn mem_vec_to_biguint(x: &[U256]) -> BigUint { + le_limbs_to_biguint(&x.iter().map(|&n| n.try_into().unwrap()).collect_vec()) +} + +pub(crate) fn biguint_to_le_limbs(x: BigUint) -> Vec { + let mut digits = x.to_u32_digits(); + + // Pad to a multiple of 8. + digits.resize((digits.len() + 7) / 8 * 8, 0); + + digits + .chunks(4) + .map(|c| (c[3] as u128) << 96 | (c[2] as u128) << 64 | (c[1] as u128) << 32 | c[0] as u128) + .collect() +} + +pub(crate) fn biguint_to_mem_vec(x: BigUint) -> Vec { + biguint_to_le_limbs(x) + .into_iter() + .map(|n| n.into()) + .collect() +} diff --git a/plonky2/src/fri/recursive_verifier.rs b/plonky2/src/fri/recursive_verifier.rs index 8e9329d5..307c4785 100644 --- a/plonky2/src/fri/recursive_verifier.rs +++ b/plonky2/src/fri/recursive_verifier.rs @@ -78,16 +78,12 @@ impl, const D: usize> CircuitBuilder { assert!( self.config.num_wires >= min_wires, - "To efficiently perform FRI checks with an arity of 2^{}, at least {} wires are needed. Consider reducing arity.", - max_fri_arity_bits, - min_wires + "To efficiently perform FRI checks with an arity of 2^{max_fri_arity_bits}, at least {min_wires} wires are needed. Consider reducing arity." ); assert!( self.config.num_routed_wires >= min_routed_wires, - "To efficiently perform FRI checks with an arity of 2^{}, at least {} routed wires are needed. Consider reducing arity.", - max_fri_arity_bits, - min_routed_wires + "To efficiently perform FRI checks with an arity of 2^{max_fri_arity_bits}, at least {min_routed_wires} routed wires are needed. Consider reducing arity." ); } diff --git a/plonky2/src/gadgets/split_base.rs b/plonky2/src/gadgets/split_base.rs index dd0edf5d..7558be3d 100644 --- a/plonky2/src/gadgets/split_base.rs +++ b/plonky2/src/gadgets/split_base.rs @@ -38,8 +38,7 @@ impl, const D: usize> CircuitBuilder { let num_bits = bits.len(); assert!( num_bits <= log_floor(F::ORDER, 2), - "{} bits may overflow the field", - num_bits + "{num_bits} bits may overflow the field" ); if num_bits == 0 { return self.zero(); diff --git a/plonky2/src/gates/random_access.rs b/plonky2/src/gates/random_access.rs index 80874505..b74b1169 100644 --- a/plonky2/src/gates/random_access.rs +++ b/plonky2/src/gates/random_access.rs @@ -361,9 +361,7 @@ impl, const D: usize> SimpleGenerator let access_index = access_index_f.to_canonical_u64() as usize; debug_assert!( access_index < vec_size, - "Access index {} is larger than the vector size {}", - access_index, - vec_size + "Access index {access_index} is larger than the vector size {vec_size}" ); set_local_wire( diff --git a/plonky2/src/hash/merkle_tree.rs b/plonky2/src/hash/merkle_tree.rs index e884554f..beb22b07 100644 --- a/plonky2/src/hash/merkle_tree.rs +++ b/plonky2/src/hash/merkle_tree.rs @@ -136,9 +136,7 @@ impl> MerkleTree { let log2_leaves_len = log2_strict(leaves.len()); assert!( cap_height <= log2_leaves_len, - "cap_height={} should be at most log2(leaves.len())={}", - cap_height, - log2_leaves_len + "cap_height={cap_height} should be at most log2(leaves.len())={log2_leaves_len}" ); let num_digests = 2 * (leaves.len() - (1 << cap_height)); diff --git a/plonky2/src/iop/generator.rs b/plonky2/src/iop/generator.rs index a65d1748..80eb0094 100644 --- a/plonky2/src/iop/generator.rs +++ b/plonky2/src/iop/generator.rs @@ -89,8 +89,7 @@ pub(crate) fn generate_partial_witness< assert_eq!( remaining_generators, 0, - "{} generators weren't run", - remaining_generators, + "{remaining_generators} generators weren't run", ); witness diff --git a/plonky2/src/iop/witness.rs b/plonky2/src/iop/witness.rs index 14213d0d..d0e3e7e4 100644 --- a/plonky2/src/iop/witness.rs +++ b/plonky2/src/iop/witness.rs @@ -284,8 +284,7 @@ impl WitnessWrite for PartialWitness { if let Some(old_value) = opt_old_value { assert_eq!( value, old_value, - "Target {:?} was set twice with different values: {} != {}", - target, old_value, value + "Target {target:?} was set twice with different values: {old_value} != {value}" ); } } @@ -325,8 +324,7 @@ impl<'a, F: Field> PartitionWitness<'a, F> { if let Some(old_value) = *rep_value { assert_eq!( value, old_value, - "Partition containing {:?} was set twice with different values: {} != {}", - target, old_value, value + "Partition containing {target:?} was set twice with different values: {old_value} != {value}" ); None } else { From aa605b673b25d0ef09725f1a00fb0a6235c7ad52 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Mon, 13 Feb 2023 10:47:30 -0800 Subject: [PATCH 010/121] flag functions used only in tests --- evm/src/util.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/evm/src/util.rs b/evm/src/util.rs index 55344dcb..6b2ca479 100644 --- a/evm/src/util.rs +++ b/evm/src/util.rs @@ -145,6 +145,7 @@ pub(crate) fn biguint_to_u256(x: BigUint) -> U256 { U256::from_little_endian(&bytes) } +#[cfg(test)] pub(crate) fn le_limbs_to_biguint(x: &[u128]) -> BigUint { BigUint::from_slice( &x.iter() @@ -160,10 +161,12 @@ pub(crate) fn le_limbs_to_biguint(x: &[u128]) -> BigUint { ) } +#[cfg(test)] pub(crate) fn mem_vec_to_biguint(x: &[U256]) -> BigUint { le_limbs_to_biguint(&x.iter().map(|&n| n.try_into().unwrap()).collect_vec()) } +#[cfg(test)] pub(crate) fn biguint_to_le_limbs(x: BigUint) -> Vec { let mut digits = x.to_u32_digits(); @@ -176,6 +179,7 @@ pub(crate) fn biguint_to_le_limbs(x: BigUint) -> Vec { .collect() } +#[cfg(test)] pub(crate) fn biguint_to_mem_vec(x: BigUint) -> Vec { biguint_to_le_limbs(x) .into_iter() From 9976a4b04062200e220d8d51b8dc924a5a10c467 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Mon, 13 Feb 2023 12:53:49 -0800 Subject: [PATCH 011/121] addmul initial --- evm/src/cpu/kernel/aggregator.rs | 1 + evm/src/cpu/kernel/asm/bignum/add.asm | 2 +- evm/src/cpu/kernel/asm/bignum/addmul.asm | 99 ++++++++++++++++ evm/src/cpu/kernel/asm/bignum/mul.asm | 141 ++--------------------- evm/src/cpu/kernel/tests/bignum.rs | 2 + 5 files changed, 115 insertions(+), 130 deletions(-) create mode 100644 evm/src/cpu/kernel/asm/bignum/addmul.asm diff --git a/evm/src/cpu/kernel/aggregator.rs b/evm/src/cpu/kernel/aggregator.rs index 53787e48..53584a1f 100644 --- a/evm/src/cpu/kernel/aggregator.rs +++ b/evm/src/cpu/kernel/aggregator.rs @@ -12,6 +12,7 @@ pub static KERNEL: Lazy = Lazy::new(combined_kernel); pub(crate) fn combined_kernel() -> Kernel { let files = vec![ include_str!("asm/bignum/add.asm"), + include_str!("asm/bignum/addmul.asm"), include_str!("asm/bignum/ge.asm"), include_str!("asm/bignum/iszero.asm"), include_str!("asm/bignum/mul.asm"), diff --git a/evm/src/cpu/kernel/asm/bignum/add.asm b/evm/src/cpu/kernel/asm/bignum/add.asm index 508078ce..d38c9701 100644 --- a/evm/src/cpu/kernel/asm/bignum/add.asm +++ b/evm/src/cpu/kernel/asm/bignum/add.asm @@ -5,7 +5,7 @@ global add_bignum: // stack: len, a_start_loc, b_start_loc, retdest PUSH 0 - // stack: carry=0, i=len, a_start_loc, b_start_loc, retdest + // stack: carry=0, i=len, a_cur_loc=a_start_loc, b_cur_loc=b_start_loc, retdest add_loop: // stack: carry, i, a_cur_loc, b_cur_loc, retdest DUP4 diff --git a/evm/src/cpu/kernel/asm/bignum/addmul.asm b/evm/src/cpu/kernel/asm/bignum/addmul.asm new file mode 100644 index 00000000..742bb829 --- /dev/null +++ b/evm/src/cpu/kernel/asm/bignum/addmul.asm @@ -0,0 +1,99 @@ +// Arithmetic on little-endian integers represented with 128-bit limbs. +// All integers must be under a given length bound, and are padded with leading zeroes. + +// Sets a[0:len] += b[0:len] * val. +global addmul_bignum: + // stack: len, a_start_loc, b_start_loc, val, retdest + PUSH 0 + // stack: carry=0, i=len, a_cur_loc=a_start_loc, b_cur_loc=b_start_loc, val, retdest +addmul_loop: + // stack: carry, i, a_cur_loc, b_cur_loc, val, retdest + DUP4 + // stack: b_cur_loc, carry, i, a_cur_loc, b_cur_loc, val, retdest + %mload_kernel_general + // stack: b[cur], carry, i, a_cur_loc, b_cur_loc, val, retdest + DUP6 + // stack: val, b[cur], carry, i, a_cur_loc, b_cur_loc, val, retdest + MUL + // stack: val * b[cur], carry, i, a_cur_loc, b_cur_loc, val, retdest + DUP1 + // stack: val * b[cur], val * b[cur], carry, i, a_cur_loc, b_cur_loc, val, retdest + %shr_const(128) + // stack: (val * b[cur]) // 2^128, val * b[cur], carry, i, a_cur_loc, b_cur_loc, val, retdest + SWAP1 + // stack: val * b[cur], (val * b[cur]) // 2^128, carry, i, a_cur_loc, b_cur_loc, val, retdest + %shl_const(128) + %shr_const(128) + // stack: prod_lo = val * b[cur] % 2^128, prod_hi = (val * b[cur]) // 2^128, carry, i, a_cur_loc, b_cur_loc, val, retdest + DUP5 + // stack: a_cur_loc, prod_lo, prod_hi, carry, i, a_cur_loc, b_cur_loc, val, retdest + %mload_kernel_general + // stack: a[cur], prod_lo, prod_hi, carry, i, a_cur_loc, b_cur_loc, val, retdest + DUP1 + // stack: a[cur], a[cur], prod_lo, prod_hi, carry, i, a_cur_loc, b_cur_loc, val, retdest + SWAP2 + // stack: prod_lo, a[cur], a[cur], prod_hi, carry, i, a_cur_loc, b_cur_loc, val, retdest + ADD + %shl_const(128) + %shr_const(128) + // stack: prod_lo' = (prod_lo + a[cur]) % 2^128, a[cur], prod_hi, carry, i, a_cur_loc, b_cur_loc, val, retdest + DUP1 + // stack: prod_lo', prod_lo', a[cur], prod_hi, carry, i, a_cur_loc, b_cur_loc, val, retdest + SWAP2 + // stack: a[cur], prod_lo', prod_lo', prod_hi, carry, i, a_cur_loc, b_cur_loc, val, retdest + GT + // stack: prod_lo_carry = a[cur] > prod_lo', prod_lo', prod_hi, carry, i, a_cur_loc, b_cur_loc, val, retdest + SWAP1 + // stack: prod_lo', prod_lo_carry, prod_hi, carry, i, a_cur_loc, b_cur_loc, val, retdest + SWAP2 + // stack: prod_hi, prod_lo_carry, prod_lo', carry, i, a_cur_loc, b_cur_loc, val, retdest + ADD + // stack: prod_hi' = prod_hi + prod_lo_carry, prod_lo', carry, i, a_cur_loc, b_cur_loc, val, retdest + DUP3 + // stack: carry, prod_lo', prod_hi', carry, i, a_cur_loc, b_cur_loc, val, retdest + DUP2 + // stack: prod_lo', carry, prod_lo', prod_hi', carry, i, a_cur_loc, b_cur_loc, val, retdest + ADD + %shl_const(128) + %shr_const(128) + // stack: to_write = (prod_lo' + carry) % 2^128, prod_lo', prod_hi', carry, i, a_cur_loc, b_cur_loc, val, retdest + SWAP1 + // stack: prod_lo', to_write, prod_hi', carry, i, a_cur_loc, b_cur_loc, val, retdest + DUP2 + // stack: to_write, prod_lo', to_write, prod_hi', carry, i, a_cur_loc, b_cur_loc, val, retdest + LT + // stack: carry_new = to_write < prod_lo', to_write, prod_hi', carry, i, a_cur_loc, b_cur_loc, val, retdest + %stack (cn, tw, ph, c) -> (cn, ph, tw) + // stack: carry_new, prod_hi', to_write, i, a_cur_loc, b_cur_loc, val, retdest + ADD + // stack: carry = carry_new' + prod_hi', to_write, i, a_cur_loc, b_cur_loc, val, retdest + SWAP1 + // stack: to_write, carry, i, a_cur_loc, b_cur_loc, val, retdest + DUP4 + // stack: a_cur_loc, to_write, carry, i, a_cur_loc, b_cur_loc, val, retdest + %mstore_kernel_general + // stack: carry, i, a_cur_loc, b_cur_loc, val, retdest + SWAP1 + // stack: i, carry, a_cur_loc, b_cur_loc, val, retdest + %decrement + // stack: i-1, carry, a_cur_loc, b_cur_loc, val, retdest + SWAP2 + // stack: a_cur_loc, carry, i-1, b_cur_loc, val, retdest + %increment + // stack: a_cur_loc+1, carry, i-1, b_cur_loc, val, retdest + SWAP3 + // stack: b_cur_loc, carry, i-1, a_cur_loc+1, val, retdest + %increment + // stack: b_cur_loc+1, carry, i-1, a_cur_loc+1, val, retdest + %stack (b, c, i, a) -> (c, i, a, b) + // stack: carry, i-1, a_cur_loc+1, b_cur_loc+1, val, retdest + DUP2 + // stack: i-1, carry, i-1, a_cur_loc+1, b_cur_loc+1, val, retdest + %jumpi(addmul_loop) +addmul_end: + // stack: carry_new, i-1, a_cur_loc+1, b_cur_loc+1, retdest + %stack (c, i, a, b) -> (c) + // stack: carry_new, retdest + SWAP1 + // stack: retdest, carry_new + JUMP diff --git a/evm/src/cpu/kernel/asm/bignum/mul.asm b/evm/src/cpu/kernel/asm/bignum/mul.asm index d96518fe..1b947c23 100644 --- a/evm/src/cpu/kernel/asm/bignum/mul.asm +++ b/evm/src/cpu/kernel/asm/bignum/mul.asm @@ -1,101 +1,6 @@ // Arithmetic on little-endian integers represented with 128-bit limbs. // All integers must be under a given length bound, and are padded with leading zeroes. -// Multiplies a bignum by a single-limb value. Resulting limbs may be larger than 128 bits. -// This is a naive multiplication algorithm (BasecaseMultiply from Modern Computer Arithmetic). -mul_bignum_helper: - // stack: len, start_loc, val, retdest - DUP2 - // stack: start_loc, len, start_loc, val, retdest - ADD - // stack: end_loc, start_loc, val, retdest - SWAP2 - SWAP1 - // stack: i=start_loc, val, end_loc, retdest -mul_helper_loop: - // stack: i, val, end_loc, retdest - DUP1 - // stack: i, i, val, end_loc, retdest - %mload_kernel_general - // stack: bignum[i], i, val, end_loc, retdest - DUP3 - // stack: val, bignum[i], i, val, end_loc, retdest - MUL - // stack: val * bignum[i], i, val, end_loc, retdest - DUP2 - // stack: i, val * bignum[i], i, val, end_loc, retdest - %mstore_kernel_general - // stack: i, val, end_loc, retdest - %increment - // stack: i + 1, val, end_loc, retdest - DUP1 - // stack: i + 1, i + 1, val, end_loc, retdest - DUP4 - // stack: end_loc, i + 1, i + 1, val, end_loc, retdest - GT - %jumpi(mul_helper_loop) - // stack: n = 0, i, val, retdest - %pop3 - // stack: retdest - JUMP - -// Reduces a bignum with limbs possibly greater than 128 bits to a normalized bignum with length len + 1. -// Used after `mul_bignum_helper` to complete the process of multiplying a bignum by a constant value. -mul_bignum_reduce_helper: - // stack: len, start_loc, retdest - DUP2 - // stack: start_loc, len, start_loc, retdest - ADD - // stack: end_loc, start_loc, retdest - SWAP1 - // stack: i=start_loc, end_loc, retdest -reduce_loop: - // stack: i, end_loc, retdest - DUP1 - // stack: i, i, end_loc, retdest - %mload_kernel_general - // stack: bignum[i], i, end_loc, retdest - DUP1 - // stack: bignum[i], bignum[i], i, end_loc, retdest - %shl_const(128) - %shr_const(128) - // stack: bignum[i] % 2^128, bignum[i], i, end_loc, retdest - SWAP1 - // stack: bignum[i], bignum[i] % 2^128, i, end_loc, retdest - %shr_const(128) - // stack: bignum[i] // 2^128, bignum[i] % 2^128, i, end_loc, retdest - DUP3 - // stack: i, bignum[i] // 2^128, bignum[i] % 2^128, i, end_loc, retdest - %increment - // stack: i+1, bignum[i] // 2^128, bignum[i] % 2^128, i, end_loc, retdest - SWAP1 - // stack: bignum[i] // 2^128, i+1, bignum[i] % 2^128, i, end_loc, retdest - DUP2 - // stack: i+1, bignum[i] // 2^128, i+1, bignum[i] % 2^128, i, end_loc, retdest - %mload_kernel_general - // stack: bignum[i+1], bignum[i] // 2^128, i+1, bignum[i] % 2^128, i, end_loc, retdest - ADD - // stack: bignum[i+1] + bignum[i] // 2^128, i+1, bignum[i] % 2^128, i, end_loc, retdest - SWAP1 - // stack: i+1, bignum[i+1] + bignum[i] // 2^128, bignum[i] % 2^128, i, end_loc, retdest - %mstore_kernel_general - // stack: bignum[i] % 2^128, i, end_loc, retdest - DUP2 - // stack: i, bignum[i] % 2^128, i, end_loc, retdest - %mstore_kernel_general - // stack: i, end_loc, retdest - %increment - // stack: i + 1, end_loc, retdest - %stack (vals: 2) -> (vals, vals) - // stack: i + 1, end_loc, i + 1, end_loc, retdest - EQ - %jumpi(reduce_loop) -reduce_end: - // stack: n = 0, i, retdest - %pop2 - // stack: retdest - JUMP - // Stores a * b in output_loc, leaving a and b unchanged. // Both a and b have length len; a * b will have length 2 * len. // Both output_loc and scratch_space must be initialized as zeroes (2 * len of them in the case @@ -130,43 +35,21 @@ mul_loop: %mstore_kernel_general // stack: len, n, a_start_loc, bi, output_cur, scratch_space, retdest - // Use scratch_space to multiply a by b[i]. - PUSH mul_return_1 - // stack: mul_return_1, len, n, a_start_loc, bi, output_cur, scratch_space, retdest + // Multiply a by b[i] and add into output_cur. + PUSH mul_return + // stack: mul_return, len, n, a_start_loc, bi, output_cur, scratch_space, retdest DUP5 - // stack: bi, mul_return_1, len, n, a_start_loc, bi, output_cur, scratch_space, retdest + // stack: bi, mul_return, len, n, a_start_loc, bi, output_cur, scratch_space, retdest %mload_kernel_general - // stack: b[i], mul_return_1, len, n, a_start_loc, bi, output_cur, scratch_space, retdest + // stack: b[i], mul_return, len, n, a_start_loc, bi, output_cur, scratch_space, retdest + DUP5 + // stack: a_start_loc, b[i], mul_return, len, n, a_start_loc, bi, output_cur, scratch_space, retdest DUP8 - // stack: scratch_space, b[i], mul_return_1, len, n, a_start_loc, bi, output_cur, scratch_space, retdest - DUP4 - // stack: len, scratch_space, b[i], mul_return_1, len, n, a_start_loc, bi, output_cur, scratch_space, retdest - %jump(mul_bignum_helper) -mul_return_1: - // stack: len, n, a_start_loc, bi, output_cur, scratch_space, retdest - PUSH mul_return_2 - // stack: mul_return_2, len, n, a_start_loc, bi, output_cur, scratch_space, retdest - DUP7 - // stack: scratch_space, mul_return_2, len, n, a_start_loc, bi, output_cur, scratch_space, retdest - DUP3 - // stack: len, scratch_space, mul_return_2, len, n, a_start_loc, bi, output_cur, scratch_space, retdest - %jump(mul_bignum_reduce_helper) -mul_return_2: - // stack: len, n, a_start_loc, bi, output_cur, scratch_space, retdest - - // Add the multiplication result into output_cur = output_len[i]. - PUSH mul_return_3 - // stack: mul_return_3, len, n, a_start_loc, bi, output_cur, scratch_space, retdest - DUP7 - // stack: scratch_space, mul_return_3, len, n, a_start_loc, bi, output_cur, scratch_space, retdest - DUP7 - // stack: output_cur, scratch_space, mul_return_3, len, n, a_start_loc, bi, output_cur, scratch_space, retdest - DUP4 - // stack: len, output_cur, scratch_space, mul_return_3, len, n, a_start_loc, bi, output_cur, scratch_space, retdest - %increment - // stack: len + 1, output_cur, scratch_space, mul_return_3, len, n, a_start_loc, bi, output_cur, scratch_space, retdest - %jump(add_bignum) -mul_return_3: + // stack: output_cur, a_start_loc, b[i], mul_return, len, n, a_start_loc, bi, output_cur, scratch_space, retdest + DUP5 + // stack: len, output_cur, a_start_loc, b[i], mul_return, len, n, a_start_loc, bi, output_cur, scratch_space, retdest + %jump(addmul_bignum) +mul_return: // stack: carry, len, n, a_start_loc, bi, output_cur, scratch_space, retdest DUP6 // stack: output_cur, carry, len, n, a_start_loc, bi, output_cur, scratch_space, retdest diff --git a/evm/src/cpu/kernel/tests/bignum.rs b/evm/src/cpu/kernel/tests/bignum.rs index f866caad..49d28342 100644 --- a/evm/src/cpu/kernel/tests/bignum.rs +++ b/evm/src/cpu/kernel/tests/bignum.rs @@ -210,6 +210,8 @@ fn test_mul_bignum() -> Result<()> { // Run mul function. interpreter.run()?; + dbg!(interpreter.stack()); + // Determine actual product. let new_memory = interpreter.get_kernel_general_memory(); let output_location: usize = output_loc.try_into().unwrap(); From 119eae95fd855ba75e9f935086d6de01ec85f5df Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Mon, 13 Feb 2023 14:09:27 -0800 Subject: [PATCH 012/121] fix --- evm/src/cpu/kernel/asm/bignum/addmul.asm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/evm/src/cpu/kernel/asm/bignum/addmul.asm b/evm/src/cpu/kernel/asm/bignum/addmul.asm index 742bb829..3ead50c5 100644 --- a/evm/src/cpu/kernel/asm/bignum/addmul.asm +++ b/evm/src/cpu/kernel/asm/bignum/addmul.asm @@ -91,8 +91,8 @@ addmul_loop: // stack: i-1, carry, i-1, a_cur_loc+1, b_cur_loc+1, val, retdest %jumpi(addmul_loop) addmul_end: - // stack: carry_new, i-1, a_cur_loc+1, b_cur_loc+1, retdest - %stack (c, i, a, b) -> (c) + // stack: carry_new, i-1, a_cur_loc+1, b_cur_loc+1, val, retdest + %stack (c, i, a, b, v) -> (c) // stack: carry_new, retdest SWAP1 // stack: retdest, carry_new From 5477c7ddbebbee462785171bf7b2d0681a7e147a Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Wed, 15 Feb 2023 11:20:09 -0800 Subject: [PATCH 013/121] fixes --- evm/src/cpu/kernel/asm/bignum/addmul.asm | 20 +++++------ evm/src/cpu/kernel/tests/bignum.rs | 46 ++++++++++++++++++++++-- 2 files changed, 53 insertions(+), 13 deletions(-) diff --git a/evm/src/cpu/kernel/asm/bignum/addmul.asm b/evm/src/cpu/kernel/asm/bignum/addmul.asm index 3ead50c5..701a2afa 100644 --- a/evm/src/cpu/kernel/asm/bignum/addmul.asm +++ b/evm/src/cpu/kernel/asm/bignum/addmul.asm @@ -50,20 +50,20 @@ addmul_loop: ADD // stack: prod_hi' = prod_hi + prod_lo_carry, prod_lo', carry, i, a_cur_loc, b_cur_loc, val, retdest DUP3 - // stack: carry, prod_lo', prod_hi', carry, i, a_cur_loc, b_cur_loc, val, retdest - DUP2 - // stack: prod_lo', carry, prod_lo', prod_hi', carry, i, a_cur_loc, b_cur_loc, val, retdest + // stack: carry, prod_hi', prod_lo', carry, i, a_cur_loc, b_cur_loc, val, retdest + DUP3 + // stack: prod_lo', carry, prod_hi', prod_lo', carry, i, a_cur_loc, b_cur_loc, val, retdest ADD %shl_const(128) %shr_const(128) - // stack: to_write = (prod_lo' + carry) % 2^128, prod_lo', prod_hi', carry, i, a_cur_loc, b_cur_loc, val, retdest - SWAP1 - // stack: prod_lo', to_write, prod_hi', carry, i, a_cur_loc, b_cur_loc, val, retdest - DUP2 - // stack: to_write, prod_lo', to_write, prod_hi', carry, i, a_cur_loc, b_cur_loc, val, retdest + // stack: to_write = (prod_lo' + carry) % 2^128, prod_hi', prod_lo', carry, i, a_cur_loc, b_cur_loc, val, retdest + SWAP2 + // stack: prod_lo', prod_hi', to_write, carry, i, a_cur_loc, b_cur_loc, val, retdest + DUP3 + // stack: to_write, prod_lo', prod_hi', to_write, carry, i, a_cur_loc, b_cur_loc, val, retdest LT - // stack: carry_new = to_write < prod_lo', to_write, prod_hi', carry, i, a_cur_loc, b_cur_loc, val, retdest - %stack (cn, tw, ph, c) -> (cn, ph, tw) + // stack: carry_new = to_write < prod_lo', prod_hi', to_write, carry, i, a_cur_loc, b_cur_loc, val, retdest + %stack (vals: 3, c) -> (vals) // stack: carry_new, prod_hi', to_write, i, a_cur_loc, b_cur_loc, val, retdest ADD // stack: carry = carry_new' + prod_hi', to_write, i, a_cur_loc, b_cur_loc, val, retdest diff --git a/evm/src/cpu/kernel/tests/bignum.rs b/evm/src/cpu/kernel/tests/bignum.rs index 49d28342..6f0edb4c 100644 --- a/evm/src/cpu/kernel/tests/bignum.rs +++ b/evm/src/cpu/kernel/tests/bignum.rs @@ -3,6 +3,7 @@ use ethereum_types::U256; use itertools::Itertools; use num::{BigUint, Signed}; use num_bigint::RandBigInt; +use rand::Rng; use crate::cpu::kernel::aggregator::KERNEL; use crate::cpu::kernel::interpreter::Interpreter; @@ -21,7 +22,7 @@ fn pack_bignums(biguints: &[BigUint], length: usize) -> Vec { fn gen_bignum(bit_size: usize) -> BigUint { let mut rng = rand::thread_rng(); - rng.gen_bigint(bit_size as u64).abs().to_biguint().unwrap() + rng.gen_biguint(bit_size as u64) } fn bignum_len(a: &BigUint) -> usize { @@ -31,8 +32,8 @@ fn bignum_len(a: &BigUint) -> usize { fn gen_two_bignums_ordered(bit_size: usize) -> (BigUint, BigUint) { let mut rng = rand::thread_rng(); let (a, b) = { - let a = rng.gen_bigint(bit_size as u64).abs().to_biguint().unwrap(); - let b = rng.gen_bigint(bit_size as u64).abs().to_biguint().unwrap(); + let a = rng.gen_biguint(bit_size as u64); + let b = rng.gen_biguint(bit_size as u64); (a.clone().max(b.clone()), a.min(b)) }; @@ -176,6 +177,45 @@ fn test_add_bignum() -> Result<()> { Ok(()) } +#[test] +fn test_addmul_bignum() -> Result<()> { + let mut rng = rand::thread_rng(); + let (a, b, length, memory) = prepare_two_bignums(1000); + let val: u64 = 1; + let val_u256 = U256::from(val); + + // Determine expected result. + let result = a + b * BigUint::from(val); + let expected_result: Vec = biguint_to_mem_vec(result); + + let a_start_loc = 0.into(); + let b_start_loc = length; + + // Prepare stack. + let retdest = 0xDEADBEEFu32.into(); + let mut initial_stack: Vec = vec![length, a_start_loc, b_start_loc, val_u256, retdest]; + initial_stack.reverse(); + + // Prepare interpreter. + let addmul_bignum = KERNEL.global_labels["addmul_bignum"]; + let mut interpreter = Interpreter::new_with_kernel(addmul_bignum, initial_stack); + interpreter.set_kernel_general_memory(memory); + + // Run add function. + interpreter.run()?; + + // Determine actual result. + let new_memory = interpreter.get_kernel_general_memory(); + let actual_result: Vec<_> = new_memory[..expected_result.len()].into(); + + dbg!(interpreter.stack()); + + // Compare. + assert_eq!(actual_result, expected_result); + + Ok(()) +} + #[test] fn test_mul_bignum() -> Result<()> { let (a, b, length, memory) = prepare_two_bignums(1000); From efd5e6ec9a28c9807c18265eada1715a57fdea25 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Wed, 15 Feb 2023 11:20:48 -0800 Subject: [PATCH 014/121] cleanup --- evm/src/cpu/kernel/tests/bignum.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/evm/src/cpu/kernel/tests/bignum.rs b/evm/src/cpu/kernel/tests/bignum.rs index 6f0edb4c..7f5b3de4 100644 --- a/evm/src/cpu/kernel/tests/bignum.rs +++ b/evm/src/cpu/kernel/tests/bignum.rs @@ -1,9 +1,8 @@ use anyhow::Result; use ethereum_types::U256; use itertools::Itertools; -use num::{BigUint, Signed}; +use num::BigUint; use num_bigint::RandBigInt; -use rand::Rng; use crate::cpu::kernel::aggregator::KERNEL; use crate::cpu::kernel::interpreter::Interpreter; @@ -179,7 +178,7 @@ fn test_add_bignum() -> Result<()> { #[test] fn test_addmul_bignum() -> Result<()> { - let mut rng = rand::thread_rng(); + let _rng = rand::thread_rng(); let (a, b, length, memory) = prepare_two_bignums(1000); let val: u64 = 1; let val_u256 = U256::from(val); From 10893fe056bc053892afec0a7d06fdb69f95ef48 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Wed, 15 Feb 2023 14:50:41 -0800 Subject: [PATCH 015/121] addmul test: use carry --- evm/src/cpu/kernel/asm/bignum/addmul.asm | 2 +- evm/src/cpu/kernel/tests/bignum.rs | 18 ++++++++++++------ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/evm/src/cpu/kernel/asm/bignum/addmul.asm b/evm/src/cpu/kernel/asm/bignum/addmul.asm index 701a2afa..55769bf8 100644 --- a/evm/src/cpu/kernel/asm/bignum/addmul.asm +++ b/evm/src/cpu/kernel/asm/bignum/addmul.asm @@ -1,7 +1,7 @@ // Arithmetic on little-endian integers represented with 128-bit limbs. // All integers must be under a given length bound, and are padded with leading zeroes. -// Sets a[0:len] += b[0:len] * val. +// Sets a[0:len+1] += b[0:len] * val. global addmul_bignum: // stack: len, a_start_loc, b_start_loc, val, retdest PUSH 0 diff --git a/evm/src/cpu/kernel/tests/bignum.rs b/evm/src/cpu/kernel/tests/bignum.rs index 7f5b3de4..c2b96afa 100644 --- a/evm/src/cpu/kernel/tests/bignum.rs +++ b/evm/src/cpu/kernel/tests/bignum.rs @@ -3,6 +3,7 @@ use ethereum_types::U256; use itertools::Itertools; use num::BigUint; use num_bigint::RandBigInt; +use rand::Rng; use crate::cpu::kernel::aggregator::KERNEL; use crate::cpu::kernel::interpreter::Interpreter; @@ -151,7 +152,7 @@ fn test_add_bignum() -> Result<()> { let expected_sum: Vec = biguint_to_mem_vec(sum); let a_start_loc = 0.into(); - let b_start_loc = length; + let b_start_loc = length ; // Prepare stack. let retdest = 0xDEADBEEFu32.into(); @@ -178,9 +179,12 @@ fn test_add_bignum() -> Result<()> { #[test] fn test_addmul_bignum() -> Result<()> { - let _rng = rand::thread_rng(); - let (a, b, length, memory) = prepare_two_bignums(1000); - let val: u64 = 1; + let mut rng = rand::thread_rng(); + let (a, b, length, mut memory) = prepare_two_bignums(1000); + let len: usize = length.try_into().unwrap(); + memory.splice(len..len, vec![0.into(); 2].iter().cloned()); + + let val: u64 = rng.gen(); let val_u256 = U256::from(val); // Determine expected result. @@ -188,7 +192,7 @@ fn test_addmul_bignum() -> Result<()> { let expected_result: Vec = biguint_to_mem_vec(result); let a_start_loc = 0.into(); - let b_start_loc = length; + let b_start_loc = length + 2; // Prepare stack. let retdest = 0xDEADBEEFu32.into(); @@ -204,7 +208,9 @@ fn test_addmul_bignum() -> Result<()> { interpreter.run()?; // Determine actual result. - let new_memory = interpreter.get_kernel_general_memory(); + let carry = interpreter.stack()[0]; + let mut new_memory = interpreter.get_kernel_general_memory(); + new_memory[len] = carry; let actual_result: Vec<_> = new_memory[..expected_result.len()].into(); dbg!(interpreter.stack()); From af3dc287dfaf44b7d5f558368f90dff0b9530b2b Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Wed, 15 Feb 2023 14:50:54 -0800 Subject: [PATCH 016/121] cleanup --- evm/src/cpu/kernel/tests/bignum.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/evm/src/cpu/kernel/tests/bignum.rs b/evm/src/cpu/kernel/tests/bignum.rs index c2b96afa..38f5ec52 100644 --- a/evm/src/cpu/kernel/tests/bignum.rs +++ b/evm/src/cpu/kernel/tests/bignum.rs @@ -213,8 +213,6 @@ fn test_addmul_bignum() -> Result<()> { new_memory[len] = carry; let actual_result: Vec<_> = new_memory[..expected_result.len()].into(); - dbg!(interpreter.stack()); - // Compare. assert_eq!(actual_result, expected_result); From c98bfb0b2c710ac8a292af2251bbce2f7ae1da78 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Wed, 15 Feb 2023 14:51:22 -0800 Subject: [PATCH 017/121] cleanup --- evm/src/cpu/kernel/tests/bignum.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/evm/src/cpu/kernel/tests/bignum.rs b/evm/src/cpu/kernel/tests/bignum.rs index 38f5ec52..72e38ab1 100644 --- a/evm/src/cpu/kernel/tests/bignum.rs +++ b/evm/src/cpu/kernel/tests/bignum.rs @@ -152,7 +152,7 @@ fn test_add_bignum() -> Result<()> { let expected_sum: Vec = biguint_to_mem_vec(sum); let a_start_loc = 0.into(); - let b_start_loc = length ; + let b_start_loc = length; // Prepare stack. let retdest = 0xDEADBEEFu32.into(); From 1d7c28ee1d37dfabd623e2d32b73c51c6cf23103 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Thu, 16 Feb 2023 11:36:40 -0800 Subject: [PATCH 018/121] bug fixes --- evm/src/cpu/kernel/asm/bignum/addmul.asm | 2 +- evm/src/cpu/kernel/asm/bignum/mul.asm | 96 ++++++++---------------- evm/src/cpu/kernel/tests/bignum.rs | 2 - 3 files changed, 33 insertions(+), 67 deletions(-) diff --git a/evm/src/cpu/kernel/asm/bignum/addmul.asm b/evm/src/cpu/kernel/asm/bignum/addmul.asm index 55769bf8..e1bd3bf2 100644 --- a/evm/src/cpu/kernel/asm/bignum/addmul.asm +++ b/evm/src/cpu/kernel/asm/bignum/addmul.asm @@ -1,7 +1,7 @@ // Arithmetic on little-endian integers represented with 128-bit limbs. // All integers must be under a given length bound, and are padded with leading zeroes. -// Sets a[0:len+1] += b[0:len] * val. +// Sets a[0:len] += b[0:len] * val, and returns the carry. global addmul_bignum: // stack: len, a_start_loc, b_start_loc, val, retdest PUSH 0 diff --git a/evm/src/cpu/kernel/asm/bignum/mul.asm b/evm/src/cpu/kernel/asm/bignum/mul.asm index 1b947c23..d62ce907 100644 --- a/evm/src/cpu/kernel/asm/bignum/mul.asm +++ b/evm/src/cpu/kernel/asm/bignum/mul.asm @@ -3,83 +3,51 @@ // Stores a * b in output_loc, leaving a and b unchanged. // Both a and b have length len; a * b will have length 2 * len. -// Both output_loc and scratch_space must be initialized as zeroes (2 * len of them in the case -// of output_loc, and len + 1 of them in the case of scratch_space). +// output_loc must be initialized as 2 * len zeroes. global mul_bignum: - // stack: len, a_start_loc, b_start_loc, output_loc, scratch_space, retdest + // stack: len, a_start_loc, b_start_loc, output_loc, retdest DUP1 - // stack: len, n=len, a_start_loc, bi=b_start_loc, output_cur=output_loc, scratch_space, retdest + // stack: n=len, len, a_start_loc, bi=b_start_loc, output_cur=output_loc, retdest mul_loop: - // stack: len, n, a_start_loc, bi, output_cur, scratch_space, retdest - - // Copy a from a_start_loc into scratch_space. - DUP1 - // stack: len, len, n, a_start_loc, bi, output_cur, scratch_space, retdest - DUP4 - // stack: a_start_loc, len, len, n, a_start_loc, bi, output_cur, scratch_space, retdest - DUP8 - // stack: scratch_space, a_start_loc, len, len, n, a_start_loc, bi, output_cur, scratch_space, retdest - %memcpy_kernel_general - // stack: len, n, a_start_loc, bi, output_cur, scratch_space, retdest - - // Insert a zero into scratch_space[len]. - DUP6 - // stack: scratch_space, len, n, a_start_loc, bi, output_cur, scratch_space, retdest - DUP2 - // stack: len, scratch_space, len, n, a_start_loc, bi, output_cur, scratch_space, retdest - ADD - // stack: scratch_space + len, len, n, a_start_loc, bi, output_cur, scratch_space, retdest - PUSH 0 - SWAP1 - // stack: scratch_space + len, 0, len, n, a_start_loc, bi, output_cur, scratch_space, retdest - %mstore_kernel_general - // stack: len, n, a_start_loc, bi, output_cur, scratch_space, retdest - - // Multiply a by b[i] and add into output_cur. + // stack: n, len, a_start_loc, bi, output_cur, retdest PUSH mul_return - // stack: mul_return, len, n, a_start_loc, bi, output_cur, scratch_space, retdest + // stack: mul_return, n, len, a_start_loc, bi, output_cur, retdest DUP5 - // stack: bi, mul_return, len, n, a_start_loc, bi, output_cur, scratch_space, retdest + // stack: bi, mul_return, n, len, a_start_loc, bi, output_cur, retdest %mload_kernel_general - // stack: b[i], mul_return, len, n, a_start_loc, bi, output_cur, scratch_space, retdest + // stack: b[i], mul_return, n, len, a_start_loc, bi, output_cur, retdest, b DUP5 - // stack: a_start_loc, b[i], mul_return, len, n, a_start_loc, bi, output_cur, scratch_space, retdest + // stack: a_start_loc, b[i], mul_return, n, len, a_start_loc, bi, output_cur, retdest, b DUP8 - // stack: output_cur, a_start_loc, b[i], mul_return, len, n, a_start_loc, bi, output_cur, scratch_space, retdest - DUP5 - // stack: len, output_cur, a_start_loc, b[i], mul_return, len, n, a_start_loc, bi, output_cur, scratch_space, retdest + // stack: output_loc, a_start_loc, b[i], mul_return, n, len, a_start_loc, bi, output_cur, retdest, b + DUP6 + // stack: len, output_loc, a_start_loc, b[i], mul_return, n, len, a_start_loc, bi, output_cur, retdest, b %jump(addmul_bignum) mul_return: - // stack: carry, len, n, a_start_loc, bi, output_cur, scratch_space, retdest + // stack: carry, n, len, a_start_loc, bi, output_cur, retdest DUP6 - // stack: output_cur, carry, len, n, a_start_loc, bi, output_cur, scratch_space, retdest - DUP3 - // stack: len, output_cur, carry, len, n, a_start_loc, bi, output_cur, scratch_space, retdest + // stack: output_cur, carry, n, len, a_start_loc, bi, output_cur, retdest + DUP4 + // stack: len, output_cur, carry, n, len, a_start_loc, bi, output_cur, retdest ADD - // stack: output_cur + len, carry, len, n, a_start_loc, bi, output_cur, scratch_space, retdest - %increment - // stack: output_cur + len + 1, carry, len, n, a_start_loc, bi, output_cur, scratch_space, retdest + // stack: output_cur + len, carry, n, len, a_start_loc, bi, output_cur, retdest %mstore_kernel_general - // stack: len, n, a_start_loc, bi, output_cur, scratch_space, retdest - - // Increment output_cur and b[i], decrement n, and check if we're done. - DUP5 - // stack: output_cur, len, n, a_start_loc, bi, output_cur, scratch_space, retdest - %increment - // stack: output_cur+1, len, n, a_start_loc, bi, output_cur, scratch_space, retdest - DUP5 - %increment - // stack: bi+1, output_cur+1, len, n, a_start_loc, bi, output_cur, scratch_space, retdest - DUP5 - // stack: a_start_loc, bi+1, output_cur+1, len, n, a_start_loc, bi, output_cur, scratch_space, retdest - DUP5 + // stack: n, len, a_start_loc, bi, output_cur, retdest %decrement - // stack: n-1, a_start_loc, bi+1, output_cur+1, len, n, a_start_loc, bi, output_cur, scratch_space, retdest - %stack (new: 4, len, old: 4) -> (len, new) - // stack: len, n-1, a_start_loc, bi+1, output_cur+1, scratch_space, retdest - DUP2 - // stack: n-1, len, n-1, a_start_loc, bi+1, output_cur+1, scratch_space, retdest + // stack: n-1, len, a_start_loc, bi, output_cur, retdest + SWAP3 + %increment + SWAP3 + // stack: n-1, len, a_start_loc, bi+1, output_cur, retdest + SWAP4 + %increment + SWAP4 + // stack: n-1, len, a_start_loc, bi+1, output_cur+1, retdest + DUP1 + // stack: n-1, n-1, len, a_start_loc, bi+1, output_cur+1, retdest %jumpi(mul_loop) - // stack: len, n, a_start_loc, bi, output_cur, scratch_space, retdest - %pop6 +mul_end: + // stack: n-1, len, a_start_loc, bi+1, output_cur+1, retdest + %pop5 + // stack: retdest JUMP diff --git a/evm/src/cpu/kernel/tests/bignum.rs b/evm/src/cpu/kernel/tests/bignum.rs index 72e38ab1..0b0cfe2f 100644 --- a/evm/src/cpu/kernel/tests/bignum.rs +++ b/evm/src/cpu/kernel/tests/bignum.rs @@ -231,7 +231,6 @@ fn test_mul_bignum() -> Result<()> { let a_start_loc = 0.into(); let b_start_loc = length; let output_loc = length * 2; - let scratch_space = length * 4; // Prepare stack. let retdest = 0xDEADBEEFu32.into(); @@ -240,7 +239,6 @@ fn test_mul_bignum() -> Result<()> { a_start_loc, b_start_loc, output_loc, - scratch_space, retdest, ]; initial_stack.reverse(); From 2aff3e10da59051327a1345656552be7d468c9dc Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Thu, 16 Feb 2023 11:37:43 -0800 Subject: [PATCH 019/121] cleanup --- evm/src/cpu/kernel/tests/bignum.rs | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/evm/src/cpu/kernel/tests/bignum.rs b/evm/src/cpu/kernel/tests/bignum.rs index 0b0cfe2f..544c7ec5 100644 --- a/evm/src/cpu/kernel/tests/bignum.rs +++ b/evm/src/cpu/kernel/tests/bignum.rs @@ -234,13 +234,7 @@ fn test_mul_bignum() -> Result<()> { // Prepare stack. let retdest = 0xDEADBEEFu32.into(); - let mut initial_stack: Vec = vec![ - length, - a_start_loc, - b_start_loc, - output_loc, - retdest, - ]; + let mut initial_stack: Vec = vec![length, a_start_loc, b_start_loc, output_loc, retdest]; initial_stack.reverse(); // Prepare interpreter. @@ -251,8 +245,6 @@ fn test_mul_bignum() -> Result<()> { // Run mul function. interpreter.run()?; - dbg!(interpreter.stack()); - // Determine actual product. let new_memory = interpreter.get_kernel_general_memory(); let output_location: usize = output_loc.try_into().unwrap(); From f46694e74d86f51ab006b208efe5106815e004b4 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Thu, 16 Feb 2023 11:52:04 -0800 Subject: [PATCH 020/121] more thorough tests --- evm/src/cpu/kernel/tests/bignum.rs | 148 ++++++++++++++++++++++++----- 1 file changed, 126 insertions(+), 22 deletions(-) diff --git a/evm/src/cpu/kernel/tests/bignum.rs b/evm/src/cpu/kernel/tests/bignum.rs index 544c7ec5..17dc5dda 100644 --- a/evm/src/cpu/kernel/tests/bignum.rs +++ b/evm/src/cpu/kernel/tests/bignum.rs @@ -1,7 +1,7 @@ use anyhow::Result; use ethereum_types::U256; use itertools::Itertools; -use num::BigUint; +use num::{BigUint, Zero, One}; use num_bigint::RandBigInt; use rand::Rng; @@ -40,7 +40,7 @@ fn gen_two_bignums_ordered(bit_size: usize) -> (BigUint, BigUint) { (a, b) } -fn prepare_bignum(bit_size: usize) -> (BigUint, U256, Vec) { +fn prepare_bignum_random(bit_size: usize) -> (BigUint, U256, Vec) { let a = gen_bignum(bit_size); let length: U256 = bignum_len(&a).into(); let a_limbs = biguint_to_mem_vec(a.clone()); @@ -48,7 +48,23 @@ fn prepare_bignum(bit_size: usize) -> (BigUint, U256, Vec) { (a, length, a_limbs) } -fn prepare_two_bignums(bit_size: usize) -> (BigUint, BigUint, U256, Vec) { +fn prepare_bignum_max(bit_size: usize) -> (BigUint, U256, Vec) { + let a = BigUint::one() << bit_size - 1; + let length: U256 = bignum_len(&a).into(); + let a_limbs = biguint_to_mem_vec(a.clone()); + + (a, length, a_limbs) +} + +fn prepare_bignum_min(bit_size: usize) -> (BigUint, U256, Vec) { + let a = BigUint::zero(); + let length: U256 = bignum_len(&a).into(); + let a_limbs = biguint_to_mem_vec(a.clone()); + + (a, length, a_limbs) +} + +fn prepare_two_bignums_random(bit_size: usize) -> (BigUint, BigUint, U256, Vec) { let (a, b) = gen_two_bignums_ordered(bit_size); let length: U256 = bignum_len(&a).into(); let memory = pack_bignums(&[a.clone(), b.clone()], length.try_into().unwrap()); @@ -56,9 +72,37 @@ fn prepare_two_bignums(bit_size: usize) -> (BigUint, BigUint, U256, Vec) { (a, b, length, memory) } -#[test] -fn test_shr_bignum() -> Result<()> { - let (a, length, memory) = prepare_bignum(1000); +fn prepare_two_bignums_max(bit_size: usize) -> (BigUint, BigUint, U256, Vec) { + let a = BigUint::one() << bit_size - 1; + let b = BigUint::one() << bit_size - 2; + let length: U256 = bignum_len(&a).into(); + let memory = pack_bignums(&[a.clone(), b.clone()], length.try_into().unwrap()); + + (a, b, length, memory) +} + +fn prepare_two_bignums_min(bit_size: usize) -> (BigUint, BigUint, U256, Vec) { + let a = BigUint::one(); + let b = BigUint::zero(); + let length: U256 = bignum_len(&a).into(); + let memory = pack_bignums(&[a.clone(), b.clone()], length.try_into().unwrap()); + + (a, b, length, memory) +} + +fn prepare_two_bignums_diff(bit_size: usize) -> (BigUint, BigUint, U256, Vec) { + let a = BigUint::one() << bit_size - 1; + let b = BigUint::zero(); + let length: U256 = bignum_len(&a).into(); + let memory = pack_bignums(&[a.clone(), b.clone()], length.try_into().unwrap()); + + (a, b, length, memory) +} + +fn test_shr_bignum(prepare_bignum_fn: &F) -> Result<()> +where F: Fn(usize) -> (BigUint, U256, Vec) { + + let (a, length, memory) = prepare_bignum_fn(1000); let halved = a >> 1; @@ -80,9 +124,15 @@ fn test_shr_bignum() -> Result<()> { Ok(()) } -#[test] -fn test_iszero_bignum() -> Result<()> { - let (_a, length, memory) = prepare_bignum(1000); +fn test_iszero_bignum(prepare_bignum_fn: &F) -> Result<()> +where F: Fn(usize) -> (BigUint, U256, Vec) { + let (a, length, memory) = { + let (a, length, memory) = prepare_bignum_fn(1000); + while a == BigUint::zero() { + (a, length, memory) = prepare_bignum_fn(1000); + } + (a, length, memory) + }; let retdest = 0xDEADBEEFu32.into(); let iszero_bignum = KERNEL.global_labels["iszero_bignum"]; @@ -112,9 +162,9 @@ fn test_iszero_bignum() -> Result<()> { Ok(()) } -#[test] -fn test_ge_bignum() -> Result<()> { - let (_a, _b, length, memory) = prepare_two_bignums(1000); +fn test_ge_bignum(prepare_two_bignums_fn: &F) -> Result<()> +where F: Fn(usize) -> (BigUint, BigUint, U256, Vec) { + let (_a, _b, length, memory) = prepare_two_bignums_fn(1000); let retdest = 0xDEADBEEFu32.into(); let ge_bignum = KERNEL.global_labels["ge_bignum"]; @@ -143,9 +193,9 @@ fn test_ge_bignum() -> Result<()> { Ok(()) } -#[test] -fn test_add_bignum() -> Result<()> { - let (a, b, length, memory) = prepare_two_bignums(1000); +fn test_add_bignum(prepare_two_bignums_fn: &F) -> Result<()> +where F: Fn(usize) -> (BigUint, BigUint, U256, Vec) { + let (a, b, length, memory) = prepare_two_bignums_fn(1000); // Determine expected sum. let sum = a + b; @@ -177,14 +227,14 @@ fn test_add_bignum() -> Result<()> { Ok(()) } -#[test] -fn test_addmul_bignum() -> Result<()> { +fn test_addmul_bignum(prepare_two_bignums_fn: &F) -> Result<()> +where F: Fn(usize) -> (BigUint, BigUint, U256, Vec) { let mut rng = rand::thread_rng(); - let (a, b, length, mut memory) = prepare_two_bignums(1000); + let (a, b, length, mut memory) = prepare_two_bignums_fn(1000); let len: usize = length.try_into().unwrap(); memory.splice(len..len, vec![0.into(); 2].iter().cloned()); - let val: u64 = rng.gen(); + let val: u128 = rng.gen(); let val_u256 = U256::from(val); // Determine expected result. @@ -219,9 +269,9 @@ fn test_addmul_bignum() -> Result<()> { Ok(()) } -#[test] -fn test_mul_bignum() -> Result<()> { - let (a, b, length, memory) = prepare_two_bignums(1000); +fn test_mul_bignum(prepare_bignum_fn: &F) -> Result<()> +where F: Fn(usize) -> (BigUint, U256, Vec) { + let (a, b, length, memory) = prepare_two_bignums_fn(1000); // Determine expected product. let product = a * b; @@ -255,3 +305,57 @@ fn test_mul_bignum() -> Result<()> { Ok(()) } + +#[test] +fn test_shr_bignum_all() -> Result<()> { + test_shr_bignum(&prepare_bignum_random)?; + test_shr_bignum(&prepare_bignum_max)?; + test_shr_bignum(&prepare_bignum_min)?; + + Ok(()) +} + +#[test] +fn test_iszero_bignum_all() -> Result<()> { + test_iszero_bignum(&prepare_bignum_random)?; + test_iszero_bignum(&prepare_bignum_max)?; + // No need to test for min, since it is zero. + + Ok(()) +} + +#[test] +fn test_ge_bignum_all() -> Result<()> { + test_ge_bignum(&prepare_bignum_random)?; + test_ge_bignum(&prepare_bignum_max)?; + test_ge_bignum(&prepare_bignum_min)?; + + Ok(()) +} + +#[test] +fn test_add_bignum_all() -> Result<()> { + test_add_bignum(&prepare_two_bignums_random)?; + test_add_bignum(&prepare_two_bignums_max)?; + test_add_bignum(&prepare_two_bignums_min)?; + + Ok(()) +} + +#[test] +fn test_addmul_bignum_all() -> Result<()> { + test_addmul_bignum(&prepare_two_bignums_random)?; + test_addmul_bignum(&prepare_two_bignums_max)?; + test_addmul_bignum(&prepare_two_bignums_min)?; + + Ok(()) +} + +#[test] +fn test_mul_bignum_all() -> Result<()> { + test_mul_bignum(&prepare_bignum_random)?; + test_mul_bignum(&prepare_bignum_max)?; + test_mul_bignum(&prepare_bignum_min)?; + + Ok(()) +} From 0fdd93b8ce1a3559aa9fa740bcbfaa0e87c96682 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Thu, 16 Feb 2023 11:54:18 -0800 Subject: [PATCH 021/121] cleanup --- evm/src/cpu/kernel/tests/bignum.rs | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/evm/src/cpu/kernel/tests/bignum.rs b/evm/src/cpu/kernel/tests/bignum.rs index 17dc5dda..12e8b357 100644 --- a/evm/src/cpu/kernel/tests/bignum.rs +++ b/evm/src/cpu/kernel/tests/bignum.rs @@ -1,7 +1,7 @@ use anyhow::Result; use ethereum_types::U256; use itertools::Itertools; -use num::{BigUint, Zero, One}; +use num::{BigUint, One, Zero}; use num_bigint::RandBigInt; use rand::Rng; @@ -100,8 +100,9 @@ fn prepare_two_bignums_diff(bit_size: usize) -> (BigUint, BigUint, U256, Vec(prepare_bignum_fn: &F) -> Result<()> -where F: Fn(usize) -> (BigUint, U256, Vec) { - +where + F: Fn(usize) -> (BigUint, U256, Vec), +{ let (a, length, memory) = prepare_bignum_fn(1000); let halved = a >> 1; @@ -125,7 +126,9 @@ where F: Fn(usize) -> (BigUint, U256, Vec) { } fn test_iszero_bignum(prepare_bignum_fn: &F) -> Result<()> -where F: Fn(usize) -> (BigUint, U256, Vec) { +where + F: Fn(usize) -> (BigUint, U256, Vec), +{ let (a, length, memory) = { let (a, length, memory) = prepare_bignum_fn(1000); while a == BigUint::zero() { @@ -163,7 +166,9 @@ where F: Fn(usize) -> (BigUint, U256, Vec) { } fn test_ge_bignum(prepare_two_bignums_fn: &F) -> Result<()> -where F: Fn(usize) -> (BigUint, BigUint, U256, Vec) { +where + F: Fn(usize) -> (BigUint, BigUint, U256, Vec), +{ let (_a, _b, length, memory) = prepare_two_bignums_fn(1000); let retdest = 0xDEADBEEFu32.into(); @@ -194,7 +199,9 @@ where F: Fn(usize) -> (BigUint, BigUint, U256, Vec) { } fn test_add_bignum(prepare_two_bignums_fn: &F) -> Result<()> -where F: Fn(usize) -> (BigUint, BigUint, U256, Vec) { +where + F: Fn(usize) -> (BigUint, BigUint, U256, Vec), +{ let (a, b, length, memory) = prepare_two_bignums_fn(1000); // Determine expected sum. @@ -228,7 +235,9 @@ where F: Fn(usize) -> (BigUint, BigUint, U256, Vec) { } fn test_addmul_bignum(prepare_two_bignums_fn: &F) -> Result<()> -where F: Fn(usize) -> (BigUint, BigUint, U256, Vec) { +where + F: Fn(usize) -> (BigUint, BigUint, U256, Vec), +{ let mut rng = rand::thread_rng(); let (a, b, length, mut memory) = prepare_two_bignums_fn(1000); let len: usize = length.try_into().unwrap(); @@ -270,7 +279,9 @@ where F: Fn(usize) -> (BigUint, BigUint, U256, Vec) { } fn test_mul_bignum(prepare_bignum_fn: &F) -> Result<()> -where F: Fn(usize) -> (BigUint, U256, Vec) { +where + F: Fn(usize) -> (BigUint, U256, Vec), +{ let (a, b, length, memory) = prepare_two_bignums_fn(1000); // Determine expected product. From 4f41218229aa342b957c59a23bb7e793e4c5ff6e Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Thu, 16 Feb 2023 11:54:27 -0800 Subject: [PATCH 022/121] cleanup --- evm/src/cpu/kernel/tests/bignum.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/evm/src/cpu/kernel/tests/bignum.rs b/evm/src/cpu/kernel/tests/bignum.rs index 12e8b357..d5735baf 100644 --- a/evm/src/cpu/kernel/tests/bignum.rs +++ b/evm/src/cpu/kernel/tests/bignum.rs @@ -337,9 +337,9 @@ fn test_iszero_bignum_all() -> Result<()> { #[test] fn test_ge_bignum_all() -> Result<()> { - test_ge_bignum(&prepare_bignum_random)?; - test_ge_bignum(&prepare_bignum_max)?; - test_ge_bignum(&prepare_bignum_min)?; + test_ge_bignum(&prepare_two_bignums_random)?; + test_ge_bignum(&prepare_two_bignums_max)?; + test_ge_bignum(&prepare_two_bignums_min)?; Ok(()) } From 1100445d9cdc2efb161eba40cc10f6b9e7036d85 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Thu, 16 Feb 2023 11:55:00 -0800 Subject: [PATCH 023/121] cleanup --- evm/src/cpu/kernel/tests/bignum.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/evm/src/cpu/kernel/tests/bignum.rs b/evm/src/cpu/kernel/tests/bignum.rs index d5735baf..b108ade8 100644 --- a/evm/src/cpu/kernel/tests/bignum.rs +++ b/evm/src/cpu/kernel/tests/bignum.rs @@ -278,9 +278,9 @@ where Ok(()) } -fn test_mul_bignum(prepare_bignum_fn: &F) -> Result<()> +fn test_mul_bignum(prepare_two_bignums_fn: &F: &F) -> Result<()> where - F: Fn(usize) -> (BigUint, U256, Vec), + F: Fn(usize) -> (BigUint, BigUint, U256, Vec), { let (a, b, length, memory) = prepare_two_bignums_fn(1000); From 3662e41df7b7ab966ecceecc6933663d59047e6c Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Thu, 16 Feb 2023 11:55:12 -0800 Subject: [PATCH 024/121] fixes --- evm/src/cpu/kernel/tests/bignum.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/evm/src/cpu/kernel/tests/bignum.rs b/evm/src/cpu/kernel/tests/bignum.rs index b108ade8..e71fac87 100644 --- a/evm/src/cpu/kernel/tests/bignum.rs +++ b/evm/src/cpu/kernel/tests/bignum.rs @@ -278,7 +278,7 @@ where Ok(()) } -fn test_mul_bignum(prepare_two_bignums_fn: &F: &F) -> Result<()> +fn test_mul_bignum(prepare_two_bignums_fn: &F) -> Result<()> where F: Fn(usize) -> (BigUint, BigUint, U256, Vec), { From 3a019f99af98de287c8799bd097c2bd7e94b6fa3 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Thu, 16 Feb 2023 11:55:44 -0800 Subject: [PATCH 025/121] fix --- evm/src/cpu/kernel/tests/bignum.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/evm/src/cpu/kernel/tests/bignum.rs b/evm/src/cpu/kernel/tests/bignum.rs index e71fac87..28d43739 100644 --- a/evm/src/cpu/kernel/tests/bignum.rs +++ b/evm/src/cpu/kernel/tests/bignum.rs @@ -364,9 +364,9 @@ fn test_addmul_bignum_all() -> Result<()> { #[test] fn test_mul_bignum_all() -> Result<()> { - test_mul_bignum(&prepare_bignum_random)?; - test_mul_bignum(&prepare_bignum_max)?; - test_mul_bignum(&prepare_bignum_min)?; + test_mul_bignum(&prepare_two_bignums_random)?; + test_mul_bignum(&prepare_two_bignums_max)?; + test_mul_bignum(&prepare_two_bignums_min)?; Ok(()) } From bac38f8276e41d579455fac6d69b531e9a037bf3 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Thu, 16 Feb 2023 11:56:54 -0800 Subject: [PATCH 026/121] fix --- evm/src/cpu/kernel/tests/bignum.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/evm/src/cpu/kernel/tests/bignum.rs b/evm/src/cpu/kernel/tests/bignum.rs index 28d43739..b6be9a70 100644 --- a/evm/src/cpu/kernel/tests/bignum.rs +++ b/evm/src/cpu/kernel/tests/bignum.rs @@ -129,12 +129,12 @@ fn test_iszero_bignum(prepare_bignum_fn: &F) -> Result<()> where F: Fn(usize) -> (BigUint, U256, Vec), { - let (a, length, memory) = { - let (a, length, memory) = prepare_bignum_fn(1000); + let (length, memory) = { + let (mut a, mut length, mut memory) = prepare_bignum_fn(1000); while a == BigUint::zero() { (a, length, memory) = prepare_bignum_fn(1000); } - (a, length, memory) + (length, memory) }; let retdest = 0xDEADBEEFu32.into(); From f2538fff418b83f6b4788521fffffce950c9d282 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Thu, 16 Feb 2023 12:23:54 -0800 Subject: [PATCH 027/121] cleanup --- evm/src/cpu/kernel/tests/bignum.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/evm/src/cpu/kernel/tests/bignum.rs b/evm/src/cpu/kernel/tests/bignum.rs index b6be9a70..cdb71f22 100644 --- a/evm/src/cpu/kernel/tests/bignum.rs +++ b/evm/src/cpu/kernel/tests/bignum.rs @@ -49,14 +49,14 @@ fn prepare_bignum_random(bit_size: usize) -> (BigUint, U256, Vec) { } fn prepare_bignum_max(bit_size: usize) -> (BigUint, U256, Vec) { - let a = BigUint::one() << bit_size - 1; + let a = BigUint::one() << (bit_size - 1); let length: U256 = bignum_len(&a).into(); let a_limbs = biguint_to_mem_vec(a.clone()); (a, length, a_limbs) } -fn prepare_bignum_min(bit_size: usize) -> (BigUint, U256, Vec) { +fn prepare_bignum_min(_bit_size: usize) -> (BigUint, U256, Vec) { let a = BigUint::zero(); let length: U256 = bignum_len(&a).into(); let a_limbs = biguint_to_mem_vec(a.clone()); @@ -73,15 +73,15 @@ fn prepare_two_bignums_random(bit_size: usize) -> (BigUint, BigUint, U256, Vec (BigUint, BigUint, U256, Vec) { - let a = BigUint::one() << bit_size - 1; - let b = BigUint::one() << bit_size - 2; + let a = BigUint::one() << (bit_size - 1); + let b = BigUint::one() << (bit_size - 2); let length: U256 = bignum_len(&a).into(); let memory = pack_bignums(&[a.clone(), b.clone()], length.try_into().unwrap()); (a, b, length, memory) } -fn prepare_two_bignums_min(bit_size: usize) -> (BigUint, BigUint, U256, Vec) { +fn prepare_two_bignums_min(_bit_size: usize) -> (BigUint, BigUint, U256, Vec) { let a = BigUint::one(); let b = BigUint::zero(); let length: U256 = bignum_len(&a).into(); @@ -91,7 +91,7 @@ fn prepare_two_bignums_min(bit_size: usize) -> (BigUint, BigUint, U256, Vec (BigUint, BigUint, U256, Vec) { - let a = BigUint::one() << bit_size - 1; + let a = BigUint::one() << (bit_size - 1); let b = BigUint::zero(); let length: U256 = bignum_len(&a).into(); let memory = pack_bignums(&[a.clone(), b.clone()], length.try_into().unwrap()); From 6d997a6566eb14111ebe7ebc81a1b9371eff8db3 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Thu, 16 Feb 2023 13:49:16 -0800 Subject: [PATCH 028/121] more tests --- evm/src/cpu/kernel/tests/bignum.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/evm/src/cpu/kernel/tests/bignum.rs b/evm/src/cpu/kernel/tests/bignum.rs index cdb71f22..ff92ac50 100644 --- a/evm/src/cpu/kernel/tests/bignum.rs +++ b/evm/src/cpu/kernel/tests/bignum.rs @@ -340,6 +340,7 @@ fn test_ge_bignum_all() -> Result<()> { test_ge_bignum(&prepare_two_bignums_random)?; test_ge_bignum(&prepare_two_bignums_max)?; test_ge_bignum(&prepare_two_bignums_min)?; + test_ge_bignum(&prepare_two_bignums_diff)?; Ok(()) } @@ -349,6 +350,7 @@ fn test_add_bignum_all() -> Result<()> { test_add_bignum(&prepare_two_bignums_random)?; test_add_bignum(&prepare_two_bignums_max)?; test_add_bignum(&prepare_two_bignums_min)?; + test_add_bignum(&prepare_two_bignums_diff)?; Ok(()) } @@ -358,6 +360,7 @@ fn test_addmul_bignum_all() -> Result<()> { test_addmul_bignum(&prepare_two_bignums_random)?; test_addmul_bignum(&prepare_two_bignums_max)?; test_addmul_bignum(&prepare_two_bignums_min)?; + test_addmul_bignum(&prepare_two_bignums_diff)?; Ok(()) } @@ -367,6 +370,7 @@ fn test_mul_bignum_all() -> Result<()> { test_mul_bignum(&prepare_two_bignums_random)?; test_mul_bignum(&prepare_two_bignums_max)?; test_mul_bignum(&prepare_two_bignums_min)?; + test_mul_bignum(&prepare_two_bignums_diff)?; Ok(()) } From fda2e19054e01c344e214d4ac6c580e97b3fe597 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Wed, 8 Mar 2023 12:13:38 -0800 Subject: [PATCH 029/121] restored blake2b_g_function and call_blake2b_g_function macros --- .../kernel/asm/hash/blake2b/g_functions.asm | 183 +++++++----------- 1 file changed, 68 insertions(+), 115 deletions(-) diff --git a/evm/src/cpu/kernel/asm/hash/blake2b/g_functions.asm b/evm/src/cpu/kernel/asm/hash/blake2b/g_functions.asm index ff3ee43a..782393de 100644 --- a/evm/src/cpu/kernel/asm/hash/blake2b/g_functions.asm +++ b/evm/src/cpu/kernel/asm/hash/blake2b/g_functions.asm @@ -1,89 +1,89 @@ -blake2b_g_function: +%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, retdest + // 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, retdest + // 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, retdest + // 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, retdest + // 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, retdest + // 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, retdest + // 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, retdest + // 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, retdest + // 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, retdest + // 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, retdest + // 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, retdest + // 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, retdest + // 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, retdest + // 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, retdest + // 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, retdest + // 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, retdest + // 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, retdest + // 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, retdest + // 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, retdest + // 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, retdest + // 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, retdest + // 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, retdest + // 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, retdest + // 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, retdest + // 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, retdest + // 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, retdest + // 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, retdest + // 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, retdest + // 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, retdest + // 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, retdest + // 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, retdest + // 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, retdest + // 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, retdest + // 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]'', retdest + // stack: start, a, v[a]'', start, b, v[b]'', start, c, v[c]'', start, d, v[d]'' ADD %mstore_kernel_general ADD @@ -92,100 +92,53 @@ blake2b_g_function: %mstore_kernel_general ADD %mstore_kernel_general - // stack: retdest - JUMP +%endmacro -call_blake2b_g_function: - // stack: a, b, c, d, x_idx, y_idx, round, start, retdest - DUP6 - // stack: y_idx, a, b, c, d, x_idx, y_idx, round, start, retdest - DUP8 - // stack: round, y_idx, a, b, c, d, x_idx, y_idx, round, start, retdest +%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], a, b, c, d, x_idx, y_idx, round, start, retdest + // stack: s[y_idx], round, start %blake2b_message_addr ADD %mload_kernel_general - // stack: m[s[y_idx]], a, b, c, d, x_idx, y_idx, round, start, retdest - DUP6 - // stack: x_idx, m[s[y_idx]], a, b, c, d, x_idx, y_idx, round, start, retdest - DUP9 - // stack: round, x_idx, m[s[y_idx]], a, b, c, d, x_idx, y_idx, round, start, retdest + // 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]], a, b, c, d, x_idx, y_idx, round, start, retdest + // 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]], a, b, c, d, x_idx, y_idx, round, start, retdest - %stack (mm: 2, abcd: 4, xy: 2, r, s) -> (abcd, mm, s) - // stack: a, b, c, d, m[s[x_idx]], m[s[y_idx]], start, retdest - %jump(blake2b_g_function) + // 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 -global run_g_function_round: +run_g_function_round: // stack: round, start, retdest - PUSH g_function_return_1 - // stack: g_function_return_1, round, start, retdest - %stack (ret, r, s) -> (0, 4, 8, 12, 0, 1, r, s, ret, r, s) - // stack: a=0, b=4, c=8, d=12, x_idx=0, y_idx=1, round, start, g_function_return_1, round, start, retdest - %jump(call_blake2b_g_function) -g_function_return_1: - // stack: round, start, retdest - PUSH g_function_return_2 - // stack: g_function_return_2, round, start, retdest - %stack (ret, r, s) -> (1, 5, 9, 13, 2, 3, r, s, ret, r, s) - // stack: a=1, b=5, c=9, d=13, x_idx=2, y_idx=3, round, start, g_function_return_2, round, start, retdest - %jump(call_blake2b_g_function) -g_function_return_2: - // stack: round, start, retdest - PUSH g_function_return_3 - // stack: g_function_return_3, round, start, retdest - %stack (ret, r, s) -> (2, 6, 10, 14, 4, 5, r, s, ret, r, s) - // stack: a=2, b=6, c=10, d=14, x_idx=4, y_idx=5, round, start, g_function_return_3, round, start, retdest - %jump(call_blake2b_g_function) -g_function_return_3: - // stack: round, start, retdest - PUSH g_function_return_4 - // stack: g_function_return_4, round, start, retdest - %stack (ret, r, s) -> (3, 7, 11, 15, 6, 7, r, s, ret, r, s) - // stack: a=3, b=7, c=11, d=15, x_idx=6, y_idx=7, round, start, g_function_return_4, round, start, retdest - %jump(call_blake2b_g_function) -g_function_return_4: - // stack: round, start, retdest - PUSH g_function_return_5 - // stack: g_function_return_5, round, start, retdest - %stack (ret, r, s) -> (0, 5, 10, 15, 8, 9, r, s, ret, r, s) - // stack: a=0, b=5, c=10, d=15, x_idx=8, y_idx=9, round, start, g_function_return_5, round, start, retdest - %jump(call_blake2b_g_function) -g_function_return_5: - // stack: round, start, retdest - PUSH g_function_return_6 - // stack: g_function_return_6, round, start, retdest - %stack (ret, r, s) -> (1, 6, 11, 12, 10, 11, r, s, ret, r, s) - // stack: a=1, b=6, c=11, d=12, x_idx=10, y_idx=11, round, start, g_function_return_6, round, start, retdest - %jump(call_blake2b_g_function) -g_function_return_6: - // stack: round, start, retdest - PUSH g_function_return_7 - // stack: g_function_return_7, round, start, retdest - %stack (ret, r, s) -> (2, 7, 8, 13, 12, 13, r, s, ret, r, s) - // stack: a=2, b=7, c=8, d=13, x_idx=12, y_idx=13, round, start, g_function_return_7, round, start, retdest - %jump(call_blake2b_g_function) -g_function_return_7: - // stack: round, start, retdest - PUSH g_function_return_8 - // stack: g_function_return_8, round, start, retdest - %stack (ret, r, s) -> (3, 4, 9, 14, 14, 15, r, s, ret, r, s) - // stack: a=3, b=4, c=9, d=14, x_idx=14, y_idx=15, round, start, g_function_return_8, round, start, retdest - %jump(call_blake2b_g_function) -g_function_return_8: - // stack: round, start, retdest - SWAP1 - // stack: start, round, retdest - SWAP2 + %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 (r, s, ret) -> (ret, r, s) // stack: retdest, round, start JUMP - global run_12_rounds_g_function: // stack: start, retdest PUSH 0 From 33ccf8987ea4bd346f2619f35ac1f71b05276781 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Wed, 8 Mar 2023 12:34:50 -0800 Subject: [PATCH 030/121] small optimizations --- .../kernel/asm/hash/blake2b/g_functions.asm | 32 ++++++++++++------- .../kernel/asm/hash/blake2b/permutations.asm | 25 +++++++++++---- 2 files changed, 39 insertions(+), 18 deletions(-) diff --git a/evm/src/cpu/kernel/asm/hash/blake2b/g_functions.asm b/evm/src/cpu/kernel/asm/hash/blake2b/g_functions.asm index 782393de..f2d3b1d2 100644 --- a/evm/src/cpu/kernel/asm/hash/blake2b/g_functions.asm +++ b/evm/src/cpu/kernel/asm/hash/blake2b/g_functions.asm @@ -3,28 +3,38 @@ // 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) + DUP4 + DUP4 + DUP4 + DUP4 // 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 + // stack: v[a], b, c, d, a, b, c, d, x, y, start + SWAP1 + // stack: b, v[a], c, d, a, b, c, d, x, y, start + DUP11 + // stack: start, b, v[a], c, 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 + // stack: v[b], v[a], c, d, a, b, c, d, x, y, start + SWAP2 + // stack: c, v[a], v[b], d, a, b, c, d, x, y, start + DUP11 + // stack: start, c, v[a], v[b], 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 + // stack: v[c], v[a], v[b], d, a, b, c, d, x, y, start + SWAP3 + // stack: d, v[a], v[b], v[c], a, b, c, d, x, y, start + DUP11 + // stack: start, d, v[a], v[b], v[c], a, b, c, d, x, y, start ADD %mload_kernel_general + // stack: v[d], v[a], v[b], v[c], a, b, c, d, x, y, start + %stack (vd, vs: 3) -> (vs, vd) // 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 diff --git a/evm/src/cpu/kernel/asm/hash/blake2b/permutations.asm b/evm/src/cpu/kernel/asm/hash/blake2b/permutations.asm index 5277e611..1ef455f1 100644 --- a/evm/src/cpu/kernel/asm/hash/blake2b/permutations.asm +++ b/evm/src/cpu/kernel/asm/hash/blake2b/permutations.asm @@ -58,17 +58,28 @@ global permutation_9_constants: BYTES 15, 11, 9, 14 BYTES 3, 12, 13, 0 -%macro blake2b_permutation - // stack: round, i +global blake2b_permutation: + // stack: i, round, retdest PUSH permutation_0_constants - // stack: permutation_0_constants, round, i - SWAP1 - // stack: round, permutation_1_constants, i + // stack: permutation_0_constants, i, round, retdest + SWAP2 + // stack: round, i, permutation_0_constants, retdest %mod_const(10) - // stack: round % 10, permutation_1_constants, i + // stack: round % 10, i, permutation_0_constants, retdest %mul_const(16) ADD - // stack: permutation_(round)_constants, i ADD %mload_kernel_code + // stack: permutation_(round%10)_constants[i], retdest + SWAP1 + JUMP + +%macro blake2b_permutation + // stack: round, i + PUSH %%after + // stack: %%after, round, i + SWAP2 + // stack: i, round, %%after + %jump(blake2b_permutation) +%%after: %endmacro From 9e7dc7ca79c2c4517f21694dab9cbbe4face5507 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Tue, 14 Mar 2023 12:18:16 -0700 Subject: [PATCH 031/121] addressed comments --- evm/src/cpu/kernel/asm/bignum/ge.asm | 3 ++- evm/src/cpu/kernel/asm/bignum/iszero.asm | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/evm/src/cpu/kernel/asm/bignum/ge.asm b/evm/src/cpu/kernel/asm/bignum/ge.asm index cdd7712f..e7f5aca2 100644 --- a/evm/src/cpu/kernel/asm/bignum/ge.asm +++ b/evm/src/cpu/kernel/asm/bignum/ge.asm @@ -1,7 +1,8 @@ // Arithmetic on little-endian integers represented with 128-bit limbs. // All integers must be under a given length bound, and are padded with leading zeroes. -// Returns a >= b. +// Compares two bignums of the same given length. Assumes that len > 0. +// Returns 1 if a > b, 3 if a == b, and 0 if a < b. global ge_bignum: // stack: len, a_start_loc, b_start_loc, retdest SWAP1 diff --git a/evm/src/cpu/kernel/asm/bignum/iszero.asm b/evm/src/cpu/kernel/asm/bignum/iszero.asm index ff755270..2f742f77 100644 --- a/evm/src/cpu/kernel/asm/bignum/iszero.asm +++ b/evm/src/cpu/kernel/asm/bignum/iszero.asm @@ -3,6 +3,10 @@ global iszero_bignum: // stack: len, start_loc, retdest + DUP1 + // stack: len, len, start_loc, retdest + ISZERO + %jumpi(eqzero) DUP2 // stack: start_loc, len, start_loc, retdest ADD From 04f44ef4da1a5781c5da6b6a170de95e288adaf2 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Tue, 14 Mar 2023 12:19:13 -0700 Subject: [PATCH 032/121] addressed comments --- evm/src/cpu/kernel/asm/bignum/add.asm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/evm/src/cpu/kernel/asm/bignum/add.asm b/evm/src/cpu/kernel/asm/bignum/add.asm index d38c9701..038c7675 100644 --- a/evm/src/cpu/kernel/asm/bignum/add.asm +++ b/evm/src/cpu/kernel/asm/bignum/add.asm @@ -1,7 +1,8 @@ // Arithmetic on little-endian integers represented with 128-bit limbs. // All integers must be under a given length bound, and are padded with leading zeroes. -// Replaces a with a + b, leaving b unchanged. +// Adds two bignums of the same given length. Assumes that len > 0. +// Replaces a with a + b, leaving b unchanged, and returns the final carry. global add_bignum: // stack: len, a_start_loc, b_start_loc, retdest PUSH 0 From 87ad5714aa8938633a7e210c5fa4308296bcb87c Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Tue, 14 Mar 2023 12:20:38 -0700 Subject: [PATCH 033/121] addressed comments --- evm/src/cpu/kernel/asm/bignum/shr.asm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/evm/src/cpu/kernel/asm/bignum/shr.asm b/evm/src/cpu/kernel/asm/bignum/shr.asm index 69d32b07..5e3a56ef 100644 --- a/evm/src/cpu/kernel/asm/bignum/shr.asm +++ b/evm/src/cpu/kernel/asm/bignum/shr.asm @@ -2,6 +2,7 @@ // All integers must be under a given length bound, and are padded with leading zeroes. // Shifts a given bignum right by one bit (in place). +// Assumes that len > 0. global shr_bignum: // stack: len, start_loc, retdest DUP2 @@ -30,7 +31,7 @@ shr_loop: // stack: carry, a[i] >> 1, i, new_carry, start_loc, retdest %shl_const(127) // stack: carry << 127, a[i] >> 1, i, new_carry, start_loc, retdest - OR + ADD // stack: carry << 127 | a[i] >> 1, i, new_carry, start_loc, retdest DUP2 // stack: i, carry << 127 | a[i] >> 1, i, new_carry, start_loc, retdest From 476a554aea93dc1f399cf87ea4900b6fb780cf42 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Tue, 14 Mar 2023 12:29:30 -0700 Subject: [PATCH 034/121] OR -> ADD --- .../kernel/asm/curve/secp256k1/ecrecover.asm | 14 ++++------ evm/src/cpu/kernel/asm/hash/blake2b/iv.asm | 2 +- .../cpu/kernel/asm/hash/ripemd/functions.asm | 2 +- evm/src/cpu/kernel/asm/hash/ripemd/main.asm | 8 +++--- .../cpu/kernel/asm/hash/sha2/compression.asm | 14 +++++----- evm/src/cpu/kernel/asm/memory/core.asm | 28 +++++++++---------- evm/src/cpu/kernel/asm/util/basic_macros.asm | 10 +++---- 7 files changed, 37 insertions(+), 41 deletions(-) diff --git a/evm/src/cpu/kernel/asm/curve/secp256k1/ecrecover.asm b/evm/src/cpu/kernel/asm/curve/secp256k1/ecrecover.asm index dd2b86f6..c243a748 100644 --- a/evm/src/cpu/kernel/asm/curve/secp256k1/ecrecover.asm +++ b/evm/src/cpu/kernel/asm/curve/secp256k1/ecrecover.asm @@ -134,17 +134,13 @@ pubkey_to_addr: // stack: hash, v, r, s, retdest DUP2 // stack: v, hash, v, r, s, retdest - PUSH 27 - // stack: 27, v, hash, v, r, s, retdest - EQ + %eq_consts(27) // stack: v==27, hash, v, r, s, retdest DUP3 // stack: v, v==27, hash, v, r, s, retdest - PUSH 28 - // stack: 28, v, v==27, hash, v, r, s, retdest - EQ + %eq_consts(28) // stack: v==28, v==27, hash, v, r, s, retdest - OR + ADD // OR // stack: (v==28 || v==27), hash, v, r, s, retdest DUP5 // stack: s, (v==28 || v==27), hash, v, r, s, retdest @@ -154,7 +150,7 @@ pubkey_to_addr: // stack: r, (s >= N || s==0), (v==28 || v==27), hash, v, r, s, retdest %secp_is_out_of_bounds // stack: (r >= N || r==0), (s >= N || s==0), (v==28 || v==27), hash, v, r, s, retdest - OR + ADD // OR // stack: (r >= N || r==0 || s >= N || s==0), (v==28 || v==27), hash, v, r, s, retdest ISZERO // stack: (r < N & r!=0 & s < N & s!=0), (v==28 || v==27), hash, v, r, s, retdest @@ -178,7 +174,7 @@ pubkey_to_addr: // stack: x < N, x==0 ISZERO // stack: x >= N, x==0 - OR + ADD // OR // stack: x >= N || x==0 %endmacro diff --git a/evm/src/cpu/kernel/asm/hash/blake2b/iv.asm b/evm/src/cpu/kernel/asm/hash/blake2b/iv.asm index 174afd33..94e9ba27 100644 --- a/evm/src/cpu/kernel/asm/hash/blake2b/iv.asm +++ b/evm/src/cpu/kernel/asm/hash/blake2b/iv.asm @@ -52,7 +52,7 @@ global blake2b_iv_const: // stack: IV_i[32:], IV_i[:32], ... %shl_const(32) // stack: IV_i[32:] << 32, IV_i[:32], ... - OR + ADD // OR // stack: IV_i, ... %endmacro diff --git a/evm/src/cpu/kernel/asm/hash/ripemd/functions.asm b/evm/src/cpu/kernel/asm/hash/ripemd/functions.asm index ac111215..de2fdcf6 100644 --- a/evm/src/cpu/kernel/asm/hash/ripemd/functions.asm +++ b/evm/src/cpu/kernel/asm/hash/ripemd/functions.asm @@ -18,7 +18,7 @@ global rol: // stack: x << n, x >> (32-n), retdest %as_u32 // stack: u32(x << n), x >> (32-n), retdest - OR + ADD // OR // stack: u32(x << n) | (x >> (32-n)), retdest SWAP1 JUMP diff --git a/evm/src/cpu/kernel/asm/hash/ripemd/main.asm b/evm/src/cpu/kernel/asm/hash/ripemd/main.asm index 4aa6a6ad..0ad1e4e5 100644 --- a/evm/src/cpu/kernel/asm/hash/ripemd/main.asm +++ b/evm/src/cpu/kernel/asm/hash/ripemd/main.asm @@ -81,21 +81,21 @@ process: SWAP1 %reverse_bytes_u32 %shl_const(96) - OR + ADD // OR // stack: b' a', c, d, e, VARS SWAP1 %reverse_bytes_u32 %shl_const(64) - OR + ADD // OR // stack: c' b' a', d, e, VARS SWAP1 %reverse_bytes_u32 %shl_const(32) - OR + ADD // OR // stack: d' c' b' a', e, VARS SWAP1 %reverse_bytes_u32 - OR + ADD // OR // stack: e' d' c' b' a', VARS %stack (result, VARS: 3, retdest) -> (retdest, result) // stack: 0xdeadbeef, result diff --git a/evm/src/cpu/kernel/asm/hash/sha2/compression.asm b/evm/src/cpu/kernel/asm/hash/sha2/compression.asm index 8850c1c8..8c219ebb 100644 --- a/evm/src/cpu/kernel/asm/hash/sha2/compression.asm +++ b/evm/src/cpu/kernel/asm/hash/sha2/compression.asm @@ -263,19 +263,19 @@ compression_end: POP // stack: a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], e[0]+e[64], f[0]+f[64], g[0]+g[64], h[0]+h[64], scratch_space_addr, message_schedule_addr, i, retdest %shl_const(32) - OR + ADD // OR %shl_const(32) - OR + ADD // OR %shl_const(32) - OR + ADD // OR %shl_const(32) - OR + ADD // OR %shl_const(32) - OR + ADD // OR %shl_const(32) - OR + ADD // OR %shl_const(32) - OR + ADD // OR // stack: concat(a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], e[0]+e[64], f[0]+f[64], g[0]+g[64], h[0]+h[64]), scratch_space_addr, message_schedule_addr, i, retdest SWAP3 // stack: i, scratch_space_addr, message_schedule_addr, concat(a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], e[0]+e[64], f[0]+f[64], g[0]+g[64], h[0]+h[64]), retdest diff --git a/evm/src/cpu/kernel/asm/memory/core.asm b/evm/src/cpu/kernel/asm/memory/core.asm index a979f930..8f59a128 100644 --- a/evm/src/cpu/kernel/asm/memory/core.asm +++ b/evm/src/cpu/kernel/asm/memory/core.asm @@ -79,21 +79,21 @@ DUP2 %increment %mload_kernel($segment) - OR + ADD // OR // stack: (c_3 << 8) | c_2, offset %shl_const(8) // stack: ((c_3 << 8) | c_2) << 8, offset DUP2 %add_const(2) %mload_kernel($segment) - OR + ADD // OR // stack: (((c_3 << 8) | c_2) << 8) | c_1, offset %shl_const(8) // stack: ((((c_3 << 8) | c_2) << 8) | c_1) << 8, offset SWAP1 %add_const(3) %mload_kernel($segment) - OR + ADD // OR // stack: (((((c_3 << 8) | c_2) << 8) | c_1) << 8) | c_0 %endmacro @@ -107,19 +107,19 @@ %increment %mload_kernel($segment) %shl_const(8) - OR + ADD // stack: c0 | (c1 << 8) , offset DUP2 %add_const(2) %mload_kernel($segment) %shl_const(16) - OR + ADD // stack: c0 | (c1 << 8) | (c2 << 16), offset SWAP1 %add_const(3) %mload_kernel($segment) %shl_const(24) - OR + ADD // OR // stack: c0 | (c1 << 8) | (c2 << 16) | (c3 << 24) %endmacro @@ -137,7 +137,7 @@ // stack: hi, lo %shl_const(32) // stack: hi << 32, lo - OR + ADD // OR // stack: (hi << 32) | lo %endmacro @@ -152,49 +152,49 @@ DUP2 %add_const(4) %mload_kernel_u32($segment) - OR + ADD // OR // stack: (c_7 << 32) | c_6, offset %shl_const(32) // stack: ((c_7 << 32) | c_6) << 32, offset DUP2 %add_const(8) %mload_kernel_u32($segment) - OR + ADD // OR // stack: (c_7 << 64) | (c_6 << 32) | c_5, offset %shl_const(32) // stack: ((c_7 << 64) | (c_6 << 32) | c_5) << 32, offset DUP2 %add_const(12) %mload_kernel_u32($segment) - OR + ADD // OR // stack: (c_7 << 96) | (c_6 << 64) | (c_5 << 32) | c_4, offset %shl_const(32) // stack: ((c_7 << 96) | (c_6 << 64) | (c_5 << 32) | c_4) << 32, offset DUP2 %add_const(16) %mload_kernel_u32($segment) - OR + ADD // OR // stack: (c_7 << 128) | (c_6 << 96) | (c_5 << 64) | (c_4 << 32) | c_3, offset %shl_const(32) // stack: ((c_7 << 128) | (c_6 << 96) | (c_5 << 64) | (c_4 << 32) | c_3) << 32, offset DUP2 %add_const(20) %mload_kernel_u32($segment) - OR + ADD // OR // stack: (c_7 << 160) | (c_6 << 128) | (c_5 << 96) | (c_4 << 64) | (c_3 << 32) | c_2, offset %shl_const(32) // stack: ((c_7 << 160) | (c_6 << 128) | (c_5 << 96) | (c_4 << 64) | (c_3 << 32) | c_2) << 32, offset DUP2 %add_const(24) %mload_kernel_u32($segment) - OR + ADD // OR // stack: (c_7 << 192) | (c_6 << 160) | (c_5 << 128) | (c_4 << 96) | (c_3 << 64) | (c_2 << 32) | c_1, offset %shl_const(32) // stack: ((c_7 << 192) | (c_6 << 160) | (c_5 << 128) | (c_4 << 96) | (c_3 << 64) | (c_2 << 32) | c_1) << 32, offset DUP2 %add_const(28) %mload_kernel_u32($segment) - OR + ADD // OR // stack: (c_7 << 224) | (c_6 << 192) | (c_5 << 160) | (c_4 << 128) | (c_3 << 96) | (c_2 << 64) | (c_1 << 32) | c_0, offset SWAP1 POP diff --git a/evm/src/cpu/kernel/asm/util/basic_macros.asm b/evm/src/cpu/kernel/asm/util/basic_macros.asm index 5ee4a1e7..52556d3f 100644 --- a/evm/src/cpu/kernel/asm/util/basic_macros.asm +++ b/evm/src/cpu/kernel/asm/util/basic_macros.asm @@ -309,9 +309,9 @@ BYTE %shl_const(24) // stack: d000, b0, a, c00 - OR - OR - OR + ADD // OR + ADD // OR + ADD // OR // stack: dcba %endmacro @@ -332,7 +332,7 @@ %reverse_bytes_u32 // stack: word_lo_inverted, word_hi_inverted %shl_const(32) - OR + ADD // OR // stack: word_inverted %endmacro @@ -341,7 +341,7 @@ // stack: a, b, c, d %rep 3 %shl_const(64) - OR + ADD // OR %endrep // stack: a || b || c || d %endmacro From 676a483c06c4ec004def5f9ed45eacddb7d34310 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Tue, 14 Mar 2023 12:34:51 -0700 Subject: [PATCH 035/121] fix --- evm/src/cpu/kernel/asm/curve/secp256k1/ecrecover.asm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/evm/src/cpu/kernel/asm/curve/secp256k1/ecrecover.asm b/evm/src/cpu/kernel/asm/curve/secp256k1/ecrecover.asm index c243a748..11ec27c8 100644 --- a/evm/src/cpu/kernel/asm/curve/secp256k1/ecrecover.asm +++ b/evm/src/cpu/kernel/asm/curve/secp256k1/ecrecover.asm @@ -134,11 +134,11 @@ pubkey_to_addr: // stack: hash, v, r, s, retdest DUP2 // stack: v, hash, v, r, s, retdest - %eq_consts(27) + %eq_const(27) // stack: v==27, hash, v, r, s, retdest DUP3 // stack: v, v==27, hash, v, r, s, retdest - %eq_consts(28) + %eq_const(28) // stack: v==28, v==27, hash, v, r, s, retdest ADD // OR // stack: (v==28 || v==27), hash, v, r, s, retdest From 2000d308f86ad32448ab99b70ef72f3ea5d1ef11 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Tue, 14 Mar 2023 14:03:59 -0700 Subject: [PATCH 036/121] addressed comments --- evm/src/cpu/kernel/tests/bignum.rs | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/evm/src/cpu/kernel/tests/bignum.rs b/evm/src/cpu/kernel/tests/bignum.rs index ff92ac50..eb1726db 100644 --- a/evm/src/cpu/kernel/tests/bignum.rs +++ b/evm/src/cpu/kernel/tests/bignum.rs @@ -3,12 +3,15 @@ use ethereum_types::U256; use itertools::Itertools; use num::{BigUint, One, Zero}; use num_bigint::RandBigInt; +use plonky2_util::ceil_div_usize; use rand::Rng; use crate::cpu::kernel::aggregator::KERNEL; use crate::cpu::kernel::interpreter::Interpreter; use crate::util::{biguint_to_mem_vec, mem_vec_to_biguint}; +const BIGNUM_LIMB_BITS: usize = 128; + fn pack_bignums(biguints: &[BigUint], length: usize) -> Vec { biguints .iter() @@ -26,18 +29,13 @@ fn gen_bignum(bit_size: usize) -> BigUint { } fn bignum_len(a: &BigUint) -> usize { - (a.bits() as usize) / 128 + 1 + a.bits() as usize / BIGNUM_LIMB_BITS + 1 } fn gen_two_bignums_ordered(bit_size: usize) -> (BigUint, BigUint) { let mut rng = rand::thread_rng(); - let (a, b) = { - let a = rng.gen_biguint(bit_size as u64); - let b = rng.gen_biguint(bit_size as u64); - (a.clone().max(b.clone()), a.min(b)) - }; - - (a, b) + let (a, b) = (rng.gen_biguint(bit_size as u64), rng.gen_biguint(bit_size as u64)); + if b < a { (a, b) } else { (b, a) } } fn prepare_bignum_random(bit_size: usize) -> (BigUint, U256, Vec) { @@ -49,7 +47,7 @@ fn prepare_bignum_random(bit_size: usize) -> (BigUint, U256, Vec) { } fn prepare_bignum_max(bit_size: usize) -> (BigUint, U256, Vec) { - let a = BigUint::one() << (bit_size - 1); + let a = (BigUint::one() << bit_size) - BigUint::one(); let length: U256 = bignum_len(&a).into(); let a_limbs = biguint_to_mem_vec(a.clone()); @@ -73,8 +71,8 @@ fn prepare_two_bignums_random(bit_size: usize) -> (BigUint, BigUint, U256, Vec (BigUint, BigUint, U256, Vec) { - let a = BigUint::one() << (bit_size - 1); - let b = BigUint::one() << (bit_size - 2); + let a = (BigUint::one() << bit_size) - BigUint::one(); + let b = (BigUint::one() << bit_size) - BigUint::from(2u8); let length: U256 = bignum_len(&a).into(); let memory = pack_bignums(&[a.clone(), b.clone()], length.try_into().unwrap()); From c4b511baf457933adc315a7ebad3a0c2e0fa3e2a Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Tue, 14 Mar 2023 14:28:21 -0700 Subject: [PATCH 037/121] addressed comments --- evm/src/cpu/kernel/asm/bignum/shr.asm | 10 ++++++++++ evm/src/cpu/kernel/interpreter.rs | 4 +++- evm/src/cpu/kernel/tests/bignum.rs | 2 +- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/evm/src/cpu/kernel/asm/bignum/shr.asm b/evm/src/cpu/kernel/asm/bignum/shr.asm index 5e3a56ef..399b372e 100644 --- a/evm/src/cpu/kernel/asm/bignum/shr.asm +++ b/evm/src/cpu/kernel/asm/bignum/shr.asm @@ -4,6 +4,11 @@ // Shifts a given bignum right by one bit (in place). // Assumes that len > 0. global shr_bignum: + // stack: len, start_loc, retdest + DUP1 + // stack: len, len, start_loc, retdest + ISZERO + %jumpi(shr_end_len_zero) // stack: len, start_loc, retdest DUP2 // stack: start_loc, len, start_loc, retdest @@ -55,3 +60,8 @@ shr_end: %pop3 // stack: retdest JUMP +shr_end_len_zero: + // stack: len, start_loc, retdest + %pop2 + // stack: retdest + JUMP diff --git a/evm/src/cpu/kernel/interpreter.rs b/evm/src/cpu/kernel/interpreter.rs index b0d3a784..d856bc2b 100644 --- a/evm/src/cpu/kernel/interpreter.rs +++ b/evm/src/cpu/kernel/interpreter.rs @@ -770,7 +770,9 @@ impl<'a> Interpreter<'a> { fn run_mload_general(&mut self) { let context = self.pop().as_usize(); let segment = Segment::all()[self.pop().as_usize()]; - let offset = self.pop().as_usize(); + let x = self.pop(); + dbg!(x); + let offset = x.as_usize(); let value = self .generation_state .memory diff --git a/evm/src/cpu/kernel/tests/bignum.rs b/evm/src/cpu/kernel/tests/bignum.rs index eb1726db..ce030b54 100644 --- a/evm/src/cpu/kernel/tests/bignum.rs +++ b/evm/src/cpu/kernel/tests/bignum.rs @@ -29,7 +29,7 @@ fn gen_bignum(bit_size: usize) -> BigUint { } fn bignum_len(a: &BigUint) -> usize { - a.bits() as usize / BIGNUM_LIMB_BITS + 1 + ceil_div_usize(a.bits() as usize, BIGNUM_LIMB_BITS) } fn gen_two_bignums_ordered(bit_size: usize) -> (BigUint, BigUint) { From 4a76255341358ce6e03646c2ac3a0ded343beb03 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Tue, 14 Mar 2023 14:37:20 -0700 Subject: [PATCH 038/121] name change --- evm/src/cpu/kernel/tests/bignum.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/evm/src/cpu/kernel/tests/bignum.rs b/evm/src/cpu/kernel/tests/bignum.rs index ce030b54..704989c6 100644 --- a/evm/src/cpu/kernel/tests/bignum.rs +++ b/evm/src/cpu/kernel/tests/bignum.rs @@ -12,7 +12,7 @@ use crate::util::{biguint_to_mem_vec, mem_vec_to_biguint}; const BIGNUM_LIMB_BITS: usize = 128; -fn pack_bignums(biguints: &[BigUint], length: usize) -> Vec { +fn pad_bignums(biguints: &[BigUint], length: usize) -> Vec { biguints .iter() .flat_map(|biguint| { @@ -65,7 +65,7 @@ fn prepare_bignum_min(_bit_size: usize) -> (BigUint, U256, Vec) { fn prepare_two_bignums_random(bit_size: usize) -> (BigUint, BigUint, U256, Vec) { let (a, b) = gen_two_bignums_ordered(bit_size); let length: U256 = bignum_len(&a).into(); - let memory = pack_bignums(&[a.clone(), b.clone()], length.try_into().unwrap()); + let memory = pad_bignums(&[a.clone(), b.clone()], length.try_into().unwrap()); (a, b, length, memory) } @@ -74,7 +74,7 @@ fn prepare_two_bignums_max(bit_size: usize) -> (BigUint, BigUint, U256, Vec (BigUint, BigUint, U256, Vec (BigUint, BigUint, U256, Vec Date: Tue, 14 Mar 2023 14:37:47 -0700 Subject: [PATCH 039/121] cleanup --- evm/src/cpu/kernel/tests/bignum.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/evm/src/cpu/kernel/tests/bignum.rs b/evm/src/cpu/kernel/tests/bignum.rs index 704989c6..db4faebd 100644 --- a/evm/src/cpu/kernel/tests/bignum.rs +++ b/evm/src/cpu/kernel/tests/bignum.rs @@ -34,8 +34,15 @@ fn bignum_len(a: &BigUint) -> usize { fn gen_two_bignums_ordered(bit_size: usize) -> (BigUint, BigUint) { let mut rng = rand::thread_rng(); - let (a, b) = (rng.gen_biguint(bit_size as u64), rng.gen_biguint(bit_size as u64)); - if b < a { (a, b) } else { (b, a) } + let (a, b) = ( + rng.gen_biguint(bit_size as u64), + rng.gen_biguint(bit_size as u64), + ); + if b < a { + (a, b) + } else { + (b, a) + } } fn prepare_bignum_random(bit_size: usize) -> (BigUint, U256, Vec) { From d4c7bfd59262b5b608eb71b09d0217191a489eac Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Tue, 14 Mar 2023 15:15:19 -0700 Subject: [PATCH 040/121] addressed comments --- evm/src/cpu/kernel/asm/bignum/mul.asm | 1 + evm/src/cpu/kernel/interpreter.rs | 4 +--- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/evm/src/cpu/kernel/asm/bignum/mul.asm b/evm/src/cpu/kernel/asm/bignum/mul.asm index d62ce907..cc53c3a0 100644 --- a/evm/src/cpu/kernel/asm/bignum/mul.asm +++ b/evm/src/cpu/kernel/asm/bignum/mul.asm @@ -45,6 +45,7 @@ mul_return: // stack: n-1, len, a_start_loc, bi+1, output_cur+1, retdest DUP1 // stack: n-1, n-1, len, a_start_loc, bi+1, output_cur+1, retdest + STOP %jumpi(mul_loop) mul_end: // stack: n-1, len, a_start_loc, bi+1, output_cur+1, retdest diff --git a/evm/src/cpu/kernel/interpreter.rs b/evm/src/cpu/kernel/interpreter.rs index d856bc2b..b0d3a784 100644 --- a/evm/src/cpu/kernel/interpreter.rs +++ b/evm/src/cpu/kernel/interpreter.rs @@ -770,9 +770,7 @@ impl<'a> Interpreter<'a> { fn run_mload_general(&mut self) { let context = self.pop().as_usize(); let segment = Segment::all()[self.pop().as_usize()]; - let x = self.pop(); - dbg!(x); - let offset = x.as_usize(); + let offset = self.pop().as_usize(); let value = self .generation_state .memory From 4b6a51469f7e123f230f888133e62fb7cacf4146 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Tue, 14 Mar 2023 15:21:25 -0700 Subject: [PATCH 041/121] fix --- evm/src/cpu/kernel/asm/bignum/mul.asm | 1 - 1 file changed, 1 deletion(-) diff --git a/evm/src/cpu/kernel/asm/bignum/mul.asm b/evm/src/cpu/kernel/asm/bignum/mul.asm index cc53c3a0..d62ce907 100644 --- a/evm/src/cpu/kernel/asm/bignum/mul.asm +++ b/evm/src/cpu/kernel/asm/bignum/mul.asm @@ -45,7 +45,6 @@ mul_return: // stack: n-1, len, a_start_loc, bi+1, output_cur+1, retdest DUP1 // stack: n-1, n-1, len, a_start_loc, bi+1, output_cur+1, retdest - STOP %jumpi(mul_loop) mul_end: // stack: n-1, len, a_start_loc, bi+1, output_cur+1, retdest From d23e4e20b6a8a253afa13fcf6cd879eb6e42ed8a Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Tue, 14 Mar 2023 15:33:36 -0700 Subject: [PATCH 042/121] deal with and test zero-len case --- evm/src/cpu/kernel/asm/bignum/add.asm | 13 +++++++++++++ evm/src/cpu/kernel/asm/bignum/addmul.asm | 12 ++++++++++++ evm/src/cpu/kernel/asm/bignum/mul.asm | 9 +++++++++ evm/src/cpu/kernel/asm/bignum/shr.asm | 4 ++-- evm/src/cpu/kernel/tests/bignum.rs | 12 ++++++++++++ 5 files changed, 48 insertions(+), 2 deletions(-) diff --git a/evm/src/cpu/kernel/asm/bignum/add.asm b/evm/src/cpu/kernel/asm/bignum/add.asm index 038c7675..64293f11 100644 --- a/evm/src/cpu/kernel/asm/bignum/add.asm +++ b/evm/src/cpu/kernel/asm/bignum/add.asm @@ -4,6 +4,11 @@ // Adds two bignums of the same given length. Assumes that len > 0. // Replaces a with a + b, leaving b unchanged, and returns the final carry. global add_bignum: + // stack: len, a_start_loc, b_start_loc, retdest + DUP1 + // stack: len, len, a_start_loc, b_start_loc, retdest + ISZERO + %jumpi(len_zero) // stack: len, a_start_loc, b_start_loc, retdest PUSH 0 // stack: carry=0, i=len, a_cur_loc=a_start_loc, b_cur_loc=b_start_loc, retdest @@ -55,3 +60,11 @@ add_end: SWAP1 // stack: retdest, carry_new JUMP +len_zero: + // stack: len, a_start_loc, b_start_loc, retdest + %pop3 + // stack: retdest + PUSH 0 + // stack: carry=0, retdest + SWAP1 + JUMP \ No newline at end of file diff --git a/evm/src/cpu/kernel/asm/bignum/addmul.asm b/evm/src/cpu/kernel/asm/bignum/addmul.asm index e1bd3bf2..9e4ce2ba 100644 --- a/evm/src/cpu/kernel/asm/bignum/addmul.asm +++ b/evm/src/cpu/kernel/asm/bignum/addmul.asm @@ -4,6 +4,10 @@ // Sets a[0:len] += b[0:len] * val, and returns the carry. global addmul_bignum: // stack: len, a_start_loc, b_start_loc, val, retdest + DUP1 + // stack: len, len, a_start_loc, b_start_loc, val, retdest + ISZERO + %jumpi(len_zero) PUSH 0 // stack: carry=0, i=len, a_cur_loc=a_start_loc, b_cur_loc=b_start_loc, val, retdest addmul_loop: @@ -97,3 +101,11 @@ addmul_end: SWAP1 // stack: retdest, carry_new JUMP +len_zero: + // stack: len, a_start_loc, b_start_loc, val, retdest + %pop4 + // stack: retdest + PUSH 0 + // stack: carry=0, retdest + SWAP1 + JUMP diff --git a/evm/src/cpu/kernel/asm/bignum/mul.asm b/evm/src/cpu/kernel/asm/bignum/mul.asm index d62ce907..cbf6a645 100644 --- a/evm/src/cpu/kernel/asm/bignum/mul.asm +++ b/evm/src/cpu/kernel/asm/bignum/mul.asm @@ -7,6 +7,10 @@ global mul_bignum: // stack: len, a_start_loc, b_start_loc, output_loc, retdest DUP1 + // stack: len, len, a_start_loc, b_start_loc, output_loc, retdest + ISZERO + %jumpi(len_zero) + DUP1 // stack: n=len, len, a_start_loc, bi=b_start_loc, output_cur=output_loc, retdest mul_loop: // stack: n, len, a_start_loc, bi, output_cur, retdest @@ -51,3 +55,8 @@ mul_end: %pop5 // stack: retdest JUMP +len_zero: + // stack: len, a_start_loc, b_start_loc, output_loc, retdest + %pop4 + // stack: retdest + JUMP diff --git a/evm/src/cpu/kernel/asm/bignum/shr.asm b/evm/src/cpu/kernel/asm/bignum/shr.asm index 399b372e..42f5cd3b 100644 --- a/evm/src/cpu/kernel/asm/bignum/shr.asm +++ b/evm/src/cpu/kernel/asm/bignum/shr.asm @@ -8,7 +8,7 @@ global shr_bignum: DUP1 // stack: len, len, start_loc, retdest ISZERO - %jumpi(shr_end_len_zero) + %jumpi(len_zero) // stack: len, start_loc, retdest DUP2 // stack: start_loc, len, start_loc, retdest @@ -60,7 +60,7 @@ shr_end: %pop3 // stack: retdest JUMP -shr_end_len_zero: +len_zero: // stack: len, start_loc, retdest %pop2 // stack: retdest diff --git a/evm/src/cpu/kernel/tests/bignum.rs b/evm/src/cpu/kernel/tests/bignum.rs index db4faebd..141761ba 100644 --- a/evm/src/cpu/kernel/tests/bignum.rs +++ b/evm/src/cpu/kernel/tests/bignum.rs @@ -104,6 +104,15 @@ fn prepare_two_bignums_diff(bit_size: usize) -> (BigUint, BigUint, U256, Vec (BigUint, BigUint, U256, Vec) { + let a = BigUint::zero(); + let b = BigUint::zero(); + let length: U256 = bignum_len(&a).into(); + let memory = pad_bignums(&[a.clone(), b.clone()], length.try_into().unwrap()); + + (a, b, length, memory) +} + fn test_shr_bignum(prepare_bignum_fn: &F) -> Result<()> where F: Fn(usize) -> (BigUint, U256, Vec), @@ -356,6 +365,7 @@ fn test_add_bignum_all() -> Result<()> { test_add_bignum(&prepare_two_bignums_max)?; test_add_bignum(&prepare_two_bignums_min)?; test_add_bignum(&prepare_two_bignums_diff)?; + test_add_bignum(&prepare_two_bignums_zero)?; Ok(()) } @@ -366,6 +376,7 @@ fn test_addmul_bignum_all() -> Result<()> { test_addmul_bignum(&prepare_two_bignums_max)?; test_addmul_bignum(&prepare_two_bignums_min)?; test_addmul_bignum(&prepare_two_bignums_diff)?; + test_addmul_bignum(&prepare_two_bignums_zero)?; Ok(()) } @@ -376,6 +387,7 @@ fn test_mul_bignum_all() -> Result<()> { test_mul_bignum(&prepare_two_bignums_max)?; test_mul_bignum(&prepare_two_bignums_min)?; test_mul_bignum(&prepare_two_bignums_diff)?; + test_mul_bignum(&prepare_two_bignums_zero)?; Ok(()) } From 9ad25b2aac5b86439575ccfaf257bd271bcde28d Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Tue, 7 Mar 2023 11:06:49 -0800 Subject: [PATCH 043/121] optimizations --- .../kernel/asm/hash/blake2b/compression.asm | 29 +-- .../kernel/asm/hash/blake2b/g_functions.asm | 205 +++++++++++++----- 2 files changed, 154 insertions(+), 80 deletions(-) diff --git a/evm/src/cpu/kernel/asm/hash/blake2b/compression.asm b/evm/src/cpu/kernel/asm/hash/blake2b/compression.asm index a25158d9..840d8c54 100644 --- a/evm/src/cpu/kernel/asm/hash/blake2b/compression.asm +++ b/evm/src/cpu/kernel/asm/hash/blake2b/compression.asm @@ -181,30 +181,15 @@ compression_loop: 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 - + PUSH g_functions_return + // stack: g_functions_return, cur_block, retdest + %blake2b_internal_state_addr + // stack: start, g_functions_return, cur_block, retdest + %jump(run_12_rounds_g_function) +g_functions_return: + // Finalize hash value. // stack: cur_block, retdest %blake2b_generate_new_hash_value(7) diff --git a/evm/src/cpu/kernel/asm/hash/blake2b/g_functions.asm b/evm/src/cpu/kernel/asm/hash/blake2b/g_functions.asm index 11e879fc..831841c5 100644 --- a/evm/src/cpu/kernel/asm/hash/blake2b/g_functions.asm +++ b/evm/src/cpu/kernel/asm/hash/blake2b/g_functions.asm @@ -1,89 +1,89 @@ -%macro blake2b_g_function +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: a, b, c, d, x, y, start, retdest %stack (indices: 4) -> (indices, indices) - // stack: a, b, c, d, a, b, c, d, x, y, start + // stack: a, b, c, d, a, b, c, d, x, y, start, retdest DUP11 - // stack: start, a, b, c, d, a, b, c, d, x, y, start + // stack: start, a, b, c, d, a, b, c, d, x, y, start, retdest %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 + // stack: d, start, c, start, b, start, a, start, a, b, c, d, x, y, start, retdest ADD %mload_kernel_general - // stack: v[d], c, start, b, start, a, start, a, b, c, d, x, y, start + // stack: v[d], c, start, b, start, a, start, a, b, c, d, x, y, start, retdest %stack (vd, remaining: 6) -> (remaining, vd) - // stack: c, start, b, start, a, start, v[d], a, b, c, d, x, y, start + // stack: c, start, b, start, a, start, v[d], a, b, c, d, x, y, start, retdest 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 + // stack: b, start, a, start, v[c], v[d], a, b, c, d, x, y, start, retdest ADD %mload_kernel_general - // stack: v[b], a, start, v[c], v[d], a, b, c, d, x, y, start + // stack: v[b], a, start, v[c], v[d], a, b, c, d, x, y, start, retdest %stack (vb, remaining: 2) -> (remaining, vb) - // stack: a, start, v[b], v[c], v[d], a, b, c, d, x, y, start + // stack: a, start, v[b], v[c], v[d], a, b, c, d, x, y, start, retdest ADD %mload_kernel_general - // stack: v[a], v[b], v[c], v[d], a, b, c, d, x, y, start + // stack: v[a], v[b], v[c], v[d], a, b, c, d, x, y, start, retdest DUP2 - // stack: v[b], v[a], v[b], v[c], v[d], a, b, c, d, x, y, start + // stack: v[b], v[a], v[b], v[c], v[d], a, b, c, d, x, y, start, retdest DUP10 - // stack: x, v[b], v[a], v[b], v[c], v[d], a, b, c, d, x, y, start + // stack: x, v[b], v[a], v[b], v[c], v[d], a, b, c, d, x, y, start, retdest 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: v[a]' = (v[a] + v[b] + x) % 2^64, v[b], v[c], v[d], a, b, c, d, x, y, start, retdest %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 + // stack: v[a]', v[d], v[a]', v[b], v[c], v[d], a, b, c, d, x, y, start, retdest 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: v[d]' = (v[d] ^ v[a]') >>> 32, v[a]', v[b], v[c], v[d], a, b, c, d, x, y, start, retdest %stack (top: 4, vd) -> (top) - // stack: v[d]', v[a]', v[b], v[c], a, b, c, d, x, y, start + // stack: v[d]', v[a]', v[b], v[c], a, b, c, d, x, y, start, retdest %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 + // stack: v[c], v[d]', v[a]', v[b], v[d]', a, b, c, d, x, y, start, retdest 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: v[c]' = (v[c] + v[d]') % 2^64, v[a]', v[b], v[d]', a, b, c, d, x, y, start, retdest %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 + // stack: v[b], v[c]', v[a]', v[c]', v[d]', a, b, c, d, x, y, start, retdest 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 + // stack: v[b]' = (v[b] ^ v[c]') >>> 24, v[a]', v[c]', v[d]', a, b, c, d, x, y, start, retdest SWAP1 - // stack: v[a]', v[b]', v[c]', v[d]', a, b, c, d, x, y, start + // stack: v[a]', v[b]', v[c]', v[d]', a, b, c, d, x, y, start, retdest DUP2 - // stack: v[b]', v[a]', v[b]', v[c]', v[d]', a, b, c, d, x, y, start + // stack: v[b]', v[a]', v[b]', v[c]', v[d]', a, b, c, d, x, y, start, retdest DUP11 - // stack: y, v[b]', v[a]', v[b]', v[c]', v[d]', a, b, c, d, x, y, start + // stack: y, v[b]', v[a]', v[b]', v[c]', v[d]', a, b, c, d, x, y, start, retdest 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 + // stack: v[a]'' = (v[a]' + v[b]' + y) % 2^64, v[b]', v[c]', v[d]', a, b, c, d, x, y, start, retdest SWAP3 - // stack: v[d]', v[b]', v[c]', v[a]'', a, b, c, d, x, y, start + // stack: v[d]', v[b]', v[c]', v[a]'', a, b, c, d, x, y, start, retdest DUP4 - // stack: v[a]'', v[d]', v[b]', v[c]', v[a]'', a, b, c, d, x, y, start + // stack: v[a]'', v[d]', v[b]', v[c]', v[a]'', a, b, c, d, x, y, start, retdest 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 + // stack: v[d]'' = (v[a]'' ^ v[d]') >>> 8, v[b]', v[c]', v[a]'', a, b, c, d, x, y, start, retdest SWAP2 - // stack: v[c]', v[b]', v[d]'', v[a]'', a, b, c, d, x, y, start + // stack: v[c]', v[b]', v[d]'', v[a]'', a, b, c, d, x, y, start, retdest DUP3 - // stack: v[d]'', v[c]', v[b]', v[d]'', v[a]'', a, b, c, d, x, y, start + // stack: v[d]'', v[c]', v[b]', v[d]'', v[a]'', a, b, c, d, x, y, start, retdest 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 + // stack: v[c]'' = (v[c]' + v[d]'') % 2^64, v[b]', v[d]'', v[a]'', a, b, c, d, x, y, start, retdest DUP1 - // stack: v[c]'', v[c]'', v[b]', v[d]'', v[a]'', a, b, c, d, x, y, start + // stack: v[c]'', v[c]'', v[b]', v[d]'', v[a]'', a, b, c, d, x, y, start, retdest SWAP2 - // stack: v[b]', v[c]'', v[c]'', v[d]'', v[a]'', a, b, c, d, x, y, start + // stack: v[b]', v[c]'', v[c]'', v[d]'', v[a]'', a, b, c, d, x, y, start, retdest 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: v[b]'' = (v[b]' ^ v[c]'') >>> 7, v[c]'', v[d]'', v[a]'', a, b, c, d, x, y, start, retdest %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]'' + // stack: start, a, v[a]'', start, b, v[b]'', start, c, v[c]'', start, d, v[d]'', retdest ADD %mstore_kernel_general ADD @@ -92,35 +92,124 @@ %mstore_kernel_general ADD %mstore_kernel_general -%endmacro + // stack: retdest + JUMP -%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 +call_blake2b_g_function: + // stack: a, b, c, d, x_idx, y_idx, round, start, retdest + DUP6 + // stack: y_idx, a, b, c, d, x_idx, y_idx, round, start, retdest + DUP8 + // stack: round, y_idx, a, b, c, d, x_idx, y_idx, round, start, retdest %blake2b_permutation - // stack: s[y_idx], round, start + // stack: s[y_idx], a, b, c, d, x_idx, y_idx, round, start, retdest %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 + // stack: m[s[y_idx]], a, b, c, d, x_idx, y_idx, round, start, retdest + DUP6 + // stack: x_idx, m[s[y_idx]], a, b, c, d, x_idx, y_idx, round, start, retdest + DUP9 + // stack: round, x_idx, m[s[y_idx]], a, b, c, d, x_idx, y_idx, round, start, retdest %blake2b_permutation - // stack: s[x_idx], m[s[y_idx]], round, start + // stack: s[x_idx], m[s[y_idx]], a, b, c, d, x_idx, y_idx, round, start, retdest %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 + // stack: m[s[x_idx]], m[s[y_idx]], a, b, c, d, x_idx, y_idx, round, start, retdest + %stack (mm: 2, abcd: 4, xy: 2, r, s) -> (abcd, mm, s, r, s) + // stack: a, b, c, d, m[s[x_idx]], m[s[y_idx]], start, round, start, retdest + %jump(blake2b_g_function) + +global run_g_function_round: + // stack: round, start, retdest + PUSH g_function_return_1 + // stack: g_function_return_1, round, start, retdest + %stack (ret, r, s) -> (0, 4, 8, 12, 0, 1, r, s, ret, r, s) + // stack: a=0, b=4, c=8, d=12, x_idx=0, y_idx=1, round, start, g_function_return_1, round, start, retdest + %jump(call_blake2b_g_function) +g_function_return_1: + // stack: round, start, retdest + PUSH g_function_return_2 + // stack: g_function_return_2, round, start, retdest + %stack (ret, r, s) -> (1, 5, 9, 13, 2, 3, r, s, ret, r, s) + // stack: a=1, b=5, c=9, d=13, x_idx=2, y_idx=3, round, start, g_function_return_2, round, start, retdest + %jump(call_blake2b_g_function) +g_function_return_2: + // stack: round, start, retdest + PUSH g_function_return_3 + // stack: g_function_return_3, round, start, retdest + %stack (ret, r, s) -> (2, 6, 10, 14, 4, 5, r, s, ret, r, s) + // stack: a=2, b=6, c=10, d=14, x_idx=4, y_idx=5, round, start, g_function_return_3, round, start, retdest + %jump(call_blake2b_g_function) +g_function_return_3: + // stack: round, start, retdest + PUSH g_function_return_4 + // stack: g_function_return_4, round, start, retdest + %stack (ret, r, s) -> (3, 7, 11, 15, 6, 7, r, s, ret, r, s) + // stack: a=3, b=7, c=11, d=15, x_idx=6, y_idx=7, round, start, g_function_return_4, round, start, retdest + %jump(call_blake2b_g_function) +g_function_return_4: + // stack: round, start, retdest + PUSH g_function_return_5 + // stack: g_function_return_5, round, start, retdest + %stack (ret, r, s) -> (0, 5, 10, 15, 8, 9, r, s, ret, r, s) + // stack: a=0, b=5, c=10, d=15, x_idx=8, y_idx=9, round, start, g_function_return_5, round, start, retdest + %jump(call_blake2b_g_function) +g_function_return_5: + // stack: round, start, retdest + PUSH g_function_return_6 + // stack: g_function_return_6, round, start, retdest + %stack (ret, r, s) -> (1, 6, 11, 12, 10, 11, r, s, ret, r, s) + // stack: a=1, b=6, c=11, d=12, x_idx=10, y_idx=11, round, start, g_function_return_6, round, start, retdest + %jump(call_blake2b_g_function) +g_function_return_6: + // stack: round, start, retdest + PUSH g_function_return_7 + // stack: g_function_return_7, round, start, retdest + %stack (ret, r, s) -> (2, 7, 8, 13, 12, 13, r, s, ret, r, s) + // stack: a=2, b=7, c=8, d=13, x_idx=12, y_idx=13, round, start, g_function_return_7, round, start, retdest + %jump(call_blake2b_g_function) +g_function_return_7: + // stack: round, start, retdest + PUSH g_function_return_8 + // stack: g_function_return_8, round, start, retdest + %stack (ret, r, s) -> (3, 4, 9, 14, 14, 15, r, s, ret, r, s) + // stack: a=3, b=4, c=9, d=14, x_idx=14, y_idx=15, round, start, g_function_return_8, round, start, retdest + %jump(call_blake2b_g_function) +g_function_return_8: + // stack: round, start, retdest + SWAP1 + // stack: start, round, retdest + SWAP2 + // stack: retdest, round, start + JUMP + + +global run_12_rounds_g_function: + // stack: start, retdest + PUSH 0 + // stack: round=0, start, retdest +run_next_round_g_function: + // stack: round, start, retdest + PUSH run_g_function_round_return + // stack: run_g_function_round_return, round, start, retdest + SWAP2 + // stack: start, round, run_g_function_round_return, retdest + SWAP1 + // stack: round, start, run_g_function_round_return, retdest + %jump(run_g_function_round) +run_next_round_g_function_return: + // stack: round, start, retdest + %increment + // stack: round+1, start, retdest + DUP1 + // stack: round+1, round+1, start, retdest + %lt_const(12) + // stack: round+1 < 12, round+1, start, retdest + %jumpi(run_next_round_g_function) + // stack: round+1, start, retdest + %pop2 + // stack: retdest + JUMP + From 4e8af821aefb3042008aefcfe906e520619f949b Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Tue, 7 Mar 2023 12:25:34 -0800 Subject: [PATCH 044/121] fixes --- evm/src/cpu/kernel/asm/hash/blake2b/g_functions.asm | 12 ++++++------ evm/src/cpu/kernel/tests/hash.rs | 2 ++ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/evm/src/cpu/kernel/asm/hash/blake2b/g_functions.asm b/evm/src/cpu/kernel/asm/hash/blake2b/g_functions.asm index 831841c5..ff3ee43a 100644 --- a/evm/src/cpu/kernel/asm/hash/blake2b/g_functions.asm +++ b/evm/src/cpu/kernel/asm/hash/blake2b/g_functions.asm @@ -117,8 +117,8 @@ call_blake2b_g_function: ADD %mload_kernel_general // stack: m[s[x_idx]], m[s[y_idx]], a, b, c, d, x_idx, y_idx, round, start, retdest - %stack (mm: 2, abcd: 4, xy: 2, r, s) -> (abcd, mm, s, r, s) - // stack: a, b, c, d, m[s[x_idx]], m[s[y_idx]], start, round, start, retdest + %stack (mm: 2, abcd: 4, xy: 2, r, s) -> (abcd, mm, s) + // stack: a, b, c, d, m[s[x_idx]], m[s[y_idx]], start, retdest %jump(blake2b_g_function) global run_g_function_round: @@ -192,12 +192,12 @@ global run_12_rounds_g_function: // stack: round=0, start, retdest run_next_round_g_function: // stack: round, start, retdest - PUSH run_g_function_round_return - // stack: run_g_function_round_return, round, start, retdest + PUSH run_next_round_g_function_return + // stack: run_next_round_g_function_return, round, start, retdest SWAP2 - // stack: start, round, run_g_function_round_return, retdest + // stack: start, round, run_next_round_g_function_return, retdest SWAP1 - // stack: round, start, run_g_function_round_return, retdest + // stack: round, start, run_next_round_g_function_return, retdest %jump(run_g_function_round) run_next_round_g_function_return: // stack: round, start, retdest diff --git a/evm/src/cpu/kernel/tests/hash.rs b/evm/src/cpu/kernel/tests/hash.rs index bc73ecd5..cc2c96eb 100644 --- a/evm/src/cpu/kernel/tests/hash.rs +++ b/evm/src/cpu/kernel/tests/hash.rs @@ -79,6 +79,8 @@ fn prepare_test( // Run the interpeter let result = run_interpreter_with_memory(interpreter_setup).unwrap(); + dbg!(result.stack().to_vec()); + Ok((expected, result.stack().to_vec())) } From ef377c0b4f612a3e65ffa3beb2fe95fa23f4cbe5 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Tue, 7 Mar 2023 12:27:08 -0800 Subject: [PATCH 045/121] cleanup --- evm/src/cpu/kernel/tests/hash.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/evm/src/cpu/kernel/tests/hash.rs b/evm/src/cpu/kernel/tests/hash.rs index cc2c96eb..bc73ecd5 100644 --- a/evm/src/cpu/kernel/tests/hash.rs +++ b/evm/src/cpu/kernel/tests/hash.rs @@ -79,8 +79,6 @@ fn prepare_test( // Run the interpeter let result = run_interpreter_with_memory(interpreter_setup).unwrap(); - dbg!(result.stack().to_vec()); - Ok((expected, result.stack().to_vec())) } From 3a0d86e26268404857eee9e71ba4874437408d49 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Tue, 7 Mar 2023 15:45:20 -0800 Subject: [PATCH 046/121] hash function optimization --- .../kernel/asm/hash/blake2b/compression.asm | 12 +-- evm/src/cpu/kernel/asm/hash/blake2b/hash.asm | 91 +++++++++++++++++-- 2 files changed, 86 insertions(+), 17 deletions(-) diff --git a/evm/src/cpu/kernel/asm/hash/blake2b/compression.asm b/evm/src/cpu/kernel/asm/hash/blake2b/compression.asm index 840d8c54..fdf02d69 100644 --- a/evm/src/cpu/kernel/asm/hash/blake2b/compression.asm +++ b/evm/src/cpu/kernel/asm/hash/blake2b/compression.asm @@ -192,14 +192,10 @@ g_functions_return: // 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) + PUSH hash_generate_return + // stack: hash_generate_return, cur_block, retdest + %jump(blake2b_generate_all_hash_values) +hash_generate_return: // 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 diff --git a/evm/src/cpu/kernel/asm/hash/blake2b/hash.asm b/evm/src/cpu/kernel/asm/hash/blake2b/hash.asm index 712a97c0..91a5530e 100644 --- a/evm/src/cpu/kernel/asm/hash/blake2b/hash.asm +++ b/evm/src/cpu/kernel/asm/hash/blake2b/hash.asm @@ -1,18 +1,91 @@ -%macro blake2b_generate_new_hash_value(i) +blake2b_generate_new_hash_value: + // stack: i, retdest %blake2b_hash_value_addr - %add_const($i) + // stack: addr, i, retdest + DUP2 + ADD %mload_kernel_general - // stack: h_i, ... + // stack: h_i, i, retdest %blake2b_internal_state_addr - %add_const($i) + // stack: addr, h_i, i, retdest + DUP3 + ADD %mload_kernel_general - // stack: v_i, h_i, ... + // stack: v_i, h_i, i, retdest %blake2b_internal_state_addr - %add_const($i) + // stack: addr, v_i, h_i, i, retdest + DUP4 + ADD %add_const(8) %mload_kernel_general - // stack: v_(i+8), v_i, h_i, ... + // stack: v_(i+8), v_i, h_i, i, retdest XOR XOR - // stack: h_i' = v_(i+8) ^ v_i ^ h_i, ... -%endmacro + // stack: h_i' = v_(i+8) ^ v_i ^ h_i, i, retdest + SWAP1 + POP + // stack: h_i', retdest + SWAP1 + JUMP + +global blake2b_generate_all_hash_values: + // stack: retdest + PUSH blake2b_generate_hash_return_7 + // stack: blake2b_generate_hash_return_7, retdest + PUSH 7 + // stack: 7, blake2b_generate_hash_return_7, retdest + %jump(blake2b_generate_new_hash_value) +blake2b_generate_hash_return_7: + // stack: h_7', retdest + PUSH blake2b_generate_hash_return_6 + // stack: blake2b_generate_hash_return_6, h_7', retdest + PUSH 6 + // stack: 6, blake2b_generate_hash_return_6, h_7', retdest + %jump(blake2b_generate_new_hash_value) +blake2b_generate_hash_return_6: + // stack: h_6', h_7', retdest + PUSH blake2b_generate_hash_return_5 + // stack: blake2b_generate_hash_return_5, h_6', h_7', retdest + PUSH 5 + // stack: 5, blake2b_generate_hash_return_5, h_6', h_7', retdest + %jump(blake2b_generate_new_hash_value) +blake2b_generate_hash_return_5: + // stack: h_5', h_6', h_7', retdest + PUSH blake2b_generate_hash_return_4 + // stack: blake2b_generate_hash_return_4, h_5', h_6', h_7', retdest + PUSH 4 + // stack: 4, blake2b_generate_hash_return_4, h_5', h_6', h_7', retdest + %jump(blake2b_generate_new_hash_value) +blake2b_generate_hash_return_4: + // stack: h_4', h_5', h_6', h_7', retdest + PUSH blake2b_generate_hash_return_3 + // stack: blake2b_generate_hash_return_3, h_4', h_5', h_6', h_7', retdest + PUSH 3 + // stack: 3, blake2b_generate_hash_return_3, h_4', h_5', h_6', h_7', retdest + %jump(blake2b_generate_new_hash_value) +blake2b_generate_hash_return_3: + // stack: h_3', h_4', h_5', h_6', h_7', retdest + PUSH blake2b_generate_hash_return_2 + // stack: blake2b_generate_hash_return_2, h_3', h_4', h_5', h_6', h_7', retdest + PUSH 2 + // stack: 2, blake2b_generate_hash_return_2, h_3', h_4', h_5', h_6', h_7', retdest + %jump(blake2b_generate_new_hash_value) +blake2b_generate_hash_return_2: + // stack: h_2', h_3', h_4', h_5', h_6', h_7', retdest + PUSH blake2b_generate_hash_return_1 + // stack: blake2b_generate_hash_return_1, h_2', h_3', h_4', h_5', h_6', h_7', retdest + PUSH 1 + // stack: 1, blake2b_generate_hash_return_1, h_2', h_3', h_4', h_5', h_6', h_7', retdest + %jump(blake2b_generate_new_hash_value) +blake2b_generate_hash_return_1: + // stack: h_1', h_2', h_3', h_4', h_5', h_6', h_7', retdest + PUSH blake2b_generate_hash_return_0 + // stack: blake2b_generate_hash_return_0, h_1', h_2', h_3', h_4', h_5', h_6', h_7', retdest + PUSH 0 + // stack: 0, blake2b_generate_hash_return_0, h_1', h_2', h_3', h_4', h_5', h_6', h_7', retdest + %jump(blake2b_generate_new_hash_value) +blake2b_generate_hash_return_0: + // stack: h_0', h_1', h_2', h_3', h_4', h_5', h_6', h_7', retdest + %stack (h: 8, ret) -> (ret, h) + // stack: retdest, h_0', h_1', h_2', h_3', h_4', h_5', h_6', h_7' + JUMP \ No newline at end of file From df7ea93ab330ec444801d8022ed151f25209cb10 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Tue, 7 Mar 2023 15:45:52 -0800 Subject: [PATCH 047/121] optimize hash generation further --- evm/src/cpu/kernel/asm/hash/blake2b/hash.asm | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/evm/src/cpu/kernel/asm/hash/blake2b/hash.asm b/evm/src/cpu/kernel/asm/hash/blake2b/hash.asm index 91a5530e..945c7fb0 100644 --- a/evm/src/cpu/kernel/asm/hash/blake2b/hash.asm +++ b/evm/src/cpu/kernel/asm/hash/blake2b/hash.asm @@ -14,17 +14,17 @@ blake2b_generate_new_hash_value: // stack: v_i, h_i, i, retdest %blake2b_internal_state_addr // stack: addr, v_i, h_i, i, retdest - DUP4 + SWAP1 + // stack: v_i, addr, h_i, i, retdest + SWAP3 + // stack: i, addr, h_i, v_i, retdest ADD %add_const(8) %mload_kernel_general - // stack: v_(i+8), v_i, h_i, i, retdest + // stack: v_(i+8), h_i, v_i, retdest XOR XOR - // stack: h_i' = v_(i+8) ^ v_i ^ h_i, i, retdest - SWAP1 - POP - // stack: h_i', retdest + // stack: h_i' = v_(i+8) ^ v_i ^ h_i, retdest SWAP1 JUMP @@ -88,4 +88,4 @@ blake2b_generate_hash_return_0: // stack: h_0', h_1', h_2', h_3', h_4', h_5', h_6', h_7', retdest %stack (h: 8, ret) -> (ret, h) // stack: retdest, h_0', h_1', h_2', h_3', h_4', h_5', h_6', h_7' - JUMP \ No newline at end of file + JUMP From 2020202e507595da62867f8d2760c8918379daac Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Tue, 7 Mar 2023 16:19:15 -0800 Subject: [PATCH 048/121] optimize hash generation further further --- evm/src/cpu/kernel/asm/hash/blake2b/hash.asm | 77 +++++--------------- evm/src/cpu/kernel/tests/hash.rs | 2 + 2 files changed, 22 insertions(+), 57 deletions(-) diff --git a/evm/src/cpu/kernel/asm/hash/blake2b/hash.asm b/evm/src/cpu/kernel/asm/hash/blake2b/hash.asm index 945c7fb0..654b51b3 100644 --- a/evm/src/cpu/kernel/asm/hash/blake2b/hash.asm +++ b/evm/src/cpu/kernel/asm/hash/blake2b/hash.asm @@ -30,62 +30,25 @@ blake2b_generate_new_hash_value: global blake2b_generate_all_hash_values: // stack: retdest - PUSH blake2b_generate_hash_return_7 - // stack: blake2b_generate_hash_return_7, retdest - PUSH 7 - // stack: 7, blake2b_generate_hash_return_7, retdest + PUSH 8 + // stack: i=8, retdest +blake2b_generate_hash_loop: + // stack: i, h_i', ..., h_7', retdest + %decrement + // stack: i-1, h_i', ..., h_7', retdest + PUSH blake2b_generate_hash_return + // stack: blake2b_generate_hash_return, i-1, h_i', ..., h_7', retdest + DUP2 + // stack: i-1, blake2b_generate_hash_return, i-1, h_i', ..., h_7', retdest %jump(blake2b_generate_new_hash_value) -blake2b_generate_hash_return_7: - // stack: h_7', retdest - PUSH blake2b_generate_hash_return_6 - // stack: blake2b_generate_hash_return_6, h_7', retdest - PUSH 6 - // stack: 6, blake2b_generate_hash_return_6, h_7', retdest - %jump(blake2b_generate_new_hash_value) -blake2b_generate_hash_return_6: - // stack: h_6', h_7', retdest - PUSH blake2b_generate_hash_return_5 - // stack: blake2b_generate_hash_return_5, h_6', h_7', retdest - PUSH 5 - // stack: 5, blake2b_generate_hash_return_5, h_6', h_7', retdest - %jump(blake2b_generate_new_hash_value) -blake2b_generate_hash_return_5: - // stack: h_5', h_6', h_7', retdest - PUSH blake2b_generate_hash_return_4 - // stack: blake2b_generate_hash_return_4, h_5', h_6', h_7', retdest - PUSH 4 - // stack: 4, blake2b_generate_hash_return_4, h_5', h_6', h_7', retdest - %jump(blake2b_generate_new_hash_value) -blake2b_generate_hash_return_4: - // stack: h_4', h_5', h_6', h_7', retdest - PUSH blake2b_generate_hash_return_3 - // stack: blake2b_generate_hash_return_3, h_4', h_5', h_6', h_7', retdest - PUSH 3 - // stack: 3, blake2b_generate_hash_return_3, h_4', h_5', h_6', h_7', retdest - %jump(blake2b_generate_new_hash_value) -blake2b_generate_hash_return_3: - // stack: h_3', h_4', h_5', h_6', h_7', retdest - PUSH blake2b_generate_hash_return_2 - // stack: blake2b_generate_hash_return_2, h_3', h_4', h_5', h_6', h_7', retdest - PUSH 2 - // stack: 2, blake2b_generate_hash_return_2, h_3', h_4', h_5', h_6', h_7', retdest - %jump(blake2b_generate_new_hash_value) -blake2b_generate_hash_return_2: - // stack: h_2', h_3', h_4', h_5', h_6', h_7', retdest - PUSH blake2b_generate_hash_return_1 - // stack: blake2b_generate_hash_return_1, h_2', h_3', h_4', h_5', h_6', h_7', retdest - PUSH 1 - // stack: 1, blake2b_generate_hash_return_1, h_2', h_3', h_4', h_5', h_6', h_7', retdest - %jump(blake2b_generate_new_hash_value) -blake2b_generate_hash_return_1: - // stack: h_1', h_2', h_3', h_4', h_5', h_6', h_7', retdest - PUSH blake2b_generate_hash_return_0 - // stack: blake2b_generate_hash_return_0, h_1', h_2', h_3', h_4', h_5', h_6', h_7', retdest - PUSH 0 - // stack: 0, blake2b_generate_hash_return_0, h_1', h_2', h_3', h_4', h_5', h_6', h_7', retdest - %jump(blake2b_generate_new_hash_value) -blake2b_generate_hash_return_0: - // stack: h_0', h_1', h_2', h_3', h_4', h_5', h_6', h_7', retdest - %stack (h: 8, ret) -> (ret, h) - // stack: retdest, h_0', h_1', h_2', h_3', h_4', h_5', h_6', h_7' +blake2b_generate_hash_return: + // stack: h_(i-1)', i-1, h_i', ..., h_7', retdest + SWAP1 + // stack: i-1, h_(i-1)', h_i', ..., h_7', retdest + DUP1 + // stack: i-1, i-1, h_(i-1)', ..., h_7', retdest + %jumpi(blake2b_generate_hash_loop) + // stack: i-1=0, h_0', ..., h_7', retdest + %stack (i, h: 8, ret) -> (ret, h) + // stack: retdest, h_0'...h_7' JUMP diff --git a/evm/src/cpu/kernel/tests/hash.rs b/evm/src/cpu/kernel/tests/hash.rs index bc73ecd5..cc2c96eb 100644 --- a/evm/src/cpu/kernel/tests/hash.rs +++ b/evm/src/cpu/kernel/tests/hash.rs @@ -79,6 +79,8 @@ fn prepare_test( // Run the interpeter let result = run_interpreter_with_memory(interpreter_setup).unwrap(); + dbg!(result.stack().to_vec()); + Ok((expected, result.stack().to_vec())) } From 7c8026e893952fb721d422b36c512e7caa9fd8be Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Tue, 7 Mar 2023 16:49:28 -0800 Subject: [PATCH 049/121] cleanup --- evm/src/cpu/kernel/asm/hash/blake2b/compression.asm | 1 - 1 file changed, 1 deletion(-) diff --git a/evm/src/cpu/kernel/asm/hash/blake2b/compression.asm b/evm/src/cpu/kernel/asm/hash/blake2b/compression.asm index fdf02d69..11e5389b 100644 --- a/evm/src/cpu/kernel/asm/hash/blake2b/compression.asm +++ b/evm/src/cpu/kernel/asm/hash/blake2b/compression.asm @@ -189,7 +189,6 @@ compression_loop: // stack: start, g_functions_return, cur_block, retdest %jump(run_12_rounds_g_function) g_functions_return: - // Finalize hash value. // stack: cur_block, retdest PUSH hash_generate_return From 213ba8ff50835d99039b418dcaf31cd6f7698137 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Tue, 7 Mar 2023 17:17:23 -0800 Subject: [PATCH 050/121] optimized initial hash value generation --- .../cpu/kernel/asm/hash/blake2b/addresses.asm | 16 ----- .../kernel/asm/hash/blake2b/compression.asm | 4 +- evm/src/cpu/kernel/asm/hash/blake2b/iv.asm | 61 ++++++++++++++----- evm/src/cpu/kernel/tests/hash.rs | 2 - 4 files changed, 50 insertions(+), 33 deletions(-) diff --git a/evm/src/cpu/kernel/asm/hash/blake2b/addresses.asm b/evm/src/cpu/kernel/asm/hash/blake2b/addresses.asm index 9d65b9ed..f1d7c3e9 100644 --- a/evm/src/cpu/kernel/asm/hash/blake2b/addresses.asm +++ b/evm/src/cpu/kernel/asm/hash/blake2b/addresses.asm @@ -1,19 +1,3 @@ -// 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 diff --git a/evm/src/cpu/kernel/asm/hash/blake2b/compression.asm b/evm/src/cpu/kernel/asm/hash/blake2b/compression.asm index 11e5389b..cd1f6a80 100644 --- a/evm/src/cpu/kernel/asm/hash/blake2b/compression.asm +++ b/evm/src/cpu/kernel/asm/hash/blake2b/compression.asm @@ -2,7 +2,9 @@ global blake2b_compression: // stack: retdest PUSH 0 // stack: cur_block = 0, retdest - %blake2b_initial_hash_value + PUSH compression_loop + // stack: compression_loop, cur_block, retdest + %jump(blake2b_initial_hash_value) compression_loop: // stack: h_0, ..., h_7, cur_block, retdest diff --git a/evm/src/cpu/kernel/asm/hash/blake2b/iv.asm b/evm/src/cpu/kernel/asm/hash/blake2b/iv.asm index 94e9ba27..48df86a3 100644 --- a/evm/src/cpu/kernel/asm/hash/blake2b/iv.asm +++ b/evm/src/cpu/kernel/asm/hash/blake2b/iv.asm @@ -33,30 +33,63 @@ global blake2b_iv_const: BYTES 91, 224, 205, 25 BYTES 19, 126, 33, 121 -%macro blake2b_iv - // stack: i, ... +global blake2b_iv: + // stack: i, retdest PUSH blake2b_iv_const - // stack: blake2b_iv_const, i, ... + // stack: blake2b_iv_const, i, retdest SWAP1 - // stack: i, blake2b_iv_const, ... + // stack: i, blake2b_iv_const, retdest %mul_const(8) ADD - // stack: blake2b_iv_const + 2 * i, ... + // stack: blake2b_iv_const + 2 * i, retdest DUP1 - // stack: blake2b_iv_const + 2 * i, blake2b_iv_const + 2 * i, ... + // stack: blake2b_iv_const + 2 * i, blake2b_iv_const + 2 * i, retdest %add_const(4) - // stack: blake2b_iv_const + 2 * i + 1, blake2b_iv_const + 2 * i, ... + // stack: blake2b_iv_const + 2 * i + 1, blake2b_iv_const + 2 * i, retdest %mload_kernel_code_u32 SWAP1 %mload_kernel_code_u32 - // stack: IV_i[32:], IV_i[:32], ... + // stack: IV_i[32:], IV_i[:32], retdest %shl_const(32) - // stack: IV_i[32:] << 32, IV_i[:32], ... + // stack: IV_i[32:] << 32, IV_i[:32], retdest ADD // OR - // stack: IV_i, ... + // stack: IV_i, retdest + SWAP1 + JUMP + +%macro blake2b_iv + %stack (i) -> (i, %%after) + %jump(blake2b_iv) +%%after: %endmacro -%macro blake2b_iv_i(i) - PUSH $i - %blake2b_iv -%endmacro +// Load the initial hash value (the IV, but with params XOR'd into the first word). +global blake2b_initial_hash_value: + // stack: retdest + PUSH 8 + // stack: i=8, retdest +blake2b_initial_hash_loop: + // stack: i, IV_i, ..., IV_7, retdest + %decrement + // stack: i-1, IV_i, ..., IV_7, retdest + PUSH blake2b_initial_hash_return + // stack: blake2b_initial_hash_return, i-1, IV_i, ..., IV_7, retdest + DUP2 + // stack: i-1, blake2b_initial_hash_return, i-1, IV_i, ..., IV_7, retdest + %jump(blake2b_iv) +blake2b_initial_hash_return: + // stack: IV_(i-1), i-1, IV_i, ..., IV_7, retdest + SWAP1 + // stack: i-1, IV_(i-1), IV_i, ..., IV_7, retdest + DUP1 + // stack: i-1, i-1, IV_(i-1), ..., IV_7, retdest + %jumpi(blake2b_initial_hash_loop) + // stack: i-1=0, IV_0, ..., IV_7, retdest + POP + // stack: IV_0, ..., IV_7, retdest + PUSH 0x01010040 // params: key = 00, digest_size = 64 = 0x40 + XOR + // stack: IV_0 ^ params, IV_1, IV_2, IV_3, IV_4, IV_5, IV_6, IV_7, retdest + %stack(iv: 8, ret) -> (ret, iv) + JUMP + diff --git a/evm/src/cpu/kernel/tests/hash.rs b/evm/src/cpu/kernel/tests/hash.rs index cc2c96eb..bc73ecd5 100644 --- a/evm/src/cpu/kernel/tests/hash.rs +++ b/evm/src/cpu/kernel/tests/hash.rs @@ -79,8 +79,6 @@ fn prepare_test( // Run the interpeter let result = run_interpreter_with_memory(interpreter_setup).unwrap(); - dbg!(result.stack().to_vec()); - Ok((expected, result.stack().to_vec())) } From e5f8632b5e1fdda1476ac978d7b3390d3d92bb9e Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Wed, 22 Feb 2023 15:44:31 -0800 Subject: [PATCH 051/121] small optimizations --- evm/src/cpu/kernel/asm/hash/blake2b/compression.asm | 7 +++---- evm/src/cpu/kernel/asm/hash/sha2/compression.asm | 4 +--- .../cpu/kernel/asm/hash/sha2/message_schedule.asm | 12 +++--------- 3 files changed, 7 insertions(+), 16 deletions(-) diff --git a/evm/src/cpu/kernel/asm/hash/blake2b/compression.asm b/evm/src/cpu/kernel/asm/hash/blake2b/compression.asm index cd1f6a80..bf3dd1c4 100644 --- a/evm/src/cpu/kernel/asm/hash/blake2b/compression.asm +++ b/evm/src/cpu/kernel/asm/hash/blake2b/compression.asm @@ -209,10 +209,9 @@ hash_generate_return: 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) + GT + // stack: not_last_block, h_0', h_1', h_2', h_3', h_4', h_5', h_6', h_7', cur_block + 1, retdest + %jumpi(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 diff --git a/evm/src/cpu/kernel/asm/hash/sha2/compression.asm b/evm/src/cpu/kernel/asm/hash/sha2/compression.asm index 8c219ebb..fa58dce8 100644 --- a/evm/src/cpu/kernel/asm/hash/sha2/compression.asm +++ b/evm/src/cpu/kernel/asm/hash/sha2/compression.asm @@ -180,9 +180,7 @@ compression_loop: // stack: a[i+1], b[i+1], c[i+1], d[i+1], e[i+1], f[i+1], g[i+1], h[i+1], num_blocks new, scratch_space_addr, message_schedule_addr new, (i+1)%64, retdest DUP12 // stack: (i+1)%64, a[i+1], b[i+1], c[i+1], d[i+1], e[i+1], f[i+1], g[i+1], h[i+1], num_blocks new, scratch_space_addr, message_schedule_addr new, (i+1)%64, retdest - ISZERO - %jumpi(compression_end_block) - %jump(compression_loop) + %jumpi(compression_loop) compression_end_block: // Add the initial values of the eight working variables (from the start of this block's compression) back into them. // stack: a[64], b[64], c[64], d[64], e[64], f[64], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, retdest diff --git a/evm/src/cpu/kernel/asm/hash/sha2/message_schedule.asm b/evm/src/cpu/kernel/asm/hash/sha2/message_schedule.asm index 78d98634..0d7c2637 100644 --- a/evm/src/cpu/kernel/asm/hash/sha2/message_schedule.asm +++ b/evm/src/cpu/kernel/asm/hash/sha2/message_schedule.asm @@ -55,9 +55,7 @@ gen_message_schedule_from_block_0_loop: // stack: counter, output_addr - 4, block[0] >> 32, block[1], retdest %decrement DUP1 - ISZERO - %jumpi(gen_message_schedule_from_block_0_end) - %jump(gen_message_schedule_from_block_0_loop) + %jumpi(gen_message_schedule_from_block_0_loop) gen_message_schedule_from_block_0_end: // stack: old counter=0, output_addr, block[0], block[1], retdest POP @@ -185,9 +183,7 @@ gen_message_schedule_remaining_loop: %decrement // stack: counter - 1, output_addr + 4, block[0], block[1], retdest DUP1 - ISZERO - %jumpi(gen_message_schedule_remaining_end) - %jump(gen_message_schedule_remaining_loop) + %jumpi(gen_message_schedule_remaining_loop) gen_message_schedule_remaining_end: // stack: counter=0, output_addr, block[0], block[1], retdest %pop4 @@ -230,9 +226,7 @@ gen_all_message_schedules_loop_end: // stack: cur_addr + 64, counter - 1, cur_output_addr + 256, output_addr, retdest DUP2 // stack: counter - 1, cur_addr + 64, counter - 1, cur_output_addr + 256, output_addr, retdest - ISZERO - %jumpi(gen_all_message_schedules_end) - %jump(gen_all_message_schedules_loop) + %jumpi(gen_all_message_schedules_loop) gen_all_message_schedules_end: // stack: cur_addr + 64, counter - 1, cur_output_addr + 256, output_addr, retdest %pop3 From 2236f30ae557e82901b24f5114e3fb06c033e640 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Tue, 14 Mar 2023 15:52:50 -0700 Subject: [PATCH 052/121] more small optimizations --- .../kernel/asm/hash/blake2b/compression.asm | 54 +++++++++---------- .../cpu/kernel/asm/hash/sha2/compression.asm | 21 ++------ 2 files changed, 32 insertions(+), 43 deletions(-) diff --git a/evm/src/cpu/kernel/asm/hash/blake2b/compression.asm b/evm/src/cpu/kernel/asm/hash/blake2b/compression.asm index bf3dd1c4..9cf8aeef 100644 --- a/evm/src/cpu/kernel/asm/hash/blake2b/compression.asm +++ b/evm/src/cpu/kernel/asm/hash/blake2b/compression.asm @@ -85,8 +85,7 @@ compression_loop: // 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 + %pop2 // stack: t, cur_block, is_last_block, retdest SWAP1 // stack: cur_block, t, is_last_block, retdest @@ -128,15 +127,14 @@ compression_loop: // stack: 0, start + 8, invert_if_last_block, t, cur_block, retdest %rep 4 // stack: i, loc, ... - DUP2 - DUP2 - // stack: i, loc, i, loc,... + DUP1 + // stack: i, i, loc, ... %blake2b_iv - // stack: IV_i, loc, i, loc,... - SWAP1 - // stack: loc, IV_i, i, loc,... + // stack: IV_i, i, loc, ... + DUP2 + // stack: loc, IV_i, i, loc, ... %mstore_kernel_general - // stack: i, loc,... + // stack: i, loc, ... %increment SWAP1 %increment @@ -147,15 +145,11 @@ compression_loop: %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 + // stack: t_hi = 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, t_hi, 4, start + 12, invert_if_last_block, cur_block, retdest + %mod_const(PUSH 0x10000000000000000) + // stack: t_lo = t % (1 << 64), t_hi, 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 @@ -163,25 +157,31 @@ compression_loop: // 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,... + DUP1 + // stack: i, i, loc, val, next_val,... %blake2b_iv - // stack: IV_i, val, loc, i, loc, next_val,... + // stack: IV_i, i, loc, val, next_val,... + DUP4 + // stack: val, IV_i, i, loc, val, next_val,... XOR - // stack: val ^ IV_i, loc, i, loc, next_val,... - SWAP1 - // stack: loc, val ^ IV_i, i, loc, next_val,... + // stack: val ^ IV_i, i, loc, val, next_val,... + DUP3 + // stack: loc, val ^ IV_i, i, loc, val, next_val,... %mstore_kernel_general - // stack: i, loc, next_val,... + // stack: i, loc, val, next_val,... %increment - SWAP1 + // stack: i + 1, loc, val, next_val,... + SWAP2 + // stack: val, loc, i + 1, next_val,... + POP + // stack: loc, i + 1, next_val,... %increment + // stack: loc + 1, i + 1, next_val,... SWAP1 // stack: i + 1, loc + 1, next_val,... %endrep // stack: 8, loc + 16, cur_block, retdest - POP - POP + %pop2 // stack: cur_block, retdest // Run 12 rounds of G functions. diff --git a/evm/src/cpu/kernel/asm/hash/sha2/compression.asm b/evm/src/cpu/kernel/asm/hash/sha2/compression.asm index fa58dce8..c28a19a2 100644 --- a/evm/src/cpu/kernel/asm/hash/sha2/compression.asm +++ b/evm/src/cpu/kernel/asm/hash/sha2/compression.asm @@ -161,8 +161,7 @@ compression_loop: // stack: message_schedule_addr, i+1==64, i+1, a[i+1], b[i+1], c[i+1], d[i+1], e[i+1], f[i+1], g[i+1], h[i+1], num_blocks, scratch_space_addr, num_blocks new, i, retdest SWAP1 // stack: i+1==64, message_schedule_addr, i+1, a[i+1], b[i+1], c[i+1], d[i+1], e[i+1], f[i+1], g[i+1], h[i+1], num_blocks, scratch_space_addr, num_blocks new, i, retdest - PUSH 256 - MUL + %mul_const(256) // stack: (i+1==64)*256, message_schedule_addr, i+1, a[i+1], b[i+1], c[i+1], d[i+1], e[i+1], f[i+1], g[i+1], h[i+1], num_blocks, scratch_space_addr, num_blocks new, i, retdest ADD // stack: message_schedule_addr new, i+1, a[i+1], b[i+1], c[i+1], d[i+1], e[i+1], f[i+1], g[i+1], h[i+1], num_blocks, scratch_space_addr, num_blocks new, i, retdest @@ -260,20 +259,10 @@ compression_end: // stack: num_blocks, a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], e[0]+e[64], f[0]+f[64], g[0]+g[64], h[0]+h[64], scratch_space_addr, message_schedule_addr, i, retdest POP // stack: a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], e[0]+e[64], f[0]+f[64], g[0]+g[64], h[0]+h[64], scratch_space_addr, message_schedule_addr, i, retdest - %shl_const(32) - ADD // OR - %shl_const(32) - ADD // OR - %shl_const(32) - ADD // OR - %shl_const(32) - ADD // OR - %shl_const(32) - ADD // OR - %shl_const(32) - ADD // OR - %shl_const(32) - ADD // OR + %rep 7 + %shl_const(32) + ADD // OR + %endrep // stack: concat(a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], e[0]+e[64], f[0]+f[64], g[0]+g[64], h[0]+h[64]), scratch_space_addr, message_schedule_addr, i, retdest SWAP3 // stack: i, scratch_space_addr, message_schedule_addr, concat(a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], e[0]+e[64], f[0]+f[64], g[0]+g[64], h[0]+h[64]), retdest From 63301d6b8cab3e08e5668cd819497d723ca7ae70 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Fri, 24 Feb 2023 11:59:22 -0800 Subject: [PATCH 053/121] refactor sha2 compression --- .../cpu/kernel/asm/hash/sha2/compression.asm | 291 +++++++----------- 1 file changed, 110 insertions(+), 181 deletions(-) diff --git a/evm/src/cpu/kernel/asm/hash/sha2/compression.asm b/evm/src/cpu/kernel/asm/hash/sha2/compression.asm index c28a19a2..8b361ead 100644 --- a/evm/src/cpu/kernel/asm/hash/sha2/compression.asm +++ b/evm/src/cpu/kernel/asm/hash/sha2/compression.asm @@ -8,22 +8,7 @@ global sha2_compression: // stack: message_schedule_addr, retdest - PUSH 0 - // stack: i=0, message_schedule_addr, retdest - SWAP1 - // stack: message_schedule_addr, i=0, retdest - PUSH 0 - // stack: 0, message_schedule_addr, i=0, retdest - %mload_kernel_general - // stack: num_blocks, message_schedule_addr, i=0, retdest - DUP1 - // stack: num_blocks, num_blocks, message_schedule_addr, i=0, retdest - %scratch_space_addr_from_num_blocks - // stack: scratch_space_addr, num_blocks, message_schedule_addr, i=0, retdest - SWAP1 - // stack: num_blocks, scratch_space_addr, message_schedule_addr, i=0, retdest // Push the initial hash values; these constants are called H^(0) in the spec. - PUSH 0x5be0cd19 // H^(0)_7 PUSH 0x1f83d9ab // H^(0)_6 PUSH 0x9b05688c // H^(0)_5 PUSH 0x510e527f // H^(0)_4 @@ -31,229 +16,173 @@ global sha2_compression: PUSH 0x3c6ef372 // H^(0)_2 PUSH 0xbb67ae85 // H^(0)_1 PUSH 0x6a09e667 // H^(0)_0 - // stack: a[0], b[0], c[0], d[0], e[0], f[0], g[0], h[0], num_blocks, scratch_space_addr, message_schedule_addr, i=0, retdest + PUSH 0x5be0cd19 // H^(0)_7 + // stack: h[0], a[0], b[0], c[0], d[0], e[0], f[0], g[0], message_schedule_addr, retdest + SWAP8 + // stack: message_schedule_addr, a[0], b[0], c[0], d[0], e[0], f[0], g[0], h[0], retdest + PUSH 0 + // stack: i=0, message_schedule_addr, a[0]..h[0], retdest + SWAP1 + // stack: message_schedule_addr, i=0, a[0]..h[0], retdest + PUSH 0 + // stack: 0, message_schedule_addr, i=0, a[0]..h[0], retdest + %mload_kernel_general + // stack: num_blocks, message_schedule_addr, i=0, a[0]..h[0], retdest + DUP1 + // stack: num_blocks, num_blocks, message_schedule_addr, i=0, a[0]..h[0], retdest + %scratch_space_addr_from_num_blocks + // stack: scratch_space_addr, num_blocks, message_schedule_addr, i=0, a[0]..h[0], retdest + SWAP1 + // stack: num_blocks, scratch_space_addr, message_schedule_addr, i=0, a[0]..h[0], retdest +compression_start_block: + // stack: num_blocks, scratch_space_addr, message_schedule_addr, i=0, a[0]..h[0], retdest + %rep 8 + DUP12 + %endrep + // stack: a[0], b[0], c[0], d[0], e[0], f[0], g[0], h[0], num_blocks, scratch_space_addr, message_schedule_addr, i=0, a[0]..h[0], retdest compression_start_block: - // Store the current values of the working variables, as the "initial values" to be added back in at the end of this block. - DUP10 - // stack: scratch_space_addr, a[0], b[0], c[0], d[0], e[0], f[0], g[0], h[0], num_blocks, scratch_space_addr, message_schedule_addr, i=0, retdest - - DUP2 - DUP2 - // stack: scratch_space_addr, a[0], scratch_space_addr, a[0], b[0], c[0], d[0], e[0], f[0], g[0], h[0], num_blocks, scratch_space_addr, message_schedule_addr, i=0, retdest - %mstore_kernel_general_u32 - // stack: scratch_space_addr, a[0], b[0], c[0], d[0], e[0], f[0], g[0], h[0], num_blocks, scratch_space_addr, message_schedule_addr, i=0, retdest - %add_const(4) - // stack: scratch_space_addr+4, a[0], b[0], c[0], d[0], e[0], f[0], g[0], h[0], num_blocks, scratch_space_addr, message_schedule_addr, i=0, retdest - - DUP3 - DUP2 - // stack: scratch_space_addr+4, b[0], scratch_space_addr+4, a[0], b[0], c[0], d[0], e[0], f[0], g[0], h[0], num_blocks, scratch_space_addr, message_schedule_addr, i=0, retdest - %mstore_kernel_general_u32 - // stack: scratch_space_addr+4, a[0], b[0], c[0], d[0], e[0], f[0], g[0], h[0], num_blocks, scratch_space_addr, message_schedule_addr, i=0, retdest - %add_const(4) - // stack: scratch_space_addr+8, a[0], b[0], c[0], d[0], e[0], f[0], g[0], h[0], num_blocks, scratch_space_addr, message_schedule_addr, i=0, retdest - DUP4 - DUP2 - // stack: scratch_space_addr+8, c[0], scratch_space_addr+8, a[0], b[0], c[0], d[0], e[0], f[0], g[0], h[0], num_blocks, scratch_space_addr, message_schedule_addr, i=0, retdest - %mstore_kernel_general_u32 - // stack: scratch_space_addr+8, a[0], b[0], c[0], d[0], e[0], f[0], g[0], h[0], num_blocks, scratch_space_addr, message_schedule_addr, i=0, retdest - %add_const(4) - // stack: scratch_space_addr+12, a[0], b[0], c[0], d[0], e[0], f[0], g[0], h[0], num_blocks, scratch_space_addr, message_schedule_addr, i=0, retdest - - DUP5 - DUP2 - // stack: scratch_space_addr+12, c[0], scratch_space_addr+8, a[0], b[0], c[0], d[0], e[0], f[0], g[0], h[0], num_blocks, scratch_space_addr, message_schedule_addr, i=0, retdest - %mstore_kernel_general_u32 - // stack: scratch_space_addr+12, a[0], b[0], c[0], d[0], e[0], f[0], g[0], h[0], num_blocks, scratch_space_addr, message_schedule_addr, i=0, retdest - %add_const(4) - // stack: scratch_space_addr+16, a[0], b[0], c[0], d[0], e[0], f[0], g[0], h[0], num_blocks, scratch_space_addr, message_schedule_addr, i=0, retdest - - DUP6 - DUP2 - // stack: scratch_space_addr+16, c[0], scratch_space_addr+8, a[0], b[0], c[0], d[0], e[0], f[0], g[0], h[0], num_blocks, scratch_space_addr, message_schedule_addr, i=0, retdest - %mstore_kernel_general_u32 - // stack: scratch_space_addr+16, a[0], b[0], c[0], d[0], e[0], f[0], g[0], h[0], num_blocks, scratch_space_addr, message_schedule_addr, i=0, retdest - %add_const(4) - // stack: scratch_space_addr+20, a[0], b[0], c[0], d[0], e[0], f[0], g[0], h[0], num_blocks, scratch_space_addr, message_schedule_addr, i=0, retdest - - DUP7 - DUP2 - // stack: scratch_space_addr+20, c[0], scratch_space_addr+8, a[0], b[0], c[0], d[0], e[0], f[0], g[0], h[0], num_blocks, scratch_space_addr, message_schedule_addr, i=0, retdest - %mstore_kernel_general_u32 - // stack: scratch_space_addr+20, a[0], b[0], c[0], d[0], e[0], f[0], g[0], h[0], num_blocks, scratch_space_addr, message_schedule_addr, i=0, retdest - %add_const(4) - // stack: scratch_space_addr+24, a[0], b[0], c[0], d[0], e[0], f[0], g[0], h[0], num_blocks, scratch_space_addr, message_schedule_addr, i=0, retdest - - DUP8 - DUP2 - // stack: scratch_space_addr+24, c[0], scratch_space_addr+8, a[0], b[0], c[0], d[0], e[0], f[0], g[0], h[0], num_blocks, scratch_space_addr, message_schedule_addr, i=0, retdest - %mstore_kernel_general_u32 - // stack: scratch_space_addr+24, a[0], b[0], c[0], d[0], e[0], f[0], g[0], h[0], num_blocks, scratch_space_addr, message_schedule_addr, i=0, retdest - %add_const(4) - // stack: scratch_space_addr+28, a[0], b[0], c[0], d[0], e[0], f[0], g[0], h[0], num_blocks, scratch_space_addr, message_schedule_addr, i=0, retdest - - DUP9 - DUP2 - // stack: scratch_space_addr+28, c[0], scratch_space_addr+8, a[0], b[0], c[0], d[0], e[0], f[0], g[0], h[0], num_blocks, scratch_space_addr, message_schedule_addr, i=0, retdest - %mstore_kernel_general_u32 - // stack: scratch_space_addr+28, a[0], b[0], c[0], d[0], e[0], f[0], g[0], h[0], num_blocks, scratch_space_addr, message_schedule_addr, i=0, retdest - POP - // stack: a[0], b[0], c[0], d[0], e[0], f[0], g[0], h[0], num_blocks, scratch_space_addr, message_schedule_addr, i=0, retdest compression_loop: // Update the eight working variables, using the next constant K[i] and the next message schedule chunk W[i]. - // stack: a[i], b[i], c[i], d[i], e[i], f[i], g[i], h[i], num_blocks, scratch_space_addr, message_schedule_addr, i, retdest + // stack: a[i], b[i], c[i], d[i], e[i], f[i], g[i], h[i], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]..h[0], retdest DUP11 - // stack: message_schedule_addr, a[i], b[i], c[i], d[i], e[i], f[i], g[i], h[i], num_blocks, scratch_space_addr, message_schedule_addr, i, retdest + // stack: message_schedule_addr, a[i], b[i], c[i], d[i], e[i], f[i], g[i], h[i], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]..h[0], retdest DUP13 - // stack: i, message_schedule_addr, a[i], b[i], c[i], d[i], e[i], f[i], g[i], h[i], num_blocks, scratch_space_addr, message_schedule_addr, i, retdest + // stack: i, message_schedule_addr, a[i], b[i], c[i], d[i], e[i], f[i], g[i], h[i], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]..h[0], retdest %mul_const(4) - // stack: 4*i, message_schedule_addr, a[i], b[i], c[i], d[i], e[i], f[i], g[i], h[i], num_blocks, scratch_space_addr, message_schedule_addr, i, retdest + // stack: 4*i, message_schedule_addr, a[i], b[i], c[i], d[i], e[i], f[i], g[i], h[i], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]..h[0], retdest ADD - // stack: message_schedule_addr + 4*i, a[i], b[i], c[i], d[i], e[i], f[i], g[i], h[i], num_blocks, scratch_space_addr, message_schedule_addr, i, retdest + // stack: message_schedule_addr + 4*i, a[i], b[i], c[i], d[i], e[i], f[i], g[i], h[i], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]..h[0], retdest %mload_kernel_general_u32 - // stack: W[i], a[i], b[i], c[i], d[i], e[i], f[i], g[i], h[i], num_blocks, scratch_space_addr, message_schedule_addr, i, retdest + // stack: W[i], a[i], b[i], c[i], d[i], e[i], f[i], g[i], h[i], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]..h[0], retdest PUSH sha2_constants_k - // stack: sha2_constants_k, W[i], a[i], b[i], c[i], d[i], e[i], f[i], g[i], h[i], num_blocks, scratch_space_addr, message_schedule_addr, i, retdest + // stack: sha2_constants_k, W[i], a[i], b[i], c[i], d[i], e[i], f[i], g[i], h[i], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]..h[0], retdest DUP14 - // stack: i, sha2_constants_k, W[i], a[i], b[i], c[i], d[i], e[i], f[i], g[i], h[i], num_blocks, scratch_space_addr, message_schedule_addr, i, retdest + // stack: i, sha2_constants_k, W[i], a[i], b[i], c[i], d[i], e[i], f[i], g[i], h[i], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]..h[0], retdest %mul_const(4) - // stack: 4*i, sha2_constants_k, W[i], a[i], b[i], c[i], d[i], e[i], f[i], g[i], h[i], num_blocks, scratch_space_addr, message_schedule_addr, i, retdest + // stack: 4*i, sha2_constants_k, W[i], a[i], b[i], c[i], d[i], e[i], f[i], g[i], h[i], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]..h[0], retdest ADD - // stack: sha2_constants_k + 4*i, W[i], a[i], b[i], c[i], d[i], e[i], f[i], g[i], h[i], num_blocks, scratch_space_addr, message_schedule_addr, i, retdest + // stack: sha2_constants_k + 4*i, W[i], a[i], b[i], c[i], d[i], e[i], f[i], g[i], h[i], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]..h[0], retdest %mload_kernel_code_u32 - // stack: K[i], W[i], a[i], b[i], c[i], d[i], e[i], f[i], g[i], h[i], num_blocks, scratch_space_addr, message_schedule_addr, i, retdest + // stack: K[i], W[i], a[i], b[i], c[i], d[i], e[i], f[i], g[i], h[i], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]..h[0], retdest %stack (start: 6, e, f, g, h) -> (e, f, g, h, start, e, f, g, h) - // stack: e[i], f[i], g[i], h[i], K[i], W[i], a[i], b[i], c[i], d[i], e[i], f[i], g[i], h[i], num_blocks, scratch_space_addr, message_schedule_addr, i, retdest + // stack: e[i], f[i], g[i], h[i], K[i], W[i], a[i], b[i], c[i], d[i], e[i], f[i], g[i], h[i], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]..h[0], retdest %sha2_temp_word1 - // stack: T1[i], a[i], b[i], c[i], d[i], e[i], f[i], g[i], h[i], num_blocks, scratch_space_addr, message_schedule_addr, i, retdest + // stack: T1[i], a[i], b[i], c[i], d[i], e[i], f[i], g[i], h[i], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]..h[0], retdest %stack (t, a, b, c) -> (a, b, c, t, a, b, c) - // stack: a[i], b[i], c[i], T1[i], a[i], b[i], c[i], d[i], e[i], f[i], g[i], h[i], num_blocks, scratch_space_addr, message_schedule_addr, i, retdest + // stack: a[i], b[i], c[i], T1[i], a[i], b[i], c[i], d[i], e[i], f[i], g[i], h[i], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]..h[0], retdest %sha2_temp_word2 - // stack: T2[i], T1[i], a[i], b[i], c[i], d[i], e[i], f[i], g[i], h[i], num_blocks, scratch_space_addr, message_schedule_addr, i, retdest + // stack: T2[i], T1[i], a[i], b[i], c[i], d[i], e[i], f[i], g[i], h[i], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]..h[0], retdest DUP6 - // stack: d[i], T2[i], T1[i], a[i], b[i], c[i], d[i], e[i], f[i], g[i], h[i], num_blocks, scratch_space_addr, message_schedule_addr, i, retdest + // stack: d[i], T2[i], T1[i], a[i], b[i], c[i], d[i], e[i], f[i], g[i], h[i], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]..h[0], retdest DUP3 - // stack: T1[i], d[i], T2[i], T1[i], a[i], b[i], c[i], d[i], e[i], f[i], g[i], h[i], num_blocks, scratch_space_addr, message_schedule_addr, i, retdest + // stack: T1[i], d[i], T2[i], T1[i], a[i], b[i], c[i], d[i], e[i], f[i], g[i], h[i], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]..h[0], retdest %add_u32 - // stack: e[i+1]=T1[i]+d[i], T2[i], T1[i], a[i], b[i], c[i], d[i], e[i], f[i], g[i], h[i], num_blocks, scratch_space_addr, message_schedule_addr, i, retdest + // stack: e[i+1]=T1[i]+d[i], T2[i], T1[i], a[i], b[i], c[i], d[i], e[i], f[i], g[i], h[i], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]..h[0], retdest SWAP2 - // stack: T2[i], T1[i], e[i+1], a[i], b[i], c[i], d[i], e[i], f[i], g[i], h[i], num_blocks, scratch_space_addr, message_schedule_addr, i, retdest + // stack: T2[i], T1[i], e[i+1], a[i], b[i], c[i], d[i], e[i], f[i], g[i], h[i], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]..h[0], retdest %add_u32 - // stack: a[i+1]=T1[i]+T2[i], e[i+1], b[i+1]=a[i], c[i+1]=b[i], d[i+1]=c[i], d[i], f[i+1]=e[i], g[i+1]=f[i], h[i+1]=g[i], h[i], num_blocks, scratch_space_addr, message_schedule_addr, i, retdest + // stack: a[i+1]=T1[i]+T2[i], e[i+1], b[i+1]=a[i], c[i+1]=b[i], d[i+1]=c[i], d[i], f[i+1]=e[i], g[i+1]=f[i], h[i+1]=g[i], h[i], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]..h[0], retdest %stack (a, e, b, c, d, old_d, f, g, h, old_h) -> (a, b, c, d, e, f, g, h) - // stack: a[i+1], b[i+1], c[i+1], d[i+1], e[i+1], f[i+1], g[i+1], h[i+1], num_blocks, scratch_space_addr, message_schedule_addr, i, retdest + // stack: a[i+1], b[i+1], c[i+1], d[i+1], e[i+1], f[i+1], g[i+1], h[i+1], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]..h[0], retdest DUP12 - // stack: i, a[i+1], b[i+1], c[i+1], d[i+1], e[i+1], f[i+1], g[i+1], h[i+1], num_blocks, scratch_space_addr, message_schedule_addr, i, retdest + // stack: i, a[i+1], b[i+1], c[i+1], d[i+1], e[i+1], f[i+1], g[i+1], h[i+1], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]..h[0], retdest %increment - // stack: i+1, a[i+1], b[i+1], c[i+1], d[i+1], e[i+1], f[i+1], g[i+1], h[i+1], num_blocks, scratch_space_addr, message_schedule_addr, i, retdest + // stack: i+1, a[i+1], b[i+1], c[i+1], d[i+1], e[i+1], f[i+1], g[i+1], h[i+1], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]..h[0], retdest DUP1 - // stack: i+1, i+1, a[i+1], b[i+1], c[i+1], d[i+1], e[i+1], f[i+1], g[i+1], h[i+1], num_blocks, scratch_space_addr, message_schedule_addr, i, retdest + // stack: i+1, i+1, a[i+1], b[i+1], c[i+1], d[i+1], e[i+1], f[i+1], g[i+1], h[i+1], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]..h[0], retdest %eq_const(64) - // stack: i+1==64, i+1, a[i+1], b[i+1], c[i+1], d[i+1], e[i+1], f[i+1], g[i+1], h[i+1], num_blocks, scratch_space_addr, message_schedule_addr, i, retdest + // stack: i+1==64, i+1, a[i+1], b[i+1], c[i+1], d[i+1], e[i+1], f[i+1], g[i+1], h[i+1], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]..h[0], retdest DUP1 - // stack: i+1==64, i+1==64, i+1, a[i+1], b[i+1], c[i+1], d[i+1], e[i+1], f[i+1], g[i+1], h[i+1], num_blocks, scratch_space_addr, message_schedule_addr, i, retdest + // stack: i+1==64, i+1==64, i+1, a[i+1], b[i+1], c[i+1], d[i+1], e[i+1], f[i+1], g[i+1], h[i+1], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]..h[0], retdest DUP12 - // stack: num_blocks, i+1==64, i+1==64, i+1, a[i+1], b[i+1], c[i+1], d[i+1], e[i+1], f[i+1], g[i+1], h[i+1], num_blocks, scratch_space_addr, message_schedule_addr, i, retdest + // stack: num_blocks, i+1==64, i+1==64, i+1, a[i+1], b[i+1], c[i+1], d[i+1], e[i+1], f[i+1], g[i+1], h[i+1], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]..h[0], retdest SUB - // stack: num_blocks new, i+1==64, i+1, a[i+1], b[i+1], c[i+1], d[i+1], e[i+1], f[i+1], g[i+1], h[i+1], num_blocks, scratch_space_addr, message_schedule_addr, i, retdest + // stack: num_blocks new, i+1==64, i+1, a[i+1], b[i+1], c[i+1], d[i+1], e[i+1], f[i+1], g[i+1], h[i+1], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]..h[0], retdest SWAP13 - // stack: message_schedule_addr, i+1==64, i+1, a[i+1], b[i+1], c[i+1], d[i+1], e[i+1], f[i+1], g[i+1], h[i+1], num_blocks, scratch_space_addr, num_blocks new, i, retdest + // stack: message_schedule_addr, i+1==64, i+1, a[i+1], b[i+1], c[i+1], d[i+1], e[i+1], f[i+1], g[i+1], h[i+1], num_blocks, scratch_space_addr, num_blocks new, i, a[0]..h[0], retdest SWAP1 - // stack: i+1==64, message_schedule_addr, i+1, a[i+1], b[i+1], c[i+1], d[i+1], e[i+1], f[i+1], g[i+1], h[i+1], num_blocks, scratch_space_addr, num_blocks new, i, retdest + // stack: i+1==64, message_schedule_addr, i+1, a[i+1], b[i+1], c[i+1], d[i+1], e[i+1], f[i+1], g[i+1], h[i+1], num_blocks, scratch_space_addr, num_blocks new, i, a[0]..h[0], retdest %mul_const(256) - // stack: (i+1==64)*256, message_schedule_addr, i+1, a[i+1], b[i+1], c[i+1], d[i+1], e[i+1], f[i+1], g[i+1], h[i+1], num_blocks, scratch_space_addr, num_blocks new, i, retdest + // stack: (i+1==64)*256, message_schedule_addr, i+1, a[i+1], b[i+1], c[i+1], d[i+1], e[i+1], f[i+1], g[i+1], h[i+1], num_blocks, scratch_space_addr, num_blocks new, i, a[0]..h[0], retdest ADD - // stack: message_schedule_addr new, i+1, a[i+1], b[i+1], c[i+1], d[i+1], e[i+1], f[i+1], g[i+1], h[i+1], num_blocks, scratch_space_addr, num_blocks new, i, retdest + // stack: message_schedule_addr new, i+1, a[i+1], b[i+1], c[i+1], d[i+1], e[i+1], f[i+1], g[i+1], h[i+1], num_blocks, scratch_space_addr, num_blocks new, i, a[0]..h[0], retdest SWAP12 - // stack: num_blocks new, i+1, a[i+1], b[i+1], c[i+1], d[i+1], e[i+1], f[i+1], g[i+1], h[i+1], num_blocks, scratch_space_addr, message_schedule_addr new, i, retdest + // stack: num_blocks new, i+1, a[i+1], b[i+1], c[i+1], d[i+1], e[i+1], f[i+1], g[i+1], h[i+1], num_blocks, scratch_space_addr, message_schedule_addr new, i, a[0]..h[0], retdest SWAP10 - // stack: num_blocks, i+1, a[i+1], b[i+1], c[i+1], d[i+1], e[i+1], f[i+1], g[i+1], h[i+1], num_blocks new, scratch_space_addr, message_schedule_addr new, i, new_retdest + // stack: num_blocks, i+1, a[i+1], b[i+1], c[i+1], d[i+1], e[i+1], f[i+1], g[i+1], h[i+1], num_blocks new, scratch_space_addr, message_schedule_addr new, i, new_a[0]..h[0], retdest POP - // stack: i+1, a[i+1], b[i+1], c[i+1], d[i+1], e[i+1], f[i+1], g[i+1], h[i+1], num_blocks new, scratch_space_addr, message_schedule_addr new, i, new_retdest + // stack: i+1, a[i+1], b[i+1], c[i+1], d[i+1], e[i+1], f[i+1], g[i+1], h[i+1], num_blocks new, scratch_space_addr, message_schedule_addr new, i, new_a[0]..h[0], retdest %and_const(63) - // stack: (i+1)%64, a[i+1], b[i+1], c[i+1], d[i+1], e[i+1], f[i+1], g[i+1], h[i+1], num_blocks new, scratch_space_addr, message_schedule_addr new, i, retdest + // stack: (i+1)%64, a[i+1], b[i+1], c[i+1], d[i+1], e[i+1], f[i+1], g[i+1], h[i+1], num_blocks new, scratch_space_addr, message_schedule_addr new, i, a[0]..h[0], retdest SWAP12 - // stack: i, a[i+1], b[i+1], c[i+1], d[i+1], e[i+1], f[i+1], g[i+1], h[i+1], num_blocks new, scratch_space_addr, message_schedule_addr new, (i+1)%64, retdest + // stack: i, a[i+1], b[i+1], c[i+1], d[i+1], e[i+1], f[i+1], g[i+1], h[i+1], num_blocks new, scratch_space_addr, message_schedule_addr new, (i+1)%64, a[0]..h[0], retdest POP - // stack: a[i+1], b[i+1], c[i+1], d[i+1], e[i+1], f[i+1], g[i+1], h[i+1], num_blocks new, scratch_space_addr, message_schedule_addr new, (i+1)%64, retdest + // stack: a[i+1], b[i+1], c[i+1], d[i+1], e[i+1], f[i+1], g[i+1], h[i+1], num_blocks new, scratch_space_addr, message_schedule_addr new, (i+1)%64, a[0]..h[0], retdest DUP12 - // stack: (i+1)%64, a[i+1], b[i+1], c[i+1], d[i+1], e[i+1], f[i+1], g[i+1], h[i+1], num_blocks new, scratch_space_addr, message_schedule_addr new, (i+1)%64, retdest + // stack: (i+1)%64, a[i+1], b[i+1], c[i+1], d[i+1], e[i+1], f[i+1], g[i+1], h[i+1], num_blocks new, scratch_space_addr, message_schedule_addr new, (i+1)%64, a[0]..h[0], retdest %jumpi(compression_loop) compression_end_block: // Add the initial values of the eight working variables (from the start of this block's compression) back into them. - // stack: a[64], b[64], c[64], d[64], e[64], f[64], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, retdest - DUP10 - // stack: scratch_space_addr, a[64], b[64], c[64], d[64], e[64], f[64], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, retdest - %mload_kernel_general_u32 - // stack: a[0], a[64], b[64], c[64], d[64], e[64], f[64], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, retdest + // stack: a[64], b[64], c[64], d[64], e[64], f[64], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0], b[0], c[0], d[0], e[0], f[0], g[0], h[0], retdest + PUSH 0 + // stack: 0, a[64], b[64], c[64], d[64], e[64], f[64], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0], b[0], c[0], d[0], e[0], f[0], g[0], h[0], retdest + SWAP13 + // stack: a[0], a[64], b[64], c[64], d[64], e[64], f[64], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, 0, b[0], c[0], d[0], e[0], f[0], g[0], h[0], retdest %add_u32 - // stack: a[0]+a[64], b[64], c[64], d[64], e[64], f[64], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, retdest - SWAP1 - // stack: b[64], a[0]+a[64], c[64], d[64], e[64], f[64], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, retdest - DUP10 - %add_const(4) - %mload_kernel_general_u32 - // stack: b[0], b[64], a[0]+a[64], c[64], d[64], e[64], f[64], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, retdest + // stack: a[0]+a[64], b[64], c[64], d[64], e[64], f[64], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, 0, b[0], c[0], d[0], e[0], f[0], g[0], h[0], retdest + SWAP12 + // stack: 0, b[64], c[64], d[64], e[64], f[64], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]+a[64], b[0], c[0], d[0], e[0], f[0], g[0], h[0], retdest + SWAP13 + // stack: b[0], b[64], c[64], d[64], e[64], f[64], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]+a[64], 0, c[0], d[0], e[0], f[0], g[0], h[0], retdest %add_u32 - // stack: b[0]+b[64], a[0]+a[64], c[64], d[64], e[64], f[64], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, retdest - SWAP2 - // stack: c[64], a[0]+a[64], b[0]+b[64], d[64], e[64], f[64], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, retdest - DUP10 - %add_const(8) - %mload_kernel_general_u32 - // stack: c[0], c[64], a[0]+a[64], b[0]+b[64], d[64], e[64], f[64], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, retdest + // stack: b[0]+b[64], c[64], d[64], e[64], f[64], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]+a[64], 0, c[0], d[0], e[0], f[0], g[0], h[0], retdest + SWAP12 + // stack: 0, c[64], d[64], e[64], f[64], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]+a[64], b[0]+b[64], c[0], d[0], e[0], f[0], g[0], h[0], retdest + SWAP13 + // stack: c[0], c[64], d[64], e[64], f[64], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]+a[64], b[0]+b[64], 0, d[0], e[0], f[0], g[0], h[0], retdest %add_u32 - // stack: c[0]+c[64], a[0]+a[64], b[0]+b[64], d[64], e[64], f[64], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, retdest - SWAP3 - // stack: d[64], a[0]+a[64], b[0]+b[64], c[0]+c[64], e[64], f[64], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, retdest - DUP10 - %add_const(12) - %mload_kernel_general_u32 - // stack: d[0], d[64], a[0]+a[64], b[0]+b[64], c[0]+c[64], e[64], f[64], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, retdest + // stack: c[0]+c[64], d[64], e[64], f[64], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]+a[64], b[0]+b[64], 0, d[0], e[0], f[0], g[0], h[0], retdest + SWAP12 + // stack: 0, d[64], e[64], f[64], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0], e[0], f[0], g[0], h[0], retdest + SWAP13 + // stack: d[0], d[64], e[64], f[64], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]+a[64], b[0]+b[64], c[0]+c[64], 0, e[0], f[0], g[0], h[0], retdest %add_u32 - // stack: d[0]+d[64], a[0]+a[64], b[0]+b[64], c[0]+c[64], e[64], f[64], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, retdest - SWAP4 - // stack: e[64], a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], f[64], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, retdest - DUP10 - %add_const(16) - %mload_kernel_general_u32 - // stack: e[0], e[64], a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], f[64], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, retdest + // stack: d[0]+d[64], e[64], f[64], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]+a[64], b[0]+b[64], c[0]+c[64], 0, e[0], f[0], g[0], h[0], retdest + SWAP12 + // stack: 0, e[64], f[64], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], e[0], f[0], g[0], h[0], retdest + SWAP13 + // stack: e[0], e[64], f[64], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], 0, f[0], g[0], h[0], retdest %add_u32 - // stack: e[0]+e[64], a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], f[64], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, retdest - SWAP5 - // stack: f[64], a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], e[0]+e[64], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, retdest - DUP10 - %add_const(20) - %mload_kernel_general_u32 - // stack: f[0], f[64], a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], e[0]+e[64], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, retdest + // stack: e[0]+e[64], f[64], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], 0, f[0], g[0], h[0], retdest + SWAP12 + // stack: 0, f[64], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], e[0]+e[64], f[0], g[0], h[0], retdest + SWAP13 + // stack: f[0], f[64], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], e[0]+e[64], 0, g[0], h[0], retdest %add_u32 - // stack: f[0]+f[64], a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], e[0]+e[64], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, retdest - SWAP6 - // stack: g[64], a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], e[0]+e[64], f[0]+f[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, retdest - DUP10 - %add_const(24) - %mload_kernel_general_u32 - // stack: g[0], g[64], a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], e[0]+e[64], f[0]+f[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, retdest + // stack: f[0]+f[64], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], e[0]+e[64], 0, g[0], h[0], retdest + SWAP12 + // stack: 0, g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], e[0]+e[64], f[0]+f[64], g[0], h[0], retdest + SWAP13 + // stack: g[0], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], e[0]+e[64], f[0]+f[64], 0, h[0], retdest %add_u32 - // stack: g[0]+g[64], a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], e[0]+e[64], f[0]+f[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, retdest - SWAP7 - // stack: h[64], a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], e[0]+e[64], f[0]+f[64], g[0]+g[64], num_blocks, scratch_space_addr, message_schedule_addr, i, retdest - DUP10 - %add_const(28) - %mload_kernel_general_u32 - // stack: h[0], h[64], a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], e[0]+e[64], f[0]+f[64], g[0]+g[64], num_blocks, scratch_space_addr, message_schedule_addr, i, retdest + // stack: g[0]+g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], e[0]+e[64], f[0]+f[64], 0, h[0], retdest + SWAP12 + // stack: 0, h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], e[0]+e[64], f[0]+f[64], g[0]+g[64], h[0], retdest + SWAP13 + // stack: h[0], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], e[0]+e[64], f[0]+f[64], g[0]+g[64], 0, retdest %add_u32 - // stack: h[0]+h[64], a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], e[0]+e[64], f[0]+f[64], g[0]+g[64], num_blocks, scratch_space_addr, message_schedule_addr, i, retdest - SWAP8 - // stack: num_blocks, a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], e[0]+e[64], f[0]+f[64], g[0]+g[64], h[0]+h[64], scratch_space_addr, message_schedule_addr, i, retdest + // stack: h[0]+h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], e[0]+e[64], f[0]+f[64], g[0]+g[64], 0, retdest + SWAP12 + // stack: 0, num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], e[0]+e[64], f[0]+f[64], g[0]+g[64], h[0]+h[64], retdest + POP + // stack: num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], e[0]+e[64], f[0]+f[64], g[0]+g[64], h[0]+h[64], retdest DUP1 - // stack: num_blocks, num_blocks, a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], e[0]+e[64], f[0]+f[64], g[0]+g[64], h[0]+h[64], scratch_space_addr, message_schedule_addr, i, retdest + // stack: num_blocks, num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], e[0]+e[64], f[0]+f[64], g[0]+g[64], h[0]+h[64], retdest ISZERO // In this case, we've finished all the blocks. %jumpi(compression_end) - // stack: num_blocks, a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], e[0]+e[64], f[0]+f[64], g[0]+g[64], h[0]+h[64], scratch_space_addr, message_schedule_addr, i, retdest - %stack (num_blocks, working: 8) -> (working, num_blocks) + // stack: num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], e[0]+e[64], f[0]+f[64], g[0]+g[64], h[0]+h[64], retdest %jump(compression_start_block) compression_end: // stack: num_blocks, a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], e[0]+e[64], f[0]+f[64], g[0]+g[64], h[0]+h[64], scratch_space_addr, message_schedule_addr, i, retdest From 684b668b60c4d462410aa99e4883f20d390e6cb1 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Fri, 24 Feb 2023 11:59:26 -0800 Subject: [PATCH 054/121] fix --- evm/src/cpu/kernel/asm/hash/blake2b/compression.asm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/evm/src/cpu/kernel/asm/hash/blake2b/compression.asm b/evm/src/cpu/kernel/asm/hash/blake2b/compression.asm index 9cf8aeef..498cc9d3 100644 --- a/evm/src/cpu/kernel/asm/hash/blake2b/compression.asm +++ b/evm/src/cpu/kernel/asm/hash/blake2b/compression.asm @@ -148,7 +148,7 @@ compression_loop: // stack: t_hi = t >> 64, t, 4, start + 12, invert_if_last_block, cur_block, retdest SWAP1 // stack: t, t_hi, 4, start + 12, invert_if_last_block, cur_block, retdest - %mod_const(PUSH 0x10000000000000000) + %mod_const(0x10000000000000000) // stack: t_lo = t % (1 << 64), t_hi, 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 From 7351a1661e49e0faf0b4a17ede804691d2d48015 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Fri, 24 Feb 2023 12:02:19 -0800 Subject: [PATCH 055/121] fix --- evm/src/cpu/kernel/asm/hash/sha2/compression.asm | 2 -- 1 file changed, 2 deletions(-) diff --git a/evm/src/cpu/kernel/asm/hash/sha2/compression.asm b/evm/src/cpu/kernel/asm/hash/sha2/compression.asm index 8b361ead..800c2010 100644 --- a/evm/src/cpu/kernel/asm/hash/sha2/compression.asm +++ b/evm/src/cpu/kernel/asm/hash/sha2/compression.asm @@ -40,8 +40,6 @@ compression_start_block: DUP12 %endrep // stack: a[0], b[0], c[0], d[0], e[0], f[0], g[0], h[0], num_blocks, scratch_space_addr, message_schedule_addr, i=0, a[0]..h[0], retdest -compression_start_block: - compression_loop: // Update the eight working variables, using the next constant K[i] and the next message schedule chunk W[i]. // stack: a[i], b[i], c[i], d[i], e[i], f[i], g[i], h[i], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]..h[0], retdest From 85411ac4755f17baf5e23a1e48d45f351626a272 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Fri, 24 Feb 2023 13:59:13 -0800 Subject: [PATCH 056/121] fixes --- evm/src/cpu/kernel/asm/hash/sha2/compression.asm | 12 +++++------- evm/src/cpu/kernel/tests/hash.rs | 1 + 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/evm/src/cpu/kernel/asm/hash/sha2/compression.asm b/evm/src/cpu/kernel/asm/hash/sha2/compression.asm index 800c2010..107d20b1 100644 --- a/evm/src/cpu/kernel/asm/hash/sha2/compression.asm +++ b/evm/src/cpu/kernel/asm/hash/sha2/compression.asm @@ -35,6 +35,8 @@ global sha2_compression: SWAP1 // stack: num_blocks, scratch_space_addr, message_schedule_addr, i=0, a[0]..h[0], retdest compression_start_block: + // We keep the current values of the working variables saved at the end of the stack. + // These are the "initial values" to be added back in at the end of this block. // stack: num_blocks, scratch_space_addr, message_schedule_addr, i=0, a[0]..h[0], retdest %rep 8 DUP12 @@ -183,17 +185,13 @@ compression_end_block: // stack: num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], e[0]+e[64], f[0]+f[64], g[0]+g[64], h[0]+h[64], retdest %jump(compression_start_block) compression_end: - // stack: num_blocks, a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], e[0]+e[64], f[0]+f[64], g[0]+g[64], h[0]+h[64], scratch_space_addr, message_schedule_addr, i, retdest - POP - // stack: a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], e[0]+e[64], f[0]+f[64], g[0]+g[64], h[0]+h[64], scratch_space_addr, message_schedule_addr, i, retdest + // stack: num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], e[0]+e[64], f[0]+f[64], g[0]+g[64], h[0]+h[64], retdest + %pop4 + // stack: a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], e[0]+e[64], f[0]+f[64], g[0]+g[64], h[0]+h[64], retdest %rep 7 %shl_const(32) ADD // OR %endrep - // stack: concat(a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], e[0]+e[64], f[0]+f[64], g[0]+g[64], h[0]+h[64]), scratch_space_addr, message_schedule_addr, i, retdest - SWAP3 - // stack: i, scratch_space_addr, message_schedule_addr, concat(a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], e[0]+e[64], f[0]+f[64], g[0]+g[64], h[0]+h[64]), retdest - %pop3 // stack: sha2_result = concat(a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], e[0]+e[64], f[0]+f[64], g[0]+g[64], h[0]+h[64]), retdest SWAP1 JUMP diff --git a/evm/src/cpu/kernel/tests/hash.rs b/evm/src/cpu/kernel/tests/hash.rs index bc73ecd5..432fcf39 100644 --- a/evm/src/cpu/kernel/tests/hash.rs +++ b/evm/src/cpu/kernel/tests/hash.rs @@ -90,6 +90,7 @@ fn test_hash_256( let (expected, result_stack) = prepare_test(hash_fn_label, hash_input_virt, standard_implementation).unwrap(); + // Extract the final output. let actual = result_stack[0]; From 265d39a5a711ee5d975b55ca8bdcd451d5bf5460 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Fri, 24 Feb 2023 16:15:14 -0800 Subject: [PATCH 057/121] cleanup --- evm/src/cpu/kernel/tests/hash.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/evm/src/cpu/kernel/tests/hash.rs b/evm/src/cpu/kernel/tests/hash.rs index 432fcf39..bc73ecd5 100644 --- a/evm/src/cpu/kernel/tests/hash.rs +++ b/evm/src/cpu/kernel/tests/hash.rs @@ -90,7 +90,6 @@ fn test_hash_256( let (expected, result_stack) = prepare_test(hash_fn_label, hash_input_virt, standard_implementation).unwrap(); - // Extract the final output. let actual = result_stack[0]; From 8f231bd03d5211e7179642d8db29ed49bda5d92a Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Fri, 24 Feb 2023 16:21:45 -0800 Subject: [PATCH 058/121] optimization --- evm/src/cpu/kernel/asm/hash/sha2/message_schedule.asm | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/evm/src/cpu/kernel/asm/hash/sha2/message_schedule.asm b/evm/src/cpu/kernel/asm/hash/sha2/message_schedule.asm index 0d7c2637..c8bfae7e 100644 --- a/evm/src/cpu/kernel/asm/hash/sha2/message_schedule.asm +++ b/evm/src/cpu/kernel/asm/hash/sha2/message_schedule.asm @@ -94,9 +94,7 @@ gen_message_schedule_from_block_1_loop: // stack: counter, output_addr - 4, block[1] >> 32, block[0], retdest %decrement DUP1 - ISZERO - %jumpi(gen_message_schedule_from_block_1_end) - %jump(gen_message_schedule_from_block_1_loop) + %jumpi(gen_message_schedule_from_block_1_loop) gen_message_schedule_from_block_1_end: // stack: old counter=0, output_addr, block[1], block[0], retdest POP From 97cb5c75b67a152f095d5325f42ebc5dcd7a1b2f Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Mon, 27 Feb 2023 11:48:49 -0800 Subject: [PATCH 059/121] bug fix --- evm/src/cpu/kernel/asm/hash/blake2b/compression.asm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/evm/src/cpu/kernel/asm/hash/blake2b/compression.asm b/evm/src/cpu/kernel/asm/hash/blake2b/compression.asm index 498cc9d3..6e8cdb0a 100644 --- a/evm/src/cpu/kernel/asm/hash/blake2b/compression.asm +++ b/evm/src/cpu/kernel/asm/hash/blake2b/compression.asm @@ -131,7 +131,7 @@ compression_loop: // stack: i, i, loc, ... %blake2b_iv // stack: IV_i, i, loc, ... - DUP2 + DUP3 // stack: loc, IV_i, i, loc, ... %mstore_kernel_general // stack: i, loc, ... From 29df451d9d71321eac1334cbef25a7f3b23d6df0 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Mon, 27 Feb 2023 15:24:46 -0800 Subject: [PATCH 060/121] optimizations --- evm/src/cpu/kernel/asm/hash/sha2/main.asm | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/evm/src/cpu/kernel/asm/hash/sha2/main.asm b/evm/src/cpu/kernel/asm/hash/sha2/main.asm index 058224f6..e47d1838 100644 --- a/evm/src/cpu/kernel/asm/hash/sha2/main.asm +++ b/evm/src/cpu/kernel/asm/hash/sha2/main.asm @@ -19,9 +19,7 @@ global sha2_pad: // STEP 1: append 1 // insert 128 (= 1 << 7) at x[num_bytes+1] // stack: num_bytes, retdest - PUSH 1 - PUSH 7 - SHL + PUSH 0x80 // stack: 128, num_bytes, retdest DUP2 // stack: num_bytes, 128, num_bytes, retdest @@ -33,21 +31,19 @@ global sha2_pad: DUP1 // stack: num_bytes, num_bytes, retdest %add_const(8) - %div_const(64) + %shr_const(6) %increment // stack: num_blocks = (num_bytes+8)//64 + 1, num_bytes, retdest // STEP 3: calculate length := num_bytes*8 SWAP1 // stack: num_bytes, num_blocks, retdest - PUSH 8 - MUL + %mul_const(8) // stack: length = num_bytes*8, num_blocks, retdest // STEP 4: write length to x[num_blocks*64-7..num_blocks*64] DUP2 // stack: num_blocks, length, num_blocks, retdest - PUSH 64 - MUL + %mul_const(64) // stack: last_addr = num_blocks*64, length, num_blocks, retdest %sha2_write_length // stack: num_blocks, retdest From 424d8d221642ab91ea341adb5b04fdf80c280b36 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Mon, 27 Feb 2023 15:29:23 -0800 Subject: [PATCH 061/121] more optimizations --- .../kernel/asm/hash/sha2/message_schedule.asm | 31 +++++-------------- 1 file changed, 7 insertions(+), 24 deletions(-) diff --git a/evm/src/cpu/kernel/asm/hash/sha2/message_schedule.asm b/evm/src/cpu/kernel/asm/hash/sha2/message_schedule.asm index c8bfae7e..d8f0500d 100644 --- a/evm/src/cpu/kernel/asm/hash/sha2/message_schedule.asm +++ b/evm/src/cpu/kernel/asm/hash/sha2/message_schedule.asm @@ -59,10 +59,9 @@ gen_message_schedule_from_block_0_loop: gen_message_schedule_from_block_0_end: // stack: old counter=0, output_addr, block[0], block[1], retdest POP - PUSH 8 - // stack: counter=8, output_addr, block[0], block[1], retdest - %stack (counter, out, b0, b1) -> (out, counter, b1, b0) - // stack: output_addr, counter, block[1], block[0], retdest + // stack: output_addr, block[0], block[1], retdest + %stack (out, b0, b1) -> (out, 8, b1, b0) + // stack: output_addr, counter=8, block[1], block[0], retdest %add_const(64) // stack: output_addr + 64, counter, block[1], block[0], retdest SWAP1 @@ -114,11 +113,7 @@ gen_message_schedule_remaining_loop: // stack: output_addr, counter, block[0], block[1], retdest DUP1 // stack: output_addr, output_addr, counter, block[0], block[1], retdest - PUSH 2 - PUSH 4 - MUL - SWAP1 - SUB + %sub_const(8) // stack: output_addr - 2*4, output_addr, counter, block[0], block[1], retdest %mload_kernel_general_u32 // stack: x[output_addr - 2*4], output_addr, counter, block[0], block[1], retdest @@ -128,11 +123,7 @@ gen_message_schedule_remaining_loop: // stack: output_addr, sigma_1(x[output_addr - 2*4]), counter, block[0], block[1], retdest DUP1 // stack: output_addr, output_addr, sigma_1(x[output_addr - 2*4]), counter, block[0], block[1], retdest - PUSH 7 - PUSH 4 - MUL - SWAP1 - SUB + %sub_const(28) // stack: output_addr - 7*4, output_addr, sigma_1(x[output_addr - 2*4]), counter, block[0], block[1], retdest %mload_kernel_general_u32 // stack: x[output_addr - 7*4], output_addr, sigma_1(x[output_addr - 2*4]), counter, block[0], block[1], retdest @@ -140,11 +131,7 @@ gen_message_schedule_remaining_loop: // stack: output_addr, x[output_addr - 7*4], sigma_1(x[output_addr - 2*4]), counter, block[0], block[1], retdest DUP1 // stack: output_addr, output_addr, x[output_addr - 7*4], sigma_1(x[output_addr - 2*4]), counter, block[0], block[1], retdest - PUSH 15 - PUSH 4 - MUL - SWAP1 - SUB + %sub_const(60) // stack: output_addr - 15*4, output_addr, x[output_addr - 7*4], sigma_1(x[output_addr - 2*4]), counter, block[0], block[1], retdest %mload_kernel_general_u32 // stack: x[output_addr - 15*4], output_addr, x[output_addr - 7*4], sigma_1(x[output_addr - 2*4]), counter, block[0], block[1], retdest @@ -154,11 +141,7 @@ gen_message_schedule_remaining_loop: // stack: output_addr, sigma_0(x[output_addr - 15*4]), x[output_addr - 7*4], sigma_1(x[output_addr - 2*4]), counter, block[0], block[1], retdest DUP1 // stack: output_addr, output_addr, sigma_0(x[output_addr - 15*4]), x[output_addr - 7*4], sigma_1(x[output_addr - 2*4]), counter, block[0], block[1], retdest - PUSH 16 - PUSH 4 - MUL - SWAP1 - SUB + %sub_const(64) // stack: output_addr - 16*4, output_addr, sigma_0(x[output_addr - 15*4]), x[output_addr - 7*4], sigma_1(x[output_addr - 2*4]), counter, block[0], block[1], retdest %mload_kernel_general_u32 // stack: x[output_addr - 16*4], output_addr, sigma_0(x[output_addr - 15*4]), x[output_addr - 7*4], sigma_1(x[output_addr - 2*4]), counter, block[0], block[1], retdest From de6f01f4b6aeedd7a046264049083645cb173bf4 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Wed, 8 Mar 2023 13:50:31 -0800 Subject: [PATCH 062/121] small optimizations --- .../cpu/kernel/asm/hash/sha2/compression.asm | 9 +++- evm/src/cpu/kernel/asm/hash/sha2/ops.asm | 51 ++++++++++++------- 2 files changed, 39 insertions(+), 21 deletions(-) diff --git a/evm/src/cpu/kernel/asm/hash/sha2/compression.asm b/evm/src/cpu/kernel/asm/hash/sha2/compression.asm index 107d20b1..0bceb715 100644 --- a/evm/src/cpu/kernel/asm/hash/sha2/compression.asm +++ b/evm/src/cpu/kernel/asm/hash/sha2/compression.asm @@ -65,11 +65,16 @@ compression_loop: // stack: sha2_constants_k + 4*i, W[i], a[i], b[i], c[i], d[i], e[i], f[i], g[i], h[i], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]..h[0], retdest %mload_kernel_code_u32 // stack: K[i], W[i], a[i], b[i], c[i], d[i], e[i], f[i], g[i], h[i], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]..h[0], retdest - %stack (start: 6, e, f, g, h) -> (e, f, g, h, start, e, f, g, h) + DUP10 + DUP10 + DUP10 + DUP10 // stack: e[i], f[i], g[i], h[i], K[i], W[i], a[i], b[i], c[i], d[i], e[i], f[i], g[i], h[i], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]..h[0], retdest %sha2_temp_word1 // stack: T1[i], a[i], b[i], c[i], d[i], e[i], f[i], g[i], h[i], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]..h[0], retdest - %stack (t, a, b, c) -> (a, b, c, t, a, b, c) + DUP4 + DUP4 + DUP4 // stack: a[i], b[i], c[i], T1[i], a[i], b[i], c[i], d[i], e[i], f[i], g[i], h[i], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]..h[0], retdest %sha2_temp_word2 // stack: T2[i], T1[i], a[i], b[i], c[i], d[i], e[i], f[i], g[i], h[i], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]..h[0], retdest diff --git a/evm/src/cpu/kernel/asm/hash/sha2/ops.asm b/evm/src/cpu/kernel/asm/hash/sha2/ops.asm index 7d8054ca..d50e5c9a 100644 --- a/evm/src/cpu/kernel/asm/hash/sha2/ops.asm +++ b/evm/src/cpu/kernel/asm/hash/sha2/ops.asm @@ -26,14 +26,15 @@ // stack: x, x %rotr(7) // stack: rotr(x, 7), x - %stack (rotated, x) -> (x, x, rotated) + SWAP1 + // stack: x, rotr(x, 7) + DUP1 // stack: x, x, rotr(x, 7) %rotr(18) // stack: rotr(x, 18), x, rotr(x, 7) SWAP1 // stack: x, rotr(x, 18), rotr(x, 7) - PUSH 3 - SHR + %shr_const(3) // stack: shr(x, 3), rotr(x, 18), rotr(x, 7) XOR XOR @@ -45,7 +46,9 @@ // stack: x, x %rotr(17) // stack: rotr(x, 17), x - %stack (rotated, x) -> (x, x, rotated) + SWAP1 + // stack: x, rotr(x, 17) + DUP1 // stack: x, x, rotr(x, 17) %rotr(19) // stack: rotr(x, 19), x, rotr(x, 17) @@ -64,7 +67,9 @@ // stack: x, x %rotr(2) // stack: rotr(x, 2), x - %stack (rotated, x) -> (x, x, rotated) + SWAP1 + // stack: x, rotr(x, 2) + DUP1 // stack: x, x, rotr(x, 2) %rotr(13) // stack: rotr(x, 13), x, rotr(x, 2) @@ -82,7 +87,9 @@ // stack: x, x %rotr(6) // stack: rotr(x, 6), x - %stack (rotated, x) -> (x, x, rotated) + SWAP1 + // stack: x, rotr(x, 6) + DUP1 // stack: x, x, rotr(x, 6) %rotr(11) // stack: rotr(x, 11), x, rotr(x, 6) @@ -100,11 +107,13 @@ // stack: x, x, y, z NOT // stack: not x, x, y, z - %stack (notx, x, y, z) -> (notx, z, x, y) - // stack: not x, z, x, y + SWAP1 + // stack: x, not x, y, z + SWAP3 + // stack: z, not x, y, x AND - // stack: (not x) and z, x, y - %stack (nxz, x, y) -> (x, y, nxz) + // stack: (not x) and z, y, x + SWAP2 // stack: x, y, (not x) and z AND // stack: x and y, (not x) and z @@ -113,18 +122,22 @@ %macro sha2_majority // stack: x, y, z - %stack (xyz: 3) -> (xyz, xyz) - // stack: x, y, z, x, y, z + DUP1 + // stack: x, x, y, z + DUP3 + // stack: y, x, x, y, z + DUP5 + // stack: z, y, x, x, y, z AND - // stack: x and y, z, x, y, z + // stack: z and y, x, x, y, z + SWAP4 + // stack: z, x, x, y, z and y + AND + // stack: z and x, x, y, z and y SWAP2 - // stack: x, z, x and y, y, z + // stack: y, x, z and x, z and y AND - // stack: x and z, x and y, y, z - %stack (a: 2, b: 2) -> (b, a) - // stack: y, z, x and z, x and y - AND - // stack: y and z, x and z, x and y + // stack: y and x, z and x, z and y OR OR %endmacro From d4a485ece54c34b8d32fab9673f3337e4af2af1f Mon Sep 17 00:00:00 2001 From: Daniel Lubarov Date: Wed, 15 Mar 2023 11:23:29 -0700 Subject: [PATCH 063/121] Log stack on panic --- evm/src/cpu/kernel/asm/core/transfer.asm | 1 + evm/src/generation/state.rs | 7 +++++++ evm/src/witness/transition.rs | 16 +++++++++------- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/evm/src/cpu/kernel/asm/core/transfer.asm b/evm/src/cpu/kernel/asm/core/transfer.asm index 0ba99fd8..05582e6e 100644 --- a/evm/src/cpu/kernel/asm/core/transfer.asm +++ b/evm/src/cpu/kernel/asm/core/transfer.asm @@ -73,6 +73,7 @@ global deduct_eth_insufficient_balance: // Pre stack: addr, amount, redest // Post stack: (empty) +// TODO: Should it be copy-on-write instead of mutating the trie? global add_eth: // stack: addr, amount, retdest DUP1 %mpt_read_state_trie diff --git a/evm/src/generation/state.rs b/evm/src/generation/state.rs index 88f17ade..8bbaa0f2 100644 --- a/evm/src/generation/state.rs +++ b/evm/src/generation/state.rs @@ -7,6 +7,7 @@ use crate::generation::GenerationInputs; use crate::witness::memory::MemoryState; use crate::witness::state::RegistersState; use crate::witness::traces::{TraceCheckpoint, Traces}; +use crate::witness::util::stack_peek; pub(crate) struct GenerationStateCheckpoint { pub(crate) registers: RegistersState, @@ -67,4 +68,10 @@ impl GenerationState { self.registers = checkpoint.registers; self.traces.rollback(checkpoint.traces); } + + pub(crate) fn stack(&self) -> Vec { + (0..self.registers.stack_len) + .map(|i| stack_peek(self, i).unwrap()) + .collect() + } } diff --git a/evm/src/witness/transition.rs b/evm/src/witness/transition.rs index ff10b08b..d48561db 100644 --- a/evm/src/witness/transition.rs +++ b/evm/src/witness/transition.rs @@ -1,5 +1,4 @@ use anyhow::bail; -use itertools::Itertools; use log::log_enabled; use plonky2::field::types::Field; @@ -12,7 +11,7 @@ use crate::witness::gas::gas_to_charge; use crate::witness::memory::MemoryAddress; use crate::witness::operation::*; use crate::witness::state::RegistersState; -use crate::witness::util::{mem_read_code_with_log_and_fill, stack_peek}; +use crate::witness::util::mem_read_code_with_log_and_fill; use crate::{arithmetic, logic}; fn read_code_memory(state: &mut GenerationState, row: &mut CpuColumnsView) -> u8 { @@ -121,7 +120,7 @@ fn decode(registers: RegistersState, opcode: u8) -> Result { log::warn!( "Kernel panic at {}", - KERNEL.offset_name(registers.program_counter) + KERNEL.offset_name(registers.program_counter), ); Err(ProgramError::KernelPanic) } @@ -284,9 +283,7 @@ fn log_kernel_instruction(state: &mut GenerationState, op: Operatio state.registers.context, KERNEL.offset_name(pc), op, - (0..state.registers.stack_len) - .map(|i| stack_peek(state, i).unwrap()) - .collect_vec() + state.stack() ); assert!(pc < KERNEL.code.len(), "Kernel PC is out of range: {}", pc); @@ -310,7 +307,12 @@ pub(crate) fn transition(state: &mut GenerationState) -> anyhow::Re Err(e) => { if state.registers.is_kernel { let offset_name = KERNEL.offset_name(state.registers.program_counter); - bail!("exception in kernel mode at {}: {:?}", offset_name, e); + bail!( + "{:?} in kernel at pc={}, stack={:?}", + e, + offset_name, + state.stack() + ); } state.rollback(checkpoint); handle_error(state) From e57358bcbd44e74caa30f28ffcf7d7d2e7863b0a Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Wed, 15 Mar 2023 13:28:00 -0700 Subject: [PATCH 064/121] ge -> cmp and returns 0, 1, -1 --- evm/src/cpu/kernel/aggregator.rs | 2 +- .../cpu/kernel/asm/bignum/{ge.asm => cmp.asm} | 12 ++++---- evm/src/cpu/kernel/tests/bignum.rs | 30 ++++++++++++------- 3 files changed, 27 insertions(+), 17 deletions(-) rename evm/src/cpu/kernel/asm/bignum/{ge.asm => cmp.asm} (91%) diff --git a/evm/src/cpu/kernel/aggregator.rs b/evm/src/cpu/kernel/aggregator.rs index b82bacaf..bb861ade 100644 --- a/evm/src/cpu/kernel/aggregator.rs +++ b/evm/src/cpu/kernel/aggregator.rs @@ -15,7 +15,7 @@ pub(crate) fn combined_kernel() -> Kernel { "global jumped_to_1: PANIC", include_str!("asm/bignum/add.asm"), include_str!("asm/bignum/addmul.asm"), - include_str!("asm/bignum/ge.asm"), + include_str!("asm/bignum/cmp.asm"), include_str!("asm/bignum/iszero.asm"), include_str!("asm/bignum/mul.asm"), include_str!("asm/bignum/shr.asm"), diff --git a/evm/src/cpu/kernel/asm/bignum/ge.asm b/evm/src/cpu/kernel/asm/bignum/cmp.asm similarity index 91% rename from evm/src/cpu/kernel/asm/bignum/ge.asm rename to evm/src/cpu/kernel/asm/bignum/cmp.asm index e7f5aca2..ff8fb3e6 100644 --- a/evm/src/cpu/kernel/asm/bignum/ge.asm +++ b/evm/src/cpu/kernel/asm/bignum/cmp.asm @@ -2,8 +2,8 @@ // All integers must be under a given length bound, and are padded with leading zeroes. // Compares two bignums of the same given length. Assumes that len > 0. -// Returns 1 if a > b, 3 if a == b, and 0 if a < b. -global ge_bignum: +// Returns 1 if a > b, 0 if a == b, and -1 (that is, 2^256 - 1) if a < b. +global cmp_bignum: // stack: len, a_start_loc, b_start_loc, retdest SWAP1 // stack: a_start_loc, len, b_start_loc, retdest @@ -59,8 +59,8 @@ equal: // stack: i, a_i_loc, b_i_loc, retdest %pop3 // stack: retdest - PUSH 3 - // stack: 3, retdest + PUSH 0 + // stack: 0, retdest SWAP1 JUMP greater: @@ -75,7 +75,7 @@ less: // stack: i, a_i_loc, b_i_loc, retdest %pop3 // stack: retdest - PUSH 0 - // stack: 0, retdest + PUSH 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + // stack: -1, retdest SWAP1 JUMP diff --git a/evm/src/cpu/kernel/tests/bignum.rs b/evm/src/cpu/kernel/tests/bignum.rs index 141761ba..9dbcf6b7 100644 --- a/evm/src/cpu/kernel/tests/bignum.rs +++ b/evm/src/cpu/kernel/tests/bignum.rs @@ -179,14 +179,14 @@ where Ok(()) } -fn test_ge_bignum(prepare_two_bignums_fn: &F) -> Result<()> +fn test_cmp_bignum(prepare_two_bignums_fn: &F) -> Result<()> where F: Fn(usize) -> (BigUint, BigUint, U256, Vec), { let (_a, _b, length, memory) = prepare_two_bignums_fn(1000); let retdest = 0xDEADBEEFu32.into(); - let ge_bignum = KERNEL.global_labels["ge_bignum"]; + let cmp_bignum = KERNEL.global_labels["cmp_bignum"]; let a_start_loc = 0.into(); let b_start_loc = length; @@ -194,7 +194,7 @@ where // Test with a > b. let mut initial_stack: Vec = vec![length, a_start_loc, b_start_loc, retdest]; initial_stack.reverse(); - let mut interpreter = Interpreter::new_with_kernel(ge_bignum, initial_stack); + let mut interpreter = Interpreter::new_with_kernel(cmp_bignum, initial_stack); interpreter.set_kernel_general_memory(memory.clone()); interpreter.run()?; let result = interpreter.stack()[0]; @@ -203,11 +203,21 @@ where // Swap a and b, to test the less-than case. let mut initial_stack: Vec = vec![length, b_start_loc, a_start_loc, retdest]; initial_stack.reverse(); - let mut interpreter = Interpreter::new_with_kernel(ge_bignum, initial_stack); + let mut interpreter = Interpreter::new_with_kernel(cmp_bignum, initial_stack); + interpreter.set_kernel_general_memory(memory.clone()); + interpreter.run()?; + let result = interpreter.stack()[0]; + let minus_one = ((U256::one() << 255) - 1) * 2 + 1; + assert_eq!(result, minus_one); + + // Test equal case. + let mut initial_stack: Vec = vec![length, a_start_loc, a_start_loc, retdest]; + initial_stack.reverse(); + let mut interpreter = Interpreter::new_with_kernel(cmp_bignum, initial_stack); interpreter.set_kernel_general_memory(memory); interpreter.run()?; let result = interpreter.stack()[0]; - assert_eq!(result, 0.into()); + assert_eq!(result, U256::zero()); Ok(()) } @@ -350,11 +360,11 @@ fn test_iszero_bignum_all() -> Result<()> { } #[test] -fn test_ge_bignum_all() -> Result<()> { - test_ge_bignum(&prepare_two_bignums_random)?; - test_ge_bignum(&prepare_two_bignums_max)?; - test_ge_bignum(&prepare_two_bignums_min)?; - test_ge_bignum(&prepare_two_bignums_diff)?; +fn test_cmp_bignum_all() -> Result<()> { + test_cmp_bignum(&prepare_two_bignums_random)?; + test_cmp_bignum(&prepare_two_bignums_max)?; + test_cmp_bignum(&prepare_two_bignums_min)?; + test_cmp_bignum(&prepare_two_bignums_diff)?; Ok(()) } From 0627633439a369f9dc8bdd54aa8f0365ae93921c Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Wed, 15 Mar 2023 13:39:43 -0700 Subject: [PATCH 065/121] carry -> carry_limb --- evm/src/cpu/kernel/asm/bignum/addmul.asm | 90 ++++++++++++------------ evm/src/cpu/kernel/asm/bignum/mul.asm | 24 +++---- evm/src/cpu/kernel/tests/bignum.rs | 4 +- 3 files changed, 59 insertions(+), 59 deletions(-) diff --git a/evm/src/cpu/kernel/asm/bignum/addmul.asm b/evm/src/cpu/kernel/asm/bignum/addmul.asm index 9e4ce2ba..3dbb1cd3 100644 --- a/evm/src/cpu/kernel/asm/bignum/addmul.asm +++ b/evm/src/cpu/kernel/asm/bignum/addmul.asm @@ -1,7 +1,7 @@ // Arithmetic on little-endian integers represented with 128-bit limbs. // All integers must be under a given length bound, and are padded with leading zeroes. -// Sets a[0:len] += b[0:len] * val, and returns the carry. +// Sets a[0:len] += b[0:len] * val, and returns the carry (a limb of up to 128 bits). global addmul_bignum: // stack: len, a_start_loc, b_start_loc, val, retdest DUP1 @@ -9,103 +9,103 @@ global addmul_bignum: ISZERO %jumpi(len_zero) PUSH 0 - // stack: carry=0, i=len, a_cur_loc=a_start_loc, b_cur_loc=b_start_loc, val, retdest + // stack: carry_limb=0, i=len, a_cur_loc=a_start_loc, b_cur_loc=b_start_loc, val, retdest addmul_loop: - // stack: carry, i, a_cur_loc, b_cur_loc, val, retdest + // stack: carry_limb, i, a_cur_loc, b_cur_loc, val, retdest DUP4 - // stack: b_cur_loc, carry, i, a_cur_loc, b_cur_loc, val, retdest + // stack: b_cur_loc, carry_limb, i, a_cur_loc, b_cur_loc, val, retdest %mload_kernel_general - // stack: b[cur], carry, i, a_cur_loc, b_cur_loc, val, retdest + // stack: b[cur], carry_limb, i, a_cur_loc, b_cur_loc, val, retdest DUP6 - // stack: val, b[cur], carry, i, a_cur_loc, b_cur_loc, val, retdest + // stack: val, b[cur], carry_limb, i, a_cur_loc, b_cur_loc, val, retdest MUL - // stack: val * b[cur], carry, i, a_cur_loc, b_cur_loc, val, retdest + // stack: val * b[cur], carry_limb, i, a_cur_loc, b_cur_loc, val, retdest DUP1 - // stack: val * b[cur], val * b[cur], carry, i, a_cur_loc, b_cur_loc, val, retdest + // stack: val * b[cur], val * b[cur], carry_limb, i, a_cur_loc, b_cur_loc, val, retdest %shr_const(128) - // stack: (val * b[cur]) // 2^128, val * b[cur], carry, i, a_cur_loc, b_cur_loc, val, retdest + // stack: (val * b[cur]) // 2^128, val * b[cur], carry_limb, i, a_cur_loc, b_cur_loc, val, retdest SWAP1 - // stack: val * b[cur], (val * b[cur]) // 2^128, carry, i, a_cur_loc, b_cur_loc, val, retdest + // stack: val * b[cur], (val * b[cur]) // 2^128, carry_limb, i, a_cur_loc, b_cur_loc, val, retdest %shl_const(128) %shr_const(128) - // stack: prod_lo = val * b[cur] % 2^128, prod_hi = (val * b[cur]) // 2^128, carry, i, a_cur_loc, b_cur_loc, val, retdest + // stack: prod_lo = val * b[cur] % 2^128, prod_hi = (val * b[cur]) // 2^128, carry_limb, i, a_cur_loc, b_cur_loc, val, retdest DUP5 - // stack: a_cur_loc, prod_lo, prod_hi, carry, i, a_cur_loc, b_cur_loc, val, retdest + // stack: a_cur_loc, prod_lo, prod_hi, carry_limb, i, a_cur_loc, b_cur_loc, val, retdest %mload_kernel_general - // stack: a[cur], prod_lo, prod_hi, carry, i, a_cur_loc, b_cur_loc, val, retdest + // stack: a[cur], prod_lo, prod_hi, carry_limb, i, a_cur_loc, b_cur_loc, val, retdest DUP1 - // stack: a[cur], a[cur], prod_lo, prod_hi, carry, i, a_cur_loc, b_cur_loc, val, retdest + // stack: a[cur], a[cur], prod_lo, prod_hi, carry_limb, i, a_cur_loc, b_cur_loc, val, retdest SWAP2 - // stack: prod_lo, a[cur], a[cur], prod_hi, carry, i, a_cur_loc, b_cur_loc, val, retdest + // stack: prod_lo, a[cur], a[cur], prod_hi, carry_limb, i, a_cur_loc, b_cur_loc, val, retdest ADD %shl_const(128) %shr_const(128) - // stack: prod_lo' = (prod_lo + a[cur]) % 2^128, a[cur], prod_hi, carry, i, a_cur_loc, b_cur_loc, val, retdest + // stack: prod_lo' = (prod_lo + a[cur]) % 2^128, a[cur], prod_hi, carry_limb, i, a_cur_loc, b_cur_loc, val, retdest DUP1 - // stack: prod_lo', prod_lo', a[cur], prod_hi, carry, i, a_cur_loc, b_cur_loc, val, retdest + // stack: prod_lo', prod_lo', a[cur], prod_hi, carry_limb, i, a_cur_loc, b_cur_loc, val, retdest SWAP2 - // stack: a[cur], prod_lo', prod_lo', prod_hi, carry, i, a_cur_loc, b_cur_loc, val, retdest + // stack: a[cur], prod_lo', prod_lo', prod_hi, carry_limb, i, a_cur_loc, b_cur_loc, val, retdest GT - // stack: prod_lo_carry = a[cur] > prod_lo', prod_lo', prod_hi, carry, i, a_cur_loc, b_cur_loc, val, retdest + // stack: prod_lo_carry_limb = a[cur] > prod_lo', prod_lo', prod_hi, carry_limb, i, a_cur_loc, b_cur_loc, val, retdest SWAP1 - // stack: prod_lo', prod_lo_carry, prod_hi, carry, i, a_cur_loc, b_cur_loc, val, retdest + // stack: prod_lo', prod_lo_carry_limb, prod_hi, carry_limb, i, a_cur_loc, b_cur_loc, val, retdest SWAP2 - // stack: prod_hi, prod_lo_carry, prod_lo', carry, i, a_cur_loc, b_cur_loc, val, retdest + // stack: prod_hi, prod_lo_carry_limb, prod_lo', carry_limb, i, a_cur_loc, b_cur_loc, val, retdest ADD - // stack: prod_hi' = prod_hi + prod_lo_carry, prod_lo', carry, i, a_cur_loc, b_cur_loc, val, retdest + // stack: prod_hi' = prod_hi + prod_lo_carry_limb, prod_lo', carry_limb, i, a_cur_loc, b_cur_loc, val, retdest DUP3 - // stack: carry, prod_hi', prod_lo', carry, i, a_cur_loc, b_cur_loc, val, retdest + // stack: carry_limb, prod_hi', prod_lo', carry_limb, i, a_cur_loc, b_cur_loc, val, retdest DUP3 - // stack: prod_lo', carry, prod_hi', prod_lo', carry, i, a_cur_loc, b_cur_loc, val, retdest + // stack: prod_lo', carry_limb, prod_hi', prod_lo', carry_limb, i, a_cur_loc, b_cur_loc, val, retdest ADD %shl_const(128) %shr_const(128) - // stack: to_write = (prod_lo' + carry) % 2^128, prod_hi', prod_lo', carry, i, a_cur_loc, b_cur_loc, val, retdest + // stack: to_write = (prod_lo' + carry_limb) % 2^128, prod_hi', prod_lo', carry_limb, i, a_cur_loc, b_cur_loc, val, retdest SWAP2 - // stack: prod_lo', prod_hi', to_write, carry, i, a_cur_loc, b_cur_loc, val, retdest + // stack: prod_lo', prod_hi', to_write, carry_limb, i, a_cur_loc, b_cur_loc, val, retdest DUP3 - // stack: to_write, prod_lo', prod_hi', to_write, carry, i, a_cur_loc, b_cur_loc, val, retdest + // stack: to_write, prod_lo', prod_hi', to_write, carry_limb, i, a_cur_loc, b_cur_loc, val, retdest LT - // stack: carry_new = to_write < prod_lo', prod_hi', to_write, carry, i, a_cur_loc, b_cur_loc, val, retdest + // stack: carry_limb_new = to_write < prod_lo', prod_hi', to_write, carry_limb, i, a_cur_loc, b_cur_loc, val, retdest %stack (vals: 3, c) -> (vals) - // stack: carry_new, prod_hi', to_write, i, a_cur_loc, b_cur_loc, val, retdest + // stack: carry_limb_new, prod_hi', to_write, i, a_cur_loc, b_cur_loc, val, retdest ADD - // stack: carry = carry_new' + prod_hi', to_write, i, a_cur_loc, b_cur_loc, val, retdest + // stack: carry_limb = carry_limb_new' + prod_hi', to_write, i, a_cur_loc, b_cur_loc, val, retdest SWAP1 - // stack: to_write, carry, i, a_cur_loc, b_cur_loc, val, retdest + // stack: to_write, carry_limb, i, a_cur_loc, b_cur_loc, val, retdest DUP4 - // stack: a_cur_loc, to_write, carry, i, a_cur_loc, b_cur_loc, val, retdest + // stack: a_cur_loc, to_write, carry_limb, i, a_cur_loc, b_cur_loc, val, retdest %mstore_kernel_general - // stack: carry, i, a_cur_loc, b_cur_loc, val, retdest + // stack: carry_limb, i, a_cur_loc, b_cur_loc, val, retdest SWAP1 - // stack: i, carry, a_cur_loc, b_cur_loc, val, retdest + // stack: i, carry_limb, a_cur_loc, b_cur_loc, val, retdest %decrement - // stack: i-1, carry, a_cur_loc, b_cur_loc, val, retdest + // stack: i-1, carry_limb, a_cur_loc, b_cur_loc, val, retdest SWAP2 - // stack: a_cur_loc, carry, i-1, b_cur_loc, val, retdest + // stack: a_cur_loc, carry_limb, i-1, b_cur_loc, val, retdest %increment - // stack: a_cur_loc+1, carry, i-1, b_cur_loc, val, retdest + // stack: a_cur_loc+1, carry_limb, i-1, b_cur_loc, val, retdest SWAP3 - // stack: b_cur_loc, carry, i-1, a_cur_loc+1, val, retdest + // stack: b_cur_loc, carry_limb, i-1, a_cur_loc+1, val, retdest %increment - // stack: b_cur_loc+1, carry, i-1, a_cur_loc+1, val, retdest + // stack: b_cur_loc+1, carry_limb, i-1, a_cur_loc+1, val, retdest %stack (b, c, i, a) -> (c, i, a, b) - // stack: carry, i-1, a_cur_loc+1, b_cur_loc+1, val, retdest + // stack: carry_limb, i-1, a_cur_loc+1, b_cur_loc+1, val, retdest DUP2 - // stack: i-1, carry, i-1, a_cur_loc+1, b_cur_loc+1, val, retdest + // stack: i-1, carry_limb, i-1, a_cur_loc+1, b_cur_loc+1, val, retdest %jumpi(addmul_loop) addmul_end: - // stack: carry_new, i-1, a_cur_loc+1, b_cur_loc+1, val, retdest + // stack: carry_limb_new, i-1, a_cur_loc+1, b_cur_loc+1, val, retdest %stack (c, i, a, b, v) -> (c) - // stack: carry_new, retdest + // stack: carry_limb_new, retdest SWAP1 - // stack: retdest, carry_new + // stack: retdest, carry_limb_new JUMP len_zero: // stack: len, a_start_loc, b_start_loc, val, retdest %pop4 // stack: retdest PUSH 0 - // stack: carry=0, retdest + // stack: carry_limb=0, retdest SWAP1 JUMP diff --git a/evm/src/cpu/kernel/asm/bignum/mul.asm b/evm/src/cpu/kernel/asm/bignum/mul.asm index cbf6a645..a7d19fb5 100644 --- a/evm/src/cpu/kernel/asm/bignum/mul.asm +++ b/evm/src/cpu/kernel/asm/bignum/mul.asm @@ -14,27 +14,27 @@ global mul_bignum: // stack: n=len, len, a_start_loc, bi=b_start_loc, output_cur=output_loc, retdest mul_loop: // stack: n, len, a_start_loc, bi, output_cur, retdest - PUSH mul_return - // stack: mul_return, n, len, a_start_loc, bi, output_cur, retdest + PUSH mul_addmul_return + // stack: mul_addmul_return, n, len, a_start_loc, bi, output_cur, retdest DUP5 - // stack: bi, mul_return, n, len, a_start_loc, bi, output_cur, retdest + // stack: bi, mul_addmul_return, n, len, a_start_loc, bi, output_cur, retdest %mload_kernel_general - // stack: b[i], mul_return, n, len, a_start_loc, bi, output_cur, retdest, b + // stack: b[i], mul_addmul_return, n, len, a_start_loc, bi, output_cur, retdest, b DUP5 - // stack: a_start_loc, b[i], mul_return, n, len, a_start_loc, bi, output_cur, retdest, b + // stack: a_start_loc, b[i], mul_addmul_return, n, len, a_start_loc, bi, output_cur, retdest, b DUP8 - // stack: output_loc, a_start_loc, b[i], mul_return, n, len, a_start_loc, bi, output_cur, retdest, b + // stack: output_loc, a_start_loc, b[i], mul_addmul_return, n, len, a_start_loc, bi, output_cur, retdest, b DUP6 - // stack: len, output_loc, a_start_loc, b[i], mul_return, n, len, a_start_loc, bi, output_cur, retdest, b + // stack: len, output_loc, a_start_loc, b[i], mul_addmul_return, n, len, a_start_loc, bi, output_cur, retdest, b %jump(addmul_bignum) -mul_return: - // stack: carry, n, len, a_start_loc, bi, output_cur, retdest +mul_addmul_return: + // stack: carry_limb, n, len, a_start_loc, bi, output_cur, retdest DUP6 - // stack: output_cur, carry, n, len, a_start_loc, bi, output_cur, retdest + // stack: output_cur, carry_limb, n, len, a_start_loc, bi, output_cur, retdest DUP4 - // stack: len, output_cur, carry, n, len, a_start_loc, bi, output_cur, retdest + // stack: len, output_cur, carry_limb, n, len, a_start_loc, bi, output_cur, retdest ADD - // stack: output_cur + len, carry, n, len, a_start_loc, bi, output_cur, retdest + // stack: output_cur + len, carry_limb, n, len, a_start_loc, bi, output_cur, retdest %mstore_kernel_general // stack: n, len, a_start_loc, bi, output_cur, retdest %decrement diff --git a/evm/src/cpu/kernel/tests/bignum.rs b/evm/src/cpu/kernel/tests/bignum.rs index 9dbcf6b7..0dd02bfa 100644 --- a/evm/src/cpu/kernel/tests/bignum.rs +++ b/evm/src/cpu/kernel/tests/bignum.rs @@ -291,9 +291,9 @@ where interpreter.run()?; // Determine actual result. - let carry = interpreter.stack()[0]; + let carry_limb = interpreter.stack()[0]; let mut new_memory = interpreter.get_kernel_general_memory(); - new_memory[len] = carry; + new_memory[len] = carry_limb; let actual_result: Vec<_> = new_memory[..expected_result.len()].into(); // Compare. From ad38f957415b93a0bf6093b7b3d7fb98c7644387 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Wed, 15 Mar 2023 13:45:55 -0700 Subject: [PATCH 066/121] TODO for possible future mul optimization --- evm/src/cpu/kernel/asm/bignum/mul.asm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/evm/src/cpu/kernel/asm/bignum/mul.asm b/evm/src/cpu/kernel/asm/bignum/mul.asm index a7d19fb5..8317fdbc 100644 --- a/evm/src/cpu/kernel/asm/bignum/mul.asm +++ b/evm/src/cpu/kernel/asm/bignum/mul.asm @@ -4,6 +4,8 @@ // Stores a * b in output_loc, leaving a and b unchanged. // Both a and b have length len; a * b will have length 2 * len. // output_loc must be initialized as 2 * len zeroes. +// TODO: possible optimization: allow output_loc to be uninitialized, and write over it with a[0:len] * b[0] (a multiplication +// with carry) in place of the first addmul. global mul_bignum: // stack: len, a_start_loc, b_start_loc, output_loc, retdest DUP1 From 4ef981e415bb63171a0eb38ce92b5181dc5dae62 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Wed, 15 Mar 2023 14:19:54 -0700 Subject: [PATCH 067/121] initial test data --- evm/src/cpu/kernel/tests/bignum.rs | 35 +++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/evm/src/cpu/kernel/tests/bignum.rs b/evm/src/cpu/kernel/tests/bignum.rs index 0dd02bfa..cc6b972e 100644 --- a/evm/src/cpu/kernel/tests/bignum.rs +++ b/evm/src/cpu/kernel/tests/bignum.rs @@ -1,3 +1,5 @@ +use std::f32::MIN; + use anyhow::Result; use ethereum_types::U256; use itertools::Itertools; @@ -8,9 +10,37 @@ use rand::Rng; use crate::cpu::kernel::aggregator::KERNEL; use crate::cpu::kernel::interpreter::Interpreter; -use crate::util::{biguint_to_mem_vec, mem_vec_to_biguint}; +use crate::util::{biguint_to_mem_vec, mem_vec_to_biguint, u256_to_biguint}; const BIGNUM_LIMB_BITS: usize = 128; +const MINUS_ONE: U256 = U256::MAX; + +fn test_data() -> Vec> { + let unary_op_inputs = vec![0u8.into(), 1u8.into(), 2u8.into()]; + + let shr_outputs = vec![0u8.into(), 0u8.into(), 1u8.into()]; + let iszero_outputs = vec![1u8.into(), 0u8.into(), 0u8.into()]; + + let binary_op_first_inputs = vec![0u8.into(), 1u8.into(), 2u8.into()]; + let binary_op_second_inputs = vec![0u8.into(), 2u8.into(), 1u8.into()]; + + let cmp_outputs = vec![0u8.into(), u256_to_biguint(MINUS_ONE), 1u8.into()]; + let add_outputs = vec![0u8.into(), 3u8.into(), 3u8.into()]; + let addmul_outputs = vec![0u8.into(), 2u8.into(), 4u8.into()]; + let mul_outputs = vec![0u8.into(), 2u8.into(), 2u8.into()]; + + vec![ + unary_op_inputs, + shr_outputs, + iszero_outputs, + binary_op_first_inputs, + binary_op_second_inputs, + cmp_outputs, + add_outputs, + addmul_outputs, + mul_outputs, + ] +} fn pad_bignums(biguints: &[BigUint], length: usize) -> Vec { biguints @@ -207,8 +237,7 @@ where interpreter.set_kernel_general_memory(memory.clone()); interpreter.run()?; let result = interpreter.stack()[0]; - let minus_one = ((U256::one() << 255) - 1) * 2 + 1; - assert_eq!(result, minus_one); + assert_eq!(result, MINUS_ONE); // Test equal case. let mut initial_stack: Vec = vec![length, a_start_loc, a_start_loc, retdest]; From b0ed6ae0d3508ec9ad557b466fae3982bacaf638 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Wed, 15 Mar 2023 14:32:18 -0700 Subject: [PATCH 068/121] cleanup --- evm/src/cpu/kernel/tests/bignum.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/evm/src/cpu/kernel/tests/bignum.rs b/evm/src/cpu/kernel/tests/bignum.rs index cc6b972e..566ace84 100644 --- a/evm/src/cpu/kernel/tests/bignum.rs +++ b/evm/src/cpu/kernel/tests/bignum.rs @@ -1,5 +1,3 @@ -use std::f32::MIN; - use anyhow::Result; use ethereum_types::U256; use itertools::Itertools; @@ -15,6 +13,7 @@ use crate::util::{biguint_to_mem_vec, mem_vec_to_biguint, u256_to_biguint}; const BIGNUM_LIMB_BITS: usize = 128; const MINUS_ONE: U256 = U256::MAX; +#[allow(dead_code)] fn test_data() -> Vec> { let unary_op_inputs = vec![0u8.into(), 1u8.into(), 2u8.into()]; From 6f8a510042067299acad0959aacdf8bcaf83bb59 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Wed, 15 Mar 2023 14:57:46 -0700 Subject: [PATCH 069/121] interface changes --- evm/src/cpu/kernel/tests/bignum.rs | 87 ++++++++++++++++++++---------- 1 file changed, 60 insertions(+), 27 deletions(-) diff --git a/evm/src/cpu/kernel/tests/bignum.rs b/evm/src/cpu/kernel/tests/bignum.rs index 566ace84..3e53995b 100644 --- a/evm/src/cpu/kernel/tests/bignum.rs +++ b/evm/src/cpu/kernel/tests/bignum.rs @@ -8,37 +8,15 @@ use rand::Rng; use crate::cpu::kernel::aggregator::KERNEL; use crate::cpu::kernel::interpreter::Interpreter; -use crate::util::{biguint_to_mem_vec, mem_vec_to_biguint, u256_to_biguint}; +use crate::util::{biguint_to_mem_vec, mem_vec_to_biguint}; const BIGNUM_LIMB_BITS: usize = 128; const MINUS_ONE: U256 = U256::MAX; -#[allow(dead_code)] -fn test_data() -> Vec> { - let unary_op_inputs = vec![0u8.into(), 1u8.into(), 2u8.into()]; - - let shr_outputs = vec![0u8.into(), 0u8.into(), 1u8.into()]; - let iszero_outputs = vec![1u8.into(), 0u8.into(), 0u8.into()]; - - let binary_op_first_inputs = vec![0u8.into(), 1u8.into(), 2u8.into()]; - let binary_op_second_inputs = vec![0u8.into(), 2u8.into(), 1u8.into()]; - - let cmp_outputs = vec![0u8.into(), u256_to_biguint(MINUS_ONE), 1u8.into()]; - let add_outputs = vec![0u8.into(), 3u8.into(), 3u8.into()]; - let addmul_outputs = vec![0u8.into(), 2u8.into(), 4u8.into()]; - let mul_outputs = vec![0u8.into(), 2u8.into(), 2u8.into()]; - - vec![ - unary_op_inputs, - shr_outputs, - iszero_outputs, - binary_op_first_inputs, - binary_op_second_inputs, - cmp_outputs, - add_outputs, - addmul_outputs, - mul_outputs, - ] +fn test_data() -> Vec { + let mut data = vec![0u8.into(), 1u8.into(), u128::MAX.into()]; + data.sort(); + data } fn pad_bignums(biguints: &[BigUint], length: usize) -> Vec { @@ -98,6 +76,14 @@ fn prepare_bignum_min(_bit_size: usize) -> (BigUint, U256, Vec) { (a, length, a_limbs) } +fn prepare_bignum_from_test_data(i: usize) -> (BigUint, U256, Vec) { + let a = test_data()[i].clone(); + let length: U256 = bignum_len(&a).into(); + let a_limbs = biguint_to_mem_vec(a.clone()); + + (a, length, a_limbs) +} + fn prepare_two_bignums_random(bit_size: usize) -> (BigUint, BigUint, U256, Vec) { let (a, b) = gen_two_bignums_ordered(bit_size); let length: U256 = bignum_len(&a).into(); @@ -142,6 +128,15 @@ fn prepare_two_bignums_zero(_bit_size: usize) -> (BigUint, BigUint, U256, Vec (BigUint, BigUint, U256, Vec) { + let a = test_data()[i].clone(); + let b = test_data()[j].clone(); + let length: U256 = bignum_len(&a).into(); + let memory = pad_bignums(&[a.clone(), b.clone()], length.try_into().unwrap()); + + (a, b, length, memory) +} + fn test_shr_bignum(prepare_bignum_fn: &F) -> Result<()> where F: Fn(usize) -> (BigUint, U256, Vec), @@ -375,6 +370,11 @@ fn test_shr_bignum_all() -> Result<()> { test_shr_bignum(&prepare_bignum_max)?; test_shr_bignum(&prepare_bignum_min)?; + let test_data = test_data(); + for i in 0..test_data.len() { + test_shr_bignum(&|_| prepare_bignum_from_test_data(i))?; + } + Ok(()) } @@ -384,6 +384,11 @@ fn test_iszero_bignum_all() -> Result<()> { test_iszero_bignum(&prepare_bignum_max)?; // No need to test for min, since it is zero. + let test_data = test_data(); + for i in 0..test_data.len() { + test_iszero_bignum(&|_| prepare_bignum_from_test_data(i))?; + } + Ok(()) } @@ -394,6 +399,13 @@ fn test_cmp_bignum_all() -> Result<()> { test_cmp_bignum(&prepare_two_bignums_min)?; test_cmp_bignum(&prepare_two_bignums_diff)?; + let test_data = test_data(); + for i in 0..test_data.len() { + for j in 0..i { + test_cmp_bignum(&|_| prepare_two_bignums_from_test_data(i, j))?; + } + } + Ok(()) } @@ -405,6 +417,13 @@ fn test_add_bignum_all() -> Result<()> { test_add_bignum(&prepare_two_bignums_diff)?; test_add_bignum(&prepare_two_bignums_zero)?; + let test_data = test_data(); + for i in 0..test_data.len() { + for j in 0..i { + test_add_bignum(&|_| prepare_two_bignums_from_test_data(i, j))?; + } + } + Ok(()) } @@ -416,6 +435,13 @@ fn test_addmul_bignum_all() -> Result<()> { test_addmul_bignum(&prepare_two_bignums_diff)?; test_addmul_bignum(&prepare_two_bignums_zero)?; + let test_data = test_data(); + for i in 0..test_data.len() { + for j in 0..i { + test_addmul_bignum(&|_| prepare_two_bignums_from_test_data(i, j))?; + } + } + Ok(()) } @@ -427,5 +453,12 @@ fn test_mul_bignum_all() -> Result<()> { test_mul_bignum(&prepare_two_bignums_diff)?; test_mul_bignum(&prepare_two_bignums_zero)?; + let test_data = test_data(); + for i in 0..test_data.len() { + for j in 0..i { + test_mul_bignum(&|_| prepare_two_bignums_from_test_data(i, j))?; + } + } + Ok(()) } From 44a0596f8dee79d2f74f92d4c55f888740c2a59a Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Wed, 15 Mar 2023 18:38:31 -0700 Subject: [PATCH 070/121] fmt --- evm/src/cpu/kernel/asm/bignum/add.asm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/evm/src/cpu/kernel/asm/bignum/add.asm b/evm/src/cpu/kernel/asm/bignum/add.asm index 64293f11..7f646097 100644 --- a/evm/src/cpu/kernel/asm/bignum/add.asm +++ b/evm/src/cpu/kernel/asm/bignum/add.asm @@ -67,4 +67,4 @@ len_zero: PUSH 0 // stack: carry=0, retdest SWAP1 - JUMP \ No newline at end of file + JUMP From 12e6527b5701992198da4245934d90c0733694d4 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Wed, 15 Mar 2023 18:46:49 -0700 Subject: [PATCH 071/121] fixed messed up merge --- .../kernel/asm/hash/blake2b/g_functions.asm | 77 +++++++++---------- 1 file changed, 37 insertions(+), 40 deletions(-) diff --git a/evm/src/cpu/kernel/asm/hash/blake2b/g_functions.asm b/evm/src/cpu/kernel/asm/hash/blake2b/g_functions.asm index f62d309c..f2d3b1d2 100644 --- a/evm/src/cpu/kernel/asm/hash/blake2b/g_functions.asm +++ b/evm/src/cpu/kernel/asm/hash/blake2b/g_functions.asm @@ -1,4 +1,4 @@ -blake2b_g_function: +%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. @@ -37,63 +37,63 @@ blake2b_g_function: %stack (vd, vs: 3) -> (vs, vd) // 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, retdest + // 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, retdest + // 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, retdest + // 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, retdest + // 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, retdest + // 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, retdest + // 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, retdest + // 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, retdest + // 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, retdest + // 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, retdest + // 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, retdest + // 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, retdest + // 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, retdest + // 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, retdest + // 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, retdest + // 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, retdest + // 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, retdest + // 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, retdest + // 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, retdest + // 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, retdest + // 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, retdest + // 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, retdest + // 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, retdest + // 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]'', retdest + // stack: start, a, v[a]'', start, b, v[b]'', start, c, v[c]'', start, d, v[d]'' ADD %mstore_kernel_general ADD @@ -102,27 +102,24 @@ blake2b_g_function: %mstore_kernel_general ADD %mstore_kernel_general - // stack: retdest - JUMP +%endmacro -call_blake2b_g_function: - // stack: a, b, c, d, x_idx, y_idx, round, start, retdest - DUP6 - // stack: y_idx, a, b, c, d, x_idx, y_idx, round, start, retdest - DUP8 - // stack: round, y_idx, a, b, c, d, x_idx, y_idx, round, start, retdest +%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], a, b, c, d, x_idx, y_idx, round, start, retdest + // stack: s[y_idx], round, start %blake2b_message_addr ADD %mload_kernel_general - // stack: m[s[y_idx]], a, b, c, d, x_idx, y_idx, round, start, retdest - DUP6 - // stack: x_idx, m[s[y_idx]], a, b, c, d, x_idx, y_idx, round, start, retdest - DUP9 - // stack: round, x_idx, m[s[y_idx]], a, b, c, d, x_idx, y_idx, round, start, retdest + // 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]], a, b, c, d, x_idx, y_idx, round, start, retdest + // stack: s[x_idx], m[s[y_idx]], round, start %blake2b_message_addr ADD %mload_kernel_general From e97e8188334d4a8a6a9f4a1e46ea59e8636af986 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Wed, 15 Mar 2023 19:25:51 -0700 Subject: [PATCH 072/121] fixed iszero and cleanup --- evm/src/cpu/kernel/tests/bignum.rs | 33 ++++++++++++++++++------------ 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/evm/src/cpu/kernel/tests/bignum.rs b/evm/src/cpu/kernel/tests/bignum.rs index 3e53995b..bce91295 100644 --- a/evm/src/cpu/kernel/tests/bignum.rs +++ b/evm/src/cpu/kernel/tests/bignum.rs @@ -76,12 +76,11 @@ fn prepare_bignum_min(_bit_size: usize) -> (BigUint, U256, Vec) { (a, length, a_limbs) } -fn prepare_bignum_from_test_data(i: usize) -> (BigUint, U256, Vec) { - let a = test_data()[i].clone(); +fn prepare_bignum_from_value(a: BigUint) -> (BigUint, U256, Vec) { let length: U256 = bignum_len(&a).into(); let a_limbs = biguint_to_mem_vec(a.clone()); - (a, length, a_limbs) + (a.clone(), length, a_limbs) } fn prepare_two_bignums_random(bit_size: usize) -> (BigUint, BigUint, U256, Vec) { @@ -128,13 +127,11 @@ fn prepare_two_bignums_zero(_bit_size: usize) -> (BigUint, BigUint, U256, Vec (BigUint, BigUint, U256, Vec) { - let a = test_data()[i].clone(); - let b = test_data()[j].clone(); +fn prepare_two_bignums_from_values(a: BigUint, b: BigUint) -> (BigUint, BigUint, U256, Vec) { let length: U256 = bignum_len(&a).into(); let memory = pad_bignums(&[a.clone(), b.clone()], length.try_into().unwrap()); - (a, b, length, memory) + (a.clone(), b.clone(), length, memory) } fn test_shr_bignum(prepare_bignum_fn: &F) -> Result<()> @@ -372,7 +369,7 @@ fn test_shr_bignum_all() -> Result<()> { let test_data = test_data(); for i in 0..test_data.len() { - test_shr_bignum(&|_| prepare_bignum_from_test_data(i))?; + test_shr_bignum(&|_| prepare_bignum_from_value(test_data[i].clone()))?; } Ok(()) @@ -386,7 +383,9 @@ fn test_iszero_bignum_all() -> Result<()> { let test_data = test_data(); for i in 0..test_data.len() { - test_iszero_bignum(&|_| prepare_bignum_from_test_data(i))?; + if test_data[i] != 0u8.into() { + test_iszero_bignum(&|_| prepare_bignum_from_value(test_data[i].clone()))?; + } } Ok(()) @@ -402,7 +401,9 @@ fn test_cmp_bignum_all() -> Result<()> { let test_data = test_data(); for i in 0..test_data.len() { for j in 0..i { - test_cmp_bignum(&|_| prepare_two_bignums_from_test_data(i, j))?; + test_cmp_bignum(&|_| { + prepare_two_bignums_from_values(test_data[i].clone(), test_data[j].clone()) + })?; } } @@ -420,7 +421,9 @@ fn test_add_bignum_all() -> Result<()> { let test_data = test_data(); for i in 0..test_data.len() { for j in 0..i { - test_add_bignum(&|_| prepare_two_bignums_from_test_data(i, j))?; + test_add_bignum(&|_| { + prepare_two_bignums_from_values(test_data[i].clone(), test_data[j].clone()) + })?; } } @@ -438,7 +441,9 @@ fn test_addmul_bignum_all() -> Result<()> { let test_data = test_data(); for i in 0..test_data.len() { for j in 0..i { - test_addmul_bignum(&|_| prepare_two_bignums_from_test_data(i, j))?; + test_addmul_bignum(&|_| { + prepare_two_bignums_from_values(test_data[i].clone(), test_data[j].clone()) + })?; } } @@ -456,7 +461,9 @@ fn test_mul_bignum_all() -> Result<()> { let test_data = test_data(); for i in 0..test_data.len() { for j in 0..i { - test_mul_bignum(&|_| prepare_two_bignums_from_test_data(i, j))?; + test_mul_bignum(&|_| { + prepare_two_bignums_from_values(test_data[i].clone(), test_data[j].clone()) + })?; } } From 6f6c808d80d8836a10f86a94c742089821020e7d Mon Sep 17 00:00:00 2001 From: Dmitry Vagner Date: Wed, 15 Mar 2023 19:41:55 -0700 Subject: [PATCH 073/121] more efficient divmod --- evm/src/bls381_arithmetic.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/evm/src/bls381_arithmetic.rs b/evm/src/bls381_arithmetic.rs index bf886e1c..f3217639 100644 --- a/evm/src/bls381_arithmetic.rs +++ b/evm/src/bls381_arithmetic.rs @@ -105,10 +105,11 @@ impl Mul for Fp { type Output = Self; fn mul(self, other: Self) -> Self { - let b256: U512 = U512([0, 0, 0, 0, 1, 0, 0, 0]); // x1, y1 are at most (q-1) // 2^256 < 2^125 - let (x1, x0) = self.val.div_mod(b256); - let (y1, y0) = other.val.div_mod(b256); + let x1 = U512(self.val.0[..4].try_into().unwrap()); + let x0 = U512(self.val.0[4..].try_into().unwrap()); + let y1 = U512(other.val.0[..4].try_into().unwrap()); + let y0 = U512(other.val.0[4..].try_into().unwrap()); let z00 = Fp { val: x0.saturating_mul(y0) % BLS_BASE, From 54eb29e7070a86c601b33e9f82090c8f883206e9 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Wed, 15 Mar 2023 19:58:26 -0700 Subject: [PATCH 074/121] fix --- evm/src/util.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/evm/src/util.rs b/evm/src/util.rs index 6b2ca479..fba97372 100644 --- a/evm/src/util.rs +++ b/evm/src/util.rs @@ -170,8 +170,8 @@ pub(crate) fn mem_vec_to_biguint(x: &[U256]) -> BigUint { pub(crate) fn biguint_to_le_limbs(x: BigUint) -> Vec { let mut digits = x.to_u32_digits(); - // Pad to a multiple of 8. - digits.resize((digits.len() + 7) / 8 * 8, 0); + // Pad to a multiple of 4. + digits.resize((digits.len() + 3) / 4 * 4, 0); digits .chunks(4) From e60271424ce8fbc787e35c17464b92de3d566b41 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Wed, 15 Mar 2023 19:59:04 -0700 Subject: [PATCH 075/121] cleanup --- evm/src/cpu/kernel/tests/bignum.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/evm/src/cpu/kernel/tests/bignum.rs b/evm/src/cpu/kernel/tests/bignum.rs index bce91295..25b11c17 100644 --- a/evm/src/cpu/kernel/tests/bignum.rs +++ b/evm/src/cpu/kernel/tests/bignum.rs @@ -80,7 +80,7 @@ fn prepare_bignum_from_value(a: BigUint) -> (BigUint, U256, Vec) { let length: U256 = bignum_len(&a).into(); let a_limbs = biguint_to_mem_vec(a.clone()); - (a.clone(), length, a_limbs) + (a, length, a_limbs) } fn prepare_two_bignums_random(bit_size: usize) -> (BigUint, BigUint, U256, Vec) { @@ -131,7 +131,7 @@ fn prepare_two_bignums_from_values(a: BigUint, b: BigUint) -> (BigUint, BigUint, let length: U256 = bignum_len(&a).into(); let memory = pad_bignums(&[a.clone(), b.clone()], length.try_into().unwrap()); - (a.clone(), b.clone(), length, memory) + (a, b, length, memory) } fn test_shr_bignum(prepare_bignum_fn: &F) -> Result<()> From 73633354e00f9697d4ae356f6ed3bf514eebc3e7 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Wed, 15 Mar 2023 22:30:17 -0700 Subject: [PATCH 076/121] test data --- evm/src/cpu/kernel/tests/bignum.rs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/evm/src/cpu/kernel/tests/bignum.rs b/evm/src/cpu/kernel/tests/bignum.rs index 25b11c17..17a68d89 100644 --- a/evm/src/cpu/kernel/tests/bignum.rs +++ b/evm/src/cpu/kernel/tests/bignum.rs @@ -1,3 +1,5 @@ +use std::str::FromStr; + use anyhow::Result; use ethereum_types::U256; use itertools::Itertools; @@ -14,7 +16,21 @@ const BIGNUM_LIMB_BITS: usize = 128; const MINUS_ONE: U256 = U256::MAX; fn test_data() -> Vec { - let mut data = vec![0u8.into(), 1u8.into(), u128::MAX.into()]; + let mut data = vec![0u128.into(), 1u128.into(), u128::MAX.into(), + 21u128.into(), +908u128.into(), +1267650597867046177654064545792u128.into(), +BigUint::from_str("57896044618658097611351864738157061705262361561497619362091104892532012613632").unwrap(), +BigUint::from_str("115792089237105570840234253759177109864155645142784332660520492325483608801280").unwrap(), +BigUint::from_str("231583736816786089484927226016147767929578972263620494977377884571370600267775").unwrap(), +BigUint::from_str("3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725446174963629590181147084998049792").unwrap(), +BigUint::from_str("5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851378448187094873990326993486348287").unwrap(), +BigUint::from_str("13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756016346166874193365792884690780159").unwrap(), +BigUint::from_str("26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459867671853087539206018919387103232").unwrap(), +BigUint::from_str("10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232059366253413058442519879029375369216").unwrap(), +BigUint::from_str("35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998255571752838316161056568930429957046271").unwrap(), + ]; + data.sort(); data } From 534395ee4d8587938e40ebf1c688b7e7e656b185 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Wed, 15 Mar 2023 22:30:54 -0700 Subject: [PATCH 077/121] fmt --- evm/src/cpu/kernel/tests/bignum.rs | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/evm/src/cpu/kernel/tests/bignum.rs b/evm/src/cpu/kernel/tests/bignum.rs index 17a68d89..1d4196b2 100644 --- a/evm/src/cpu/kernel/tests/bignum.rs +++ b/evm/src/cpu/kernel/tests/bignum.rs @@ -16,19 +16,22 @@ const BIGNUM_LIMB_BITS: usize = 128; const MINUS_ONE: U256 = U256::MAX; fn test_data() -> Vec { - let mut data = vec![0u128.into(), 1u128.into(), u128::MAX.into(), - 21u128.into(), -908u128.into(), -1267650597867046177654064545792u128.into(), -BigUint::from_str("57896044618658097611351864738157061705262361561497619362091104892532012613632").unwrap(), -BigUint::from_str("115792089237105570840234253759177109864155645142784332660520492325483608801280").unwrap(), -BigUint::from_str("231583736816786089484927226016147767929578972263620494977377884571370600267775").unwrap(), -BigUint::from_str("3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725446174963629590181147084998049792").unwrap(), -BigUint::from_str("5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851378448187094873990326993486348287").unwrap(), -BigUint::from_str("13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756016346166874193365792884690780159").unwrap(), -BigUint::from_str("26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459867671853087539206018919387103232").unwrap(), -BigUint::from_str("10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232059366253413058442519879029375369216").unwrap(), -BigUint::from_str("35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998255571752838316161056568930429957046271").unwrap(), + let mut data = vec![ + 0u128.into(), + 1u128.into(), + u128::MAX.into(), + 21u128.into(), + 908u128.into(), + 1267650597867046177654064545792u128.into(), + BigUint::from_str("57896044618658097611351864738157061705262361561497619362091104892532012613632").unwrap(), + BigUint::from_str("115792089237105570840234253759177109864155645142784332660520492325483608801280").unwrap(), + BigUint::from_str("231583736816786089484927226016147767929578972263620494977377884571370600267775").unwrap(), + BigUint::from_str("3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725446174963629590181147084998049792").unwrap(), + BigUint::from_str("5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851378448187094873990326993486348287").unwrap(), + BigUint::from_str("13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756016346166874193365792884690780159").unwrap(), + BigUint::from_str("26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459867671853087539206018919387103232").unwrap(), + BigUint::from_str("10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232059366253413058442519879029375369216").unwrap(), + BigUint::from_str("35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998255571752838316161056568930429957046271").unwrap(), ]; data.sort(); From 4e736b63b8c712940b24842e934ca6aa73d77952 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Wed, 15 Mar 2023 23:05:44 -0700 Subject: [PATCH 078/121] fixes --- evm/src/cpu/kernel/asm/bignum/add.asm | 19 ++++++++----------- evm/src/cpu/kernel/tests/bignum.rs | 7 ++++++- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/evm/src/cpu/kernel/asm/bignum/add.asm b/evm/src/cpu/kernel/asm/bignum/add.asm index 7f646097..09b405e8 100644 --- a/evm/src/cpu/kernel/asm/bignum/add.asm +++ b/evm/src/cpu/kernel/asm/bignum/add.asm @@ -29,25 +29,22 @@ add_loop: // stack: (a[cur] + b[cur] + carry) // 2^128, a[cur] + b[cur] + carry, i, a_cur_loc, b_cur_loc, retdest SWAP1 // stack: a[cur] + b[cur] + carry, (a[cur] + b[cur] + carry) // 2^128, i, a_cur_loc, b_cur_loc, retdest - %shl_const(128) - %shr_const(128) + %mod_const(0x100000000000000000000000000000000) // stack: c[cur] = (a[cur] + b[cur] + carry) % 2^128, carry_new = (a[cur] + b[cur] + carry) // 2^128, i, a_cur_loc, b_cur_loc, retdest DUP4 // stack: a_cur_loc, c[cur], carry_new, i, a_cur_loc, b_cur_loc, retdest %mstore_kernel_general // stack: carry_new, i, a_cur_loc, b_cur_loc, retdest - %stack (c, i, a, b) -> (a, b, c, i) - // stack: a_cur_loc, b_cur_loc, carry_new, i, retdest + SWAP2 %increment - // stack: a_cur_loc + 1, b_cur_loc, carry_new, i, retdest + SWAP2 + // stack: carry_new, i, a_cur_loc + 1, b_cur_loc, retdest + SWAP3 + %increment + SWAP3 + // stack: carry_new, i, a_cur_loc + 1, b_cur_loc + 1, retdest SWAP1 - // stack: b_cur_loc, a_cur_loc + 1, carry_new, i, retdest - %increment - // stack: b_cur_loc + 1, a_cur_loc + 1, carry_new, i, retdest - %stack (b, a, c, i) -> (i, c, a, b) - // stack: i, carry_new, a_cur_loc + 1, b_cur_loc + 1, retdest %decrement - // stack: i - 1, carry_new, a_cur_loc + 1, b_cur_loc + 1, retdest SWAP1 // stack: carry_new, i - 1, a_cur_loc + 1, b_cur_loc + 1, retdest DUP2 diff --git a/evm/src/cpu/kernel/tests/bignum.rs b/evm/src/cpu/kernel/tests/bignum.rs index 1d4196b2..bd3daa95 100644 --- a/evm/src/cpu/kernel/tests/bignum.rs +++ b/evm/src/cpu/kernel/tests/bignum.rs @@ -20,6 +20,8 @@ fn test_data() -> Vec { 0u128.into(), 1u128.into(), u128::MAX.into(), + + // Generated by GMP's mpz_rrandomb for bit lengths 5, 10, 100, 255, 256, 257, 500, 511, 512, 513, 1000, and 1500. 21u128.into(), 908u128.into(), 1267650597867046177654064545792u128.into(), @@ -266,6 +268,7 @@ where F: Fn(usize) -> (BigUint, BigUint, U256, Vec), { let (a, b, length, memory) = prepare_two_bignums_fn(1000); + let len: usize = length.try_into().unwrap(); // Determine expected sum. let sum = a + b; @@ -288,7 +291,9 @@ where interpreter.run()?; // Determine actual sum. - let new_memory = interpreter.get_kernel_general_memory(); + let carry_limb = interpreter.stack()[0]; + let mut new_memory = interpreter.get_kernel_general_memory(); + new_memory[len] = carry_limb; let actual_sum: Vec<_> = new_memory[..expected_sum.len()].into(); // Compare. From ee9bfb0822633af0dc0599609fbdebc0c0f59ab1 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Wed, 15 Mar 2023 23:11:39 -0700 Subject: [PATCH 079/121] fix --- evm/src/cpu/kernel/tests/bignum.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/evm/src/cpu/kernel/tests/bignum.rs b/evm/src/cpu/kernel/tests/bignum.rs index bd3daa95..2d59988f 100644 --- a/evm/src/cpu/kernel/tests/bignum.rs +++ b/evm/src/cpu/kernel/tests/bignum.rs @@ -290,10 +290,12 @@ where // Run add function. interpreter.run()?; - // Determine actual sum. + // Determine actual sum, appending the final carry if nonzero. let carry_limb = interpreter.stack()[0]; let mut new_memory = interpreter.get_kernel_general_memory(); - new_memory[len] = carry_limb; + if carry_limb > 0.into() { + new_memory[len] = carry_limb; + } let actual_sum: Vec<_> = new_memory[..expected_sum.len()].into(); // Compare. From 10e7329a95924a64a0f4548eddb672d8f090a349 Mon Sep 17 00:00:00 2001 From: Robin Salen Date: Mon, 20 Feb 2023 10:36:16 -0500 Subject: [PATCH 080/121] Add FFT-based specification for Poseidon MDS layer on x86 targets --- plonky2/src/hash/poseidon_goldilocks.rs | 172 ++++++++++++++++++++++++ 1 file changed, 172 insertions(+) diff --git a/plonky2/src/hash/poseidon_goldilocks.rs b/plonky2/src/hash/poseidon_goldilocks.rs index b6e9bc74..0d03b3e9 100644 --- a/plonky2/src/hash/poseidon_goldilocks.rs +++ b/plonky2/src/hash/poseidon_goldilocks.rs @@ -4,6 +4,9 @@ //! `poseidon_constants.sage` script in the `mir-protocol/hash-constants` //! repository. +use plonky2_field::types::Field; +use unroll::unroll_for_loops; + use crate::field::goldilocks_field::GoldilocksField; use crate::hash::poseidon::{Poseidon, N_PARTIAL_ROUNDS}; @@ -211,6 +214,39 @@ impl Poseidon for GoldilocksField { 0xdcedab70f40718ba, 0xe796d293a47a64cb, 0x80772dc2645b280b, ], ]; + #[cfg(target_arch="x86_64")] + #[inline(always)] + #[unroll_for_loops] + fn mds_layer(state: &[Self; 12]) -> [Self; 12] { + let mut result = [GoldilocksField::ZERO; 12]; + + // Using the linearity of the operations we can split the state into a low||high decomposition + // and operate on each with no overflow and then combine/reduce the result to a field element. + let mut state_l = [0u64; 12]; + let mut state_h = [0u64; 12]; + + for r in 0..12 { + let s = state[r].0; + state_h[r] = s >> 32; + state_l[r] = (s as u32) as u64; + } + + let state_h = mds_multiply_freq(state_h); + let state_l = mds_multiply_freq(state_l); + + for r in 0..12 { + let s = state_l[r] as u128 + ((state_h[r] as u128) << 32); + + result[r] = GoldilocksField::from_noncanonical_u96((s as u64, (s >> 64) as u32)); + } + + // Add first element with the only non-zero diagonal matrix coefficient. + let s = Self::MDS_MATRIX_DIAG[0] as u128 * (state[0].0 as u128); + result[0] += GoldilocksField::from_noncanonical_u96((s as u64, (s >> 64) as u32)); + + result + } + // #[cfg(all(target_arch="x86_64", target_feature="avx2", target_feature="bmi2"))] // #[inline] // fn poseidon(input: [Self; 12]) -> [Self; 12] { @@ -268,6 +304,142 @@ impl Poseidon for GoldilocksField { } } +// MDS layer helper methods +// The following code has been adapted from winterfell/crypto/src/hash/mds/mds_f64_12x12.rs +// located at https://github.com/facebook/winterfell. + +const MDS_FREQ_BLOCK_ONE: [i64; 3] = [16, 32, 16]; +const MDS_FREQ_BLOCK_TWO: [(i64, i64); 3] = [(2, -1), (-4, 1), (16, 1)]; +const MDS_FREQ_BLOCK_THREE: [i64; 3] = [-1, -8, 2]; + +/// Split 3 x 4 FFT-based MDS vector-multiplication with the Poseidon circulant MDS matrix. +#[inline(always)] +fn mds_multiply_freq(state: [u64; 12]) -> [u64; 12] { + let [s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11] = state; + + let (u0, u1, u2) = fft4_real([s0, s3, s6, s9]); + let (u4, u5, u6) = fft4_real([s1, s4, s7, s10]); + let (u8, u9, u10) = fft4_real([s2, s5, s8, s11]); + + // This where the multiplication in frequency domain is done. More precisely, and with + // the appropriate permuations in between, the sequence of + // 3-point FFTs --> multiplication by twiddle factors --> Hadamard multiplication --> + // 3 point iFFTs --> multiplication by (inverse) twiddle factors + // is "squashed" into one step composed of the functions "block1", "block2" and "block3". + // The expressions in the aforementioned functions are the result of explicit computations + // combined with the Karatsuba trick for the multiplication of complex numbers. + + let [v0, v4, v8] = block1([u0, u4, u8], MDS_FREQ_BLOCK_ONE); + let [v1, v5, v9] = block2([u1, u5, u9], MDS_FREQ_BLOCK_TWO); + let [v2, v6, v10] = block3([u2, u6, u10], MDS_FREQ_BLOCK_THREE); + // The 4th block is not computed as it is similar to the 2nd one, up to complex conjugation. + + let [s0, s3, s6, s9] = ifft4_real_unreduced((v0, v1, v2)); + let [s1, s4, s7, s10] = ifft4_real_unreduced((v4, v5, v6)); + let [s2, s5, s8, s11] = ifft4_real_unreduced((v8, v9, v10)); + + [s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11] +} + +/// Real 2-FFT over u64 integers. +#[inline(always)] +fn fft2_real(x: [u64; 2]) -> [i64; 2] { + [(x[0] as i64 + x[1] as i64), (x[0] as i64 - x[1] as i64)] +} + +/// Real 2-iFFT over u64 integers. +/// Division by two to complete the inverse FFT is not performed here. +#[inline(always)] +fn ifft2_real_unreduced(y: [i64; 2]) -> [u64; 2] { + [(y[0] + y[1]) as u64, (y[0] - y[1]) as u64] +} + +/// Real 4-FFT over u64 integers. +#[inline(always)] +fn fft4_real(x: [u64; 4]) -> (i64, (i64, i64), i64) { + let [z0, z2] = fft2_real([x[0], x[2]]); + let [z1, z3] = fft2_real([x[1], x[3]]); + let y0 = z0 + z1; + let y1 = (z2, -z3); + let y2 = z0 - z1; + (y0, y1, y2) +} + +/// Real 4-iFFT over u64 integers. +/// Division by four to complete the inverse FFT is not performed here. +#[inline(always)] +fn ifft4_real_unreduced(y: (i64, (i64, i64), i64)) -> [u64; 4] { + let z0 = y.0 + y.2; + let z1 = y.0 - y.2; + let z2 = y.1 .0; + let z3 = -y.1 .1; + + let [x0, x2] = ifft2_real_unreduced([z0, z2]); + let [x1, x3] = ifft2_real_unreduced([z1, z3]); + + [x0, x1, x2, x3] +} + +#[inline(always)] +fn block1(x: [i64; 3], y: [i64; 3]) -> [i64; 3] { + let [x0, x1, x2] = x; + let [y0, y1, y2] = y; + let z0 = x0 * y0 + x1 * y2 + x2 * y1; + let z1 = x0 * y1 + x1 * y0 + x2 * y2; + let z2 = x0 * y2 + x1 * y1 + x2 * y0; + + [z0, z1, z2] +} + +#[inline(always)] +fn block2(x: [(i64, i64); 3], y: [(i64, i64); 3]) -> [(i64, i64); 3] { + let [(x0r, x0i), (x1r, x1i), (x2r, x2i)] = x; + let [(y0r, y0i), (y1r, y1i), (y2r, y2i)] = y; + let x0s = x0r + x0i; + let x1s = x1r + x1i; + let x2s = x2r + x2i; + let y0s = y0r + y0i; + let y1s = y1r + y1i; + let y2s = y2r + y2i; + + // Compute x0​y0 ​− ix1​y2​ − ix2​y1​ using Karatsuba for complex numbers multiplication + let m0 = (x0r * y0r, x0i * y0i); + let m1 = (x1r * y2r, x1i * y2i); + let m2 = (x2r * y1r, x2i * y1i); + let z0r = (m0.0 - m0.1) + (x1s * y2s - m1.0 - m1.1) + (x2s * y1s - m2.0 - m2.1); + let z0i = (x0s * y0s - m0.0 - m0.1) + (-m1.0 + m1.1) + (-m2.0 + m2.1); + let z0 = (z0r, z0i); + + // Compute x0​y1​ + x1​y0​ − ix2​y2 using Karatsuba for complex numbers multiplication + let m0 = (x0r * y1r, x0i * y1i); + let m1 = (x1r * y0r, x1i * y0i); + let m2 = (x2r * y2r, x2i * y2i); + let z1r = (m0.0 - m0.1) + (m1.0 - m1.1) + (x2s * y2s - m2.0 - m2.1); + let z1i = (x0s * y1s - m0.0 - m0.1) + (x1s * y0s - m1.0 - m1.1) + (-m2.0 + m2.1); + let z1 = (z1r, z1i); + + // Compute x0​y2​ + x1​y1 ​+ x2​y0​ using Karatsuba for complex numbers multiplication + let m0 = (x0r * y2r, x0i * y2i); + let m1 = (x1r * y1r, x1i * y1i); + let m2 = (x2r * y0r, x2i * y0i); + let z2r = (m0.0 - m0.1) + (m1.0 - m1.1) + (m2.0 - m2.1); + let z2i = (x0s * y2s - m0.0 - m0.1) + (x1s * y1s - m1.0 - m1.1) + (x2s * y0s - m2.0 - m2.1); + let z2 = (z2r, z2i); + + [z0, z1, z2] +} + +#[inline(always)] +fn block3(x: [i64; 3], y: [i64; 3]) -> [i64; 3] { + let [x0, x1, x2] = x; + let [y0, y1, y2] = y; + let z0 = x0 * y0 - x1 * y2 - x2 * y1; + let z1 = x0 * y1 + x1 * y0 - x2 * y2; + let z2 = x0 * y2 + x1 * y1 + x2 * y0; + + [z0, z1, z2] +} + #[cfg(test)] mod tests { use crate::field::goldilocks_field::GoldilocksField as F; From bb2233cb2100603d5122be6b6afc0e9ff3a95c49 Mon Sep 17 00:00:00 2001 From: Robin Salen Date: Tue, 14 Feb 2023 15:34:37 -0500 Subject: [PATCH 081/121] Override from_noncanonical_u96() for Goldilocks field --- field/src/field_testing.rs | 15 ++++++++++++++- field/src/goldilocks_field.rs | 13 +++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/field/src/field_testing.rs b/field/src/field_testing.rs index 4c53c234..16dd87f4 100644 --- a/field/src/field_testing.rs +++ b/field/src/field_testing.rs @@ -10,9 +10,22 @@ macro_rules! test_field_arithmetic { use num::bigint::BigUint; use rand::rngs::OsRng; - use rand::Rng; + use rand::{Rng, RngCore}; use $crate::types::{Field, Sample}; + #[test] + fn modular_reduction() { + let mut rng = OsRng; + for _ in 0..10 { + let x_lo = rng.next_u64(); + let x_hi = rng.next_u32(); + let x = (x_lo as u128) + ((x_hi as u128) << 64); + let a = <$field>::from_noncanonical_u128(x); + let b = <$field>::from_noncanonical_u96((x_lo, x_hi)); + assert_eq!(a, b); + } + } + #[test] fn batch_inversion() { for n in 0..20 { diff --git a/field/src/goldilocks_field.rs b/field/src/goldilocks_field.rs index 9f0b0519..8c8d8bc3 100644 --- a/field/src/goldilocks_field.rs +++ b/field/src/goldilocks_field.rs @@ -110,6 +110,10 @@ impl Field for GoldilocksField { Self(n) } + fn from_noncanonical_u96((n_lo, n_hi): (u64, u32)) -> Self { + reduce96((n_lo, n_hi)) + } + fn from_noncanonical_u128(n: u128) -> Self { reduce128(n) } @@ -337,6 +341,15 @@ unsafe fn add_no_canonicalize_trashing_input(x: u64, y: u64) -> u64 { res_wrapped + EPSILON * (carry as u64) } +/// Reduces to a 64-bit value. The result might not be in canonical form; it could be in between the +/// field order and `2^64`. +#[inline] +fn reduce96((x_lo, x_hi): (u64, u32)) -> GoldilocksField { + let t1 = x_hi as u64 * EPSILON; + let t2 = unsafe { add_no_canonicalize_trashing_input(x_lo, t1) }; + GoldilocksField(t2) +} + /// Reduces to a 64-bit value. The result might not be in canonical form; it could be in between the /// field order and `2^64`. #[inline] From fa3443a50bda812b5c6bbd7429098549f7a31765 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Thu, 16 Mar 2023 10:52:20 -0700 Subject: [PATCH 082/121] new testing interface, and test data --- evm/src/cpu/kernel/tests/bignum.rs | 497 ------ evm/src/cpu/kernel/tests/bignum/mod.rs | 356 +++++ .../kernel/tests/bignum/test_data/add_outputs | 225 +++ .../tests/bignum/test_data/addmul_outputs | 1350 +++++++++++++++++ .../tests/bignum/test_data/bignum_inputs | 15 + .../kernel/tests/bignum/test_data/cmp_outputs | 225 +++ .../tests/bignum/test_data/iszero_outputs | 15 + .../kernel/tests/bignum/test_data/mul_outputs | 225 +++ .../kernel/tests/bignum/test_data/shr_outputs | 15 + .../kernel/tests/bignum/test_data/u128_inputs | 6 + 10 files changed, 2432 insertions(+), 497 deletions(-) delete mode 100644 evm/src/cpu/kernel/tests/bignum.rs create mode 100644 evm/src/cpu/kernel/tests/bignum/mod.rs create mode 100644 evm/src/cpu/kernel/tests/bignum/test_data/add_outputs create mode 100644 evm/src/cpu/kernel/tests/bignum/test_data/addmul_outputs create mode 100644 evm/src/cpu/kernel/tests/bignum/test_data/bignum_inputs create mode 100644 evm/src/cpu/kernel/tests/bignum/test_data/cmp_outputs create mode 100644 evm/src/cpu/kernel/tests/bignum/test_data/iszero_outputs create mode 100644 evm/src/cpu/kernel/tests/bignum/test_data/mul_outputs create mode 100644 evm/src/cpu/kernel/tests/bignum/test_data/shr_outputs create mode 100644 evm/src/cpu/kernel/tests/bignum/test_data/u128_inputs diff --git a/evm/src/cpu/kernel/tests/bignum.rs b/evm/src/cpu/kernel/tests/bignum.rs deleted file mode 100644 index 2d59988f..00000000 --- a/evm/src/cpu/kernel/tests/bignum.rs +++ /dev/null @@ -1,497 +0,0 @@ -use std::str::FromStr; - -use anyhow::Result; -use ethereum_types::U256; -use itertools::Itertools; -use num::{BigUint, One, Zero}; -use num_bigint::RandBigInt; -use plonky2_util::ceil_div_usize; -use rand::Rng; - -use crate::cpu::kernel::aggregator::KERNEL; -use crate::cpu::kernel::interpreter::Interpreter; -use crate::util::{biguint_to_mem_vec, mem_vec_to_biguint}; - -const BIGNUM_LIMB_BITS: usize = 128; -const MINUS_ONE: U256 = U256::MAX; - -fn test_data() -> Vec { - let mut data = vec![ - 0u128.into(), - 1u128.into(), - u128::MAX.into(), - - // Generated by GMP's mpz_rrandomb for bit lengths 5, 10, 100, 255, 256, 257, 500, 511, 512, 513, 1000, and 1500. - 21u128.into(), - 908u128.into(), - 1267650597867046177654064545792u128.into(), - BigUint::from_str("57896044618658097611351864738157061705262361561497619362091104892532012613632").unwrap(), - BigUint::from_str("115792089237105570840234253759177109864155645142784332660520492325483608801280").unwrap(), - BigUint::from_str("231583736816786089484927226016147767929578972263620494977377884571370600267775").unwrap(), - BigUint::from_str("3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725446174963629590181147084998049792").unwrap(), - BigUint::from_str("5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851378448187094873990326993486348287").unwrap(), - BigUint::from_str("13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756016346166874193365792884690780159").unwrap(), - BigUint::from_str("26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459867671853087539206018919387103232").unwrap(), - BigUint::from_str("10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232059366253413058442519879029375369216").unwrap(), - BigUint::from_str("35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998255571752838316161056568930429957046271").unwrap(), - ]; - - data.sort(); - data -} - -fn pad_bignums(biguints: &[BigUint], length: usize) -> Vec { - biguints - .iter() - .flat_map(|biguint| { - biguint_to_mem_vec(biguint.clone()) - .into_iter() - .pad_using(length, |_| U256::zero()) - }) - .collect() -} - -fn gen_bignum(bit_size: usize) -> BigUint { - let mut rng = rand::thread_rng(); - rng.gen_biguint(bit_size as u64) -} - -fn bignum_len(a: &BigUint) -> usize { - ceil_div_usize(a.bits() as usize, BIGNUM_LIMB_BITS) -} - -fn gen_two_bignums_ordered(bit_size: usize) -> (BigUint, BigUint) { - let mut rng = rand::thread_rng(); - let (a, b) = ( - rng.gen_biguint(bit_size as u64), - rng.gen_biguint(bit_size as u64), - ); - if b < a { - (a, b) - } else { - (b, a) - } -} - -fn prepare_bignum_random(bit_size: usize) -> (BigUint, U256, Vec) { - let a = gen_bignum(bit_size); - let length: U256 = bignum_len(&a).into(); - let a_limbs = biguint_to_mem_vec(a.clone()); - - (a, length, a_limbs) -} - -fn prepare_bignum_max(bit_size: usize) -> (BigUint, U256, Vec) { - let a = (BigUint::one() << bit_size) - BigUint::one(); - let length: U256 = bignum_len(&a).into(); - let a_limbs = biguint_to_mem_vec(a.clone()); - - (a, length, a_limbs) -} - -fn prepare_bignum_min(_bit_size: usize) -> (BigUint, U256, Vec) { - let a = BigUint::zero(); - let length: U256 = bignum_len(&a).into(); - let a_limbs = biguint_to_mem_vec(a.clone()); - - (a, length, a_limbs) -} - -fn prepare_bignum_from_value(a: BigUint) -> (BigUint, U256, Vec) { - let length: U256 = bignum_len(&a).into(); - let a_limbs = biguint_to_mem_vec(a.clone()); - - (a, length, a_limbs) -} - -fn prepare_two_bignums_random(bit_size: usize) -> (BigUint, BigUint, U256, Vec) { - let (a, b) = gen_two_bignums_ordered(bit_size); - let length: U256 = bignum_len(&a).into(); - let memory = pad_bignums(&[a.clone(), b.clone()], length.try_into().unwrap()); - - (a, b, length, memory) -} - -fn prepare_two_bignums_max(bit_size: usize) -> (BigUint, BigUint, U256, Vec) { - let a = (BigUint::one() << bit_size) - BigUint::one(); - let b = (BigUint::one() << bit_size) - BigUint::from(2u8); - let length: U256 = bignum_len(&a).into(); - let memory = pad_bignums(&[a.clone(), b.clone()], length.try_into().unwrap()); - - (a, b, length, memory) -} - -fn prepare_two_bignums_min(_bit_size: usize) -> (BigUint, BigUint, U256, Vec) { - let a = BigUint::one(); - let b = BigUint::zero(); - let length: U256 = bignum_len(&a).into(); - let memory = pad_bignums(&[a.clone(), b.clone()], length.try_into().unwrap()); - - (a, b, length, memory) -} - -fn prepare_two_bignums_diff(bit_size: usize) -> (BigUint, BigUint, U256, Vec) { - let a = BigUint::one() << (bit_size - 1); - let b = BigUint::zero(); - let length: U256 = bignum_len(&a).into(); - let memory = pad_bignums(&[a.clone(), b.clone()], length.try_into().unwrap()); - - (a, b, length, memory) -} - -fn prepare_two_bignums_zero(_bit_size: usize) -> (BigUint, BigUint, U256, Vec) { - let a = BigUint::zero(); - let b = BigUint::zero(); - let length: U256 = bignum_len(&a).into(); - let memory = pad_bignums(&[a.clone(), b.clone()], length.try_into().unwrap()); - - (a, b, length, memory) -} - -fn prepare_two_bignums_from_values(a: BigUint, b: BigUint) -> (BigUint, BigUint, U256, Vec) { - let length: U256 = bignum_len(&a).into(); - let memory = pad_bignums(&[a.clone(), b.clone()], length.try_into().unwrap()); - - (a, b, length, memory) -} - -fn test_shr_bignum(prepare_bignum_fn: &F) -> Result<()> -where - F: Fn(usize) -> (BigUint, U256, Vec), -{ - let (a, length, memory) = prepare_bignum_fn(1000); - - let halved = a >> 1; - - let retdest = 0xDEADBEEFu32.into(); - let shr_bignum = KERNEL.global_labels["shr_bignum"]; - - let a_start_loc = 0.into(); - - let mut initial_stack: Vec = vec![length, a_start_loc, retdest]; - initial_stack.reverse(); - let mut interpreter = Interpreter::new_with_kernel(shr_bignum, initial_stack); - interpreter.set_kernel_general_memory(memory); - interpreter.run()?; - - let new_memory = interpreter.get_kernel_general_memory(); - let new_a = mem_vec_to_biguint(&new_memory[0..length.as_usize()]); - assert_eq!(new_a, halved); - - Ok(()) -} - -fn test_iszero_bignum(prepare_bignum_fn: &F) -> Result<()> -where - F: Fn(usize) -> (BigUint, U256, Vec), -{ - let (length, memory) = { - let (mut a, mut length, mut memory) = prepare_bignum_fn(1000); - while a == BigUint::zero() { - (a, length, memory) = prepare_bignum_fn(1000); - } - (length, memory) - }; - - let retdest = 0xDEADBEEFu32.into(); - let iszero_bignum = KERNEL.global_labels["iszero_bignum"]; - - let a_start_loc = 0.into(); - - // Test with a > 0. - let mut initial_stack: Vec = vec![length, a_start_loc, retdest]; - initial_stack.reverse(); - let mut interpreter = Interpreter::new_with_kernel(iszero_bignum, initial_stack); - interpreter.set_kernel_general_memory(memory.clone()); - interpreter.run()?; - let result = interpreter.stack()[0]; - assert_eq!(result, 0.into()); - - let memory = vec![0.into(); memory.len()]; - - // Test with a == 0. - let mut initial_stack: Vec = vec![length, a_start_loc, retdest]; - initial_stack.reverse(); - let mut interpreter = Interpreter::new_with_kernel(iszero_bignum, initial_stack); - interpreter.set_kernel_general_memory(memory); - interpreter.run()?; - let result = interpreter.stack()[0]; - assert_eq!(result, U256::one()); - - Ok(()) -} - -fn test_cmp_bignum(prepare_two_bignums_fn: &F) -> Result<()> -where - F: Fn(usize) -> (BigUint, BigUint, U256, Vec), -{ - let (_a, _b, length, memory) = prepare_two_bignums_fn(1000); - - let retdest = 0xDEADBEEFu32.into(); - let cmp_bignum = KERNEL.global_labels["cmp_bignum"]; - - let a_start_loc = 0.into(); - let b_start_loc = length; - - // Test with a > b. - let mut initial_stack: Vec = vec![length, a_start_loc, b_start_loc, retdest]; - initial_stack.reverse(); - let mut interpreter = Interpreter::new_with_kernel(cmp_bignum, initial_stack); - interpreter.set_kernel_general_memory(memory.clone()); - interpreter.run()?; - let result = interpreter.stack()[0]; - assert_eq!(result, U256::one()); - - // Swap a and b, to test the less-than case. - let mut initial_stack: Vec = vec![length, b_start_loc, a_start_loc, retdest]; - initial_stack.reverse(); - let mut interpreter = Interpreter::new_with_kernel(cmp_bignum, initial_stack); - interpreter.set_kernel_general_memory(memory.clone()); - interpreter.run()?; - let result = interpreter.stack()[0]; - assert_eq!(result, MINUS_ONE); - - // Test equal case. - let mut initial_stack: Vec = vec![length, a_start_loc, a_start_loc, retdest]; - initial_stack.reverse(); - let mut interpreter = Interpreter::new_with_kernel(cmp_bignum, initial_stack); - interpreter.set_kernel_general_memory(memory); - interpreter.run()?; - let result = interpreter.stack()[0]; - assert_eq!(result, U256::zero()); - - Ok(()) -} - -fn test_add_bignum(prepare_two_bignums_fn: &F) -> Result<()> -where - F: Fn(usize) -> (BigUint, BigUint, U256, Vec), -{ - let (a, b, length, memory) = prepare_two_bignums_fn(1000); - let len: usize = length.try_into().unwrap(); - - // Determine expected sum. - let sum = a + b; - let expected_sum: Vec = biguint_to_mem_vec(sum); - - let a_start_loc = 0.into(); - let b_start_loc = length; - - // Prepare stack. - let retdest = 0xDEADBEEFu32.into(); - let mut initial_stack: Vec = vec![length, a_start_loc, b_start_loc, retdest]; - initial_stack.reverse(); - - // Prepare interpreter. - let add_bignum = KERNEL.global_labels["add_bignum"]; - let mut interpreter = Interpreter::new_with_kernel(add_bignum, initial_stack); - interpreter.set_kernel_general_memory(memory); - - // Run add function. - interpreter.run()?; - - // Determine actual sum, appending the final carry if nonzero. - let carry_limb = interpreter.stack()[0]; - let mut new_memory = interpreter.get_kernel_general_memory(); - if carry_limb > 0.into() { - new_memory[len] = carry_limb; - } - let actual_sum: Vec<_> = new_memory[..expected_sum.len()].into(); - - // Compare. - assert_eq!(actual_sum, expected_sum); - - Ok(()) -} - -fn test_addmul_bignum(prepare_two_bignums_fn: &F) -> Result<()> -where - F: Fn(usize) -> (BigUint, BigUint, U256, Vec), -{ - let mut rng = rand::thread_rng(); - let (a, b, length, mut memory) = prepare_two_bignums_fn(1000); - let len: usize = length.try_into().unwrap(); - memory.splice(len..len, vec![0.into(); 2].iter().cloned()); - - let val: u128 = rng.gen(); - let val_u256 = U256::from(val); - - // Determine expected result. - let result = a + b * BigUint::from(val); - let expected_result: Vec = biguint_to_mem_vec(result); - - let a_start_loc = 0.into(); - let b_start_loc = length + 2; - - // Prepare stack. - let retdest = 0xDEADBEEFu32.into(); - let mut initial_stack: Vec = vec![length, a_start_loc, b_start_loc, val_u256, retdest]; - initial_stack.reverse(); - - // Prepare interpreter. - let addmul_bignum = KERNEL.global_labels["addmul_bignum"]; - let mut interpreter = Interpreter::new_with_kernel(addmul_bignum, initial_stack); - interpreter.set_kernel_general_memory(memory); - - // Run add function. - interpreter.run()?; - - // Determine actual result. - let carry_limb = interpreter.stack()[0]; - let mut new_memory = interpreter.get_kernel_general_memory(); - new_memory[len] = carry_limb; - let actual_result: Vec<_> = new_memory[..expected_result.len()].into(); - - // Compare. - assert_eq!(actual_result, expected_result); - - Ok(()) -} - -fn test_mul_bignum(prepare_two_bignums_fn: &F) -> Result<()> -where - F: Fn(usize) -> (BigUint, BigUint, U256, Vec), -{ - let (a, b, length, memory) = prepare_two_bignums_fn(1000); - - // Determine expected product. - let product = a * b; - let expected_product: Vec = biguint_to_mem_vec(product); - - // Output and scratch space locations (initialized as zeroes) follow a and b in memory. - let a_start_loc = 0.into(); - let b_start_loc = length; - let output_loc = length * 2; - - // Prepare stack. - let retdest = 0xDEADBEEFu32.into(); - let mut initial_stack: Vec = vec![length, a_start_loc, b_start_loc, output_loc, retdest]; - initial_stack.reverse(); - - // Prepare interpreter. - let mul_bignum = KERNEL.global_labels["mul_bignum"]; - let mut interpreter = Interpreter::new_with_kernel(mul_bignum, initial_stack); - interpreter.set_kernel_general_memory(memory); - - // Run mul function. - interpreter.run()?; - - // Determine actual product. - let new_memory = interpreter.get_kernel_general_memory(); - let output_location: usize = output_loc.try_into().unwrap(); - let actual_product: Vec<_> = - new_memory[output_location..output_location + expected_product.len()].into(); - - assert_eq!(actual_product, expected_product); - - Ok(()) -} - -#[test] -fn test_shr_bignum_all() -> Result<()> { - test_shr_bignum(&prepare_bignum_random)?; - test_shr_bignum(&prepare_bignum_max)?; - test_shr_bignum(&prepare_bignum_min)?; - - let test_data = test_data(); - for i in 0..test_data.len() { - test_shr_bignum(&|_| prepare_bignum_from_value(test_data[i].clone()))?; - } - - Ok(()) -} - -#[test] -fn test_iszero_bignum_all() -> Result<()> { - test_iszero_bignum(&prepare_bignum_random)?; - test_iszero_bignum(&prepare_bignum_max)?; - // No need to test for min, since it is zero. - - let test_data = test_data(); - for i in 0..test_data.len() { - if test_data[i] != 0u8.into() { - test_iszero_bignum(&|_| prepare_bignum_from_value(test_data[i].clone()))?; - } - } - - Ok(()) -} - -#[test] -fn test_cmp_bignum_all() -> Result<()> { - test_cmp_bignum(&prepare_two_bignums_random)?; - test_cmp_bignum(&prepare_two_bignums_max)?; - test_cmp_bignum(&prepare_two_bignums_min)?; - test_cmp_bignum(&prepare_two_bignums_diff)?; - - let test_data = test_data(); - for i in 0..test_data.len() { - for j in 0..i { - test_cmp_bignum(&|_| { - prepare_two_bignums_from_values(test_data[i].clone(), test_data[j].clone()) - })?; - } - } - - Ok(()) -} - -#[test] -fn test_add_bignum_all() -> Result<()> { - test_add_bignum(&prepare_two_bignums_random)?; - test_add_bignum(&prepare_two_bignums_max)?; - test_add_bignum(&prepare_two_bignums_min)?; - test_add_bignum(&prepare_two_bignums_diff)?; - test_add_bignum(&prepare_two_bignums_zero)?; - - let test_data = test_data(); - for i in 0..test_data.len() { - for j in 0..i { - test_add_bignum(&|_| { - prepare_two_bignums_from_values(test_data[i].clone(), test_data[j].clone()) - })?; - } - } - - Ok(()) -} - -#[test] -fn test_addmul_bignum_all() -> Result<()> { - test_addmul_bignum(&prepare_two_bignums_random)?; - test_addmul_bignum(&prepare_two_bignums_max)?; - test_addmul_bignum(&prepare_two_bignums_min)?; - test_addmul_bignum(&prepare_two_bignums_diff)?; - test_addmul_bignum(&prepare_two_bignums_zero)?; - - let test_data = test_data(); - for i in 0..test_data.len() { - for j in 0..i { - test_addmul_bignum(&|_| { - prepare_two_bignums_from_values(test_data[i].clone(), test_data[j].clone()) - })?; - } - } - - Ok(()) -} - -#[test] -fn test_mul_bignum_all() -> Result<()> { - test_mul_bignum(&prepare_two_bignums_random)?; - test_mul_bignum(&prepare_two_bignums_max)?; - test_mul_bignum(&prepare_two_bignums_min)?; - test_mul_bignum(&prepare_two_bignums_diff)?; - test_mul_bignum(&prepare_two_bignums_zero)?; - - let test_data = test_data(); - for i in 0..test_data.len() { - for j in 0..i { - test_mul_bignum(&|_| { - prepare_two_bignums_from_values(test_data[i].clone(), test_data[j].clone()) - })?; - } - } - - Ok(()) -} diff --git a/evm/src/cpu/kernel/tests/bignum/mod.rs b/evm/src/cpu/kernel/tests/bignum/mod.rs new file mode 100644 index 00000000..687347a5 --- /dev/null +++ b/evm/src/cpu/kernel/tests/bignum/mod.rs @@ -0,0 +1,356 @@ +use std::fs::File; +use std::io::{BufReader, BufRead}; +use std::path::PathBuf; + +use anyhow::Result; +use ethereum_types::U256; +use itertools::Itertools; +use num::{BigUint, One, Zero}; +use num_bigint::RandBigInt; +use plonky2_util::ceil_div_usize; +use rand::Rng; + +use crate::cpu::kernel::aggregator::KERNEL; +use crate::cpu::kernel::interpreter::Interpreter; +use crate::util::{biguint_to_mem_vec, mem_vec_to_biguint}; + +const BIGNUM_LIMB_BITS: usize = 128; +const MINUS_ONE: U256 = U256::MAX; + +const TEST_DATA_BIGNUM_INPUTS: &str = "bignum_inputs"; +const TEST_DATA_U128_INPUTS: &str = "u128_inputs"; +const TEST_DATA_SHR_OUTPUTS: &str = "shr_outputs"; +const TEST_DATA_ISZERO_OUTPUTS: &str = "iszero_outputs"; +const TEST_DATA_CMP_OUTPUTS: &str = "cmp_outputs"; +const TEST_DATA_ADD_OUTPUTS: &str = "add_outputs"; +const TEST_DATA_ADDMUL_OUTPUTS: &str = "addmul_outputs"; +const TEST_DATA_MUL_OUTPUTS: &str = "mul_outputs"; + +const BIT_SIZES_TO_TEST: [usize; 4] = [128, 256, 512, 1000]; + +fn full_path(filename: &str) -> PathBuf { + let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + path.push("src/cpu/kernel/tests/bignum/test_data"); + path.push(filename); + path +} + +fn test_data(filename: &str) -> Vec { + let file = File::open(full_path(filename)).unwrap(); + let lines = BufReader::new(file).lines(); + lines.map(|line| BigUint::parse_bytes(&line.unwrap().as_bytes(), 10).unwrap()).collect() +} + +fn test_data_u128(filename: &str) -> Vec { + let file = File::open(full_path(filename)).unwrap(); + let lines = BufReader::new(file).lines(); + lines.map(|line| line.unwrap().parse::().unwrap()).collect() +} + +fn test_data_u256(filename: &str) -> Vec { + let file = File::open(full_path(filename)).unwrap(); + let lines = BufReader::new(file).lines(); + lines.map(|line| U256::from_dec_str(&line.unwrap()).unwrap()).collect() +} + +// Convert each biguint to a vector of bignum limbs, pad to the given length, and concatenate. +fn pad_bignums(biguints: &[BigUint], length: usize) -> Vec { + biguints + .iter() + .flat_map(|biguint| { + biguint_to_mem_vec(biguint.clone()) + .into_iter() + .pad_using(length, |_| U256::zero()) + }) + .collect() +} + +fn gen_bignum(bit_size: usize) -> BigUint { + let mut rng = rand::thread_rng(); + rng.gen_biguint(bit_size as u64) +} + +fn max_bignum(bit_size: usize) -> BigUint { + (BigUint::one() << bit_size) - BigUint::one() +} + +fn bignum_len(a: &BigUint) -> usize { + ceil_div_usize(a.bits() as usize, BIGNUM_LIMB_BITS) +} + +fn run_test(fn_label: &str, memory: Vec, stack: Vec) -> Result<(Vec, Vec)> { + let fn_label = KERNEL.global_labels[fn_label]; + let retdest = 0xDEADBEEFu32.into(); + + let mut initial_stack: Vec = stack; + initial_stack.push(retdest); + initial_stack.reverse(); + + let mut interpreter = Interpreter::new_with_kernel(fn_label, initial_stack); + interpreter.set_kernel_general_memory(memory); + interpreter.run()?; + + let new_memory = interpreter.get_kernel_general_memory(); + + Ok((new_memory, interpreter.stack().to_vec())) +} + +fn test_shr_bignum(input: BigUint, expected_output: BigUint) -> Result<()> +{ + let len = bignum_len(&input); + let memory = biguint_to_mem_vec(input.clone()); + + let input_start_loc = 0; + let (new_memory, _new_stack) = run_test("shr_bignum", memory, vec![len.into(), input_start_loc.into()])?; + + let output = mem_vec_to_biguint(&new_memory[input_start_loc..input_start_loc+len]); + assert_eq!(output, expected_output); + + Ok(()) +} + +fn test_iszero_bignum(input: BigUint, expected_output: U256) -> Result<()> +{ + let len = bignum_len(&input); + let memory = biguint_to_mem_vec(input.clone()); + + let input_start_loc = 0; + let (_new_memory, new_stack) = run_test("iszero_bignum", memory, vec![len.into(), input_start_loc.into()])?; + + let output = new_stack[0]; + assert_eq!(output, expected_output); + + Ok(()) +} + +fn test_cmp_bignum(a: BigUint, b: BigUint, expected_output: U256) -> Result<()> +{ + let len = bignum_len(&a).max(bignum_len(&b)); + let memory = pad_bignums(&[a.clone(), b.clone()], len); + + let a_start_loc = 0; + let b_start_loc = len; + let (_new_memory, new_stack) = run_test("cmp_bignum", memory, vec![len.into(), a_start_loc.into(), b_start_loc.into()])?; + + let output = new_stack[0]; + assert_eq!(output, expected_output); + + Ok(()) +} + +fn test_add_bignum(a: BigUint, b: BigUint, expected_output: BigUint) -> Result<()> +{ + let len = bignum_len(&a).max(bignum_len(&b)); + let memory = pad_bignums(&[a.clone(), b.clone()], len); + + let a_start_loc = 0; + let b_start_loc = len; + let (mut new_memory, new_stack) = run_test("add_bignum", memory, vec![len.into(), a_start_loc.into(), b_start_loc.into()])?; + + // Determine actual sum, appending the final carry if nonzero. + let carry_limb = new_stack[0]; + if carry_limb > 0.into() { + new_memory[len] = carry_limb; + } + let output = mem_vec_to_biguint(&new_memory[a_start_loc..a_start_loc+len]); + assert_eq!(output, expected_output); + + Ok(()) +} + +fn test_addmul_bignum(a: BigUint, b: BigUint, c: u128, expected_output: BigUint) -> Result<()> +{ + let len = bignum_len(&a).max(bignum_len(&b)); + let mut memory = pad_bignums(&[a.clone(), b.clone()], len); + memory.splice(len..len, vec![0.into(); 2].iter().cloned()); + + let a_start_loc = 0; + let b_start_loc = len + 2; + let (mut new_memory, new_stack) = run_test("addmul_bignum", memory, vec![len.into(), a_start_loc.into(), b_start_loc.into(), c.into()])?; + + // Determine actual sum, appending the final carry if nonzero. + let carry_limb = new_stack[0]; + if carry_limb > 0.into() { + new_memory[len] = carry_limb; + } + let output = mem_vec_to_biguint(&new_memory[a_start_loc..a_start_loc+len]); + assert_eq!(output, expected_output); + + Ok(()) +} + +fn test_mul_bignum(a: BigUint, b: BigUint, expected_output: BigUint) -> Result<()> +{ + let len = bignum_len(&a).max(bignum_len(&b)); + let output_len = len * 2; + let memory = pad_bignums(&[a.clone(), b.clone()], len); + + let a_start_loc = 0; + let b_start_loc = len; + let output_start_loc = 2 * len; + let (new_memory, _new_stack) = run_test("mul_bignum", memory, vec![len.into(), a_start_loc.into(), b_start_loc.into(), output_start_loc.into()])?; + + let output = mem_vec_to_biguint(&new_memory[output_start_loc..output_start_loc+output_len]); + assert_eq!(output, expected_output); + + Ok(()) +} + +#[test] +fn test_shr_bignum_all() -> Result<()> { + for bit_size in BIT_SIZES_TO_TEST { + let input = gen_bignum(bit_size); + let output = input.clone() >> 1; + test_shr_bignum(input, output)?; + + let input = max_bignum(bit_size); + let output = input.clone() >> 1; + test_shr_bignum(input, output)?; + } + + let inputs = test_data(TEST_DATA_BIGNUM_INPUTS); + let shr_outputs = test_data(TEST_DATA_SHR_OUTPUTS); + for (input, output) in inputs.iter().zip(shr_outputs.iter()) { + test_shr_bignum(input.clone(), output.clone())?; + } + + Ok(()) +} + +#[test] +fn test_iszero_bignum_all() -> Result<()> { + for bit_size in BIT_SIZES_TO_TEST { + let input = gen_bignum(bit_size); + let output = input.is_zero() as u8; + test_iszero_bignum(input, output.into())?; + + let input = max_bignum(bit_size); + let output = 0; + test_iszero_bignum(input, output.into())?; + } + + let inputs = test_data(TEST_DATA_BIGNUM_INPUTS); + let iszero_outputs = test_data_u256(TEST_DATA_ISZERO_OUTPUTS); + let mut iszero_outputs_iter = iszero_outputs.iter(); + for input in inputs { + let output = iszero_outputs_iter.next().unwrap(); + test_iszero_bignum(input.clone(), *output)?; + } + + Ok(()) +} + +#[test] +fn test_cmp_bignum_all() -> Result<()> { + for bit_size in BIT_SIZES_TO_TEST { + let a = gen_bignum(bit_size); + let b = gen_bignum(bit_size); + let output = if a < b { MINUS_ONE } else if a == b { 0.into() } else { 1.into() }; + test_cmp_bignum(a, b, output)?; + + let a = max_bignum(bit_size); + let b = max_bignum(bit_size); + let output = 0.into(); + test_cmp_bignum(a, b, output)?; + } + + let inputs = test_data(TEST_DATA_BIGNUM_INPUTS); + let cmp_outputs = test_data_u256(TEST_DATA_CMP_OUTPUTS); + let mut cmp_outputs_iter = cmp_outputs.iter(); + for a in inputs.clone() { + for b in inputs.clone() { + let output = cmp_outputs_iter.next().unwrap(); + test_cmp_bignum(a.clone(), b.clone(), *output)?; + } + } + + Ok(()) +} + +#[test] +fn test_add_bignum_all() -> Result<()> { + for bit_size in BIT_SIZES_TO_TEST { + let a = gen_bignum(bit_size); + let b = gen_bignum(bit_size); + let output = a.clone() + b.clone(); + test_add_bignum(a, b, output)?; + + let a = max_bignum(bit_size); + let b = max_bignum(bit_size); + let output = a.clone() + b.clone(); + test_add_bignum(a, b, output)?; + } + + let inputs = test_data(TEST_DATA_BIGNUM_INPUTS); + let add_outputs = test_data(TEST_DATA_ADD_OUTPUTS); + let mut add_outputs_iter = add_outputs.iter(); + for a in inputs.clone() { + for b in inputs.clone() { + let output = add_outputs_iter.next().unwrap(); + test_add_bignum(a.clone(), b.clone(), output.clone())?; + } + } + + Ok(()) +} + +#[test] +fn test_addmul_bignum_all() -> Result<()> { + let mut rng = rand::thread_rng(); + + for bit_size in BIT_SIZES_TO_TEST { + let a = gen_bignum(bit_size); + let b = gen_bignum(bit_size); + let c: u128 = rng.gen(); + let output = a.clone() + b.clone() * c; + test_addmul_bignum(a, b, c, output)?; + + let a = max_bignum(bit_size); + let b = max_bignum(bit_size); + let c: u128 = rng.gen(); + let output = a.clone() + b.clone() * c; + test_addmul_bignum(a, b, c, output)?; + } + + let inputs = test_data(TEST_DATA_BIGNUM_INPUTS); + let u128_inputs = test_data_u128(TEST_DATA_U128_INPUTS); + let addmul_outputs = test_data(TEST_DATA_ADDMUL_OUTPUTS); + let mut addmul_outputs_iter = addmul_outputs.iter(); + for a in inputs.clone() { + for b in inputs.clone() { + for c in u128_inputs.clone() { + let output = addmul_outputs_iter.next().unwrap(); + test_addmul_bignum(a.clone(), b.clone(), c, output.clone())?; + } + } + } + + Ok(()) +} + +#[test] +fn test_mul_bignum_all() -> Result<()> { + for bit_size in BIT_SIZES_TO_TEST { + let a = gen_bignum(bit_size); + let b = gen_bignum(bit_size); + let output = a.clone() * b.clone(); + test_mul_bignum(a, b, output)?; + + let a = max_bignum(bit_size); + let b = max_bignum(bit_size); + let output = a.clone() * b.clone(); + test_mul_bignum(a, b, output)?; + } + + let inputs = test_data(TEST_DATA_BIGNUM_INPUTS); + let mul_outputs = test_data(TEST_DATA_MUL_OUTPUTS); + let mut mul_outputs_iter = mul_outputs.iter(); + for a in inputs.clone() { + for b in inputs.clone() { + let output = mul_outputs_iter.next().unwrap(); + test_mul_bignum(a.clone(), b.clone(), output.clone())?; + } + } + + Ok(()) +} diff --git a/evm/src/cpu/kernel/tests/bignum/test_data/add_outputs b/evm/src/cpu/kernel/tests/bignum/test_data/add_outputs new file mode 100644 index 00000000..36ebe049 --- /dev/null +++ b/evm/src/cpu/kernel/tests/bignum/test_data/add_outputs @@ -0,0 +1,225 @@ +0 +1 +21 +908 +1267650597867046177654064545792 +340282366920938463463374607431768211455 +57896044618658097611351864738157061705262361561497619362091104892532012613632 +115792089237105570840234253759177109864155645142784332660520492325483608801280 +231583736816786089484927226016147767929578972263620494977377884571370600267775 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725446174963629590181147084998049792 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851378448187094873990326993486348287 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756016346166874193365792884690780159 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459867671853087539206018919387103232 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232059366253413058442519879029375369216 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998255571752838316161056568930429957046271 +1 +2 +22 +909 +1267650597867046177654064545793 +340282366920938463463374607431768211456 +57896044618658097611351864738157061705262361561497619362091104892532012613633 +115792089237105570840234253759177109864155645142784332660520492325483608801281 +231583736816786089484927226016147767929578972263620494977377884571370600267776 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725446174963629590181147084998049793 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851378448187094873990326993486348288 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756016346166874193365792884690780160 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459867671853087539206018919387103233 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232059366253413058442519879029375369217 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998255571752838316161056568930429957046272 +21 +22 +42 +929 +1267650597867046177654064545813 +340282366920938463463374607431768211476 +57896044618658097611351864738157061705262361561497619362091104892532012613653 +115792089237105570840234253759177109864155645142784332660520492325483608801301 +231583736816786089484927226016147767929578972263620494977377884571370600267796 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725446174963629590181147084998049813 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851378448187094873990326993486348308 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756016346166874193365792884690780180 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459867671853087539206018919387103253 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232059366253413058442519879029375369237 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998255571752838316161056568930429957046292 +908 +909 +929 +1816 +1267650597867046177654064546700 +340282366920938463463374607431768212363 +57896044618658097611351864738157061705262361561497619362091104892532012614540 +115792089237105570840234253759177109864155645142784332660520492325483608802188 +231583736816786089484927226016147767929578972263620494977377884571370600268683 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725446174963629590181147084998050700 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851378448187094873990326993486349195 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756016346166874193365792884690781067 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459867671853087539206018919387104140 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232059366253413058442519879029375370124 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998255571752838316161056568930429957047179 +1267650597867046177654064545792 +1267650597867046177654064545793 +1267650597867046177654064545813 +1267650597867046177654064546700 +2535301195734092355308129091584 +340282368188589061330420785085832757247 +57896044618658097611351864738157061705262361562765269959958151070186077159424 +115792089237105570840234253759177109864155645144051983258387538503137673347072 +231583736816786089484927226016147767929578972264888145575244930749024664813567 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725447442614227457227324739062595584 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851379715837692741036504647550894079 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756017613817472060411970538755325951 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459868939503685406252196573451649024 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232059367521063656309566056683439915008 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998255571754105966758923615108084021592063 +340282366920938463463374607431768211455 +340282366920938463463374607431768211456 +340282366920938463463374607431768211476 +340282366920938463463374607431768212363 +340282368188589061330420785085832757247 +680564733841876926926749214863536422910 +57896044618658097611351864738157061705602643928418557825554479499963780825087 +115792089237105570840234253759177109864495927509705271123983866932915377012735 +231583736816786089484927226016147767929919254630541433440841259178802368479230 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656433007813095902093053555754516766261247 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352969133745369125558337364934425254559742 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107569038383267105337656740400316458991614 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244438742234592791551002580626351155314687 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359572341733174351521905894486461143580671 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998595854119759254624519943537861725257726 +57896044618658097611351864738157061705262361561497619362091104892532012613632 +57896044618658097611351864738157061705262361561497619362091104892532012613633 +57896044618658097611351864738157061705262361561497619362091104892532012613653 +57896044618658097611351864738157061705262361561497619362091104892532012614540 +57896044618658097611351864738157061705262361562765269959958151070186077159424 +57896044618658097611351864738157061705602643928418557825554479499963780825087 +115792089237316195222703729476314123410524723122995238724182209785064025227264 +173688133855763668451586118497334171569418006704281952022611597218015621414912 +289479781435444187096279090754304829634841333825118114339468989463902612881407 +3273390607896141870013189696827599152216642046043064789482248405676250539586401155309462588318799202567027652361355087007672582991681286039617010663424 +5027927973729236057982426364448826617555638513633071601633370220421967636306804394074875752581912318823441521134057891212939945806456965095219525498961919 +13407807929942597099574024997867385471458758537929012740010782671329620832395892888572752773084019014537559577489812491117577843786236284470685416703393791 +26815615859885194199148049995734770942917517075858043397979502765092926124329972428655111861232797616170839264946949360821429169472449630310911451399716864 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356940333001073316904952470628102164776064494420927751032420533624771561387982848 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463796730242309831072892700701204289449703517933314335935523147673822961969659903 +115792089237105570840234253759177109864155645142784332660520492325483608801280 +115792089237105570840234253759177109864155645142784332660520492325483608801281 +115792089237105570840234253759177109864155645142784332660520492325483608801301 +115792089237105570840234253759177109864155645142784332660520492325483608802188 +115792089237105570840234253759177109864155645144051983258387538503137673347072 +115792089237105570840234253759177109864495927509705271123983866932915377012735 +173688133855763668451586118497334171569418006704281952022611597218015621414912 +231584178474211141680468507518354219728311290285568665321040984650967217602560 +347375826053891660325161479775324877793734617406404827637898376896854209069055 +3273390607896141870013189696827599152216642046043064789482248405676250539644297199927910061547681591588047700520248370588959296290110673472568606851072 +5027927973729236057982426364448826617555638513633071601633370220421967636306862290119494200055141201212462541182216784496521232519755394482652477095149567 +13407807929942597099574024997867385471458758537929012740010782671329620832395950784617371220557247896926580597537971384401159130499534713858118368299581439 +26815615859885194199148049995734770942917517075858043397979502765092926124330030324699730308706026498559860284995108254105010456185748059698344402995904512 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356998229045691764378181353017123184824223387704509037745718963012204512984170496 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463854626286928278546121583090225309497862411216895622648821577061255913565847551 +231583736816786089484927226016147767929578972263620494977377884571370600267775 +231583736816786089484927226016147767929578972263620494977377884571370600267776 +231583736816786089484927226016147767929578972263620494977377884571370600267796 +231583736816786089484927226016147767929578972263620494977377884571370600268683 +231583736816786089484927226016147767929578972264888145575244930749024664813567 +231583736816786089484927226016147767929919254630541433440841259178802368479230 +289479781435444187096279090754304829634841333825118114339468989463902612881407 +347375826053891660325161479775324877793734617406404827637898376896854209069055 +463167473633572178969854452032295535859157944527240989954755769142741200535550 +3273390607896141870013189696827599152216642046043064789482248405676250539760088847507590580192374563845018358585671697709795458606968065718455598317567 +5027927973729236057982426364448826617555638513633071601633370220421967636306978081767073880573785894184719511840282207823642068682072251874898364086616062 +13407807929942597099574024997867385471458758537929012740010782671329620832396066576264950901075892589898837568196036807728279966661851571250364255291047934 +26815615859885194199148049995734770942917517075858043397979502765092926124330146116347309989224671191532117255653173677432131292348064917090590289987371007 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322357114020693271444896826045989380155482288811031629873908035820404450399975636991 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463970417934507959064766276062482280155927834544016458811138434453501800557314046 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725446174963629590181147084998049792 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725446174963629590181147084998049793 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725446174963629590181147084998049813 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725446174963629590181147084998050700 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725447442614227457227324739062595584 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656433007813095902093053555754516766261247 +3273390607896141870013189696827599152216642046043064789482248405676250539586401155309462588318799202567027652361355087007672582991681286039617010663424 +3273390607896141870013189696827599152216642046043064789482248405676250539644297199927910061547681591588047700520248370588959296290110673472568606851072 +3273390607896141870013189696827599152216642046043064789482248405676250539760088847507590580192374563845018358585671697709795458606968065718455598317567 +6546781215792283740026379393655198304433284092086129578964496811352501079057010221381608981414894675657741181312185450892349927259180362294169996099584 +5031201364337132199852439554145654216707855155679114666422852468827643886846275003140947898975008414296532234663008721576824623150724464171474078484398079 +13411081320550493241444038187564213070610975179975055804800264919735297082935363497638824919477115110010650291018763321481462521130503783546939969688829951 +26818889250493090341018063185431598542069733717904086462768985013498602374869443037721184007625893711643929978475900191185313846816717129387166004385153024 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094859873731529946340457125253265606438475403785866280608383688705623749572896410942067145463298048566101192878305015324784812428376688032701026114373419008 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988312365191525626829590504228669795829923743060941349315981180118158171906003267339308381977465988796174295002978654348297199013279790646750077514955096063 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851378448187094873990326993486348287 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851378448187094873990326993486348288 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851378448187094873990326993486348308 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851378448187094873990326993486349195 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851379715837692741036504647550894079 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352969133745369125558337364934425254559742 +5027927973729236057982426364448826617555638513633071601633370220421967636306804394074875752581912318823441521134057891212939945806456965095219525498961919 +5027927973729236057982426364448826617555638513633071601633370220421967636306862290119494200055141201212462541182216784496521232519755394482652477095149567 +5027927973729236057982426364448826617555638513633071601633370220421967636306978081767073880573785894184719511840282207823642068682072251874898364086616062 +5031201364337132199852439554145654216707855155679114666422852468827643886846275003140947898975008414296532234663008721576824623150724464171474078484398079 +10055855947458472115964852728897653235111277027266143203266740440843935272613492996060514188968601933917406728144705257702756896374189747980653986972696574 +18435735903671833157556451362316212089014397051562084341644152891751588468702581490558391209470708629631524784500459857607394794353969067356119878177128446 +31843543833614430257130476360183597560473155589491114999612872985514893760636661030640750297619487231264804471957596727311246120040182413196345912873451519 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604099884528314651286256569538428017605456878825657453309145227576677640040958663628934986711753291642085722067371786711860910744701600153316510206022861717503 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060993337019774646966745702917403421794848327164932528377852825068090174463291770485332227948267459582315795169496460350884423131286503255930559257423443394558 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756016346166874193365792884690780159 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756016346166874193365792884690780160 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756016346166874193365792884690780180 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756016346166874193365792884690781067 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756017613817472060411970538755325951 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107569038383267105337656740400316458991614 +13407807929942597099574024997867385471458758537929012740010782671329620832395892888572752773084019014537559577489812491117577843786236284470685416703393791 +13407807929942597099574024997867385471458758537929012740010782671329620832395950784617371220557247896926580597537971384401159130499534713858118368299581439 +13407807929942597099574024997867385471458758537929012740010782671329620832396066576264950901075892589898837568196036807728279966661851571250364255291047934 +13411081320550493241444038187564213070610975179975055804800264919735297082935363497638824919477115110010650291018763321481462521130503783546939969688829951 +18435735903671833157556451362316212089014397051562084341644152891751588468702581490558391209470708629631524784500459857607394794353969067356119878177128446 +26815615859885194199148049995734770942917517075858025480021565342659241664791669985056268229972815325345642840856214457512032692333748386731585769381560318 +40223423789827791298722074993602156414376275613787056137990285436422546956725749525138627318121593926978922528313351327215884018019961732571811804077883391 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604108264408270864647298161137061436164310781945681749250283604989128547694154752717429484588773793748781436185428142466460815382599579932635885671914066149375 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581061001716899730860327787294516036840353702230284956824318991202480541082116487859573826725825287961689011509287552816105484327769184483035249934723314647826430 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459867671853087539206018919387103232 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459867671853087539206018919387103233 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459867671853087539206018919387103253 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459867671853087539206018919387104140 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459868939503685406252196573451649024 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244438742234592791551002580626351155314687 +26815615859885194199148049995734770942917517075858043397979502765092926124329972428655111861232797616170839264946949360821429169472449630310911451399716864 +26815615859885194199148049995734770942917517075858043397979502765092926124330030324699730308706026498559860284995108254105010456185748059698344402995904512 +26815615859885194199148049995734770942917517075858043397979502765092926124330146116347309989224671191532117255653173677432131292348064917090590289987371007 +26818889250493090341018063185431598542069733717904086462768985013498602374869443037721184007625893711643929978475900191185313846816717129387166004385153024 +31843543833614430257130476360183597560473155589491114999612872985514893760636661030640750297619487231264804471957596727311246120040182413196345912873451519 +40223423789827791298722074993602156414376275613787056137990285436422546956725749525138627318121593926978922528313351327215884018019961732571811804077883391 +53631231719770388398296099991469541885835034151716086795959005530185852248659829065220986406270372528612202215770488196919735343706175078412037838774206464 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604121672216200807244397735162059303549782240704219678280941573709222310999446686796969566947861942527383069465115599603330519233925266145981725897948762472448 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581061015124707660802924886868541034707739173689043494753349649171200634845421779793653366808184376110467613142567240273242354031620510169248595774949349344149503 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232059366253413058442519879029375369216 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232059366253413058442519879029375369217 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232059366253413058442519879029375369237 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232059366253413058442519879029375370124 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232059367521063656309566056683439915008 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359572341733174351521905894486461143580671 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356940333001073316904952470628102164776064494420927751032420533624771561387982848 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356998229045691764378181353017123184824223387704509037745718963012204512984170496 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322357114020693271444896826045989380155482288811031629873908035820404450399975636991 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094859873731529946340457125253265606438475403785866280608383688705623749572896410942067145463298048566101192878305015324784812428376688032701026114373419008 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604099884528314651286256569538428017605456878825657453309145227576677640040958663628934986711753291642085722067371786711860910744701600153316510206022861717503 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604108264408270864647298161137061436164310781945681749250283604989128547694154752717429484588773793748781436185428142466460815382599579932635885671914066149375 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604121672216200807244397735162059303549782240704219678280941573709222310999446686796969566947861942527383069465115599603330519233925266145981725897948762472448 +21430172143725344039741447416747135734328099194269775938858685112579378184657786065906763159178676625205218492566825428477050725853377832065983208189713200681844100397174224127137557678646374287640475087188412914436146644713764873912909317614682237526728015428718464118732506826116885039758058750738432 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824629198276151174244463087285660418287344529756165187857520911105123842660034918703411836307538943107430287596439419222071804002615797677806638572665083165692141839780886307603102541747070094713562715543794785904326970568977820621271154145831782622467599830140102357487631119091729219499088809459332415487 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998255571752838316161056568930429957046271 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998255571752838316161056568930429957046272 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998255571752838316161056568930429957046292 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998255571752838316161056568930429957047179 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998255571754105966758923615108084021592063 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998595854119759254624519943537861725257726 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463796730242309831072892700701204289449703517933314335935523147673822961969659903 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463854626286928278546121583090225309497862411216895622648821577061255913565847551 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463970417934507959064766276062482280155927834544016458811138434453501800557314046 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988312365191525626829590504228669795829923743060941349315981180118158171906003267339308381977465988796174295002978654348297199013279790646750077514955096063 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060993337019774646966745702917403421794848327164932528377852825068090174463291770485332227948267459582315795169496460350884423131286503255930559257423443394558 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581061001716899730860327787294516036840353702230284956824318991202480541082116487859573826725825287961689011509287552816105484327769184483035249934723314647826430 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581061015124707660802924886868541034707739173689043494753349649171200634845421779793653366808184376110467613142567240273242354031620510169248595774949349344149503 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824629198276151174244463087285660418287344529756165187857520911105123842660034918703411836307538943107430287596439419222071804002615797677806638572665083165692141839780886307603102541747070094713562715543794785904326970568977820621271154145831782622467599830140102357487631119091729219499088809459332415487 +70149324220868077495255175920561715987048031760661657648151596049581927701126644407314161773169938523306300574636470765864723972756401953860971729649236966380158623144886433123904089438954731413136105939102963525135105941885179620757765851918707538235369974386271618715130954505741977781211162121976618183601835461375440982077945936461543052837790612502383395739504991310927477668395382345950562697672932264775996511143505676632322113137860859914092542 diff --git a/evm/src/cpu/kernel/tests/bignum/test_data/addmul_outputs b/evm/src/cpu/kernel/tests/bignum/test_data/addmul_outputs new file mode 100644 index 00000000..397c7451 --- /dev/null +++ b/evm/src/cpu/kernel/tests/bignum/test_data/addmul_outputs @@ -0,0 +1,1350 @@ +0 +0 +0 +0 +0 +0 +0 +1 +21 +908 +1267650597867046177654064545792 +340282366920938463463374607431768211455 +0 +21 +441 +19068 +26620662555207969730735355461632 +7145929705339707732730866756067132440555 +0 +908 +19068 +824464 +1151026742863277929309890607579136 +308976389164212124824744143548045536001140 +0 +1267650597867046177654064545792 +26620662555207969730735355461632 +1151026742863277929309890607579136 +1606938038272679619211255036084048932956190504430095264907264 +431359145870941220571487096504865044588697904564591140391738786447360 +0 +340282366920938463463374607431768211455 +7145929705339707732730866756067132440555 +308976389164212124824744143548045536001140 +431359145870941220571487096504865044588697904564591140391738786447360 +115792089237316195423570985008687907852589419931798687112530834793049593217025 +0 +57896044618658097611351864738157061705262361561497619362091104892532012613632 +1215816936991820049838389159501298295810509592791450006603913202743172264886272 +52569608513741552631107493182246612028378224297839838380778723242419067453177856 +73391955574979118963811141843059488536193514605218060347731553038824318137413435829926783487818828867436544 +19701003098197239571963727475337245584161626291901231402719522479678259504890677218990119895590117915143388591554560 +0 +115792089237105570840234253759177109864155645142784332660520492325483608801280 +2431633873979216987644919328942719307147268547998470985870930338835155784826880 +105139217027291858322932702413332815756653325789648174055752607031539116791562240 +146783911149691239803259475393272332038744581223672095908357420057841712239442615794649035123910216788213760 +39402006196322807380529480735708200350692396090822410401547663254352517428719749608020233606624972587007562114662400 +0 +231583736816786089484927226016147767929578972263620494977377884571370600267775 +4863258473152507879183471746339103126521158417536030394524935575998782605623275 +210278033029641769252313921222662173280057706815367409439459119190804505043139700 +293567262432083559770702660509494961636846893913475830448684457955877331972488384611363806317219648949452800 +78803862104411649792976274791681038936454943300723566886694079153850261012036590002656572187311458765011955822362625 +0 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725446174963629590181147084998049792 +68741202765818979270276983633379582196549482966904360579127216519201261330098607324506894304856394094406282403777947234369674236221393804088784959045632 +2972238671969696817971976244719460030212710977807102828849881552354035489891882640507250477562362182748614496315732194705126866975667884481553178229211136 +4149515561151917970063980879655710938513649460124350952720371065270297197065154634382680097543307069927884450339928718724097725668943949230978441358030208342019760039438410280075264 +1113877103911668754551067286547922686738237475419584309931192581897577662915063323503306740447008536028968181678028580322422866333819711284625174374608617279642589745120484326564854874767360 +0 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851378448187094873990326993486348287 +105586487448313957217630953653425358968668408786294503634300774628861320362441676458635398984170320306132770645519405205878947411928992353796866863213314027 +4565358600146146340648043138919534568740519770378829014283100160143146613766525820211473441791745277998502654577696186997051630953882145583216910085604244596 +6373655901930312136397229380018411440828683949391920950832693445711366448193584697763678864931677968612065262908033170282412527802037703004824976134384286640214222530054133889372258304 +1710915231608582551713494414139930175751260546116444122900349352360496966554854730076753484481830650675467827629295222707109502155201699203484369755223655341193278275893163301956243837193027585 +0 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756016346166874193365792884690780159 +281563966528794539091054524955215094900633929296509267540226436097922037480312534843090816414714560916129249828990251803876343269504358060681650578506383339 +12174289600387878166413214698063586008084552752439543567929790665567295715815418173215545776407658157706921849748721363710462842319521767576139939299228384372 +16996415738478256005382065682640742151192912704409604594012987116129634408058546371285779101609491343355313613863898166638327059654603396304113335697353121717251389843622698066460540928 +4562440617622195218641171605585119131739514871918667547682857357314343535508689562160604455918497575074715174882382908134196095677901105600185199282794955018371204524886410100925712980030521345 +0 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459867671853087539206018919387103232 +563127933057589078182109049910430189801267858593018911357569558066951448610928205184820357265838911550428123265590126067657221108914838323326397307129167872 +24348579200775756332826429396127172016169105504879103405365388510704376920891562395610327828446749127989939805959801641401559846042603485599065178803489734656 +33992831476956512010764131365281484302385825408819231901736066162392911122587750794642859557837487570646738733764326406607430768230396539092082721200286809873288301231428402460695199744 +9124881235244390437282343211170238263479029743837341192530852050551013988199468564099149809149237792502394782872367659707645708326849200364829008985690446628655225628506036591091211274089922560 +0 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232059366253413058442519879029375369216 +225016807509116112417285197875844925210445041539832647358016193682083470938906753692021013171376104564654794171951666999009032621460467236692823685991988607159363054170329353334944355625786930020224988415478335601579539769494531176085547834954163494030644162001543873246691321674227292917459616882753536 +9729298153251306194042617127203199623384957034198478276241843041111037695834634873921670474267119187843169195625338744528581029537433535757956376518129793109557221580317097753720451186105453926588775689583539463154010576700049252756460830197065735837134519004638182709904558099057065808050158672835248128 +13582985265193575509847153720290630277475301176695966793104558898916525902171099726111653252346386417687634059875171486934990855171785554727726817192028731914702681172768151028934363876033198780003232825417916826555570603003610443324900765322801514628836373961563717819815659178099324514051673737887522648522145975473923735339139072 +3646154850295010964902624396817474390399390616036693719739415376725561063085178919082942505698777176089060633115597677023110409583667009527018497076154392047301826729011247840192495744913649306569979494349478121435366144715292958165239232610420731738086890347478323006048396719686780691510330825043607290550999833104265740262684222585569280 +0 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998255571752838316161056568930429957046271 +736567904319114813700179347165898017864004333486947405305591758520610240861829766276798698618284354494716156033682943041579601713942220515540203161316988146991665543021307547800992939109024679837929112360581117013918612389794386017956541445146429151471384731055851996508875022310290766702717202280754490927819272344442130311818432332846202054796801431275025655264802408764738515518151514632480908325565788780147963367006809604639382187947539029097971691 +31847793196274107182845849867935019058119806419340392572260824606510195176311496560920629445019152089581060460884957727702584683631406487052881165260753582736592014907778440638252456605285448061563792096352745440411338097615871547824025696771093222358857968371367314896669453345606857912669867603377384655355233299464450205863387455153540545988356938076082061665735266055161074861451503585061555464743511248208302416059151577191074239364588830400998014068 +44462416394276340862910922260389321581298853470913371563358965890746390942505208917810214508921403677924050484037361854923909199530783769557857398908416797467991642660044081596444758567725905941578862500220928052627591160031402858547990440510112144073496748573294083122100295594485512238065152913601534980743295758670057701269862152855527112109603873427804287879276629501582896265202691196110634325565999430887153483257613158570830305101308846059434951620873330091758706311542341632 +11935289041890653422458560211344367565999989567726224393815132782921219808519438180124970259072038417888105302535754774032670805811336900569676094726678661851388189281957447472598923409448779291182901295823514011338832830575108282476521982723289897702706625317681157972521881629518687524749107700488703863037130875637878556278141428758998783243913325146240393321801800775493463196094645471464263521615496507631433158100292031999009575957202146963989209941350094442798986370318517904347234305 +1 +1 +1 +1 +1 +1 +1 +2 +22 +909 +1267650597867046177654064545793 +340282366920938463463374607431768211456 +1 +22 +442 +19069 +26620662555207969730735355461633 +7145929705339707732730866756067132440556 +1 +909 +19069 +824465 +1151026742863277929309890607579137 +308976389164212124824744143548045536001141 +1 +1267650597867046177654064545793 +26620662555207969730735355461633 +1151026742863277929309890607579137 +1606938038272679619211255036084048932956190504430095264907265 +431359145870941220571487096504865044588697904564591140391738786447361 +1 +340282366920938463463374607431768211456 +7145929705339707732730866756067132440556 +308976389164212124824744143548045536001141 +431359145870941220571487096504865044588697904564591140391738786447361 +115792089237316195423570985008687907852589419931798687112530834793049593217026 +1 +57896044618658097611351864738157061705262361561497619362091104892532012613633 +1215816936991820049838389159501298295810509592791450006603913202743172264886273 +52569608513741552631107493182246612028378224297839838380778723242419067453177857 +73391955574979118963811141843059488536193514605218060347731553038824318137413435829926783487818828867436545 +19701003098197239571963727475337245584161626291901231402719522479678259504890677218990119895590117915143388591554561 +1 +115792089237105570840234253759177109864155645142784332660520492325483608801281 +2431633873979216987644919328942719307147268547998470985870930338835155784826881 +105139217027291858322932702413332815756653325789648174055752607031539116791562241 +146783911149691239803259475393272332038744581223672095908357420057841712239442615794649035123910216788213761 +39402006196322807380529480735708200350692396090822410401547663254352517428719749608020233606624972587007562114662401 +1 +231583736816786089484927226016147767929578972263620494977377884571370600267776 +4863258473152507879183471746339103126521158417536030394524935575998782605623276 +210278033029641769252313921222662173280057706815367409439459119190804505043139701 +293567262432083559770702660509494961636846893913475830448684457955877331972488384611363806317219648949452801 +78803862104411649792976274791681038936454943300723566886694079153850261012036590002656572187311458765011955822362626 +1 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725446174963629590181147084998049793 +68741202765818979270276983633379582196549482966904360579127216519201261330098607324506894304856394094406282403777947234369674236221393804088784959045633 +2972238671969696817971976244719460030212710977807102828849881552354035489891882640507250477562362182748614496315732194705126866975667884481553178229211137 +4149515561151917970063980879655710938513649460124350952720371065270297197065154634382680097543307069927884450339928718724097725668943949230978441358030208342019760039438410280075265 +1113877103911668754551067286547922686738237475419584309931192581897577662915063323503306740447008536028968181678028580322422866333819711284625174374608617279642589745120484326564854874767361 +1 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851378448187094873990326993486348288 +105586487448313957217630953653425358968668408786294503634300774628861320362441676458635398984170320306132770645519405205878947411928992353796866863213314028 +4565358600146146340648043138919534568740519770378829014283100160143146613766525820211473441791745277998502654577696186997051630953882145583216910085604244597 +6373655901930312136397229380018411440828683949391920950832693445711366448193584697763678864931677968612065262908033170282412527802037703004824976134384286640214222530054133889372258305 +1710915231608582551713494414139930175751260546116444122900349352360496966554854730076753484481830650675467827629295222707109502155201699203484369755223655341193278275893163301956243837193027586 +1 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756016346166874193365792884690780160 +281563966528794539091054524955215094900633929296509267540226436097922037480312534843090816414714560916129249828990251803876343269504358060681650578506383340 +12174289600387878166413214698063586008084552752439543567929790665567295715815418173215545776407658157706921849748721363710462842319521767576139939299228384373 +16996415738478256005382065682640742151192912704409604594012987116129634408058546371285779101609491343355313613863898166638327059654603396304113335697353121717251389843622698066460540929 +4562440617622195218641171605585119131739514871918667547682857357314343535508689562160604455918497575074715174882382908134196095677901105600185199282794955018371204524886410100925712980030521346 +1 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459867671853087539206018919387103233 +563127933057589078182109049910430189801267858593018911357569558066951448610928205184820357265838911550428123265590126067657221108914838323326397307129167873 +24348579200775756332826429396127172016169105504879103405365388510704376920891562395610327828446749127989939805959801641401559846042603485599065178803489734657 +33992831476956512010764131365281484302385825408819231901736066162392911122587750794642859557837487570646738733764326406607430768230396539092082721200286809873288301231428402460695199745 +9124881235244390437282343211170238263479029743837341192530852050551013988199468564099149809149237792502394782872367659707645708326849200364829008985690446628655225628506036591091211274089922561 +1 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232059366253413058442519879029375369217 +225016807509116112417285197875844925210445041539832647358016193682083470938906753692021013171376104564654794171951666999009032621460467236692823685991988607159363054170329353334944355625786930020224988415478335601579539769494531176085547834954163494030644162001543873246691321674227292917459616882753537 +9729298153251306194042617127203199623384957034198478276241843041111037695834634873921670474267119187843169195625338744528581029537433535757956376518129793109557221580317097753720451186105453926588775689583539463154010576700049252756460830197065735837134519004638182709904558099057065808050158672835248129 +13582985265193575509847153720290630277475301176695966793104558898916525902171099726111653252346386417687634059875171486934990855171785554727726817192028731914702681172768151028934363876033198780003232825417916826555570603003610443324900765322801514628836373961563717819815659178099324514051673737887522648522145975473923735339139073 +3646154850295010964902624396817474390399390616036693719739415376725561063085178919082942505698777176089060633115597677023110409583667009527018497076154392047301826729011247840192495744913649306569979494349478121435366144715292958165239232610420731738086890347478323006048396719686780691510330825043607290550999833104265740262684222585569281 +1 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998255571752838316161056568930429957046272 +736567904319114813700179347165898017864004333486947405305591758520610240861829766276798698618284354494716156033682943041579601713942220515540203161316988146991665543021307547800992939109024679837929112360581117013918612389794386017956541445146429151471384731055851996508875022310290766702717202280754490927819272344442130311818432332846202054796801431275025655264802408764738515518151514632480908325565788780147963367006809604639382187947539029097971692 +31847793196274107182845849867935019058119806419340392572260824606510195176311496560920629445019152089581060460884957727702584683631406487052881165260753582736592014907778440638252456605285448061563792096352745440411338097615871547824025696771093222358857968371367314896669453345606857912669867603377384655355233299464450205863387455153540545988356938076082061665735266055161074861451503585061555464743511248208302416059151577191074239364588830400998014069 +44462416394276340862910922260389321581298853470913371563358965890746390942505208917810214508921403677924050484037361854923909199530783769557857398908416797467991642660044081596444758567725905941578862500220928052627591160031402858547990440510112144073496748573294083122100295594485512238065152913601534980743295758670057701269862152855527112109603873427804287879276629501582896265202691196110634325565999430887153483257613158570830305101308846059434951620873330091758706311542341633 +11935289041890653422458560211344367565999989567726224393815132782921219808519438180124970259072038417888105302535754774032670805811336900569676094726678661851388189281957447472598923409448779291182901295823514011338832830575108282476521982723289897702706625317681157972521881629518687524749107700488703863037130875637878556278141428758998783243913325146240393321801800775493463196094645471464263521615496507631433158100292031999009575957202146963989209941350094442798986370318517904347234306 +21 +21 +21 +21 +21 +21 +21 +22 +42 +929 +1267650597867046177654064545813 +340282366920938463463374607431768211476 +21 +42 +462 +19089 +26620662555207969730735355461653 +7145929705339707732730866756067132440576 +21 +929 +19089 +824485 +1151026742863277929309890607579157 +308976389164212124824744143548045536001161 +21 +1267650597867046177654064545813 +26620662555207969730735355461653 +1151026742863277929309890607579157 +1606938038272679619211255036084048932956190504430095264907285 +431359145870941220571487096504865044588697904564591140391738786447381 +21 +340282366920938463463374607431768211476 +7145929705339707732730866756067132440576 +308976389164212124824744143548045536001161 +431359145870941220571487096504865044588697904564591140391738786447381 +115792089237316195423570985008687907852589419931798687112530834793049593217046 +21 +57896044618658097611351864738157061705262361561497619362091104892532012613653 +1215816936991820049838389159501298295810509592791450006603913202743172264886293 +52569608513741552631107493182246612028378224297839838380778723242419067453177877 +73391955574979118963811141843059488536193514605218060347731553038824318137413435829926783487818828867436565 +19701003098197239571963727475337245584161626291901231402719522479678259504890677218990119895590117915143388591554581 +21 +115792089237105570840234253759177109864155645142784332660520492325483608801301 +2431633873979216987644919328942719307147268547998470985870930338835155784826901 +105139217027291858322932702413332815756653325789648174055752607031539116791562261 +146783911149691239803259475393272332038744581223672095908357420057841712239442615794649035123910216788213781 +39402006196322807380529480735708200350692396090822410401547663254352517428719749608020233606624972587007562114662421 +21 +231583736816786089484927226016147767929578972263620494977377884571370600267796 +4863258473152507879183471746339103126521158417536030394524935575998782605623296 +210278033029641769252313921222662173280057706815367409439459119190804505043139721 +293567262432083559770702660509494961636846893913475830448684457955877331972488384611363806317219648949452821 +78803862104411649792976274791681038936454943300723566886694079153850261012036590002656572187311458765011955822362646 +21 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725446174963629590181147084998049813 +68741202765818979270276983633379582196549482966904360579127216519201261330098607324506894304856394094406282403777947234369674236221393804088784959045653 +2972238671969696817971976244719460030212710977807102828849881552354035489891882640507250477562362182748614496315732194705126866975667884481553178229211157 +4149515561151917970063980879655710938513649460124350952720371065270297197065154634382680097543307069927884450339928718724097725668943949230978441358030208342019760039438410280075285 +1113877103911668754551067286547922686738237475419584309931192581897577662915063323503306740447008536028968181678028580322422866333819711284625174374608617279642589745120484326564854874767381 +21 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851378448187094873990326993486348308 +105586487448313957217630953653425358968668408786294503634300774628861320362441676458635398984170320306132770645519405205878947411928992353796866863213314048 +4565358600146146340648043138919534568740519770378829014283100160143146613766525820211473441791745277998502654577696186997051630953882145583216910085604244617 +6373655901930312136397229380018411440828683949391920950832693445711366448193584697763678864931677968612065262908033170282412527802037703004824976134384286640214222530054133889372258325 +1710915231608582551713494414139930175751260546116444122900349352360496966554854730076753484481830650675467827629295222707109502155201699203484369755223655341193278275893163301956243837193027606 +21 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756016346166874193365792884690780180 +281563966528794539091054524955215094900633929296509267540226436097922037480312534843090816414714560916129249828990251803876343269504358060681650578506383360 +12174289600387878166413214698063586008084552752439543567929790665567295715815418173215545776407658157706921849748721363710462842319521767576139939299228384393 +16996415738478256005382065682640742151192912704409604594012987116129634408058546371285779101609491343355313613863898166638327059654603396304113335697353121717251389843622698066460540949 +4562440617622195218641171605585119131739514871918667547682857357314343535508689562160604455918497575074715174882382908134196095677901105600185199282794955018371204524886410100925712980030521366 +21 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459867671853087539206018919387103253 +563127933057589078182109049910430189801267858593018911357569558066951448610928205184820357265838911550428123265590126067657221108914838323326397307129167893 +24348579200775756332826429396127172016169105504879103405365388510704376920891562395610327828446749127989939805959801641401559846042603485599065178803489734677 +33992831476956512010764131365281484302385825408819231901736066162392911122587750794642859557837487570646738733764326406607430768230396539092082721200286809873288301231428402460695199765 +9124881235244390437282343211170238263479029743837341192530852050551013988199468564099149809149237792502394782872367659707645708326849200364829008985690446628655225628506036591091211274089922581 +21 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232059366253413058442519879029375369237 +225016807509116112417285197875844925210445041539832647358016193682083470938906753692021013171376104564654794171951666999009032621460467236692823685991988607159363054170329353334944355625786930020224988415478335601579539769494531176085547834954163494030644162001543873246691321674227292917459616882753557 +9729298153251306194042617127203199623384957034198478276241843041111037695834634873921670474267119187843169195625338744528581029537433535757956376518129793109557221580317097753720451186105453926588775689583539463154010576700049252756460830197065735837134519004638182709904558099057065808050158672835248149 +13582985265193575509847153720290630277475301176695966793104558898916525902171099726111653252346386417687634059875171486934990855171785554727726817192028731914702681172768151028934363876033198780003232825417916826555570603003610443324900765322801514628836373961563717819815659178099324514051673737887522648522145975473923735339139093 +3646154850295010964902624396817474390399390616036693719739415376725561063085178919082942505698777176089060633115597677023110409583667009527018497076154392047301826729011247840192495744913649306569979494349478121435366144715292958165239232610420731738086890347478323006048396719686780691510330825043607290550999833104265740262684222585569301 +21 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998255571752838316161056568930429957046292 +736567904319114813700179347165898017864004333486947405305591758520610240861829766276798698618284354494716156033682943041579601713942220515540203161316988146991665543021307547800992939109024679837929112360581117013918612389794386017956541445146429151471384731055851996508875022310290766702717202280754490927819272344442130311818432332846202054796801431275025655264802408764738515518151514632480908325565788780147963367006809604639382187947539029097971712 +31847793196274107182845849867935019058119806419340392572260824606510195176311496560920629445019152089581060460884957727702584683631406487052881165260753582736592014907778440638252456605285448061563792096352745440411338097615871547824025696771093222358857968371367314896669453345606857912669867603377384655355233299464450205863387455153540545988356938076082061665735266055161074861451503585061555464743511248208302416059151577191074239364588830400998014089 +44462416394276340862910922260389321581298853470913371563358965890746390942505208917810214508921403677924050484037361854923909199530783769557857398908416797467991642660044081596444758567725905941578862500220928052627591160031402858547990440510112144073496748573294083122100295594485512238065152913601534980743295758670057701269862152855527112109603873427804287879276629501582896265202691196110634325565999430887153483257613158570830305101308846059434951620873330091758706311542341653 +11935289041890653422458560211344367565999989567726224393815132782921219808519438180124970259072038417888105302535754774032670805811336900569676094726678661851388189281957447472598923409448779291182901295823514011338832830575108282476521982723289897702706625317681157972521881629518687524749107700488703863037130875637878556278141428758998783243913325146240393321801800775493463196094645471464263521615496507631433158100292031999009575957202146963989209941350094442798986370318517904347234326 +908 +908 +908 +908 +908 +908 +908 +909 +929 +1816 +1267650597867046177654064546700 +340282366920938463463374607431768212363 +908 +929 +1349 +19976 +26620662555207969730735355462540 +7145929705339707732730866756067132441463 +908 +1816 +19976 +825372 +1151026742863277929309890607580044 +308976389164212124824744143548045536002048 +908 +1267650597867046177654064546700 +26620662555207969730735355462540 +1151026742863277929309890607580044 +1606938038272679619211255036084048932956190504430095264908172 +431359145870941220571487096504865044588697904564591140391738786448268 +908 +340282366920938463463374607431768212363 +7145929705339707732730866756067132441463 +308976389164212124824744143548045536002048 +431359145870941220571487096504865044588697904564591140391738786448268 +115792089237316195423570985008687907852589419931798687112530834793049593217933 +908 +57896044618658097611351864738157061705262361561497619362091104892532012614540 +1215816936991820049838389159501298295810509592791450006603913202743172264887180 +52569608513741552631107493182246612028378224297839838380778723242419067453178764 +73391955574979118963811141843059488536193514605218060347731553038824318137413435829926783487818828867437452 +19701003098197239571963727475337245584161626291901231402719522479678259504890677218990119895590117915143388591555468 +908 +115792089237105570840234253759177109864155645142784332660520492325483608802188 +2431633873979216987644919328942719307147268547998470985870930338835155784827788 +105139217027291858322932702413332815756653325789648174055752607031539116791563148 +146783911149691239803259475393272332038744581223672095908357420057841712239442615794649035123910216788214668 +39402006196322807380529480735708200350692396090822410401547663254352517428719749608020233606624972587007562114663308 +908 +231583736816786089484927226016147767929578972263620494977377884571370600268683 +4863258473152507879183471746339103126521158417536030394524935575998782605624183 +210278033029641769252313921222662173280057706815367409439459119190804505043140608 +293567262432083559770702660509494961636846893913475830448684457955877331972488384611363806317219648949453708 +78803862104411649792976274791681038936454943300723566886694079153850261012036590002656572187311458765011955822363533 +908 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725446174963629590181147084998050700 +68741202765818979270276983633379582196549482966904360579127216519201261330098607324506894304856394094406282403777947234369674236221393804088784959046540 +2972238671969696817971976244719460030212710977807102828849881552354035489891882640507250477562362182748614496315732194705126866975667884481553178229212044 +4149515561151917970063980879655710938513649460124350952720371065270297197065154634382680097543307069927884450339928718724097725668943949230978441358030208342019760039438410280076172 +1113877103911668754551067286547922686738237475419584309931192581897577662915063323503306740447008536028968181678028580322422866333819711284625174374608617279642589745120484326564854874768268 +908 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851378448187094873990326993486349195 +105586487448313957217630953653425358968668408786294503634300774628861320362441676458635398984170320306132770645519405205878947411928992353796866863213314935 +4565358600146146340648043138919534568740519770378829014283100160143146613766525820211473441791745277998502654577696186997051630953882145583216910085604245504 +6373655901930312136397229380018411440828683949391920950832693445711366448193584697763678864931677968612065262908033170282412527802037703004824976134384286640214222530054133889372259212 +1710915231608582551713494414139930175751260546116444122900349352360496966554854730076753484481830650675467827629295222707109502155201699203484369755223655341193278275893163301956243837193028493 +908 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756016346166874193365792884690781067 +281563966528794539091054524955215094900633929296509267540226436097922037480312534843090816414714560916129249828990251803876343269504358060681650578506384247 +12174289600387878166413214698063586008084552752439543567929790665567295715815418173215545776407658157706921849748721363710462842319521767576139939299228385280 +16996415738478256005382065682640742151192912704409604594012987116129634408058546371285779101609491343355313613863898166638327059654603396304113335697353121717251389843622698066460541836 +4562440617622195218641171605585119131739514871918667547682857357314343535508689562160604455918497575074715174882382908134196095677901105600185199282794955018371204524886410100925712980030522253 +908 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459867671853087539206018919387104140 +563127933057589078182109049910430189801267858593018911357569558066951448610928205184820357265838911550428123265590126067657221108914838323326397307129168780 +24348579200775756332826429396127172016169105504879103405365388510704376920891562395610327828446749127989939805959801641401559846042603485599065178803489735564 +33992831476956512010764131365281484302385825408819231901736066162392911122587750794642859557837487570646738733764326406607430768230396539092082721200286809873288301231428402460695200652 +9124881235244390437282343211170238263479029743837341192530852050551013988199468564099149809149237792502394782872367659707645708326849200364829008985690446628655225628506036591091211274089923468 +908 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232059366253413058442519879029375370124 +225016807509116112417285197875844925210445041539832647358016193682083470938906753692021013171376104564654794171951666999009032621460467236692823685991988607159363054170329353334944355625786930020224988415478335601579539769494531176085547834954163494030644162001543873246691321674227292917459616882754444 +9729298153251306194042617127203199623384957034198478276241843041111037695834634873921670474267119187843169195625338744528581029537433535757956376518129793109557221580317097753720451186105453926588775689583539463154010576700049252756460830197065735837134519004638182709904558099057065808050158672835249036 +13582985265193575509847153720290630277475301176695966793104558898916525902171099726111653252346386417687634059875171486934990855171785554727726817192028731914702681172768151028934363876033198780003232825417916826555570603003610443324900765322801514628836373961563717819815659178099324514051673737887522648522145975473923735339139980 +3646154850295010964902624396817474390399390616036693719739415376725561063085178919082942505698777176089060633115597677023110409583667009527018497076154392047301826729011247840192495744913649306569979494349478121435366144715292958165239232610420731738086890347478323006048396719686780691510330825043607290550999833104265740262684222585570188 +908 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998255571752838316161056568930429957047179 +736567904319114813700179347165898017864004333486947405305591758520610240861829766276798698618284354494716156033682943041579601713942220515540203161316988146991665543021307547800992939109024679837929112360581117013918612389794386017956541445146429151471384731055851996508875022310290766702717202280754490927819272344442130311818432332846202054796801431275025655264802408764738515518151514632480908325565788780147963367006809604639382187947539029097972599 +31847793196274107182845849867935019058119806419340392572260824606510195176311496560920629445019152089581060460884957727702584683631406487052881165260753582736592014907778440638252456605285448061563792096352745440411338097615871547824025696771093222358857968371367314896669453345606857912669867603377384655355233299464450205863387455153540545988356938076082061665735266055161074861451503585061555464743511248208302416059151577191074239364588830400998014976 +44462416394276340862910922260389321581298853470913371563358965890746390942505208917810214508921403677924050484037361854923909199530783769557857398908416797467991642660044081596444758567725905941578862500220928052627591160031402858547990440510112144073496748573294083122100295594485512238065152913601534980743295758670057701269862152855527112109603873427804287879276629501582896265202691196110634325565999430887153483257613158570830305101308846059434951620873330091758706311542342540 +11935289041890653422458560211344367565999989567726224393815132782921219808519438180124970259072038417888105302535754774032670805811336900569676094726678661851388189281957447472598923409448779291182901295823514011338832830575108282476521982723289897702706625317681157972521881629518687524749107700488703863037130875637878556278141428758998783243913325146240393321801800775493463196094645471464263521615496507631433158100292031999009575957202146963989209941350094442798986370318517904347235213 +1267650597867046177654064545792 +1267650597867046177654064545792 +1267650597867046177654064545792 +1267650597867046177654064545792 +1267650597867046177654064545792 +1267650597867046177654064545792 +1267650597867046177654064545792 +1267650597867046177654064545793 +1267650597867046177654064545813 +1267650597867046177654064546700 +2535301195734092355308129091584 +340282368188589061330420785085832757247 +1267650597867046177654064545792 +1267650597867046177654064545813 +1267650597867046177654064546233 +1267650597867046177654064564860 +27888313153075015908389420007424 +7145929706607358330597912933721196986347 +1267650597867046177654064545792 +1267650597867046177654064546700 +1267650597867046177654064564860 +1267650597867046177654065370256 +1152294393461144975487544672124928 +308976389165479775422611189725699600546932 +1267650597867046177654064545792 +2535301195734092355308129091584 +27888313153075015908389420007424 +1152294393461144975487544672124928 +1606938038272679619211255036085316583554057550607749329453056 +431359145870941220571487096504865044589965555162458186569392850993152 +1267650597867046177654064545792 +340282368188589061330420785085832757247 +7145929706607358330597912933721196986347 +308976389165479775422611189725699600546932 +431359145870941220571487096504865044589965555162458186569392850993152 +115792089237316195423570985008687907852589419933066337710397880970703657762817 +1267650597867046177654064545792 +57896044618658097611351864738157061705262361562765269959958151070186077159424 +1215816936991820049838389159501298295810509592792717657201780248920826329432064 +52569608513741552631107493182246612028378224297841106031376590288596721517723648 +73391955574979118963811141843059488536193514605218060347731553038824318137414703480524650533996482931982336 +19701003098197239571963727475337245584161626291901231402719522479678259504890677218991387546187984961321042656100352 +1267650597867046177654064545792 +115792089237105570840234253759177109864155645144051983258387538503137673347072 +2431633873979216987644919328942719307147268547999738636468797385012809849372672 +105139217027291858322932702413332815756653325789649441706350474077716770856108032 +146783911149691239803259475393272332038744581223672095908357420057841712239443883445246902170087870852759552 +39402006196322807380529480735708200350692396090822410401547663254352517428719749608021501257222839633185216179208192 +1267650597867046177654064545792 +231583736816786089484927226016147767929578972264888145575244930749024664813567 +4863258473152507879183471746339103126521158417537298045122802622176436670169067 +210278033029641769252313921222662173280057706815368677090056986236982159107685492 +293567262432083559770702660509494961636846893913475830448684457955877331972489652261961673363397303013998592 +78803862104411649792976274791681038936454943300723566886694079153850261012036590002657839837909325811189609886908417 +1267650597867046177654064545792 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725447442614227457227324739062595584 +68741202765818979270276983633379582196549482966904360579127216519201261330098607324506894304856394094406282403777947234370941886819260850266439023591424 +2972238671969696817971976244719460030212710977807102828849881552354035489891882640507250477562362182748614496315732194705128134626265751527730832293756928 +4149515561151917970063980879655710938513649460124350952720371065270297197065154634382680097543307069927884450339928718724097725668943949230978441358031475992617627085616064344621056 +1113877103911668754551067286547922686738237475419584309931192581897577662915063323503306740447008536028968181678028580322422866333819711284625174374608617279643857395718351372742508939313152 +1267650597867046177654064545792 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851379715837692741036504647550894079 +105586487448313957217630953653425358968668408786294503634300774628861320362441676458635398984170320306132770645519405205878948679579590220843044517277859819 +4565358600146146340648043138919534568740519770378829014283100160143146613766525820211473441791745277998502654577696186997051632221532743450263087739668790388 +6373655901930312136397229380018411440828683949391920950832693445711366448193584697763678864931677968612065262908033170282412527802037703004824976134384287907864820397100311543436804096 +1710915231608582551713494414139930175751260546116444122900349352360496966554854730076753484481830650675467827629295222707109502155201699203484369755223655341193279543543761169002421491257573377 +1267650597867046177654064545792 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756017613817472060411970538755325951 +281563966528794539091054524955215094900633929296509267540226436097922037480312534843090816414714560916129249828990251803876344537154955927727828232570929131 +12174289600387878166413214698063586008084552752439543567929790665567295715815418173215545776407658157706921849748721363710462843587172365443186116953292930164 +16996415738478256005382065682640742151192912704409604594012987116129634408058546371285779101609491343355313613863898166638327059654603396304113335697353122984901987710668875720525086720 +4562440617622195218641171605585119131739514871918667547682857357314343535508689562160604455918497575074715174882382908134196095677901105600185199282794955018371205792537007967971890634095067137 +1267650597867046177654064545792 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459868939503685406252196573451649024 +563127933057589078182109049910430189801267858593018911357569558066951448610928205184820357265838911550428123265590126067657222376565436190372574961193713664 +24348579200775756332826429396127172016169105504879103405365388510704376920891562395610327828446749127989939805959801641401559847310254083466111356457554280448 +33992831476956512010764131365281484302385825408819231901736066162392911122587750794642859557837487570646738733764326406607430768230396539092082721200286811140938899098474580114759745536 +9124881235244390437282343211170238263479029743837341192530852050551013988199468564099149809149237792502394782872367659707645708326849200364829008985690446628655226896156634458137388928154468352 +1267650597867046177654064545792 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232059367521063656309566056683439915008 +225016807509116112417285197875844925210445041539832647358016193682083470938906753692021013171376104564654794171951666999009032621460467236692823685991988607159363054170329353334944355625786930020224988415478335601579539769494531176085547834954163494030644162001543873246692589324825159963637270947299328 +9729298153251306194042617127203199623384957034198478276241843041111037695834634873921670474267119187843169195625338744528581029537433535757956376518129793109557221580317097753720451186105453926588775689583539463154010576700049252756460830197065735837134519004638182709904559366707663675096336326899793920 +13582985265193575509847153720290630277475301176695966793104558898916525902171099726111653252346386417687634059875171486934990855171785554727726817192028731914702681172768151028934363876033198780003232825417916826555570603003610443324900765322801514628836373961563717819815659178099324514051673737887523916172743842520101389403684864 +3646154850295010964902624396817474390399390616036693719739415376725561063085178919082942505698777176089060633115597677023110409583667009527018497076154392047301826729011247840192495744913649306569979494349478121435366144715292958165239232610420731738086890347478323006048396719686780691510330825043607290551001100754863607308861876650115072 +1267650597867046177654064545792 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998255571754105966758923615108084021592063 +736567904319114813700179347165898017864004333486947405305591758520610240861829766276798698618284354494716156033682943041579601713942220515540203161316988146991665543021307547800992939109024679837929112360581117013918612389794386017956541445146429151471384731055851996508875022310290766702717202280754490927819272344442130311818432332846202054796801431275025655264802408764738515518151514632480908325565788780147963367006810872289980054993716683162517483 +31847793196274107182845849867935019058119806419340392572260824606510195176311496560920629445019152089581060460884957727702584683631406487052881165260753582736592014907778440638252456605285448061563792096352745440411338097615871547824025696771093222358857968371367314896669453345606857912669867603377384655355233299464450205863387455153540545988356938076082061665735266055161074861451503585061555464743511248208302416059151578458724837231635008055062559860 +44462416394276340862910922260389321581298853470913371563358965890746390942505208917810214508921403677924050484037361854923909199530783769557857398908416797467991642660044081596444758567725905941578862500220928052627591160031402858547990440510112144073496748573294083122100295594485512238065152913601534980743295758670057701269862152855527112109603873427804287879276629501582896265202691196110634325565999430887153483257613158570830305101308846059434952888523927958804883965606887424 +11935289041890653422458560211344367565999989567726224393815132782921219808519438180124970259072038417888105302535754774032670805811336900569676094726678661851388189281957447472598923409448779291182901295823514011338832830575108282476521982723289897702706625317681157972521881629518687524749107700488703863037130875637878556278141428758998783243913325146240393321801800775493463196094645471464263521615496507631433158100292031999009575957202146963989209941350095710449584237364695558411780097 +340282366920938463463374607431768211455 +340282366920938463463374607431768211455 +340282366920938463463374607431768211455 +340282366920938463463374607431768211455 +340282366920938463463374607431768211455 +340282366920938463463374607431768211455 +340282366920938463463374607431768211455 +340282366920938463463374607431768211456 +340282366920938463463374607431768211476 +340282366920938463463374607431768212363 +340282368188589061330420785085832757247 +680564733841876926926749214863536422910 +340282366920938463463374607431768211455 +340282366920938463463374607431768211476 +340282366920938463463374607431768211896 +340282366920938463463374607431768230523 +340282393541601018671344338167123673087 +7486212072260646196194241363498900652010 +340282366920938463463374607431768211455 +340282366920938463463374607431768212363 +340282366920938463463374607431768230523 +340282366920938463463374607431769035919 +340283517947681326741303917322375790591 +309316671531133063288207518155477304212595 +340282366920938463463374607431768211455 +340282368188589061330420785085832757247 +340282393541601018671344338167123673087 +340283517947681326741303917322375790591 +1606938038272679619211595318450969871419653879037527033118719 +431359145870941220571487096505205326955618843028054514999170554658815 +340282366920938463463374607431768211455 +680564733841876926926749214863536422910 +7486212072260646196194241363498900652010 +309316671531133063288207518155477304212595 +431359145870941220571487096505205326955618843028054514999170554658815 +115792089237316195423570985008687907852929702298719625575994209400481361428480 +340282366920938463463374607431768211455 +57896044618658097611351864738157061705602643928418557825554479499963780825087 +1215816936991820049838389159501298295810849875158370945067376577350604033097727 +52569608513741552631107493182246612028378564580206759319242186617026499221389311 +73391955574979118963811141843059488536193514605218060347731553038824658419780356768390246862426260635647999 +19701003098197239571963727475337245584161626291901231402719522479678259504891017501357040834053581289750820359766015 +340282366920938463463374607431768211455 +115792089237105570840234253759177109864495927509705271123983866932915377012735 +2431633873979216987644919328942719307147608830365391924334393713442587553038335 +105139217027291858322932702413332815756653666072015094994216070406146548559773695 +146783911149691239803259475393272332038744581223672095908357420057842052521809536733112498498517648556425215 +39402006196322807380529480735708200350692396090822410401547663254352517428720089890387154545088435961614993882873855 +340282366920938463463374607431768211455 +231583736816786089484927226016147767929919254630541433440841259178802368479230 +4863258473152507879183471746339103126521498699902951332988398950606214373834730 +210278033029641769252313921222662173280058047097734330377922582565411936811351155 +293567262432083559770702660509494961636846893913475830448684457955877672254855305549827269691827080717664255 +78803862104411649792976274791681038936454943300723566886694079153850261012036930285023493125774922139619387590574080 +340282366920938463463374607431768211455 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656433007813095902093053555754516766261247 +68741202765818979270276983633379582196549482966904360579127216519201261330098607324506894304856394094406282403778287516736595174684857178696216727257087 +2972238671969696817971976244719460030212710977807102828849881552354035489891882640507250477562362182748614496315732534987493787914131347856160609997422591 +4149515561151917970063980879655710938513649460124350952720371065270297197065154634382680097543307069927884450339928718724097725668943949230978781640397129280483223414045842048286719 +1113877103911668754551067286547922686738237475419584309931192581897577662915063323503306740447008536028968181678028580322422866333819711284625174374608957562009510683583947701172286642978815 +340282366920938463463374607431768211455 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352969133745369125558337364934425254559742 +105586487448313957217630953653425358968668408786294503634300774628861320362441676458635398984170320306132770645519405546161314332867455817171474294981525482 +4565358600146146340648043138919534568740519770378829014283100160143146613766525820211473441791745277998502654577696187337333997874820609046591517517372456051 +6373655901930312136397229380018411440828683949391920950832693445711366448193584697763678864931677968612065262908033170282412527802037703004824976474666653561152685993428741321140469759 +1710915231608582551713494414139930175751260546116444122900349352360496966554854730076753484481830650675467827629295222707109502155201699203484369755223655681475645196831626765330851268961239040 +340282366920938463463374607431768211455 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107569038383267105337656740400316458991614 +281563966528794539091054524955215094900633929296509267540226436097922037480312534843090816414714560916129249828990252144158710190442821524056258010274594794 +12174289600387878166413214698063586008084552752439543567929790665567295715815418173215545776407658157706921849748721364050745209240460231039514546730996595827 +16996415738478256005382065682640742151192912704409604594012987116129634408058546371285779101609491343355313613863898166638327059654603396304113336037635488638189853306997305498228752383 +4562440617622195218641171605585119131739514871918667547682857357314343535508689562160604455918497575074715174882382908134196095677901105600185199282794955358653571445824873564300320411798732800 +340282366920938463463374607431768211455 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244438742234592791551002580626351155314687 +563127933057589078182109049910430189801267858593018911357569558066951448610928205184820357265838911550428123265590126407939588029853301786701004738897379327 +24348579200775756332826429396127172016169105504879103405365388510704376920891562395610327828446749127989939805959801641741842212963541949062439786235257946111 +33992831476956512010764131365281484302385825408819231901736066162392911122587750794642859557837487570646738733764326406607430768230396539092082721540569176794226764694803009892463411199 +9124881235244390437282343211170238263479029743837341192530852050551013988199468564099149809149237792502394782872367659707645708326849200364829008985690446968937592549444500054465818705858134015 +340282366920938463463374607431768211455 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359572341733174351521905894486461143580671 +225016807509116112417285197875844925210445041539832647358016193682083470938906753692021013171376104564654794171951666999009032621460467236692823685991988607159363054170329353334944355625786930020224988415478335601579539769494531176085547834954163494030644162001544213529058242612690756292067048650964991 +9729298153251306194042617127203199623384957034198478276241843041111037695834634873921670474267119187843169195625338744528581029537433535757956376518129793109557221580317097753720451186105453926588775689583539463154010576700049252756460830197065735837134519004638183050186925019995529271424766104603459583 +13582985265193575509847153720290630277475301176695966793104558898916525902171099726111653252346386417687634059875171486934990855171785554727726817192028731914702681172768151028934363876033198780003232825417916826555570603003610443324900765322801514628836373961563717819815659178099324514051674078169889569460609438848531167107350527 +3646154850295010964902624396817474390399390616036693719739415376725561063085178919082942505698777176089060633115597677023110409583667009527018497076154392047301826729011247840192495744913649306569979494349478121435366144715292958165239232610420731738086890347478323006048396719686780691510330825043607630833366754042729203637291654353780735 +340282366920938463463374607431768211455 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998595854119759254624519943537861725257726 +736567904319114813700179347165898017864004333486947405305591758520610240861829766276798698618284354494716156033682943041579601713942220515540203161316988146991665543021307547800992939109024679837929112360581117013918612389794386017956541445146429151471384731055851996508875022310290766702717202280754490927819272344442130311818432332846202054796801431275025655264802408764738515518151514632480908325565788780147963707289176525577845651322146460866183146 +31847793196274107182845849867935019058119806419340392572260824606510195176311496560920629445019152089581060460884957727702584683631406487052881165260753582736592014907778440638252456605285448061563792096352745440411338097615871547824025696771093222358857968371367314896669453345606857912669867603377384655355233299464450205863387455153540545988356938076082061665735266055161074861451503585061555464743511248208302416399433944112012702827963437832766225523 +44462416394276340862910922260389321581298853470913371563358965890746390942505208917810214508921403677924050484037361854923909199530783769557857398908416797467991642660044081596444758567725905941578862500220928052627591160031402858547990440510112144073496748573294083122100295594485512238065152913601534980743295758670057701269862152855527112109603873427804287879276629501582896265202691196110634325565999430887153483257613158570830305101308846399717318541811793555133313743310553087 +11935289041890653422458560211344367565999989567726224393815132782921219808519438180124970259072038417888105302535754774032670805811336900569676094726678661851388189281957447472598923409448779291182901295823514011338832830575108282476521982723289897702706625317681157972521881629518687524749107700488703863037130875637878556278141428758998783243913325146240393321801800775493463196094645471464263521615496507631433158100292031999009575957202146963989210281632461363737449833693125336115445760 +57896044618658097611351864738157061705262361561497619362091104892532012613632 +57896044618658097611351864738157061705262361561497619362091104892532012613632 +57896044618658097611351864738157061705262361561497619362091104892532012613632 +57896044618658097611351864738157061705262361561497619362091104892532012613632 +57896044618658097611351864738157061705262361561497619362091104892532012613632 +57896044618658097611351864738157061705262361561497619362091104892532012613632 +57896044618658097611351864738157061705262361561497619362091104892532012613632 +57896044618658097611351864738157061705262361561497619362091104892532012613633 +57896044618658097611351864738157061705262361561497619362091104892532012613653 +57896044618658097611351864738157061705262361561497619362091104892532012614540 +57896044618658097611351864738157061705262361562765269959958151070186077159424 +57896044618658097611351864738157061705602643928418557825554479499963780825087 +57896044618658097611351864738157061705262361561497619362091104892532012613632 +57896044618658097611351864738157061705262361561497619362091104892532012613653 +57896044618658097611351864738157061705262361561497619362091104892532012614073 +57896044618658097611351864738157061705262361561497619362091104892532012632700 +57896044618658097611351864738157061705262361588118281917299074623267368075264 +57896044618658097611351864738157061712408291266837327094821971648599145054187 +57896044618658097611351864738157061705262361561497619362091104892532012613632 +57896044618658097611351864738157061705262361561497619362091104892532012614540 +57896044618658097611351864738157061705262361561497619362091104892532012632700 +57896044618658097611351864738157061705262361561497619362091104892532013438096 +57896044618658097611351864738157061705262362712524362225369034202422620192768 +57896044618658097611351864738157062014238750725709744186835248440577548614772 +57896044618658097611351864738157061705262361561497619362091104892532012613632 +57896044618658097611351864738157061705262361562765269959958151070186077159424 +57896044618658097611351864738157061705262361588118281917299074623267368075264 +57896044618658097611351864738157061705262362712524362225369034202422620192768 +57896044618658099218289903010836680916517397645546552318281609322627277520896 +57896045050017243482293085309644158210127406150195523926682245284270799060992 +57896044618658097611351864738157061705262361561497619362091104892532012613632 +57896044618658097611351864738157061705602643928418557825554479499963780825087 +57896044618658097611351864738157061712408291266837327094821971648599145054187 +57896044618658097611351864738157062014238750725709744186835248440577548614772 +57896045050017243482293085309644158210127406150195523926682245284270799060992 +173688133855974293034922849746844969557851781493296306474621939685581605830657 +57896044618658097611351864738157061705262361561497619362091104892532012613632 +115792089237316195222703729476314123410524723122995238724182209785064025227264 +1273712981610478147449741024239455357515771954352947625966004307635704277499904 +52627504558360210728718845046984769090083486659401336000140814347311599465791488 +73391955574979118963811141843117384580812172702829412212469710100529580498974933449288874592711360880050176 +19701003098197239571963727475337245584219522336519889500330874344416416566595939580551617514952209020035920604168192 +57896044618658097611351864738157061705262361561497619362091104892532012613632 +173688133855763668451586118497334171569418006704281952022611597218015621414912 +2489529918597875085256271193680876368852530909559968605233021443727687797440512 +105197113071910516420544054278070972818358588151209671675114698136431648804175872 +146783911149691239803259475393330228083363239321283447773095577119546974601004113414011126228802748800827392 +39402006196322807380529480735708200350750292135441068499159015119090674490425011969581731225987063691900094127276032 +57896044618658097611351864738157061705262361561497619362091104892532012613632 +289479781435444187096279090754304829634841333825118114339468989463902612881407 +4921154517771165976794823611077260188226420779097528013887026680891314618236907 +210335929074260427349925273087400330341762969176928907058821210295697037055753332 +293567262432083559770702660509552857681465552011087182313422615017582594334049882230725897422112180962066432 +78803862104411649792976274791681038936512839345342224984305431018588418073741852364218069806673549869904487834976257 +57896044618658097611351864738157061705262361561497619362091104892532012613632 +3273390607896141870013189696827599152216642046043064789482248405676250539586401155309462588318799202567027652361355087007672582991681286039617010663424 +68741202765818979270276983633379582196549482966904360579127216519201261330156503369125552402467745959144439465483209595931171855583484908981316971659264 +2972238671969696817971976244719460030212710977807102828849881552354035489891940536551869135659973534613352653377437457066688364595029975586445710241824768 +4149515561151917970063980879655710938513649460124350952720371065270297197065154634382680097543307069927942346384547376821709077533682106292683703719591705961381851144330942292688896 +1113877103911668754551067286547922686738237475419584309931192581897577662915063323503306740447008536028968181678086476367041524431431063149363331436313879641204087364482575431457386887380992 +57896044618658097611351864738157061705262361561497619362091104892532012613632 +5027927973729236057982426364448826617555638513633071601633370220421967636306804394074875752581912318823441521134057891212939945806456965095219525498961919 +105586487448313957217630953653425358968668408786294503634300774628861320362441734354680017642267931657997508802581110468240508909548354444901759395225927659 +4565358600146146340648043138919534568740519770378829014283100160143146613766525878107518060449842889350367392734757892259413192451501507674321802617616858228 +6373655901930312136397229380018411440828683949391920950832693445711366448193584697763678864931677968612065320804077788940510139153902441161886681396745848137833584621159026421384871936 +1710915231608582551713494414139930175751260546116444122900349352360496966554854730076753484481830650675467827629295280603154120813299310555349107912285360603554839773512525393061136369205641217 +57896044618658097611351864738157061705262361561497619362091104892532012613632 +13407807929942597099574024997867385471458758537929012740010782671329620832395892888572752773084019014537559577489812491117577843786236284470685416703393791 +281563966528794539091054524955215094900633929296509267540226436097922037480312592739135435072812172267993987986051957066237904767123720151786543110518996971 +12174289600387878166413214698063586008084552752439543567929790665567295715815418231111590395065755769058786587905783068972824403817141129667244831831240998004 +16996415738478256005382065682640742151192912704409604594012987116129634408058546371285779101609491343355313671759942785296424671006468134461175040959714683214870751934727590598473154560 +4562440617622195218641171605585119131739514871918667547682857357314343535508689562160604455918497575074715174882382966030240714335998716952049937439856660280732766022505772192030605512043134977 +57896044618658097611351864738157061705262361561497619362091104892532012613632 +26815615859885194199148049995734770942917517075858043397979502765092926124329972428655111861232797616170839264946949360821429169472449630310911451399716864 +563127933057589078182109049910430189801267858593018911357569558066951448610928263080864975923936522902292861422651831330018782606534200414431289839141781504 +24348579200775756332826429396127172016169105504879103405365388510704376920891562453506372447104846739341804544116863346663921407540222847690170071335502348288 +33992831476956512010764131365281484302385825408819231901736066162392911122587750794642859557837487570646738791660371025265528379582261277249144426462648371370907663322533294992707813376 +9124881235244390437282343211170238263479029743837341192530852050551013988199468564099149809149237792502394782872367717603690326984946811716693747142752151891016787126125398682196103806102536192 +57896044618658097611351864738157061705262361561497619362091104892532012613632 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356940333001073316904952470628102164776064494420927751032420533624771561387982848 +225016807509116112417285197875844925210445041539832647358016193682083470938906753692021013171376104564654794171951666999009032621460467236692823685991988607159363054170329353334944355625786930020224988415478335601579539769494589072130166493051774845895382319063249135608252819293589384022352148895367168 +9729298153251306194042617127203199623384957034198478276241843041111037695834634873921670474267119187843169195625338744528581029537433535757956376518129793109557221580317097753720451186105453926588775689583539463154010576700049310652505448855163347188999257161699887972266119596676427899155051204847861760 +13582985265193575509847153720290630277475301176695966793104558898916525902171099726111653252346386417687634059875171486934990855171785554727726817192028731914702681172768151028934363876033198780003232825417916826555570603003610443324900765322801514628836431857608336477913270529964062671113379000249084146141508066578816267351752704 +3646154850295010964902624396817474390399390616036693719739415376725561063085178919082942505698777176089060633115597677023110409583667009527018497076154392047301826729011247840192495744913649306569979494349478121435366144715292958165239232610420731738086890347478380902093015377784392043375068982105312552912561330723627831367576754598182912 +57896044618658097611351864738157061705262361561497619362091104892532012613632 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463796730242309831072892700701204289449703517933314335935523147673822961969659903 +736567904319114813700179347165898017864004333486947405305591758520610240861829766276798698618284354494716156033682943041579601713942220515540203161316988146991665543021307547800992939109024679837929112360581117013918612389794386017956541445146429151471384731055851996508875022310290766702717202280754490927819272344442130311818432332846202054796801431275025655264802408764738573414196133290578519677430526937209668629368371102258744279052431561110585323 +31847793196274107182845849867935019058119806419340392572260824606510195176311496560920629445019152089581060460884957727702584683631406487052881165260753582736592014907778440638252456605285448061563792096352745440411338097615871547824025696771093222358857968371367314896669453345606857912669867603377384655355233299464450205863387455153540545988356938076082061665735266055161074919347548203719653076095375986365364121321513138688693601455693722933010627700 +44462416394276340862910922260389321581298853470913371563358965890746390942505208917810214508921403677924050484037361854923909199530783769557857398908416797467991642660044081596444758567725905941578862500220928052627591160031402858547990440510112144073496748573294083122100295594485512238065152913601534980743295758670057701269862152855527112109603873427804287879276629501582896265202691196110634325565999488783198101915710769922695043258370551321796513118492692182863598843554955264 +11935289041890653422458560211344367565999989567726224393815132782921219808519438180124970259072038417888105302535754774032670805811336900569676094726678661851388189281957447472598923409448779291182901295823514011338832830575108282476521982723289897702706625317681157972521881629518687524749107700488703863037130875637878556278141428758998783243913325146240393321801800775493463196094645471464263521615496507631433215996336650657107187309066885121050915203711655940418348461423410436359847937 +115792089237105570840234253759177109864155645142784332660520492325483608801280 +115792089237105570840234253759177109864155645142784332660520492325483608801280 +115792089237105570840234253759177109864155645142784332660520492325483608801280 +115792089237105570840234253759177109864155645142784332660520492325483608801280 +115792089237105570840234253759177109864155645142784332660520492325483608801280 +115792089237105570840234253759177109864155645142784332660520492325483608801280 +115792089237105570840234253759177109864155645142784332660520492325483608801280 +115792089237105570840234253759177109864155645142784332660520492325483608801281 +115792089237105570840234253759177109864155645142784332660520492325483608801301 +115792089237105570840234253759177109864155645142784332660520492325483608802188 +115792089237105570840234253759177109864155645144051983258387538503137673347072 +115792089237105570840234253759177109864495927509705271123983866932915377012735 +115792089237105570840234253759177109864155645142784332660520492325483608801280 +115792089237105570840234253759177109864155645142784332660520492325483608801301 +115792089237105570840234253759177109864155645142784332660520492325483608801721 +115792089237105570840234253759177109864155645142784332660520492325483608820348 +115792089237105570840234253759177109864155645169404995215728462056218964262912 +115792089237105570840234253759177109871301574848124040393251359081550741241835 +115792089237105570840234253759177109864155645142784332660520492325483608801280 +115792089237105570840234253759177109864155645142784332660520492325483608802188 +115792089237105570840234253759177109864155645142784332660520492325483608820348 +115792089237105570840234253759177109864155645142784332660520492325483609625744 +115792089237105570840234253759177109864155646293811075523798421635374216380416 +115792089237105570840234253759177110173132034306996457485264635873529144802420 +115792089237105570840234253759177109864155645142784332660520492325483608801280 +115792089237105570840234253759177109864155645144051983258387538503137673347072 +115792089237105570840234253759177109864155645169404995215728462056218964262912 +115792089237105570840234253759177109864155646293811075523798421635374216380416 +115792089237105572447172292031856729075410681226833265616710996755578873708544 +115792089668464716711175474330664206369020689731482237225111632717222395248640 +115792089237105570840234253759177109864155645142784332660520492325483608801280 +115792089237105570840234253759177109864495927509705271123983866932915377012735 +115792089237105570840234253759177109871301574848124040393251359081550741241835 +115792089237105570840234253759177110173132034306996457485264635873529144802420 +115792089668464716711175474330664206369020689731482237225111632717222395248640 +231584178474421766263805238767865017716745065074583019773051327118533202018305 +115792089237105570840234253759177109864155645142784332660520492325483608801280 +173688133855763668451586118497334171569418006704281952022611597218015621414912 +1331609026228925620678623413260475405674665237934234339264433695068655873687552 +52685400602978658201947727436005789138242379942982622713439243734744551061979136 +73391955574979118963811141843175280625430620176058294601490730148688473782556220162587303980144312476237824 +19701003098197239571963727475337245584277418381138336973559756733437436614754832864132904228250638407468872200355840 +115792089237105570840234253759177109864155645142784332660520492325483608801280 +231584178474211141680468507518354219728311290285568665321040984650967217602560 +2547425963216322558485153582701896417011424193141255318531450831160639393628160 +105255009116528963893772936667091992866517481434790958388413127523864600400363520 +146783911149691239803259475393388124127981686794512330162116597167705867884585400127309555616235700397015040 +39402006196322807380529480735708200350808188180059515972387897508111694538583905253163017939285493079333045723463680 +115792089237105570840234253759177109864155645142784332660520492325483608801280 +347375826053891660325161479775324877793734617406404827637898376896854209069055 +4979050562389613450023706000098280236385314062678814727185456068324266214424555 +210393825118878874823154155476421350389921862460510193772119639683129988651940980 +293567262432083559770702660509610753726083999484316064702443635065741487617631168944024326809545132558254080 +78803862104411649792976274791681038936570735389960672457534313407609438121900745647799356519971979257337439431163905 +115792089237105570840234253759177109864155645142784332660520492325483608801280 +3273390607896141870013189696827599152216642046043064789482248405676250539644297199927910061547681591588047700520248370588959296290110673472568606851072 +68741202765818979270276983633379582196549482966904360579127216519201261330214399413743999875696628348165459513642102879512458568881914296414268567846912 +2972238671969696817971976244719460030212710977807102828849881552354035489891998432596487583133202417002373673425596350350269651308328404973878661838012416 +4149515561151917970063980879655710938513649460124350952720371065270297197065154634382680097543307069928000242429165824294937959922703126340842597003172992674680280531763893888876544 +1113877103911668754551067286547922686738237475419584309931192581897577662915063323503306740447008536028968181678144372411659971904659945538384351484472772924785374077781004818890338483568640 +115792089237105570840234253759177109864155645142784332660520492325483608801280 +5027927973729236057982426364448826617555638513633071601633370220421967636306862290119494200055141201212462541182216784496521232519755394482652477095149567 +105586487448313957217630953653425358968668408786294503634300774628861320362441792250724636089741160540386529822629269361524090196261652874289192346822115307 +4565358600146146340648043138919534568740519770378829014283100160143146613766525936003562678897316118232756413754806051152696773738214806103709235569213045876 +6373655901930312136397229380018411440828683949391920950832693445711366448193584697763678864931677968612065378700122407387983368036291462181934840290029429424546883050546459372981059584 +1710915231608582551713494414139930175751260546116444122900349352360496966554854730076753484481830650675467827629295338499198739260772539437738128932333519496838421060225823822448569320801828865 +115792089237105570840234253759177109864155645142784332660520492325483608801280 +13407807929942597099574024997867385471458758537929012740010782671329620832395950784617371220557247896926580597537971384401159130499534713858118368299581439 +281563966528794539091054524955215094900633929296509267540226436097922037480312650635180053520285401150383009006100115959521486053837018581173976062115184619 +12174289600387878166413214698063586008084552752439543567929790665567295715815418289007635013513228997941175608925831227866107985103854428096632264782837185652 +16996415738478256005382065682640742151192912704409604594012987116129634408058546371285779101609491343355313729655987403743897899888857155481223199852998264501584050364115023550069342208 +4562440617622195218641171605585119131739514871918667547682857357314343535508689562160604455918497575074715174882383023926285332783471945834438958459904819174016347309219070621418038463639322625 +115792089237105570840234253759177109864155645142784332660520492325483608801280 +26815615859885194199148049995734770942917517075858043397979502765092926124330030324699730308706026498559860284995108254105010456185748059698344402995904512 +563127933057589078182109049910430189801267858593018911357569558066951448610928320976909594371409751784681882442699990223302363893247498843818722790737969152 +24348579200775756332826429396127172016169105504879103405365388510704376920891562511402417065552319968224193565136911505557204988826936146119557504287098535936 +33992831476956512010764131365281484302385825408819231901736066162392911122587750794642859557837487570646738849556415643713001608464650298269192585355931952657620961751920727944304001024 +9124881235244390437282343211170238263479029743837341192530852050551013988199468564099149809149237792502394782872367775499734945432420040599082768162800310784300368412838697111583536757698723840 +115792089237105570840234253759177109864155645142784332660520492325483608801280 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356998229045691764378181353017123184824223387704509037745718963012204512984170496 +225016807509116112417285197875844925210445041539832647358016193682083470938906753692021013171376104564654794171951666999009032621460467236692823685991988607159363054170329353334944355625786930020224988415478335601579539769494646968174784940525003728284403339111408028891834106006887813409785100491554816 +9729298153251306194042617127203199623384957034198478276241843041111037695834634873921670474267119187843169195625338744528581029537433535757956376518129793109557221580317097753720451186105453926588775689583539463154010576700049368548550067302636576071388278181748046865549700883389726328542484156444049408 +13582985265193575509847153720290630277475301176695966793104558898916525902171099726111653252346386417687634059875171486934990855171785554727726817192028731914702681172768151028934363876033198780003232825417916826555570603003610443324900765322801514628836489753652954925386499412353083691161537893532665432854806495966249218947940352 +3646154850295010964902624396817474390399390616036693719739415376725561063085178919082942505698777176089060633115597677023110409583667009527018497076154392047301826729011247840192495744913649306569979494349478121435366144715292958165239232610420731738086890347478438798137633825257620925764090002153471446196142617436926260755009706194370560 +115792089237105570840234253759177109864155645142784332660520492325483608801280 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463854626286928278546121583090225309497862411216895622648821577061255913565847551 +736567904319114813700179347165898017864004333486947405305591758520610240861829766276798698618284354494716156033682943041579601713942220515540203161316988146991665543021307547800992939109024679837929112360581117013918612389794386017956541445146429151471384731055851996508875022310290766702717202280754490927819272344442130311818432332846202054796801431275025655264802408764738631310240751738051748559819547957257827522651952388972042708439864512706772971 +31847793196274107182845849867935019058119806419340392572260824606510195176311496560920629445019152089581060460884957727702584683631406487052881165260753582736592014907778440638252456605285448061563792096352745440411338097615871547824025696771093222358857968371367314896669453345606857912669867603377384655355233299464450205863387455153540545988356938076082061665735266055161074977243592822167126304977765007385412280214796719975406899885081155884606815348 +44462416394276340862910922260389321581298853470913371563358965890746390942505208917810214508921403677924050484037361854923909199530783769557857398908416797467991642660044081596444758567725905941578862500220928052627591160031402858547990440510112144073496748573294083122100295594485512238065152913601534980743295758670057701269862152855527112109603873427804287879276629501582896265202691196110634325565999546679242720363183998805084064278418710215080094405205990612251031795151142912 +11935289041890653422458560211344367565999989567726224393815132782921219808519438180124970259072038417888105302535754774032670805811336900569676094726678661851388189281957447472598923409448779291182901295823514011338832830575108282476521982723289897702706625317681157972521881629518687524749107700488703863037130875637878556278141428758998783243913325146240393321801800775493463196094645471464263521615496507631433273892381269104580416191455906141099074096995237227131646890810843387956035585 +231583736816786089484927226016147767929578972263620494977377884571370600267775 +231583736816786089484927226016147767929578972263620494977377884571370600267775 +231583736816786089484927226016147767929578972263620494977377884571370600267775 +231583736816786089484927226016147767929578972263620494977377884571370600267775 +231583736816786089484927226016147767929578972263620494977377884571370600267775 +231583736816786089484927226016147767929578972263620494977377884571370600267775 +231583736816786089484927226016147767929578972263620494977377884571370600267775 +231583736816786089484927226016147767929578972263620494977377884571370600267776 +231583736816786089484927226016147767929578972263620494977377884571370600267796 +231583736816786089484927226016147767929578972263620494977377884571370600268683 +231583736816786089484927226016147767929578972264888145575244930749024664813567 +231583736816786089484927226016147767929919254630541433440841259178802368479230 +231583736816786089484927226016147767929578972263620494977377884571370600267775 +231583736816786089484927226016147767929578972263620494977377884571370600267796 +231583736816786089484927226016147767929578972263620494977377884571370600268216 +231583736816786089484927226016147767929578972263620494977377884571370600286843 +231583736816786089484927226016147767929578972290241157532585854302105955729407 +231583736816786089484927226016147767936724901968960202710108751327437732708330 +231583736816786089484927226016147767929578972263620494977377884571370600267775 +231583736816786089484927226016147767929578972263620494977377884571370600268683 +231583736816786089484927226016147767929578972263620494977377884571370600286843 +231583736816786089484927226016147767929578972263620494977377884571370601092239 +231583736816786089484927226016147767929578973414647237840655813881261207846911 +231583736816786089484927226016147768238555361427832619802122028119416136268915 +231583736816786089484927226016147767929578972263620494977377884571370600267775 +231583736816786089484927226016147767929578972264888145575244930749024664813567 +231583736816786089484927226016147767929578972290241157532585854302105955729407 +231583736816786089484927226016147767929578973414647237840655813881261207846911 +231583736816786091091865264288827387140834008347669427933568389001465865175039 +231583737248145235355868446587634864434444016852318399541969024963109386715135 +231583736816786089484927226016147767929578972263620494977377884571370600267775 +231583736816786089484927226016147767929919254630541433440841259178802368479230 +231583736816786089484927226016147767936724901968960202710108751327437732708330 +231583736816786089484927226016147768238555361427832619802122028119416136268915 +231583737248145235355868446587634864434444016852318399541969024963109386715135 +347375826054102284908498211024835675782168392195419182089908719364420193484800 +231583736816786089484927226016147767929578972263620494977377884571370600267775 +289479781435444187096279090754304829634841333825118114339468989463902612881407 +1447400673808606139323316385517446063740088565055070501581291087314542865154047 +52801192250558338720592420408262759796307803270103458875756101126990438053445631 +73391955574979118963811141843291072273010300694702987573747700806753897109677056324904161372390199467704319 +19701003098197239571963727475337245584393210028718017492204449705694407272820256191253740390567495799714759191822335 +231583736816786089484927226016147767929578972263620494977377884571370600267775 +347375826053891660325161479775324877793734617406404827637898376896854209069055 +2663217610796003077129846554958867075076847520262091480848308223406526385094655 +105370800764108644412417629639348963524582904761911794550729984916110487391830015 +146783911149691239803259475393503915775561367313157023134373567825771291211706236289626413008481587388481535 +39402006196322807380529480735708200350923979827639196491032590480368665196649328580283854101602350471578932714930175 +231583736816786089484927226016147767929578972263620494977377884571370600267775 +463167473633572178969854452032295535859157944527240989954755769142741200535550 +5094842209969293968668398972355250894450737389799650889502313460570153205891050 +210509616766458555341798848448678321047987285787631029934436497075375875643407475 +293567262432083559770702660509726545373663680002960757674700605723806910944752005106341184201791019549720575 +78803862104411649792976274791681038936686527037540352976179006379866408779966168974920192682288836649583326422630400 +231583736816786089484927226016147767929578972263620494977377884571370600267775 +3273390607896141870013189696827599152216642046043064789482248405676250539760088847507590580192374563845018358585671697709795458606968065718455598317567 +68741202765818979270276983633379582196549482966904360579127216519201261330330191061323680394341321320422430171707526206633294731198771688660155559313407 +2972238671969696817971976244719460030212710977807102828849881552354035489892114224244067263651847109974630644083661773677390487470645262366124548829478911 +4149515561151917970063980879655710938513649460124350952720371065270297197065154634382680097543307069928116034076745504813582652894960096998908020330293828836997137924009780880343039 +1113877103911668754551067286547922686738237475419584309931192581897577662915063323503306740447008536028968181678260164059239652423304638510641322142538196251906210240097862211136225475035135 +231583736816786089484927226016147767929578972263620494977377884571370600267775 +5027927973729236057982426364448826617555638513633071601633370220421967636306978081767073880573785894184719511840282207823642068682072251874898364086616062 +105586487448313957217630953653425358968668408786294503634300774628861320362441908042372215770259805233358786793287334784851211032423969731681438233813581802 +4565358600146146340648043138919534568740519770378829014283100160143146613766526051795210258577834762925728670725464116576023894574377122961101481456204512371 +6373655901930312136397229380018411440828683949391920950832693445711366448193584697763678864931677968612065494491769987068502012729263719152592905713356550260709199907938705259972526079 +1710915231608582551713494414139930175751260546116444122900349352360496966554854730076753484481830650675467827629295454290846318941291184130710385902991584920165541896388140679840815207793295360 +231583736816786089484927226016147767929578972263620494977377884571370600267775 +13407807929942597099574024997867385471458758537929012740010782671329620832396066576264950901075892589898837568196036807728279966661851571250364255291047934 +281563966528794539091054524955215094900633929296509267540226436097922037480312766426827633200804045843355265976758181382848606889999335438566221949106651114 +12174289600387878166413214698063586008084552752439543567929790665567295715815418404799282593193747642634147865896489293289435105940016744954024510669828652147 +16996415738478256005382065682640742151192912704409604594012987116129634408058546371285779101609491343355313845447634983424416544581829412451881265276325385337746367221507269437060808703 +4562440617622195218641171605585119131739514871918667547682857357314343535508689562160604455918497575074715174882383139717932912463990590527411215430562884597343468145381387478810284350630789120 +231583736816786089484927226016147767929578972263620494977377884571370600267775 +26815615859885194199148049995734770942917517075858043397979502765092926124330146116347309989224671191532117255653173677432131292348064917090590289987371007 +563127933057589078182109049910430189801267858593018911357569558066951448610928436768557174051928396477654139413358055646629484729409815701210968677729435647 +24348579200775756332826429396127172016169105504879103405365388510704376920891562627194064645232838612917165822107569570980532109663098462976949750174090002431 +33992831476956512010764131365281484302385825408819231901736066162392911122587750794642859557837487570646738965348063223393520253157622555239850650779259073493783278609312973831295467519 +9124881235244390437282343211170238263479029743837341192530852050551013988199468564099149809149237792502394782872367891291382525112938685292055025133458376207627489249001013968975782644690190335 +231583736816786089484927226016147767929578972263620494977377884571370600267775 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322357114020693271444896826045989380155482288811031629873908035820404450399975636991 +225016807509116112417285197875844925210445041539832647358016193682083470938906753692021013171376104564654794171951666999009032621460467236692823685991988607159363054170329353334944355625786930020224988415478335601579539769494762759822364621043648421256660309769473452218954942169204670802030987483021311 +9729298153251306194042617127203199623384957034198478276241843041111037695834634873921670474267119187843169195625338744528581029537433535757956376518129793109557221580317097753720451186105453926588775689583539463154010576700049484340197646983155220764360535152406112288876821719552043185934730043435515903 +13582985265193575509847153720290630277475301176695966793104558898916525902171099726111653252346386417687634059875171486934990855171785554727726817192028731914702681172768151028934363876033198780003232825417916826555570603003610443324900765322801514628836605545300534605905144105325340661819603316859786269017123353358495105939406847 +3646154850295010964902624396817474390399390616036693719739415376725561063085178919082942505698777176089060633115597677023110409583667009527018497076154392047301826729011247840192495744913649306569979494349478121435366144715292958165239232610420731738086890347478554589785213505776265618736346972811536869523263453599243118147255593185837055 +231583736816786089484927226016147767929578972263620494977377884571370600267775 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463970417934507959064766276062482280155927834544016458811138434453501800557314046 +736567904319114813700179347165898017864004333486947405305591758520610240861829766276798698618284354494716156033682943041579601713942220515540203161316988146991665543021307547800992939109024679837929112360581117013918612389794386017956541445146429151471384731055851996508875022310290766702717202280754490927819272344442130311818432332846202054796801431275025655264802408764738747101888331418570393252791804927915892945979073225134359565832110399698239466 +31847793196274107182845849867935019058119806419340392572260824606510195176311496560920629445019152089581060460884957727702584683631406487052881165260753582736592014907778440638252456605285448061563792096352745440411338097615871547824025696771093222358857968371367314896669453345606857912669867603377384655355233299464450205863387455153540545988356938076082061665735266055161075093035240401847644949670737264356070345638123840811569216742473401771598281843 +44462416394276340862910922260389321581298853470913371563358965890746390942505208917810214508921403677924050484037361854923909199530783769557857398908416797467991642660044081596444758567725905941578862500220928052627591160031402858547990440510112144073496748573294083122100295594485512238065152913601534980743295758670057701269862152855527112109603873427804287879276629501582896265202691196110634325565999662470890300043702643498056321249076775638407215241368307469643277682142609407 +11935289041890653422458560211344367565999989567726224393815132782921219808519438180124970259072038417888105302535754774032670805811336900569676094726678661851388189281957447472598923409448779291182901295823514011338832830575108282476521982723289897702706625317681157972521881629518687524749107700488703863037130875637878556278141428758998783243913325146240393321801800775493463196094645471464263521615496507631433389684028848785099060884428163111757139520322358063293963748203089274947502080 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725446174963629590181147084998049792 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725446174963629590181147084998049792 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725446174963629590181147084998049792 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725446174963629590181147084998049792 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725446174963629590181147084998049792 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725446174963629590181147084998049792 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725446174963629590181147084998049792 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725446174963629590181147084998049793 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725446174963629590181147084998049813 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725446174963629590181147084998050700 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725447442614227457227324739062595584 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656433007813095902093053555754516766261247 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725446174963629590181147084998049792 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725446174963629590181147084998049813 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725446174963629590181147084998050233 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725446174963629590181147084998068860 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725472795626184798150877820353511424 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590663238655151514671362321047903152130490347 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725446174963629590181147084998049792 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725446174963629590181147084998050700 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725446174963629590181147084998068860 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725446174963629590181147084998874256 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092726597201706492868110456975605628928 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590965069114610387088454334324695130534050932 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725446174963629590181147084998049792 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725447442614227457227324739062595584 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725472795626184798150877820353511424 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092726597201706492868110456975605628928 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804492314385376101550209867347761530223896585780685577180262957056 +3273390607896141870013189696827599152216642046043064789482248405676250539528505111122163636578388558400357687160957770034872868194181321538823784497152 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725446174963629590181147084998049792 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656433007813095902093053555754516766261247 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590663238655151514671362321047903152130490347 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590965069114610387088454334324695130534050932 +3273390607896141870013189696827599152216642046043064789482248405676250539528505111122163636578388558400357687160957770034872868194181321538823784497152 +3273390607896141870013189696827599152216642046043064789482248405676250539644297199928120686131018322837558498508682145377973650742121015940134591266817 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725446174963629590181147084998049792 +3273390607896141870013189696827599152216642046043064789482248405676250539586401155309462588318799202567027652361355087007672582991681286039617010663424 +3273390607896141870013189696827599152216642046043064789482248405676250540744322047682624540545836497330168886466602318237624970233503383890257262936064 +3273390607896141870013189696827599152216642046043064789482248405676250592098113624432357121814940520075482619034317023286013344408313423566152451227648 +3273390607896141870013189696827599152216642119435020364461367369487392382587993646884319095925507685560423629480410862859610793556373668965913865486336 +3273390607896141870013189696827599171917645144240304361445975881013496123690131402592035893426969817507130095546769944436294859219708096290473589604352 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725446174963629590181147084998049792 +3273390607896141870013189696827599152216642046043064789482248405676250539644297199927910061547681591588047700520248370588959296290110673472568606851072 +3273390607896141870013189696827599152216642046043064789482248405676250541960138984670021478352366666771589897803361273444645949500520519982240782876672 +3273390607896141870013189696827599152216642046043064789482248405676250644667722137982662813640149751161686347309418515094349019382197212686201789612032 +3273390607896141870013189696827599152216642192826975939173488208935725932800837149435385714379543246186290648497804964888790758278625305057301786263552 +3273390607896141870013189696827599191618648242365872170011729141384450890220901201513214892255110592181388019375842333466408570254562768154647112712192 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725446174963629590181147084998049792 +3273390607896141870013189696827599152216642046043064789482248405676250539760088847507590580192374563845018358585671697709795458606968065718455598317567 +3273390607896141870013189696827599152216642046043064789482248405676250544391763583843312369890919084167973717177251142982205358154525757145867603673067 +3273390607896141870013189696827599152216642046043064789482248405676250749806538140332573743021368560491043870713799540813584403088709371951590041189492 +3273390607896141870013189696827599152216642339610327221565808176378911049023466747537698404183277786513328546533424697934559574993396498366733947502592 +3273390607896141870013189696827599231020504150454714582458523197357289475983448411414371377401526491679131602692682728102747150941048946159040820412417 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725446174963629590181147084998049792 +6546781215792283740026379393655198304433284092086129578964496811352501079057010221381608981414894675657741181312185450892349927259180362294169996099584 +72014593373715121140290173330207181348766125012947425368609464924877511869627112435197698795563841432235152994434039959815849199850983985235869957095424 +2975512062577592959841989434416287629364927619853145893639363800759711740431411145617941282053069630086443366906388287430573041939297474662700263227260928 +4149515561151917970063980879658984329121545601994364142417198664422513839111197699172162345948983320467412955450619523214805173006772819821634534083476383305649350220585495278125056 +1113877103911668754551067286547922686741510866027480451801205771594405262067279965549349805236490784434644432217557085433113670824527158622454044965264710005088764708750074507711939872817152 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725446174963629590181147084998049792 +5031201364337132199852439554145654216707855155679114666422852468827643886846275003140947898975008414296532234663008721576824623150724464171474078484398079 +105589760838921853359500966843122186567820625428340546699090256877266996612981204963746089788661027753470599516110061298604393586892621943978013948211363819 +4565361873536754236789913152109231396339671987020875057347889642391552290017065348716584132596235985445840483448286843089777077128845775173398057170602294388 +6373655901930312136397229380018414714219291845533790964022390273310518664835630740828468347180083644862604791413143861086903235249375531875415632227109732815177852120235280974370308096 +1710915231608582551713494414139930175751263819507052019042219365550193794154006946718799527546620132923873503879834751212220192959692406650822198625814311433918724450856792892137390922191077377 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725446174963629590181147084998049792 +13411081320550493241444038187564213070610975179975055804800264919735297082935363497638824919477115110010650291018763321481462521130503783546939969688829951 +281567239919402435232924538144911922499786145938555310605015918346327713730852063348201507219205268363467078699580907896601789444467987650862797663504433131 +12174292873778486062555084711253282835683704969081589610994580147815701392065957701720656467212148865154259678619312019803188288494485397166321086384226434164 +16996415738478256005382065682640745424583520600551474607202683943728786624700592414350568583857897019605853142369008857442817767101941225174703991790078567892215019433803845151458590720 +4562440617622195218641171605585119131739518145309275443824727370504040363107841778802650498983287057323120851132922436639306786482391813047523028153385611111096650699850039691106860065028571137 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725446174963629590181147084998049792 +26818889250493090341018063185431598542069733717904086462768985013498602374869443037721184007625893711643929978475900191185313846816717129387166004385153024 +563131206448196974323979063100127017400420075235064954422359040315357124861467733689931048070329618997765952136180782160382667283878467913507544392127217664 +24348582474166364228968299409316868843768257721521149448430177992952782597142101924115438519251239835437277634830392297494285292217567115189246325888487784448 +33992831476956512010764131365281487575776433304961101914925762989992063339229796837707649040085893246897278262269437097411921475677734367962673377293012256048251930821609549545693249536 +9124881235244390437282343211170238263479033017227949088672722063740710815798620780741195852214027274750800459122907188212756399131339907812166837856281102721380671803469666181272358359087972352 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725446174963629590181147084998049792 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094859873731529946340457125253265606438475403785866280608383688705623749572896410942067145463298048566101192878305015324784812428376688032701026114373419008 +225016807509116112417285197875844925210445041539832647358016193682083470938906753692021013171376104564654794171951666999009032621460467236692823685991991880549970950312199366524641183224939146662271031480267817849985216020034059681196238639444870941368473032592199965972137496637856883098606701880803328 +9729298153251306194042617127203199623384957034198478276241843041111037695834634873921670474267119187843169195625338744528581029537433535757956376518129796382947829476458967766910148013704606143230821732648328945402416252950588781261571521001556443284472347875228838802630004274020695398231305757833297920 +13582985265193575509847153720290630277475301176695966793104558898916525902171099726111653252346386417687634059875171486934990855171785554727726817192028731914702681172768151028934367149423806676145102838607613654154722819645656486389690247571207190879375902466674408624306366625437153384642329830612968823485775565655070820337188864 +3646154850295010964902624396817474390399390616036693719739415376725561063085178919082942505698777176089060633115597677023110409583667009527018497076154392047301826729011247840192495744913652579960587390491348134625062972314445174807285275675210213986492566598017851511159087524177488138848159695634263383276446008067895330443831307583619072 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725446174963629590181147084998049792 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988312365191525626829590504228669795829923743060941349315981180118158171906003267339308381977465988796174295002978654348297199013279790646750077514955096063 +736567904319114813700179347165898017864004333486947405305591758520610240861829766276798698618284354494716156033682943041579601713942220515540203161316988146991665543021307547800992939109024679837929112360581117013918612389794386017956541445146429151471384731055851996508875022310290766702717202280754494201209880240584000325008129160445354271438847474339815137513208085015278044023262205436971615772903617650738619459732255779603011778128686114096021483 +31847793196274107182845849867935019058119806419340392572260824606510195176311496560920629445019152089581060460884957727702584683631406487052881165260753582736592014907778440638252456605285448061563792096352745440411338097615871547824025696771093222358857968371367314896669453345606857912669867603377384658628623907360592075876577151981139698204998984119146851147983671731411614389956614275866046172190849077078893072151877023366037868954769977485996063860 +44462416394276340862910922260389321581298853470913371563358965890746390942505208917810214508921403677924050484037361854923909199530783769557857398908416797467991642660044081596444758567725905941578862500220928052627591160031402858547990440510112144073496748573294083122100295594485512238065152913601534980743295758670057701269862156128917720005745743440993984706875781718224942308267480678359040001816538959392264174062103866018168133971899502152160397795836959681939853396540391424 +11935289041890653422458560211344367565999989567726224393815132782921219808519438180124970259072038417888105302535754774032670805811336900569676094726678661851388189281957447472598923409448779291182901295823514011338832830575108282476521982723289897702706625317681157972521881629518687524749107700488703863037130875637878556278141428758998786517303933042382263334991497603092615412736691514529053003863902183881972686605402722803500283404539975834579866034075540617762615960499664989345284097 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851378448187094873990326993486348287 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851378448187094873990326993486348287 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851378448187094873990326993486348287 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851378448187094873990326993486348287 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851378448187094873990326993486348287 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851378448187094873990326993486348287 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851378448187094873990326993486348287 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851378448187094873990326993486348288 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851378448187094873990326993486348308 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851378448187094873990326993486349195 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851379715837692741036504647550894079 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352969133745369125558337364934425254559742 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851378448187094873990326993486348287 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851378448187094873990326993486348308 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851378448187094873990326993486348728 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851378448187094873990326993486367355 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851405068849650081960057728841809919 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072359774781083787894827604857083060618788842 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851378448187094873990326993486348287 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851378448187094873990326993486349195 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851378448187094873990326993486367355 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851378448187094873990326993487172751 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628852529474929958151919636884093927423 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072661605240542660311919618133875039022349427 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851378448187094873990326993486348287 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851379715837692741036504647550894079 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851405068849650081960057728841809919 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628852529474929958151919636884093927423 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094485907904996976043691563883887462497120051064494757088751255551 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030688453630171908179274851168857493895967146091659465130718732272795647 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851378448187094873990326993486348287 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352969133745369125558337364934425254559742 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072359774781083787894827604857083060618788842 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072661605240542660311919618133875039022349427 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030688453630171908179274851168857493895967146091659465130718732272795647 +5027927973729236057982426364448826617555638513633071601633370220421967636306862290119494410679724537943712051980205218271310246874207404825120043079565312 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851378448187094873990326993486348287 +5027927973729236057982426364448826617555638513633071601633370220421967636306804394074875752581912318823441521134057891212939945806456965095219525498961919 +5027927973729236057982426364448826617555638513633071601633370220421967636307962314967248914534139356118204662368163138444169898193698787193070165751234559 +5027927973729236057982426364448826617555638513633071601633370220421967636359316106543998647115408460140949976100730853149218286567873597232746060939526143 +5027927973729236057982426364448826617555638513706463557208349339385778778149805986566450609089519027306434917111176946988791884017021657478145822353784831 +5027927973729236057982426364448826617575339516731268841205333947897304881890908124322158325887020489438381623577243306070368568082684991905470382077902847 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851378448187094873990326993486348287 +5027927973729236057982426364448826617555638513633071601633370220421967636306862290119494200055141201212462541182216784496521232519755394482652477095149567 +5027927973729236057982426364448826617555638513633071601633370220421967636309178131904236311471945886287646083379499897399376919172965804329162149271175167 +5027927973729236057982426364448826617555638513633071601633370220421967636411885715057548952807233669372036179829005954641026622242847481021866110277910527 +5027927973729236057982426364448826617555638513779855512783061460225227111700018830069001675707973062867060784130194341090821063981743909114237210274562047 +5027927973729236057982426364448826617595040519829394409013899701157675836657438894121079504885848630213055881501072378459398681793719846577334555601010687 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851378448187094873990326993486348287 +5027927973729236057982426364448826617555638513633071601633370220421967636306978081767073880573785894184719511840282207823642068682072251874898364086616062 +5027927973729236057982426364448826617555638513633071601633370220421967636311609756503409602363484438705042467198873787268914478581619809566325776091971562 +5027927973729236057982426364448826617555638513633071601633370220421967636517024531059898863736614888181365537352410335666745857626553993181131498529487987 +5027927973729236057982426364448826617555638513926638864065453780192670296816241459667103988397776797407387822028229960823866832798458680307546642435801087 +5027927973729236057982426364448826617634442375737483251426346495213648675243201441330980661370995046112553625084389218854035020374406332755338949308710912 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851378448187094873990326993486348287 +5031201364337132199852439554145654216707855155679114666422852468827643886846275003140947898975008414296532234663008721576824623150724464171474078484398079 +5096669176495055037252703348082206199752187996599975962212497436941168897636845105354763988789157361053109646476130576085748122423316267794415778445393919 +8000166645698932875954402609168286647768349491440174430483251772776003126198629138537507572046663149707317860388084823556505315162762758471880171715559423 +4149515561151917970063980884683638912242885518106777317169197682825935710698226236016050317965274706234630948370185813208398692627647313303331070209408656529114634029765403766423551 +1113877103911668754551067286547922691766165449148820367913618946346404280470701837136378342080378756450935817984775078352679960818120678243328538446961246131021037932215358316891848361115647 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851378448187094873990326993486348287 +10055855947458472115964852728897653235111277027266143203266740440843935272613492996060514188968601933917406728144705257702756896374189747980653986972696574 +110614415422043193275613380017874185586224047299927575235934144849283287998748422956665656078654621273091474009591757834730325860116087227787193856699662314 +4570386528119875576706025565283983395358075408892462085884733530363568581402832566709503698886229578965461357941768539625903009402069240457207237079090592883 +6373655901930312136397229380023439368802413185449903377197142272328922086707217769365312235152099936248372009406063427376896828768996406368897328763235665088401317404044460882858606591 +1710915231608582551713494414139930175756288474090173358958331778724945793172410368590386556083464020895889795265601969205139759249686000170443073119296007970044656724080258175946570830679375872 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851378448187094873990326993486348287 +18435735903671833157556451362316212089014397051562084341644152891751588468702581490558391209470708629631524784500459857607394794353969067356119878177128446 +286591894502523775149036951319663921518189567810142339141859806318344005116619281341121073509198861883087953193062604432727721717691452934671977571992731626 +12179317528361607402471197124428034834702108390953176639531424035787717683451724919713576033502142458673880553112793716339314220767708862450130266292714732659 +16996415738478256005382065682645770079166641940467587020377435942747190046572179442887412471829913310991620360361928423732811360621562099668185688326204500165438484717613025059946889215 +4562440617622195218641171605585119131744542799892396783740839783678792362126245200674237527520130945295137142518689654632226352772385406567143902646867307647222582973073504974916039973516869632 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851378448187094873990326993486348287 +31843543833614430257130476360183597560473155589491114999612872985514893760636661030640750297619487231264804471957596727311246120040182413196345912873451519 +568155861031318314240091476274879016418823497106651982959202928287373416247234951682850614360323212517386826629662478696508599557101933197316724300615516159 +24353607128749485568884411822491620842786661143392736476967021880924798888527869142108358085541233428956898509323873994030411224490790580473055505796976082943 +33992831476956512010764131365286512230359554644877214328100514989010466761101383866244492928057909538283045480262356663701915069197355242456155073829138188321475396105418729454181548031 +9124881235244390437282343211170238263484057671811070428588834476915462814817024202612782880750871162722816750508674406205675965421333501331787712349762799257506604076693131465081538267576270847 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851378448187094873990326993486348287 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604099884528314651286256569538428017605456878825657453309145227576677640040958663628934986711753291642085722067371786711860910744701600153316510206022861717503 +225016807509116112417285197875844925210445041539832647358016193682083470938906753692021013171376104564654794171951666999009032621460467236692823685997016535133092290228311779699393182243342568533858060017111705822001507405801277674115804929438464460989347526073896502098069769861322166907786610369101823 +9729298153251306194042617127203199623384957034198478276241843041111037695834634873921670474267119187843169195625338744528581029537433535757956376518134821037530950816375080180084900012723009565102408761185172833374432544336355999254491087291550036804093222368710535338755936547244160682040485666321596415 +13582985265193575509847153720290630277475301176695966793104558898916525902171099726111653252346386417687634059875171486934990855171785554727726817192028731914702681172768151028939391804006928016061215251782365653173126241517243514926534135543223482265143120459593974914299960145058027878124026366738901096709240849464250728825487359 +3646154850295010964902624396817474390399390616036693719739415376725561063085178919082942505698777176089060633115597677023110409583667009527018497076154392047301826729011247840192495744918677234543708730407460547799814971332848596678872304212054101958508857983785069504078653814171081658469034189115959919402378281291360614253011216071917567 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851378448187094873990326993486348287 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060993337019774646966745702917403421794848327164932528377852825068090174463291770485332227948267459582315795169496460350884423131286503255930559257423443394558 +736567904319114813700179347165898017864004333486947405305591758520610240861829766276798698618284354494716156033682943041579601713942220515540203161316988146991665543021307547800992939109024679837929112360581117013918612389794386017956541445146429151471384731055851996508875022310290766702717202280759518855793001580500112738182881159463757693310434502876659025485224376401045262016181771726965209292524492144220315995858188052826477061937866022584319978 +31847793196274107182845849867935019058119806419340392572260824606510195176311496560920629445019152089581060460884957727702584683631406487052881165260753582736592014907778440638252456605285448061563792096352745440411338097615871547824025696771093222358857968371367314896669453345606857912669867603377389683283207028700508188289751903980158101626870571147683695035955688022797381607949533842156039765710469951572374768688002955639261334238579157394484362355 +44462416394276340862910922260389321581298853470913371563358965890746390942505208917810214508921403677924050484037361854923909199530783769557857398908416797467991642660044081596444758567725905941578862500220928052627591160031402858547990440510112144073496748573294083122100295594485512238065152913601534980743295758670057701269867180783500841345661855854168736705894185140096529336804324566331056293202306177385183740352097459537789008465381198688286330069060424965749033305028689919 +11935289041890653422458560211344367565999989567726224393815132782921219808519438180124970259072038417888105302535754774032670805811336900569676094726678661851388189281957447472598923409448779291182901295823514011338832830575108282476521982723289897702706625317681157972521881629518687524749107700488703863037130875637878556278141428759003811171887054382298375748166249602111018834608278543065896891835918475267739904598322289093493876924160850328061562570201472890986081244308844897833582592 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756016346166874193365792884690780159 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756016346166874193365792884690780159 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756016346166874193365792884690780159 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756016346166874193365792884690780159 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756016346166874193365792884690780159 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756016346166874193365792884690780159 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756016346166874193365792884690780159 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756016346166874193365792884690780160 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756016346166874193365792884690780180 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756016346166874193365792884690781067 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756017613817472060411970538755325951 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107569038383267105337656740400316458991614 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756016346166874193365792884690780159 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756016346166874193365792884690780180 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756016346166874193365792884690780600 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756016346166874193365792884690799227 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756042966829429401335523620046241791 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428114374685721685874606924232548951823220714 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756016346166874193365792884690780159 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756016346166874193365792884690781067 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756016346166874193365792884690799227 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756016346166874193365792884691604623 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228757167372909737471295102775298359295 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428416205145180558291698937509340930226781299 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756016346166874193365792884690780159 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756017613817472060411970538755325951 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756042966829429401335523620046241791 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228757167372909737471295102775298359295 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114988014600711094100047318483792100395099830383870222979955687423 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528565474132278603893392907524612093800605044071438784506184623477227519 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756016346166874193365792884690780159 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107569038383267105337656740400316458991614 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428114374685721685874606924232548951823220714 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428416205145180558291698937509340930226781299 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528565474132278603893392907524612093800605044071438784506184623477227519 +13407807929942597099574024997867385471458758537929012740010782671329620832395950784617371431181831233657830108335959818175948144853986724200585934283997184 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756016346166874193365792884690780159 +13407807929942597099574024997867385471458758537929012740010782671329620832395892888572752773084019014537559577489812491117577843786236284470685416703393791 +13407807929942597099574024997867385471458758537929012740010782671329620832397050809465125935036246051832322718723917738348807796173478106568536056955666431 +13407807929942597099574024997867385471458758537929012740010782671329620832448404601041875667617515155855068032456485453053856184547652916608211952143958015 +13407807929942597099574024997867385471458758538002404695585761790293431974238894481064327629591625723020552973466931546893429781996800976853611713558216703 +13407807929942597099574024997867385471478459541027209979582746398804958077979996618820035346389127185152499679932997905975006466062464311280936273282334719 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756016346166874193365792884690780159 +13407807929942597099574024997867385471458758537929012740010782671329620832395950784617371220557247896926580597537971384401159130499534713858118368299581439 +13407807929942597099574024997867385471458758537929012740010782671329620832398266626402113331974052582001764139735254497304014817152745123704628040475607039 +13407807929942597099574024997867385471458758537929012740010782671329620832500974209555425973309340365086154236184760554545664520222626800397332001482342399 +13407807929942597099574024997867385471458758538075796651160473911132880307789107324566878696210079758581178840485948940995458961961523228489703101478993919 +13407807929942597099574024997867385471498160544125335547391312152065329032746527388618956525387955325927173937856826978364036579773499165952800446805442559 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756016346166874193365792884690780159 +13407807929942597099574024997867385471458758537929012740010782671329620832396066576264950901075892589898837568196036807728279966661851571250364255291047934 +13407807929942597099574024997867385471458758537929012740010782671329620832400698251001286622865591134419160523554628387173552376561399128941791667296403434 +13407807929942597099574024997867385471458758537929012740010782671329620832606113025557775884238721583895483593708164935571383755606333312556597389733919859 +13407807929942597099574024997867385471458758538222580002442866231100323492905329954164981008899883493121505878383984560728504730778237999683012533640232959 +13407807929942597099574024997867385471537562400033424389803758946121301871332289935828857681873101741826671681440143818758672918354185652130804840513142784 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756016346166874193365792884690780159 +13411081320550493241444038187564213070610975179975055804800264919735297082935363497638824919477115110010650291018763321481462521130503783546939969688829951 +13476549132708416078844301981500765053655308020895917100589909887848822093725933599852641009291264056767227702831885175990386020403095587169881669649825791 +16380046601912293917546001242586845501671469515736115568860664223683656322287717633035384592548769845421435916743839423461143213142542077847346062919991295 +4149515561151917970063980893063518868456246559698375950587756536729055734994167374393462768872927902323719442868062833710505388341765369659085670114046554508893953405231294970855423 +1113877103911668754551067286547922700146045405362181409505217579764963134373821861432319480457791207358589014073863572850556981320227373957446594802715846035658935911994677692357739565547519 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756016346166874193365792884690780159 +18435735903671833157556451362316212089014397051562084341644152891751588468702581490558391209470708629631524784500459857607394794353969067356119878177128446 +118994295378256554317204978651292744440127167324223516374311557300190941194837511451163533099156727968805592065947512434634963758095866547162659747904094186 +4578766408076088937747617163917401954211978528916758027023110942814476234598921655204001575906731685661175475998124294225807647300049019776582702970295024755 +6373655901930312136397229380031819248758626546491494975830560831182825206731513710503689647603007589444461097900561304397398935464710524425253083363140302986381096723419926774063038463 +1710915231608582551713494414139930175764668354046386719999923377358364352026313488614682497221841433346797448461691057699637636270188106866157191175651762569949294622060037495322036721883807744 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756016346166874193365792884690780159 +26815615859885194199148049995734770942917517075858025480021565342659241664791669985056268229972815325345642840856214457512032692333748386731585769381560318 +294971774458737136190628549953082480372092687834438280280237218769251658312708369835618950529700968578802071249418359032632359615671232254047443463197163498 +12187697408317820763512788723061453393556011510977472580669801448238625336647814008208073910522644565369594671169149470939218858665688641769505732183919164531 +16996415738478256005382065682654149959122855301509178619010854501601093166596475384025789884280820964187709448856426300753313467317276217724541442926109138063418264036988490951151321087 +4562440617622195218641171605585119131752922679848610144782431382312210920980148320698533468658508357746044795714778743126724229792887513262858020703223062247127220871053284294291505864721301504 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756016346166874193365792884690780159 +40223423789827791298722074993602156414376275613787056137990285436422546956725749525138627318121593926978922528313351327215884018019961732571811804077883391 +576535740987531675281683074908297575272726617130947924097580340738281069443324040177348491380825319213100944686018233296413237455081712516692190191819948031 +24361987008705698929926003421125039401640564263417032418105399293375706541723958230602855962561735535652612627380229748630315862388770359792430971688180514815 +33992831476956512010764131365294892110315768005918805926733933547864369881125679807382870340508817191479134568756854540722417175893069360512510828429042826219455175424794195345385979903 +9124881235244390437282343211170238263492437551767283789630426075548881373670927322637078821889248575173724403704763494700173842441835608027501830406118553857411241974672910784457004158780702719 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756016346166874193365792884690780159 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604108264408270864647298161137061436164310781945681749250283604989128547694154752717429484588773793748781436185428142466460815382599579932635885671914066149375 +225016807509116112417285197875844925210445041539832647358016193682083470938906753692021013171376104564654794171951666999009032621460467236692823686005396415089305651269903378332811741097245688558154001155489118272909160601890366168613681949940571156703465582429651102002707667841101486283252501573533695 +9729298153251306194042617127203199623384957034198478276241843041111037695834634873921670474267119187843169195625338744528581029537433535757956376518143200917487164177416671778718318571576912685126704702323550245825340197532445087748988964312052143499807340425066289938660574445223940001415951557526028287 +13582985265193575509847153720290630277475301176695966793104558898916525902171099726111653252346386417687634059875171486934990855171785554727726817192028731914702681172768151028947771683963141377102806850415784212027029361541539456064911547994131135461232208954091851934802066840772145934479780966643538994689020168839716620029919231 +3646154850295010964902624396817474390399390616036693719739415376725561063085178919082942505698777176089060633115597677023110409583667009527018497076154392047301826729011247840192495744927057114499922091449052146433233530186751716703168245350431514409416511179874157998576530834673188354183152245471714519307016179271139933628477107276349439 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756016346166874193365792884690780159 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581061001716899730860327787294516036840353702230284956824318991202480541082116487859573826725825287961689011509287552816105484327769184483035249934723314647826430 +736567904319114813700179347165898017864004333486947405305591758520610240861829766276798698618284354494716156033682943041579601713942220515540203161316988146991665543021307547800992939109024679837929112360581117013918612389794386017956541445146429151471384731055851996508875022310290766702717202280767898735749214941541704336816299718317660813334730444015036437936132029597134350510679648747467315988238610200576070595762825950806256381313331913788751850 +31847793196274107182845849867935019058119806419340392572260824606510195176311496560920629445019152089581060460884957727702584683631406487052881165260753582736592014907778440638252456605285448061563792096352745440411338097615871547824025696771093222358857968371367314896669453345606857912669867603377398063163163242061549779888385322539012004746894867088822072448406595675993470696444031719176541872406184069628730523287907593537241113557954623285688794227 +44462416394276340862910922260389321581298853470913371563358965890746390942505208917810214508921403677924050484037361854923909199530783769557857398908416797467991642660044081596444758567725905941578862500220928052627591160031402858547990440510112144073496748573294083122100295594485512238065152913601534980743295758670057701269875560663457054706703447452802155264748088260120825277942701978781963946398395265879681617372599566233503126521736953288190967967040204285124499196233121791 +11935289041890653422458560211344367565999989567726224393815132782921219808519438180124970259072038417888105302535754774032670805811336900569676094726678661851388189281957447472598923409448779291182901295823514011338832830575108282476521982723289897702706625317681157972521881629518687524749107700488703863037130875637878556278141428759012191051843267743339967346799668160964921954632574484204274304286826128463828993092820166113995983619874968384417317170106110788965860563684310789038014464 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459867671853087539206018919387103232 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459867671853087539206018919387103232 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459867671853087539206018919387103232 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459867671853087539206018919387103232 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459867671853087539206018919387103232 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459867671853087539206018919387103232 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459867671853087539206018919387103232 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459867671853087539206018919387103233 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459867671853087539206018919387103253 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459867671853087539206018919387104140 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459868939503685406252196573451649024 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244438742234592791551002580626351155314687 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459867671853087539206018919387103232 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459867671853087539206018919387103253 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459867671853087539206018919387103673 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459867671853087539206018919387122300 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459894292515642747175749654742564864 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885251244389573011560820270072774986519543787 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459867671853087539206018919387103232 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459867671853087539206018919387104140 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459867671853087539206018919387122300 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459867671853087539206018919387927696 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098461018698595950817135328809994682368 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885553074849031883977912283349566964923104372 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459867671853087539206018919387103232 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459868939503685406252196573451649024 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459894292515642747175749654742564864 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098461018698595950817135328809994682368 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203136793202344373787504455353495951720786043729710449014652010496 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610924562281057205526672594981748963504456369757652130346410658173550592 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459867671853087539206018919387103232 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244438742234592791551002580626351155314687 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885251244389573011560820270072774986519543787 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885553074849031883977912283349566964923104372 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610924562281057205526672594981748963504456369757652130346410658173550592 +26815615859885194199148049995734770942917517075858043397979502765092926124330030324699730519330609835291109795793096687879799470540200070040811968980320257 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459867671853087539206018919387103232 +26815615859885194199148049995734770942917517075858043397979502765092926124329972428655111861232797616170839264946949360821429169472449630310911451399716864 +26815615859885194199148049995734770942917517075858043397979502765092926124331130349547485023185024653465602406181054608052659121859691452408762091651989504 +26815615859885194199148049995734770942917517075858043397979502765092926124382484141124234755766293757488347719913622322757707510233866262448437986840281088 +26815615859885194199148049995734770942917517075931435353554481884056737266172974021146686717740404324653832660924068416597281107683014322693837748254539776 +26815615859885194199148049995734770942937218078956240637551466492568263369914076158902394434537905786785779367390134775678857791748677657121162307978657792 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459867671853087539206018919387103232 +26815615859885194199148049995734770942917517075858043397979502765092926124330030324699730308706026498559860284995108254105010456185748059698344402995904512 +26815615859885194199148049995734770942917517075858043397979502765092926124332346166484472420122831183635043827192391367007866142838958469544854075171930112 +26815615859885194199148049995734770942917517075858043397979502765092926124435053749637785061458118966719433923641897424249515845908840146237558036178665472 +26815615859885194199148049995734770942917517076004827309129194004896185599723186864649237784358858360214458527943085810699310287647736574329929136175316992 +26815615859885194199148049995734770942956919082054366205360032245828634324680606928701315613536733927560453625313963848067887905459712511793026481501765632 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459867671853087539206018919387103232 +26815615859885194199148049995734770942917517075858043397979502765092926124330146116347309989224671191532117255653173677432131292348064917090590289987371007 +26815615859885194199148049995734770942917517075858043397979502765092926124334777791083645711014369736052440211011765256877403702247612474782017701992726507 +26815615859885194199148049995734770942917517075858043397979502765092926124540192565640134972387500185528763281165301805275235081292546658396823424430242932 +26815615859885194199148049995734770942917517076151610660411586324863628784839409494247340097048662094754785565841121430432356056464451345523238568336556032 +26815615859885194199148049995734770942996320937962455047772479039884607163266369475911216770021880343459951368897280688462524244040398997971030875209465857 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459867671853087539206018919387103232 +26818889250493090341018063185431598542069733717904086462768985013498602374869443037721184007625893711643929978475900191185313846816717129387166004385153024 +26884357062651013178418326979368150525114066558824947758558629981612127385660013139935000097440042658400507390289022045694237346089308933010107704346148864 +29787854531854891017120026240454230973130228053665146226829384317446961614221797173117743680697548447054715604200976293164994538828755423687572097616314368 +4149515561151917970063980906471326798398843659272400948455142008187814272923198032362182862636233194257798982950421921859283989975045057116222539817897880195107299245457329667178496 +1113877103911668754551067286547922713553853335304778509079242577632348605832580399361350138426511301121894306007943112932916069469005975590726282259852715739510261598208023532583774261870592 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459867671853087539206018919387103232 +31843543833614430257130476360183597560473155589491114999612872985514893760636661030640750297619487231264804471957596727311246120040182413196345912873451519 +132402103308199151416779003649160129911585925862152547032280277393954246486771590991245892187305506570438871753404649304338815083782079893002885782600417259 +4592174216006031534847191188915269339683437287454687057681079662908239539890855734744083934994880464262808755685581431095511498625735233122422929004991347828 +6373655901930312136397229380045227056688569143591069000828428216654283965269442741161658367696770894736395177440643663485547714066343804112710220232844154312067310069260152808759361536 +1710915231608582551713494414139930175778076161976329317099497402356231737497772247152611527879810153440560753753625137239719995358336885467790470863108899439653145947746250841162262756580130817 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459867671853087539206018919387103232 +40223423789827791298722074993602156414376275613787056137990285436422546956725749525138627318121593926978922528313351327215884018019961732571811804077883391 +308379582388679733290202574950949865843551446372367310938205938863014963604642449375701309617849747180435350936875495902336210941357445599887669497893486571 +12201105216247763360612362748059320779027470269515401611327770168332388641939748087748156269610793343971227950856606607808922709991374855115345958218615487604 +16996415738478256005382065682667557767052797898608752644008721887072551925134404414683758604374584269479643528396508659841462245918909497411998579795812989389104477382828716985847644160 +4562440617622195218641171605585119131766330487778552741882005407310078306451607079236462499316477077839808101006712822666806588881036291864491300390680199116831072196739497640131731899417624577 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459867671853087539206018919387103232 +53631231719770388398296099991469541885835034151716086795959005530185852248659829065220986406270372528612202215770488196919735343706175078412037838774206464 +589943548917474272381257099906164960744185375668876954755549060832044374735258119717430850468974097814734224373475370166117088780767925862532416226516271104 +24375394816635641527025577446122906787112023021954961448763368013469469847015892310142938321649884314254245907067686885500019713714456573138271197722876837888 +33992831476956512010764131365308299918245710603018379951731800933335828639663608838040839060602580496771068648296936899810565954494702640199967965298746677545141388770634421380082302976 +9124881235244390437282343211170238263505845359697226386730000100546748759142386081175007852547217295267487708996697574240256201529984386629135110093575690727115093300359124130297230193477025792 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459867671853087539206018919387103232 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604121672216200807244397735162059303549782240704219678280941573709222310999446686796969566947861942527383069465115599603330519233925266145981725897948762472448 +225016807509116112417285197875844925210445041539832647358016193682083470938906753692021013171376104564654794171951666999009032621460467236692823686018804223019248248369477403330679126568704447096083031813457838366672465893824445708696041038089349758336745269886787971706558993527314832123478536269856768 +9729298153251306194042617127203199623384957034198478276241843041111037695834634873921670474267119187843169195625338744528581029537433535757956376518156608725417106774516245803716185957048371443664633732981518965919103502824379167289071323400200922101440620112523426808364425770910153347256177592222351360 +13582985265193575509847153720290630277475301176695966793104558898916525902171099726111653252346386417687634059875171486934990855171785554727726817192028731914702681172768151028961179491893083974202380875413651597498488120079468486722880268087894440753166288494174211022950845442405425621936917836347390320375233514679942654726242304 +3646154850295010964902624396817474390399390616036693719739415376725561063085178919082942505698777176089060633115597677023110409583667009527018497076154392047301826729011247840192495744940464922429864688548626171431100915658210475241097276008400234503179816471808237538658889922821966955816431932928851389010867504957353279468703141972672512 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459867671853087539206018919387103232 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581061015124707660802924886868541034707739173689043494753349649171200634845421779793653366808184376110467613142567240273242354031620510169248595774949349344149503 +736567904319114813700179347165898017864004333486947405305591758520610240861829766276798698618284354494716156033682943041579601713942220515540203161316988146991665543021307547800992939109024679837929112360581117013918612389794386017956541445146429151471384731055851996508875022310290766702717202280781306543679157538641278361814167103789119571872659474673005158029895334889068430050762007835616094589871889888033207465466677276492469727153557948485074923 +31847793196274107182845849867935019058119806419340392572260824606510195176311496560920629445019152089581060460884957727702584683631406487052881165260753582736592014907778440638252456605285448061563792096352745440411338097615871547824025696771093222358857968371367314896669453345606857912669867603377411470971093184658649353913383189924483463505432796119480041168500358981285404775984114078264690651007817349316187660157611444862927326903794849320385117300 +44462416394276340862910922260389321581298853470913371563358965890746390942505208917810214508921403677924050484037361854923909199530783769557857398908416797467991642660044081596444758567725905941578862500220928052627591160031402858547990440510112144073496748573294083122100295594485512238065152913601534980743295758670057701269888968471386997303803021477800022650219547018658754308600670698875727251690329345419763976460748344835136406209194090157894819292726417630964725230929444864 +11935289041890653422458560211344367565999989567726224393815132782921219808519438180124970259072038417888105302535754774032670805811336900569676094726678661851388189281957447472598923409448779291182901295823514011338832830575108282476521982723289897702706625317681157972521881629518687524749107700488703863037130875637878556278141428759025598859773210340439541371797535546436380713170503514862243024380589433755763072632902525202144762221508248071874454039809962114652073909524536823734337537 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232059366253413058442519879029375369216 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232059366253413058442519879029375369216 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232059366253413058442519879029375369216 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232059366253413058442519879029375369216 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232059366253413058442519879029375369216 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232059366253413058442519879029375369216 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232059366253413058442519879029375369216 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232059366253413058442519879029375369217 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232059366253413058442519879029375369237 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232059366253413058442519879029375370124 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232059367521063656309566056683439915008 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359572341733174351521905894486461143580671 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232059366253413058442519879029375369216 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232059366253413058442519879029375369237 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232059366253413058442519879029375369657 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232059366253413058442519879029375388284 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232059392874075613650489609764730830848 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714366377989071593120791173386635096507809771 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232059366253413058442519879029375369216 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232059366253413058442519879029375370124 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232059366253413058442519879029375388284 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232059366253413058442519879029376193680 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232060517280155921720449188919982948352 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714668208448530465537883186663427074911370356 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232059366253413058442519879029375369216 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232059367521063656309566056683439915008 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232059392874075613650489609764730830848 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232060517280155921720449188919982948352 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658808948056801636687333570487095450302346014633024309124640276480 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956886017953212059983935494810864097103954951317623033660270768161816576 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232059366253413058442519879029375369216 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359572341733174351521905894486461143580671 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714366377989071593120791173386635096507809771 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714668208448530465537883186663427074911370356 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956886017953212059983935494810864097103954951317623033660270768161816576 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356998229045691975002764689748372695622211821479298052100170973354672078968586241 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232059366253413058442519879029375369216 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356940333001073316904952470628102164776064494420927751032420533624771561387982848 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322358098253893446478857179507922865306010169741652157703419662355722622201640255488 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322409452045470196211438448611945610619742737456357206091793837165762298096828547072 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143893629499169185576181884464199941925492648173412559179111095560753183550196779689242985226007697858242805760 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839342888146918434783166170184693410567941044063248355890210060641243042267219249909278356373308648560435022417966923776 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232059366253413058442519879029375369216 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356998229045691764378181353017123184824223387704509037745718963012204512984170496 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322359314070830433875794986038092306727021506500607364724398929372858714185160196096 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322462021653983746517130273821176696823471012557849014427468811049551418146166931456 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143967021454743897697021332797750154768995199240031013214671721427772200944298808869207707477643789246163582976 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839362589150016560350974735937953781522707574833047277069208888782017716525143078981667386487019683415106886591490031616 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232059366253413058442519879029375369216 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322357114020693271444896826045989380155482288811031629873908035820404450399975636991 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322361745695429607166686524590509703110840880390476902283807583378095877811980992491 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322567160469986096428059655039986026180994416938874733662852517561710683534418508916 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187144113804806026290016988775982866377398593301552720816949212048465670236564031854638024422248837098678324822016 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839401991005924649193387182732009754361293337380257178225694035197917214268726395822062022825600369901284890985197731841 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232059366253413058442519879029375369216 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094859873731529946340457125253265606438475403785866280608383688705623749572896410942067145463298048566101192878305015324784812428376688032701026114373419008 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094925341543687869177857389047202158421519736626787141904173333673737274583686981044280961553112197512857770290118137179293735927649279836323967814334414848 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604097828839012891747016559088308288238869535898121627340372444088009572108812248765077463705136369703301511978504030091426764493120388726327001432207604580352 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714242674878487840834003055584974512311279435699658711463016289149904593484340885392177976886554761380392284766887296383377531438844432307956945337673417396461755078202559317439655444480 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246284526591342437031681239983319539526781594837816341634508518304645466356502238250467323544284041214993247041504034911017278877525141160830047989182088967849339008843158178926846443884250136576 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232059366253413058442519879029375369216 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604099884528314651286256569538428017605456878825657453309145227576677640040958663628934986711753291642085722067371786711860910744701600153316510206022861717503 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604200443087789236007416218065716994137807991595930114741177894981086079393684798558895591853642977661424896134653233764437938313665342050796316745892588683243 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991608660215200487068390846630250983103347579842957522649251826694366600364687088882702648429896450552619117266018585410546229110997207295204025736789114979613812 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412720612181264857001052430220984113268041169605999590508062896262224550689635337404935307273071388896041934422145344989624941219868920801067012539335366443652893627280972574012918747627520 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609247994327945847107914640183330172921779846117146457366173098936464424065745394177917220573722025424857132685900951652105144065956814009040322247733762938014573252644529306221744476122866568396801 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232059366253413058442519879029375369216 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604108264408270864647298161137061436164310781945681749250283604989128547694154752717429484588773793748781436185428142466460815382599579932635885671914066149375 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604376420566869716589289641637018783873739957116440329505083820642555140110802669417280047271073521902034892613836704611035935709522917416503201529607881752555 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991616269146200728800216611801810127154786923875939583363805473384872024513789137775055652502231066465498825685213756435722942522208572934826018659818328603753588 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412731234941101404944921415057286735598751533834754608191706076555894968957595202366608829373308066709416677670496300854621297134400773366760311827694929412487970664448286142577095835910144 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609250845853331860720581567860521618110735834371472259589597881444469377912314348012749304424693462091781531933248204739790571152550336708446718948563290509314250430570778299468543445592009405890561 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232059366253413058442519879029375369216 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604121672216200807244397735162059303549782240704219678280941573709222310999446686796969566947861942527383069465115599603330519233925266145981725897948762472448 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604657984533398511128380696161973998968640591045736839148901163764524169521933285087621776811924646252669191487273304485299716587362327896765846276336504537088 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991628443435801116678383025016508190740795008428692022923642908982717161594994213919278047284283105556469108703169967516000633619212296016544041585057832865103872 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412748231356839883200926797122969376340902726747459017819013799634941232234309731571032186453764294705643969095616201282861266238109349159903099797080432346176126701359673948281490070568960 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609255408293949482915800209032127203229867573886344178263242729439162614582767038791751242970046692831998959612856194724542144602162985656541483592372993404805860714591881919095033611090303465291776 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232059366253413058442519879029375369216 +21430172143725344039741447416747135734328099194269775938858685112579378184657786065906763159178676625205218492566825428477050725853377832065983208189713200681844100397174224127137557678646374287640475087188412914436146644713764873912909317614682237526728015428718464118732506826116885039758058750738432 +235731893580978784437155921584218493077609091136967535327445536238373160031235646724974394750965442877257403418235079713247557984387156152725815290086845207500285104368916465398513134465110117164045225959072542058797613091851413613042002493761504612794008169715903105306057575087285735437338646258122752 +9740013239323168866062487850911573191252121083795613164211272383667327384926963766954623855846708526155771804871622157242819554900360224673989368122224649709898143630515684865784019964944777113732595927127133669611228650022406135193417284855873076955897883012352541941963924352470124250570037702210617344 +13582985265193575509847153720301345363547163848715837516812932466783689951768234614081082594902676106779962952908124868514580193484388163974010229906267257277629370088801142633029220476374120830201819937481485605394893790147430680868494971780019587951193256398520172478623000296862688521766032969946888901935204417993802764714508288 +3646154850295010964902624396817474390410105702108556391759286100433934630952342968680077393668206518645350322207926570056063791163256347839621106322437804761540352091937936756225487349008505906910901544548065233498934923554616145309059470154014938195304963669835205443004851378494121810273694832757966522610366086517324182782563251960938496 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232059366253413058442519879029375369216 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824629198276151174244463087285660418287344529756165187857520911105123842660034918703411836307538943107430287596439419222071804002615797677806638572665083165692141839780886307603102541747070094713562715543794785904326970568977820621271154145831782622467599830140102357487631119091729219499088809459332415487 +736567904319114813700179347165898017864004333486947405305591758520610240861829766276798698618284354494716156033682943041579601713942220515540203161316998862077737405693327418524701312676891843887526247248550546356474902078886714910989494826726018489783987340302135409223113547673217455618750193884849347528160194394640717423882001111685525241940621668818619861722020482087095397955107969291288249444329152787862322599066175858052440630467418058473340907 +31847793196274107182845849867935019058119806419340392572260824606510195176311496560920629445019152089581060460884957727702584683631406487052881165260753593451678086770450460508976164978853315225613389231240714869753894387304963876717058650152672811697170570980613598309383691870969784601585900594981479511955574221514648792975451023932379869175500758313625655872192484128483431743888460039720362805862274612216016775291210943444487297807108709430373383284 +44462416394276340862910922260389321581298853470913371563358965890746390942505208917810214508921403677924050484037361854923909199530783769557857398908416797467991642660044081596444769282811977804250882370944636426195458324080999993435959869852668433762589077466327036503679884932798114847311436326315773506106222447586090692873957009455868034159802460539867856658115952688726716502746285402567852398888356313324109937916420499689593669109023205291494317874286388534278585340917710848 +11935289041890653422458560211344367565999989567726224393815132782921219808519438180124970259072038417888105302535754774032670805811336900569676094726678661851388189281957447472598923409448790006268973158495533882062541204142975446526119117611259327045262915006773486865554835011098276863061710309734987275751369401000805245194174420363093639844254247196438980433865369554332786383238465709007857728072714580953790040537248486657816917075965510971703569173409460696212044812838396933722603521 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998255571752838316161056568930429957046271 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998255571752838316161056568930429957046271 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998255571752838316161056568930429957046271 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998255571752838316161056568930429957046271 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998255571752838316161056568930429957046271 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998255571752838316161056568930429957046271 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998255571752838316161056568930429957046271 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998255571752838316161056568930429957046272 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998255571752838316161056568930429957046292 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998255571752838316161056568930429957047179 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998255571754105966758923615108084021592063 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998595854119759254624519943537861725257726 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998255571752838316161056568930429957046271 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998255571752838316161056568930429957046292 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998255571752838316161056568930429957046712 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998255571752838316161056568930429957065339 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998255571779458978716264538661165312507903 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132388005401501458178023893787435686497089486826 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998255571752838316161056568930429957046271 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998255571752838316161056568930429957047179 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998255571752838316161056568930429957065339 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998255571752838316161056568930429957870735 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998255572903865059024334498240320564625407 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132388307231960917050440985800712478475493047411 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998255571752838316161056568930429957046271 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998255571754105966758923615108084021592063 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998255571779458978716264538661165312507903 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998255572903865059024334498240320564625407 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172976888286874738812007209510607836887249117247073360525221953535 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834198122532121152290057037619484503120616341536220725647709322168743493631 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998255571752838316161056568930429957046271 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998595854119759254624519943537861725257726 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132388005401501458178023893787435686497089486826 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132388307231960917050440985800712478475493047411 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834198122532121152290057037619484503120616341536220725647709322168743493631 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463854626286928489170704919821474820295850844991684637003273587403723479550263296 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998255571752838316161056568930429957046271 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463796730242309831072892700701204289449703517933314335935523147673822961969659903 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655464954651134682993025119737995967430683808765164544288322764969771673602221932543 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655516308442711432725606388842018712744416376479869592676696939779811349497410224127 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418968698206766676988716306797306798322733884687580499409184197685426822573709166274146087840056749258824482815 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230791227421993503490763661597227832901047900460489592404378000871316144391892888932790742958211751174484073818548600831 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998255571752838316161056568930429957046271 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463854626286928278546121583090225309497862411216895622648821577061255913565847551 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655466170468071670389962926268165408851695145524119751309302031986907765585741873151 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655568878051224983031298214051249798948144651581361401012371913663600469546748608511 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526419042090162341389109555755130857011166236435754198953444744823552445839967811195454110810091692840646745260031 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230810928425091629058572227350488203855814431230288513583376829012090818649816718005179773071922786029155937992071708671 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998255571752838316161056568930429957046271 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463970417934507959064766276062482280155927834544016458811138434453501800557314046 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655468602092670843680854464820582805235514519413989288868710685992144929212562669546 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655674016867227332942227595270059128305668055962387120247755620175759734935000185971 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526419188873513623781429523198315973233795834538066888757179285150590343875587544241222927524862886150078906499071 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230850330280999717900984674144544176694400193777498414739861975427990316393400034845574409410503472515333942385779408896 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998255571752838316161056568930429957046271 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988312365191525626829590504228669795829923743060941349315981180118158171906003267339308381977465988796174295002978654348297199013279790646750077514955096063 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988377833003683549666990768022606347812968075901862210611770825086271696916793837441522198067280137742930872414791776202806122512552382450373019214916091903 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060991281330472887427505692467283692428260984237396702409080041579422106531145355621474704941650537643531585080628703730450276879705291828941050483608186257407 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357569626768432140808575645041867964802739431380147844841991693339296041823615960460885574377967295802725391623284537619891699379074505410081618976696929783046658180816608368840237121535 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193136923234669388921625539957892128983675047329276337314997651683620870545893686589742398612991638706405781463837141767414520114039309101060121091306762606872851395428061281540895495284831813631 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998255571752838316161056568930429957046271 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060993337019774646966745702917403421794848327164932528377852825068090174463291770485332227948267459582315795169496460350884423131286503255930559257423443394558 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581061093895579249231687905351444692398327199439935205189809885492472498613816017905415292833090157145601654969236777907403461450700250245153410365797293170360298 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581065553667691947064071335763629958507536971291296797724320534291858012899109421989559045671132964720559347339120710084185252623383792198306639785840515561290867 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809363939133154801301027002810441006720532629601680079641441871666413942137974612480004014870562801430464267529001742230861455387809150874169137212974389956039478530383586623064319329304575 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987194846724589174059804584483304745511236739569637917361853588069843399469934785626256495648790733022348545220323284758961541307193328176980552320835887611653596765031114209324358525174267150073856 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998255571752838316161056568930429957046271 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581061001716899730860327787294516036840353702230284956824318991202480541082116487859573826725825287961689011509287552816105484327769184483035249934723314647826430 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581061269873058329712269778775015994188063131405455715404573791418133967674533135776273677288507587689842264965715961378250059448096107820519117250581008463429610 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581073162598692188795897100935189102558976315324278858438874180982363437048211470881912049743467580633439055758315881109361966034595157837928632708869729185430643 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809374561892991349244895987646743629051242993830435097325085051960084360405934477441677536970799479243839010777352698095857811302341003439862436501333952924874555567550900191628496417587199 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987197698249975187672471512160496190700192727823963719585278370577848353316503739461088579499762169689272944467670537846646968393786850876386949021665415182953273942957363202571157494643409987567616 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998255571752838316161056568930429957046271 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581061015124707660802924886868541034707739173689043494753349649171200634845421779793653366808184376110467613142567240273242354031620510169248595774949349344149503 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581061551437024858506808869829540949403158032039385011914217608761255936703944266391944019018048438814192899264589397978124323228973947230999379895327737086214143 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581085336888292576674063514149887166144984399877031297998711616580208574129416547026134444525519619724409338776272092189639657131598880919646655634109233446780927 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809391558308729827500901369712426269793394186743139506952392775039130623682649006646100894051255707240066302202472598524097780406049579233005224470719455858562711604462287997332890652246015 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987202260690592809867690153332101775819324467338835638258923218572541589986956430240090518045115400429490372147278527831398541843399499824481713665475118078444884226978466822197647660141704046968831 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998255571752838316161056568930429957046271 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824629198276151174244463087285660418287344529756165187857520911105123842660034918703411836307538943107430287596439419222071804002615797677806638572665083165692141839780886307603102541747070094713562715543794785904326970568977820621271154145831782622467599830140102357487631119091729219499088809459332415487 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824843499997588427684860501759827889644687810748107885616909497956249636441881496564070903939130729873682339781365087476356574509874331456127298404746980297698960280784858049844373917323856558456439120294666670033471332035424958270010283239007929444842867110294389542128818444159990388349486390046839799807 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864834347781343330617766485833689155244342862322740766531245793324803678590666777224684300553400226472956960854182818474553886146506790304524648561957579118102201358139311004818244759424154336225453007670995834731161023763072355512991590658521370041017185970985137026180965476310937373226864619089102792294399 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382945944971643394552440333018544909113467554612749139183355056603618393891608739152695663135014913939388630223870254054412894344624289470541920862626549594209167573670063373732089922672967834116510690953316456889794786342129422505749576092463192554010284300112795761408992790940526935790646439671993459275486838307032042854165296185343 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287321881537782656997343103601327303339215017873806116005292182631938677605782562544625650995475250258938656613604058187487401993335543020778644703484269290201404867303981882236730798076805901958398370897225037198612474339112946064484584134538861612429607839386002942061840246087892662062040346796957431605546122752671420426796831614652542615551 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998255571752838316161056568930429957046271 +70149324220868077495255175920561715987048031760661657648151596049581927701126644407314161773169938523306300574636470765864723972756401953860971729649236966380158623144886433123904089438954731413136105939102963525135105941885179620757765851918707538235369974386271618715130954505741977781211162121976618183601835461375440982077945936461543052837790612502383395739504991310927477668395382345950562697672932264775996511143505676632322113137860859914092542 +771642566429548852447806935126178875857528349367278234129667556545401204712393088480455779504869323756369306321001178424511963700320421492470689026141606630181744854593750764362944983828502045544497165330132598776486165360736975828335424371105782920589069718248987805866440499563161755593322783341742800019620190075129850802857405301076973581215696737526217353134554904420202254352349205805456189674402254912535961622578562442955543244516469459055017962 +31882867858384541221593477455895299916113330435220723401084900404534986140162059883124286525905737058842713611172275963085517045617784688029811651125578201219782094219350883854814408650004925427270360149322296922173905650586814137634404579697052576127975653358560450706027018822859728901560473184438372964447034217195137926354426428121771317514775833382333253363605018550816538600285701276234530746092347714340690414314723330029390400421157760830955060339 +44462416394276340862910922260424396243409287509660999151319246748739914958385539746634290306946194641774613806241018935810494168792436919845175634291349159454369843636974567461269377050915985253151305716782880097347068525737970911517541922272679697044439338383672966048059649363603197225258288722959100457996166747560663282330850461947328029840291593918843260847507401028001791571453882893980386821221463169721351174430588439919666771233696844315006704459189491148327636741499387903 +11935289041890653422458560211344367566035064229836658432562760370881500666512962196005301087896114215912896266386318096236327886697921869831329245013996897234320551268335648449529409274273397774372980607395957227900784875294585648183090035692841379465274178288623747782900764555478041293866792687681839672394696352890749545168747009819987092335714242876928113812840773743724234722513540777715455219485249003286896896934489723171984857306038613096377208196921847281115147426887448334304280576 diff --git a/evm/src/cpu/kernel/tests/bignum/test_data/bignum_inputs b/evm/src/cpu/kernel/tests/bignum/test_data/bignum_inputs new file mode 100644 index 00000000..bd45bdf9 --- /dev/null +++ b/evm/src/cpu/kernel/tests/bignum/test_data/bignum_inputs @@ -0,0 +1,15 @@ +0 +1 +21 +908 +1267650597867046177654064545792 +340282366920938463463374607431768211455 +57896044618658097611351864738157061705262361561497619362091104892532012613632 +115792089237105570840234253759177109864155645142784332660520492325483608801280 +231583736816786089484927226016147767929578972263620494977377884571370600267775 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725446174963629590181147084998049792 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851378448187094873990326993486348287 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756016346166874193365792884690780159 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459867671853087539206018919387103232 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232059366253413058442519879029375369216 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998255571752838316161056568930429957046271 diff --git a/evm/src/cpu/kernel/tests/bignum/test_data/cmp_outputs b/evm/src/cpu/kernel/tests/bignum/test_data/cmp_outputs new file mode 100644 index 00000000..e4e41124 --- /dev/null +++ b/evm/src/cpu/kernel/tests/bignum/test_data/cmp_outputs @@ -0,0 +1,225 @@ +0 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +1 +0 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +1 +1 +0 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +1 +1 +1 +0 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +1 +1 +1 +1 +0 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +1 +1 +1 +1 +1 +0 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +1 +1 +1 +1 +1 +1 +0 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +1 +1 +1 +1 +1 +1 +1 +0 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +1 +1 +1 +1 +1 +1 +1 +1 +0 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +1 +1 +1 +1 +1 +1 +1 +1 +1 +0 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +0 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +0 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +0 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +0 +115792089237316195423570985008687907853269984665640564039457584007913129639935 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +0 diff --git a/evm/src/cpu/kernel/tests/bignum/test_data/iszero_outputs b/evm/src/cpu/kernel/tests/bignum/test_data/iszero_outputs new file mode 100644 index 00000000..e32c9c6c --- /dev/null +++ b/evm/src/cpu/kernel/tests/bignum/test_data/iszero_outputs @@ -0,0 +1,15 @@ +1 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 diff --git a/evm/src/cpu/kernel/tests/bignum/test_data/mul_outputs b/evm/src/cpu/kernel/tests/bignum/test_data/mul_outputs new file mode 100644 index 00000000..b53c5f7e --- /dev/null +++ b/evm/src/cpu/kernel/tests/bignum/test_data/mul_outputs @@ -0,0 +1,225 @@ +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +1 +21 +908 +1267650597867046177654064545792 +340282366920938463463374607431768211455 +57896044618658097611351864738157061705262361561497619362091104892532012613632 +115792089237105570840234253759177109864155645142784332660520492325483608801280 +231583736816786089484927226016147767929578972263620494977377884571370600267775 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725446174963629590181147084998049792 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851378448187094873990326993486348287 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756016346166874193365792884690780159 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459867671853087539206018919387103232 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232059366253413058442519879029375369216 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998255571752838316161056568930429957046271 +0 +21 +441 +19068 +26620662555207969730735355461632 +7145929705339707732730866756067132440555 +1215816936991820049838389159501298295810509592791450006603913202743172264886272 +2431633873979216987644919328942719307147268547998470985870930338835155784826880 +4863258473152507879183471746339103126521158417536030394524935575998782605623275 +68741202765818979270276983633379582196549482966904360579127216519201261330098607324506894304856394094406282403777947234369674236221393804088784959045632 +105586487448313957217630953653425358968668408786294503634300774628861320362441676458635398984170320306132770645519405205878947411928992353796866863213314027 +281563966528794539091054524955215094900633929296509267540226436097922037480312534843090816414714560916129249828990251803876343269504358060681650578506383339 +563127933057589078182109049910430189801267858593018911357569558066951448610928205184820357265838911550428123265590126067657221108914838323326397307129167872 +225016807509116112417285197875844925210445041539832647358016193682083470938906753692021013171376104564654794171951666999009032621460467236692823685991988607159363054170329353334944355625786930020224988415478335601579539769494531176085547834954163494030644162001543873246691321674227292917459616882753536 +736567904319114813700179347165898017864004333486947405305591758520610240861829766276798698618284354494716156033682943041579601713942220515540203161316988146991665543021307547800992939109024679837929112360581117013918612389794386017956541445146429151471384731055851996508875022310290766702717202280754490927819272344442130311818432332846202054796801431275025655264802408764738515518151514632480908325565788780147963367006809604639382187947539029097971691 +0 +908 +19068 +824464 +1151026742863277929309890607579136 +308976389164212124824744143548045536001140 +52569608513741552631107493182246612028378224297839838380778723242419067453177856 +105139217027291858322932702413332815756653325789648174055752607031539116791562240 +210278033029641769252313921222662173280057706815367409439459119190804505043139700 +2972238671969696817971976244719460030212710977807102828849881552354035489891882640507250477562362182748614496315732194705126866975667884481553178229211136 +4565358600146146340648043138919534568740519770378829014283100160143146613766525820211473441791745277998502654577696186997051630953882145583216910085604244596 +12174289600387878166413214698063586008084552752439543567929790665567295715815418173215545776407658157706921849748721363710462842319521767576139939299228384372 +24348579200775756332826429396127172016169105504879103405365388510704376920891562395610327828446749127989939805959801641401559846042603485599065178803489734656 +9729298153251306194042617127203199623384957034198478276241843041111037695834634873921670474267119187843169195625338744528581029537433535757956376518129793109557221580317097753720451186105453926588775689583539463154010576700049252756460830197065735837134519004638182709904558099057065808050158672835248128 +31847793196274107182845849867935019058119806419340392572260824606510195176311496560920629445019152089581060460884957727702584683631406487052881165260753582736592014907778440638252456605285448061563792096352745440411338097615871547824025696771093222358857968371367314896669453345606857912669867603377384655355233299464450205863387455153540545988356938076082061665735266055161074861451503585061555464743511248208302416059151577191074239364588830400998014068 +0 +1267650597867046177654064545792 +26620662555207969730735355461632 +1151026742863277929309890607579136 +1606938038272679619211255036084048932956190504430095264907264 +431359145870941220571487096504865044588697904564591140391738786447360 +73391955574979118963811141843059488536193514605218060347731553038824318137413435829926783487818828867436544 +146783911149691239803259475393272332038744581223672095908357420057841712239442615794649035123910216788213760 +293567262432083559770702660509494961636846893913475830448684457955877331972488384611363806317219648949452800 +4149515561151917970063980879655710938513649460124350952720371065270297197065154634382680097543307069927884450339928718724097725668943949230978441358030208342019760039438410280075264 +6373655901930312136397229380018411440828683949391920950832693445711366448193584697763678864931677968612065262908033170282412527802037703004824976134384286640214222530054133889372258304 +16996415738478256005382065682640742151192912704409604594012987116129634408058546371285779101609491343355313613863898166638327059654603396304113335697353121717251389843622698066460540928 +33992831476956512010764131365281484302385825408819231901736066162392911122587750794642859557837487570646738733764326406607430768230396539092082721200286809873288301231428402460695199744 +13582985265193575509847153720290630277475301176695966793104558898916525902171099726111653252346386417687634059875171486934990855171785554727726817192028731914702681172768151028934363876033198780003232825417916826555570603003610443324900765322801514628836373961563717819815659178099324514051673737887522648522145975473923735339139072 +44462416394276340862910922260389321581298853470913371563358965890746390942505208917810214508921403677924050484037361854923909199530783769557857398908416797467991642660044081596444758567725905941578862500220928052627591160031402858547990440510112144073496748573294083122100295594485512238065152913601534980743295758670057701269862152855527112109603873427804287879276629501582896265202691196110634325565999430887153483257613158570830305101308846059434951620873330091758706311542341632 +0 +340282366920938463463374607431768211455 +7145929705339707732730866756067132440555 +308976389164212124824744143548045536001140 +431359145870941220571487096504865044588697904564591140391738786447360 +115792089237316195423570985008687907852589419931798687112530834793049593217025 +19701003098197239571963727475337245584161626291901231402719522479678259504890677218990119895590117915143388591554560 +39402006196322807380529480735708200350692396090822410401547663254352517428719749608020233606624972587007562114662400 +78803862104411649792976274791681038936454943300723566886694079153850261012036590002656572187311458765011955822362625 +1113877103911668754551067286547922686738237475419584309931192581897577662915063323503306740447008536028968181678028580322422866333819711284625174374608617279642589745120484326564854874767360 +1710915231608582551713494414139930175751260546116444122900349352360496966554854730076753484481830650675467827629295222707109502155201699203484369755223655341193278275893163301956243837193027585 +4562440617622195218641171605585119131739514871918667547682857357314343535508689562160604455918497575074715174882382908134196095677901105600185199282794955018371204524886410100925712980030521345 +9124881235244390437282343211170238263479029743837341192530852050551013988199468564099149809149237792502394782872367659707645708326849200364829008985690446628655225628506036591091211274089922560 +3646154850295010964902624396817474390399390616036693719739415376725561063085178919082942505698777176089060633115597677023110409583667009527018497076154392047301826729011247840192495744913649306569979494349478121435366144715292958165239232610420731738086890347478323006048396719686780691510330825043607290550999833104265740262684222585569280 +11935289041890653422458560211344367565999989567726224393815132782921219808519438180124970259072038417888105302535754774032670805811336900569676094726678661851388189281957447472598923409448779291182901295823514011338832830575108282476521982723289897702706625317681157972521881629518687524749107700488703863037130875637878556278141428758998783243913325146240393321801800775493463196094645471464263521615496507631433158100292031999009575957202146963989209941350094442798986370318517904347234305 +0 +57896044618658097611351864738157061705262361561497619362091104892532012613632 +1215816936991820049838389159501298295810509592791450006603913202743172264886272 +52569608513741552631107493182246612028378224297839838380778723242419067453177856 +73391955574979118963811141843059488536193514605218060347731553038824318137413435829926783487818828867436544 +19701003098197239571963727475337245584161626291901231402719522479678259504890677218990119895590117915143388591554560 +3351951982485649263264086660821751293167574115217012473116062855570117177114956810549394311722122195190355926629690380263290286253266199596551551712231424 +6703903964959104207882943247098074879292236184530784614687051259089361504778664925296585557644723899819989557097938820112754998714546796218504411307048960 +13407782359700221432208153137018396716476230393601324554188676058418403973105159781474496977845448805812756231084668278028521746573850893544243696815308800 +189516368689051383356419666365934487249694726206307462692478442160356412055175068191548410359233923189538270288357620597887942150501998384340803566981539803652861191767034299241276777771401726930027167539955532412991464793964544 +291097142306427050053565423426590890568146840930776532405423684287884740444915857761347334012000265903675449121187612221625638517177392299309155307502337486020927127535947499456450345719682189031665783117734919052512795878316048384 +776259046150354466227894953415272126532120228827236797123305565388337686400499060284004070246335310139188795312112703394374362640691719752700909206017051198060493495608220461125520225112836119459965070690227765389768580522718527488 +1552518092300708932455789906830544253064240457654474631625503351024913201337446226079742769388732571127058525201398326436194714101150988019032351961389195980792206263906993685249030935631117974530339035198582125552984050009714458624 +620361101309323186180458062143306311203234091808422651940994483172973212453462540277947848500764537416293185308049243121091077089522237714087216426627812178598932718744797175293795424927554129248204812001597295596246882084347634304130710520242400817201806901439842621734294451519310289297352148130231477204202016235965703658712648032709044435339313088432114418262153009154752512 +2030684202530045702032438070068470600111523314891992114474287665026563901579442604747297208342924347358657516628421307413109601517971206668455722861607048951866317121347560401223028395731439655580245638497036905507303055096291514983167804903577061365248747133480848909746535730849828042674125732472216127172563383280944806187156793401092909358110607810689164992655422507992440651826516323860482006072417239646401793958680956430020069720523666773505207631846930990177373853120582291091033196123813538806140647566683428129469366272 +0 +115792089237105570840234253759177109864155645142784332660520492325483608801280 +2431633873979216987644919328942719307147268547998470985870930338835155784826880 +105139217027291858322932702413332815756653325789648174055752607031539116791562240 +146783911149691239803259475393272332038744581223672095908357420057841712239442615794649035123910216788213760 +39402006196322807380529480735708200350692396090822410401547663254352517428719749608020233606624972587007562114662400 +6703903964959104207882943247098074879292236184530784614687051259089361504778664925296585557644723899819989557097938820112754998714546796218504411307048960 +13407807929893819778475470707735784992488440665279129110225796518690280399801487040957178859490788616767266574533518552379422042573571257824675478529638400 +26815564719351665682859297115793503881598601899157213443769731667066042177950468012051000327834243644827516674656869253925854969676662574929007714762752000 +379032737377413310837469826127201516165849126556927185280268831441004642386080191344591587626743143491163530774059885949190517071683841202707214877193839283509836239507327810571115256102701286181423314856476535119531046873333760 +582194284611795095882563124181957331911668652816390808061798178917116866814434754607160150716463467811845369643570012125338680346889780167007790616300675328647243232411818768880659637664081627824716845155217383295556538120651407360 +1552518092297884921190276407777826343730130571016241164825192478707830380921635634356568453745503455149401263113730019700298099019902002012202155472213879518073654497303294521076488615535022163842239123103052036543841131161997803520 +3105036184595769842380552815555652687460261142032484404408169394138177593232526559709091771925126394796328107261127062087481484183515508524562872429687439110406240134689348936276584863546005281248676694097265868804492346319133736960 +1240722202616389513973922768685786106091078788555724681396110088894901580356174059693107801547999717844793849118253907517164294570375212313898259715085141105940658891307423763778538377665051892100124228941562467259128201610076266056373405707086736336167605239314782881108716366473706926696989024480092947548903006603393526774842227227605392632574744471346260936099413707173396480 +4061368405052703825017540452826323628177065892919822203995680056457293914967717151139514347845670761968317643193023213196105279034485542899856942497055973489887306964055240783810529148217259878326321073593635104947630604439996612121186052320432514468047976270758130684476727539892394554268861392044474193564110067997362607705131765085400073399409683739317269432145800594368855385753859106179981112207797478255195155380669937444019554506527587107321605367039934467094788088851405871320736566808054693946822238648612224007804026880 +0 +231583736816786089484927226016147767929578972263620494977377884571370600267775 +4863258473152507879183471746339103126521158417536030394524935575998782605623275 +210278033029641769252313921222662173280057706815367409439459119190804505043139700 +293567262432083559770702660509494961636846893913475830448684457955877331972488384611363806317219648949452800 +78803862104411649792976274791681038936454943300723566886694079153850261012036590002656572187311458765011955822362625 +13407782359700221432208153137018396716476230393601324554188676058418403973105159781474496977845448805812756231084668278028521746573850893544243696815308800 +26815564719351665682859297115793503881598601899157213443769731667066042177950468012051000327834243644827516674656869253925854969676662574929007714762752000 +53631027158026444898639041353951338860236953565976155186370673275827169990229796710610136585486710294744741538759339503142188427219888626557524901703450625 +758064029037559548223859302619650075474792064511873124215265408149659395559453789942397036648834306197292055977388138161024258210175532633810972040915105374809744387652086706188503922572983286780452241329985943497170267983052800 +1164386348601867966607659549490709240641434805493466720013626865708760416816760684474263347086593403580537140168446677038569831210140531685534851163995750025031331763664446019825967919583282914146489408839507982335431232969112551425 +3105030262937843909524927703451704725658035213057063685463909781308268889930827638236818973565112070382840731126979240983820442568989111483626724942061970361307566813811606244576718762256490550467423465073089242630619613999057076225 +6210060525875687819049855406903409451316070426114131520435474836896735901928651243521579858300210079569809751772692509393442960425269123499217289079803270033146012536744468900746753485654275750950451702497211174173610068660767948800 +2481439672835455316435450222961490952467054688477443973252759241836914049418059193066289201770080478782010589768308256548437208615056252516149995383823877308087652590010038324508787501850632011084265376115191445269164718609708653219057772287156297315205415965661016801043979428655461218374679406517792258741473669803979329510535342890018189384338466515427440201885258439091814400 +8122721319120455379930921158326117871838290539711891253924140849349950965031209192469013362813226005733220497444267273168824363782607514900842646678617218420603025285381689301022402706647780653422402593097268270904777394649862358017106423565800216445602438232961812733726274533361295534877361561034733716956723820342508274535124544488827440330912196294237990424996646092080259959888790753448676537815274083485701600749922454909872662388097681488248458568576219237116237159724865297204930388201921385039717285631411970780665217025 +0 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725446174963629590181147084998049792 +68741202765818979270276983633379582196549482966904360579127216519201261330098607324506894304856394094406282403777947234369674236221393804088784959045632 +2972238671969696817971976244719460030212710977807102828849881552354035489891882640507250477562362182748614496315732194705126866975667884481553178229211136 +4149515561151917970063980879655710938513649460124350952720371065270297197065154634382680097543307069927884450339928718724097725668943949230978441358030208342019760039438410280075264 +1113877103911668754551067286547922686738237475419584309931192581897577662915063323503306740447008536028968181678028580322422866333819711284625174374608617279642589745120484326564854874767360 +189516368689051383356419666365934487249694726206307462692478442160356412055175068191548410359233923189538270288357620597887942150501998384340803566981539803652861191767034299241276777771401726930027167539955532412991464793964544 +379032737377413310837469826127201516165849126556927185280268831441004642386080191344591587626743143491163530774059885949190517071683841202707214877193839283509836239507327810571115256102701286181423314856476535119531046873333760 +758064029037559548223859302619650075474792064511873124215265408149659395559453789942397036648834306197292055977388138161024258210175532633810972040915105374809744387652086706188503922572983286780452241329985943497170267983052800 +10715086071862673209484250490600018105614048117055336074430675836924241540472703456698285220172692381666915465456597657220856438022326048260043738079097569861723477222864084024723456654120868104119493560585512807944190828392178187984719137393049169103254142087127248661337626132381236011316443311243264 +16458372206383560850154727152772241309834362634645429482097685030171884111143709030259566480970840675586286057165552281949963074948236086284290260005656649082848245798566424861913543183906541851941660459520122404258933779435071795354694349641611033685309336221143617936715894403545863381859480370679906304 +43888992550349509466047490008389760228034918444740354476264789433451422494435484145605446873947256471512988292597450618642207676514741311261882165968599848430310026415377131508214755446432997138431116604680521746555008944242629428478468183278110882114932777127534190355484669739785885245968619478007676928 +87777985100699018932094980016779520456069836889480767605004803903623391638540464457280122746011077411993751425324753978750781979522477580196467009117071428016628499217023421730630965195213525748235513398478599337876370083082111993797578339643292113170849335330813036879783075982297998725326138636180127744 +35074662110434034853557842365135370752418744845644232722536724705537763948482350096800897815346751615649214933728622564185847196492435060706089044924648133026630781093917108095545664072447733261889308217617387286462129653489067160073127037621299577013488448084508231783465815261392679840044175715075506479855049458960417568692240224459402814116944692003822183536118940032489278563958573604110859792014017609258239480765944544557609136035015279952003072 +114813069527425452423283320117768198402231770208869520047727692128105340272556505252150160006414760200146251310083289009338166699942758143608103582817139261613860686884404865091240091700335916571366968398775231636972558602982410372368561085607640039695044427708003371630792169233277670446637805866344012196830083200549854376617192853167566486801110672010487276196765581360935421367998631422802129683085092788505721142860577202194007940588172852101767238437699363756153062785321947495141655278338111834268668260296874876439322420209270108736741859953710415066991479177424624334867465316525824363705925632 +0 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851378448187094873990326993486348287 +105586487448313957217630953653425358968668408786294503634300774628861320362441676458635398984170320306132770645519405205878947411928992353796866863213314027 +4565358600146146340648043138919534568740519770378829014283100160143146613766525820211473441791745277998502654577696186997051630953882145583216910085604244596 +6373655901930312136397229380018411440828683949391920950832693445711366448193584697763678864931677968612065262908033170282412527802037703004824976134384286640214222530054133889372258304 +1710915231608582551713494414139930175751260546116444122900349352360496966554854730076753484481830650675467827629295222707109502155201699203484369755223655341193278275893163301956243837193027585 +291097142306427050053565423426590890568146840930776532405423684287884740444915857761347334012000265903675449121187612221625638517177392299309155307502337486020927127535947499456450345719682189031665783117734919052512795878316048384 +582194284611795095882563124181957331911668652816390808061798178917116866814434754607160150716463467811845369643570012125338680346889780167007790616300675328647243232411818768880659637664081627824716845155217383295556538120651407360 +1164386348601867966607659549490709240641434805493466720013626865708760416816760684474263347086593403580537140168446677038569831210140531685534851163995750025031331763664446019825967919583282914146489408839507982335431232969112551425 +16458372206383560850154727152772241309834362634645429482097685030171884111143709030259566480970840675586286057165552281949963074948236086284290260005656649082848245798566424861913543183906541851941660459520122404258933779435071795354694349641611033685309336221143617936715894403545863381859480370679906304 +25280059709008981479231968148711644861442111696433705443231567360117402528393306066518309787037990431336656280044426224316649696164180810324022564882675140987960579876942528723700768267175237032707899300231700312150169638715161500573218061631068318350665689512114702779435677385026007774824467356638267834369 +67413492557347065242233762416053344604668789415978336070232719704519730695842285928289497175591340668357371303688672579355774019833840277487199698360245654983419254719431470785652320406511710713843764264258846732773932462012692405900266395961054012873582577495350462230973011642886763600990552681342023237633 +134826985114694130484467524832106689209337578831956762230667385079098314604114856488714967534864721366751145206577896381937685648970101488283024945486839684466321300593943839555804243973666843820217508302523380061872683673515732869098988513858354359158586336115486301550288354364817320561524260650122775363584 +53874681001634843991219960220676811838216618976411872431379454389487697453585414607630678378827390586054634875212617995067952662788488677051131226188233783645486119633174249397007355413950452332486425618874867205381482252662669001815967811090854730467120253594575199233845159152018106715728564966104973555959854476034899985603379172050429045260764066870120309159237337727562784303384359771520036909014223788365313020881488428759631128761329980986194132992 +176352874794152226923041126648344020296255845787663270025002097998433518218912651792864315498223942025499431461820100039971032945845086214853910514425858431681855101933052310870599356102672426974402827054711569107570218750844042593899023102723914290002809698086928282996956938154665332804357164535720651529889760012561396833002255365927318549914998445177047355818945707770980966071916771923738923854573521041830764111506524804411686150461839884079980325493144566147614078318969489021758698999020279168507320287970878237811504779638217033120905407240942949803405092731964364881039731836747753076040480587777 +0 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756016346166874193365792884690780159 +281563966528794539091054524955215094900633929296509267540226436097922037480312534843090816414714560916129249828990251803876343269504358060681650578506383339 +12174289600387878166413214698063586008084552752439543567929790665567295715815418173215545776407658157706921849748721363710462842319521767576139939299228384372 +16996415738478256005382065682640742151192912704409604594012987116129634408058546371285779101609491343355313613863898166638327059654603396304113335697353121717251389843622698066460540928 +4562440617622195218641171605585119131739514871918667547682857357314343535508689562160604455918497575074715174882382908134196095677901105600185199282794955018371204524886410100925712980030521345 +776259046150354466227894953415272126532120228827236797123305565388337686400499060284004070246335310139188795312112703394374362640691719752700909206017051198060493495608220461125520225112836119459965070690227765389768580522718527488 +1552518092297884921190276407777826343730130571016241164825192478707830380921635634356568453745503455149401263113730019700298099019902002012202155472213879518073654497303294521076488615535022163842239123103052036543841131161997803520 +3105030262937843909524927703451704725658035213057063685463909781308268889930827638236818973565112070382840731126979240983820442568989111483626724942061970361307566813811606244576718762256490550467423465073089242630619613999057076225 +43888992550349509466047490008389760228034918444740354476264789433451422494435484145605446873947256471512988292597450618642207676514741311261882165968599848430310026415377131508214755446432997138431116604680521746555008944242629428478468183278110882114932777127534190355484669739785885245968619478007676928 +67413492557347065242233762416053344604668789415978336070232719704519730695842285928289497175591340668357371303688672579355774019833840277487199698360245654983419254719431470785652320406511710713843764264258846732773932462012692405900266395961054012873582577495350462230973011642886763600990552681342023237633 +179769313486231590772930519069826442426264354005082326596360185112449176958549873259557850386600277367825925997915804457268344327753240407083712876794615624877762257166854166161646934596377646965522119647578649647126703396773127858133295428017635762092566594653974618708449402594449637475763618354340068065281 +359538626972463181545861038139652884852528708010164893433258891975305712994145996750811464699841724874842731010897931000393441458205293971046234853904111613343804779646728343027691647116232436982584254759296818415737834043273351893507362234301351226814369365796651940053069649153544102516262530232441150373888 +143665816004337806760172922323967843540707266966555160070938769845933482343514311921981576218185379382379331497993348644831971734671586556667433058226409769129546130073493215528938527708576559133205415270644020134698724204081225254029881946465693095984137609224865240709292656860316268992459694963883823498044606777540574301742157684362334319609311262061951308672635789253885343679712825576151996358495453517343899352653487644349083554108658142161712185344 +470274332784334653125768479190507147507942688099845821153656843754997301836979240962837606053917822376117946484914782536168160296609184534239096896145262203039351588043847354547077881392556187451052716096931348618124350989790368724551688012179157579351487604719105146798178247445433672967393357192101321816498019101823012168469706240238546733430563115610529101897377344839733586268940478469960836347004487048570855680122137578043206023975369775048480356517721340390187833972378623137126307547351741242129046523455257536374422351385724837117101473491922399552018441281779378146120832426011456202350251737089 +0 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459867671853087539206018919387103232 +563127933057589078182109049910430189801267858593018911357569558066951448610928205184820357265838911550428123265590126067657221108914838323326397307129167872 +24348579200775756332826429396127172016169105504879103405365388510704376920891562395610327828446749127989939805959801641401559846042603485599065178803489734656 +33992831476956512010764131365281484302385825408819231901736066162392911122587750794642859557837487570646738733764326406607430768230396539092082721200286809873288301231428402460695199744 +9124881235244390437282343211170238263479029743837341192530852050551013988199468564099149809149237792502394782872367659707645708326849200364829008985690446628655225628506036591091211274089922560 +1552518092300708932455789906830544253064240457654474631625503351024913201337446226079742769388732571127058525201398326436194714101150988019032351961389195980792206263906993685249030935631117974530339035198582125552984050009714458624 +3105036184595769842380552815555652687460261142032484404408169394138177593232526559709091771925126394796328107261127062087481484183515508524562872429687439110406240134689348936276584863546005281248676694097265868804492346319133736960 +6210060525875687819049855406903409451316070426114131520435474836896735901928651243521579858300210079569809751772692509393442960425269123499217289079803270033146012536744468900746753485654275750950451702497211174173610068660767948800 +87777985100699018932094980016779520456069836889480767605004803903623391638540464457280122746011077411993751425324753978750781979522477580196467009117071428016628499217023421730630965195213525748235513398478599337876370083082111993797578339643292113170849335330813036879783075982297998725326138636180127744 +134826985114694130484467524832106689209337578831956762230667385079098314604114856488714967534864721366751145206577896381937685648970101488283024945486839684466321300593943839555804243973666843820217508302523380061872683673515732869098988513858354359158586336115486301550288354364817320561524260650122775363584 +359538626972463181545861038139652884852528708010164893433258891975305712994145996750811464699841724874842731010897931000393441458205293971046234853904111613343804779646728343027691647116232436982584254759296818415737834043273351893507362234301351226814369365796651940053069649153544102516262530232441150373888 +719077253944926363091722076279305769705057416020330267347594827451426144142384493965014457252965790028388273268575745766448202845714472108972056832957787126548989380860079998712572623109761917189596553766242330909605534894906264486337757228291297942005327959842043718998160370035708197081835945941328224845824 +287331632008675613520345844647935687081414533933110512134339071188196745795513335307638657529820500030503638059893998544639282004826074078543526937501430385498822553680856810441605837007924382387640823649251663812111395581050675179334316291609265083908971530669507424781643811407050868800014638372550585796767486279157989351235817419037012278476998673070763482207177579797214780269850906321355704457864297379025560392407254253435440813631626425868706906112 +940548665568669306251536958381014295015885376199692270773634051571468443177252576492255360423853770864325258737964248491672738005473375204458692172487804734089712687353813343670064744128701098573532877590228667667008286737596697852387981631862326481177071413971930746756905828624662822957794948866823607625220615269013165228239618537011536940291208905424160713389821033135818514340985521905976691408942139437741483410228329038000371498590009406379772049151623867582176028814687068466685902099735918960489164147117893952824903803155286426295341357243145288763878804327513759861599032840758403923281677647872 +0 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232059366253413058442519879029375369216 +225016807509116112417285197875844925210445041539832647358016193682083470938906753692021013171376104564654794171951666999009032621460467236692823685991988607159363054170329353334944355625786930020224988415478335601579539769494531176085547834954163494030644162001543873246691321674227292917459616882753536 +9729298153251306194042617127203199623384957034198478276241843041111037695834634873921670474267119187843169195625338744528581029537433535757956376518129793109557221580317097753720451186105453926588775689583539463154010576700049252756460830197065735837134519004638182709904558099057065808050158672835248128 +13582985265193575509847153720290630277475301176695966793104558898916525902171099726111653252346386417687634059875171486934990855171785554727726817192028731914702681172768151028934363876033198780003232825417916826555570603003610443324900765322801514628836373961563717819815659178099324514051673737887522648522145975473923735339139072 +3646154850295010964902624396817474390399390616036693719739415376725561063085178919082942505698777176089060633115597677023110409583667009527018497076154392047301826729011247840192495744913649306569979494349478121435366144715292958165239232610420731738086890347478323006048396719686780691510330825043607290550999833104265740262684222585569280 +620361101309323186180458062143306311203234091808422651940994483172973212453462540277947848500764537416293185308049243121091077089522237714087216426627812178598932718744797175293795424927554129248204812001597295596246882084347634304130710520242400817201806901439842621734294451519310289297352148130231477204202016235965703658712648032709044435339313088432114418262153009154752512 +1240722202616389513973922768685786106091078788555724681396110088894901580356174059693107801547999717844793849118253907517164294570375212313898259715085141105940658891307423763778538377665051892100124228941562467259128201610076266056373405707086736336167605239314782881108716366473706926696989024480092947548903006603393526774842227227605392632574744471346260936099413707173396480 +2481439672835455316435450222961490952467054688477443973252759241836914049418059193066289201770080478782010589768308256548437208615056252516149995383823877308087652590010038324508787501850632011084265376115191445269164718609708653219057772287156297315205415965661016801043979428655461218374679406517792258741473669803979329510535342890018189384338466515427440201885258439091814400 +35074662110434034853557842365135370752418744845644232722536724705537763948482350096800897815346751615649214933728622564185847196492435060706089044924648133026630781093917108095545664072447733261889308217617387286462129653489067160073127037621299577013488448084508231783465815261392679840044175715075506479855049458960417568692240224459402814116944692003822183536118940032489278563958573604110859792014017609258239480765944544557609136035015279952003072 +53874681001634843991219960220676811838216618976411872431379454389487697453585414607630678378827390586054634875212617995067952662788488677051131226188233783645486119633174249397007355413950452332486425618874867205381482252662669001815967811090854730467120253594575199233845159152018106715728564966104973555959854476034899985603379172050429045260764066870120309159237337727562784303384359771520036909014223788365313020881488428759631128761329980986194132992 +143665816004337806760172922323967843540707266966555160070938769845933482343514311921981576218185379382379331497993348644831971734671586556667433058226409769129546130073493215528938527708576559133205415270644020134698724204081225254029881946465693095984137609224865240709292656860316268992459694963883823498044606777540574301742157684362334319609311262061951308672635789253885343679712825576151996358495453517343899352653487644349083554108658142161712185344 +287331632008675613520345844647935687081414533933110512134339071188196745795513335307638657529820500030503638059893998544639282004826074078543526937501430385498822553680856810441605837007924382387640823649251663812111395581050675179334316291609265083908971530669507424781643811407050868800014638372550585796767486279157989351235817419037012278476998673070763482207177579797214780269850906321355704457864297379025560392407254253435440813631626425868706906112 +114813069527425426929660656670434000556791117993150086180221643697431093173028910532415727113435976215204539871783667883838967071195340228232917109351973450013767101034272479645738741907650504496198421145870980109769343781666731468018474148841379223523433938268079692841589810552977465445261846437407748635458762124821556936873529967035483590621122322119705006554547460062408802518269990075352861435909928146945580063563725505925881145977291236879775785378910221502159993605883245075109657690762294065063726665915384443183063224455834919138638489409150864878627937633765733984255718952202044576320454656 +375828023454801161958069925084019843923978286415518836749560060086790811063826786575473978319828101315166509670501153778395493519601305062611233710167108096659872687219140685926605165995932330503576533938874126310080807833945025154398047371417183906188778761688181994841114264769649793185124682348180893134333861320517448227288705530984286877458322203246948912271425933606164725949285658013879720265044644617847420446340162585011712000860105735035610334678196167563897824599954042423669530327316471628496333180947012248953569457951187522058076800530227428892238847959130402967459985851634689104636645635632818315245484817355205865998912643567216769076790812429039605288671959330499956935814269560500882854907846825228822521982049802574527070231420993536 +0 +35074662110434038747627587960280857993524015880330828824075798024790963850563322203657080886584969261653150287318235382932361986378200976930485864824618483190079311572443216561952044719477365706568052969551481762567552970942589810378882925959353769117684987193135809357565477252870988890605581060988309091800917730687720491038972968230771526418895306251191697869752495655463738834197691172975281348836466132387998255571752838316161056568930429957046271 +736567904319114813700179347165898017864004333486947405305591758520610240861829766276798698618284354494716156033682943041579601713942220515540203161316988146991665543021307547800992939109024679837929112360581117013918612389794386017956541445146429151471384731055851996508875022310290766702717202280754490927819272344442130311818432332846202054796801431275025655264802408764738515518151514632480908325565788780147963367006809604639382187947539029097971691 +31847793196274107182845849867935019058119806419340392572260824606510195176311496560920629445019152089581060460884957727702584683631406487052881165260753582736592014907778440638252456605285448061563792096352745440411338097615871547824025696771093222358857968371367314896669453345606857912669867603377384655355233299464450205863387455153540545988356938076082061665735266055161074861451503585061555464743511248208302416059151577191074239364588830400998014068 +44462416394276340862910922260389321581298853470913371563358965890746390942505208917810214508921403677924050484037361854923909199530783769557857398908416797467991642660044081596444758567725905941578862500220928052627591160031402858547990440510112144073496748573294083122100295594485512238065152913601534980743295758670057701269862152855527112109603873427804287879276629501582896265202691196110634325565999430887153483257613158570830305101308846059434951620873330091758706311542341632 +11935289041890653422458560211344367565999989567726224393815132782921219808519438180124970259072038417888105302535754774032670805811336900569676094726678661851388189281957447472598923409448779291182901295823514011338832830575108282476521982723289897702706625317681157972521881629518687524749107700488703863037130875637878556278141428758998783243913325146240393321801800775493463196094645471464263521615496507631433158100292031999009575957202146963989209941350094442798986370318517904347234305 +2030684202530045702032438070068470600111523314891992114474287665026563901579442604747297208342924347358657516628421307413109601517971206668455722861607048951866317121347560401223028395731439655580245638497036905507303055096291514983167804903577061365248747133480848909746535730849828042674125732472216127172563383280944806187156793401092909358110607810689164992655422507992440651826516323860482006072417239646401793958680956430020069720523666773505207631846930990177373853120582291091033196123813538806140647566683428129469366272 +4061368405052703825017540452826323628177065892919822203995680056457293914967717151139514347845670761968317643193023213196105279034485542899856942497055973489887306964055240783810529148217259878326321073593635104947630604439996612121186052320432514468047976270758130684476727539892394554268861392044474193564110067997362607705131765085400073399409683739317269432145800594368855385753859106179981112207797478255195155380669937444019554506527587107321605367039934467094788088851405871320736566808054693946822238648612224007804026880 +8122721319120455379930921158326117871838290539711891253924140849349950965031209192469013362813226005733220497444267273168824363782607514900842646678617218420603025285381689301022402706647780653422402593097268270904777394649862358017106423565800216445602438232961812733726274533361295534877361561034733716956723820342508274535124544488827440330912196294237990424996646092080259959888790753448676537815274083485701600749922454909872662388097681488248458568576219237116237159724865297204930388201921385039717285631411970780665217025 +114813069527425452423283320117768198402231770208869520047727692128105340272556505252150160006414760200146251310083289009338166699942758143608103582817139261613860686884404865091240091700335916571366968398775231636972558602982410372368561085607640039695044427708003371630792169233277670446637805866344012196830083200549854376617192853167566486801110672010487276196765581360935421367998631422802129683085092788505721142860577202194007940588172852101767238437699363756153062785321947495141655278338111834268668260296874876439322420209270108736741859953710415066991479177424624334867465316525824363705925632 +176352874794152226923041126648344020296255845787663270025002097998433518218912651792864315498223942025499431461820100039971032945845086214853910514425858431681855101933052310870599356102672426974402827054711569107570218750844042593899023102723914290002809698086928282996956938154665332804357164535720651529889760012561396833002255365927318549914998445177047355818945707770980966071916771923738923854573521041830764111506524804411686150461839884079980325493144566147614078318969489021758698999020279168507320287970878237811504779638217033120905407240942949803405092731964364881039731836747753076040480587777 +470274332784334653125768479190507147507942688099845821153656843754997301836979240962837606053917822376117946484914782536168160296609184534239096896145262203039351588043847354547077881392556187451052716096931348618124350989790368724551688012179157579351487604719105146798178247445433672967393357192101321816498019101823012168469706240238546733430563115610529101897377344839733586268940478469960836347004487048570855680122137578043206023975369775048480356517721340390187833972378623137126307547351741242129046523455257536374422351385724837117101473491922399552018441281779378146120832426011456202350251737089 +940548665568669306251536958381014295015885376199692270773634051571468443177252576492255360423853770864325258737964248491672738005473375204458692172487804734089712687353813343670064744128701098573532877590228667667008286737596697852387981631862326481177071413971930746756905828624662822957794948866823607625220615269013165228239618537011536940291208905424160713389821033135818514340985521905976691408942139437741483410228329038000371498590009406379772049151623867582176028814687068466685902099735918960489164147117893952824903803155286426295341357243145288763878804327513759861599032840758403923281677647872 +375828023454801161958069925084019843923978286415518836749560060086790811063826786575473978319828101315166509670501153778395493519601305062611233710167108096659872687219140685926605165995932330503576533938874126310080807833945025154398047371417183906188778761688181994841114264769649793185124682348180893134333861320517448227288705530984286877458322203246948912271425933606164725949285658013879720265044644617847420446340162585011712000860105735035610334678196167563897824599954042423669530327316471628496333180947012248953569457951187522058076800530227428892238847959130402967459985851634689104636645635632818315245484817355205865998912643567216769076790812429039605288671959330499956935814269560500882854907846825228822521982049802574527070231420993536 +1230231922161117176931558813276752514640713895736833715766118029160058800614672948775360067838593459582429640872806815375600524611787633664372109038831131496892713847574204213375769343685580784773753635629758429922695406379579200240048301333922009856375733053746023334939149959900017297080529761791881121040475796858581600002403295404329868081465157652227751491087455277833629681152969524186808613504119583496193428420962898057357571055319374451607243028930569896539578660288198289657864101794216603970753824498208473733314597712660353208543367490975176753797670373382265859509054611517991409426349053031299407068631581080918639237312826090371923206219034977458927000306459751555164292071452400788382130601457910261333218639691866553206384714007138038691594287732934081410852761487999922797074320518605005374647219205312884015226747835223983423030251792941745800299484458323597491553884981698082835005441 diff --git a/evm/src/cpu/kernel/tests/bignum/test_data/shr_outputs b/evm/src/cpu/kernel/tests/bignum/test_data/shr_outputs new file mode 100644 index 00000000..e332af07 --- /dev/null +++ b/evm/src/cpu/kernel/tests/bignum/test_data/shr_outputs @@ -0,0 +1,15 @@ +0 +0 +10 +454 +633825298933523088827032272896 +170141183460469231731687303715884105727 +28948022309329048805675932369078530852631180780748809681045552446266006306816 +57896044618552785420117126879588554932077822571392166330260246162741804400640 +115791868408393044742463613008073883964789486131810247488688942285685300133887 +1636695303948070935006594848413799576108321023021532394741124202838125269764252555345402245353723668914435295328046362723087481814795090573542499024896 +2513963986864618028991213182224413308777819256816535800816685110210983818153373249015128547242150483479351682036176314425689224093547436995163496743174143 +6703903964971298549787012498933692735729379268964506370005391335664810416197917496264067057493203831336410710214053614378008173083437096682896442345390079 +13407807929942597099574024997867385471458758537929021698989751382546463062164957266305246601567593132153050553942622049229933835926543769603009459693551616 +5357543035931336009935361854186783933582024798567443984714671278144844546164446516476690789794669156301304623141706357119262681463344458016495802047428300170461025099293556031784389419661593571910118771797103228609036661178441218478227329403670559381682003857179616029683126706529221259939514687684608 +17537331055217019373813793980140428996762007940165414412037899012395481925281661101828540443292484630826575143659117691466180993189100488465242932412309241595039655786221608280976022359738682853284026484775740881283776485471294905189441462979676884558842493596567904678782738626435494445302790530494154545900458865343860245519486484115385763209447653125595848934876247827731869417098845586487640674418233066193999127785876419158080528284465214978523135 diff --git a/evm/src/cpu/kernel/tests/bignum/test_data/u128_inputs b/evm/src/cpu/kernel/tests/bignum/test_data/u128_inputs new file mode 100644 index 00000000..ca67d6e7 --- /dev/null +++ b/evm/src/cpu/kernel/tests/bignum/test_data/u128_inputs @@ -0,0 +1,6 @@ +0 +1 +21 +908 +1267650597867046177654064545792 +340282366920938463463374607431768211455 From fda64475bb3136b1c073c97ddca1f8dd25aebe61 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Thu, 16 Mar 2023 11:20:59 -0700 Subject: [PATCH 083/121] fmt --- evm/src/cpu/kernel/tests/bignum/mod.rs | 95 ++++++++++++++++++-------- 1 file changed, 65 insertions(+), 30 deletions(-) diff --git a/evm/src/cpu/kernel/tests/bignum/mod.rs b/evm/src/cpu/kernel/tests/bignum/mod.rs index 687347a5..b504c9b0 100644 --- a/evm/src/cpu/kernel/tests/bignum/mod.rs +++ b/evm/src/cpu/kernel/tests/bignum/mod.rs @@ -1,5 +1,5 @@ use std::fs::File; -use std::io::{BufReader, BufRead}; +use std::io::{BufRead, BufReader}; use std::path::PathBuf; use anyhow::Result; @@ -38,19 +38,25 @@ fn full_path(filename: &str) -> PathBuf { fn test_data(filename: &str) -> Vec { let file = File::open(full_path(filename)).unwrap(); let lines = BufReader::new(file).lines(); - lines.map(|line| BigUint::parse_bytes(&line.unwrap().as_bytes(), 10).unwrap()).collect() + lines + .map(|line| BigUint::parse_bytes(&line.unwrap().as_bytes(), 10).unwrap()) + .collect() } fn test_data_u128(filename: &str) -> Vec { let file = File::open(full_path(filename)).unwrap(); let lines = BufReader::new(file).lines(); - lines.map(|line| line.unwrap().parse::().unwrap()).collect() + lines + .map(|line| line.unwrap().parse::().unwrap()) + .collect() } fn test_data_u256(filename: &str) -> Vec { let file = File::open(full_path(filename)).unwrap(); let lines = BufReader::new(file).lines(); - lines.map(|line| U256::from_dec_str(&line.unwrap()).unwrap()).collect() + lines + .map(|line| U256::from_dec_str(&line.unwrap()).unwrap()) + .collect() } // Convert each biguint to a vector of bignum limbs, pad to the given length, and concatenate. @@ -95,27 +101,33 @@ fn run_test(fn_label: &str, memory: Vec, stack: Vec) -> Result<(Vec< Ok((new_memory, interpreter.stack().to_vec())) } -fn test_shr_bignum(input: BigUint, expected_output: BigUint) -> Result<()> -{ +fn test_shr_bignum(input: BigUint, expected_output: BigUint) -> Result<()> { let len = bignum_len(&input); let memory = biguint_to_mem_vec(input.clone()); - - let input_start_loc = 0; - let (new_memory, _new_stack) = run_test("shr_bignum", memory, vec![len.into(), input_start_loc.into()])?; - let output = mem_vec_to_biguint(&new_memory[input_start_loc..input_start_loc+len]); + let input_start_loc = 0; + let (new_memory, _new_stack) = run_test( + "shr_bignum", + memory, + vec![len.into(), input_start_loc.into()], + )?; + + let output = mem_vec_to_biguint(&new_memory[input_start_loc..input_start_loc + len]); assert_eq!(output, expected_output); Ok(()) } -fn test_iszero_bignum(input: BigUint, expected_output: U256) -> Result<()> -{ +fn test_iszero_bignum(input: BigUint, expected_output: U256) -> Result<()> { let len = bignum_len(&input); let memory = biguint_to_mem_vec(input.clone()); - + let input_start_loc = 0; - let (_new_memory, new_stack) = run_test("iszero_bignum", memory, vec![len.into(), input_start_loc.into()])?; + let (_new_memory, new_stack) = run_test( + "iszero_bignum", + memory, + vec![len.into(), input_start_loc.into()], + )?; let output = new_stack[0]; assert_eq!(output, expected_output); @@ -123,14 +135,17 @@ fn test_iszero_bignum(input: BigUint, expected_output: U256) -> Result<()> Ok(()) } -fn test_cmp_bignum(a: BigUint, b: BigUint, expected_output: U256) -> Result<()> -{ +fn test_cmp_bignum(a: BigUint, b: BigUint, expected_output: U256) -> Result<()> { let len = bignum_len(&a).max(bignum_len(&b)); let memory = pad_bignums(&[a.clone(), b.clone()], len); let a_start_loc = 0; let b_start_loc = len; - let (_new_memory, new_stack) = run_test("cmp_bignum", memory, vec![len.into(), a_start_loc.into(), b_start_loc.into()])?; + let (_new_memory, new_stack) = run_test( + "cmp_bignum", + memory, + vec![len.into(), a_start_loc.into(), b_start_loc.into()], + )?; let output = new_stack[0]; assert_eq!(output, expected_output); @@ -138,49 +153,54 @@ fn test_cmp_bignum(a: BigUint, b: BigUint, expected_output: U256) -> Result<()> Ok(()) } -fn test_add_bignum(a: BigUint, b: BigUint, expected_output: BigUint) -> Result<()> -{ +fn test_add_bignum(a: BigUint, b: BigUint, expected_output: BigUint) -> Result<()> { let len = bignum_len(&a).max(bignum_len(&b)); let memory = pad_bignums(&[a.clone(), b.clone()], len); let a_start_loc = 0; let b_start_loc = len; - let (mut new_memory, new_stack) = run_test("add_bignum", memory, vec![len.into(), a_start_loc.into(), b_start_loc.into()])?; + let (mut new_memory, new_stack) = run_test( + "add_bignum", + memory, + vec![len.into(), a_start_loc.into(), b_start_loc.into()], + )?; // Determine actual sum, appending the final carry if nonzero. let carry_limb = new_stack[0]; if carry_limb > 0.into() { new_memory[len] = carry_limb; } - let output = mem_vec_to_biguint(&new_memory[a_start_loc..a_start_loc+len]); + let output = mem_vec_to_biguint(&new_memory[a_start_loc..a_start_loc + len]); assert_eq!(output, expected_output); Ok(()) } -fn test_addmul_bignum(a: BigUint, b: BigUint, c: u128, expected_output: BigUint) -> Result<()> -{ +fn test_addmul_bignum(a: BigUint, b: BigUint, c: u128, expected_output: BigUint) -> Result<()> { let len = bignum_len(&a).max(bignum_len(&b)); let mut memory = pad_bignums(&[a.clone(), b.clone()], len); memory.splice(len..len, vec![0.into(); 2].iter().cloned()); let a_start_loc = 0; let b_start_loc = len + 2; - let (mut new_memory, new_stack) = run_test("addmul_bignum", memory, vec![len.into(), a_start_loc.into(), b_start_loc.into(), c.into()])?; + let (mut new_memory, new_stack) = run_test( + "addmul_bignum", + memory, + vec![len.into(), a_start_loc.into(), b_start_loc.into(), c.into()], + )?; // Determine actual sum, appending the final carry if nonzero. let carry_limb = new_stack[0]; if carry_limb > 0.into() { new_memory[len] = carry_limb; } - let output = mem_vec_to_biguint(&new_memory[a_start_loc..a_start_loc+len]); + let output = mem_vec_to_biguint(&new_memory[a_start_loc..a_start_loc + len]); assert_eq!(output, expected_output); Ok(()) } -fn test_mul_bignum(a: BigUint, b: BigUint, expected_output: BigUint) -> Result<()> -{ +fn test_mul_bignum(a: BigUint, b: BigUint, expected_output: BigUint) -> Result<()> { let len = bignum_len(&a).max(bignum_len(&b)); let output_len = len * 2; let memory = pad_bignums(&[a.clone(), b.clone()], len); @@ -188,9 +208,18 @@ fn test_mul_bignum(a: BigUint, b: BigUint, expected_output: BigUint) -> Result<( let a_start_loc = 0; let b_start_loc = len; let output_start_loc = 2 * len; - let (new_memory, _new_stack) = run_test("mul_bignum", memory, vec![len.into(), a_start_loc.into(), b_start_loc.into(), output_start_loc.into()])?; + let (new_memory, _new_stack) = run_test( + "mul_bignum", + memory, + vec![ + len.into(), + a_start_loc.into(), + b_start_loc.into(), + output_start_loc.into(), + ], + )?; - let output = mem_vec_to_biguint(&new_memory[output_start_loc..output_start_loc+output_len]); + let output = mem_vec_to_biguint(&new_memory[output_start_loc..output_start_loc + output_len]); assert_eq!(output, expected_output); Ok(()) @@ -245,7 +274,13 @@ fn test_cmp_bignum_all() -> Result<()> { for bit_size in BIT_SIZES_TO_TEST { let a = gen_bignum(bit_size); let b = gen_bignum(bit_size); - let output = if a < b { MINUS_ONE } else if a == b { 0.into() } else { 1.into() }; + let output = if a < b { + MINUS_ONE + } else if a == b { + 0.into() + } else { + 1.into() + }; test_cmp_bignum(a, b, output)?; let a = max_bignum(bit_size); From e0a4bc31577f4004a75392940959072731b3954e Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Thu, 16 Mar 2023 11:21:30 -0700 Subject: [PATCH 084/121] cleanup --- evm/src/cpu/kernel/tests/bignum/mod.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/evm/src/cpu/kernel/tests/bignum/mod.rs b/evm/src/cpu/kernel/tests/bignum/mod.rs index b504c9b0..b9f1d22e 100644 --- a/evm/src/cpu/kernel/tests/bignum/mod.rs +++ b/evm/src/cpu/kernel/tests/bignum/mod.rs @@ -39,7 +39,7 @@ fn test_data(filename: &str) -> Vec { let file = File::open(full_path(filename)).unwrap(); let lines = BufReader::new(file).lines(); lines - .map(|line| BigUint::parse_bytes(&line.unwrap().as_bytes(), 10).unwrap()) + .map(|line| BigUint::parse_bytes(line.unwrap().as_bytes(), 10).unwrap()) .collect() } @@ -103,7 +103,7 @@ fn run_test(fn_label: &str, memory: Vec, stack: Vec) -> Result<(Vec< fn test_shr_bignum(input: BigUint, expected_output: BigUint) -> Result<()> { let len = bignum_len(&input); - let memory = biguint_to_mem_vec(input.clone()); + let memory = biguint_to_mem_vec(input); let input_start_loc = 0; let (new_memory, _new_stack) = run_test( @@ -120,7 +120,7 @@ fn test_shr_bignum(input: BigUint, expected_output: BigUint) -> Result<()> { fn test_iszero_bignum(input: BigUint, expected_output: U256) -> Result<()> { let len = bignum_len(&input); - let memory = biguint_to_mem_vec(input.clone()); + let memory = biguint_to_mem_vec(input); let input_start_loc = 0; let (_new_memory, new_stack) = run_test( @@ -137,7 +137,7 @@ fn test_iszero_bignum(input: BigUint, expected_output: U256) -> Result<()> { fn test_cmp_bignum(a: BigUint, b: BigUint, expected_output: U256) -> Result<()> { let len = bignum_len(&a).max(bignum_len(&b)); - let memory = pad_bignums(&[a.clone(), b.clone()], len); + let memory = pad_bignums(&[a, b], len); let a_start_loc = 0; let b_start_loc = len; @@ -155,7 +155,7 @@ fn test_cmp_bignum(a: BigUint, b: BigUint, expected_output: U256) -> Result<()> fn test_add_bignum(a: BigUint, b: BigUint, expected_output: BigUint) -> Result<()> { let len = bignum_len(&a).max(bignum_len(&b)); - let memory = pad_bignums(&[a.clone(), b.clone()], len); + let memory = pad_bignums(&[a, b], len); let a_start_loc = 0; let b_start_loc = len; @@ -178,7 +178,7 @@ fn test_add_bignum(a: BigUint, b: BigUint, expected_output: BigUint) -> Result<( fn test_addmul_bignum(a: BigUint, b: BigUint, c: u128, expected_output: BigUint) -> Result<()> { let len = bignum_len(&a).max(bignum_len(&b)); - let mut memory = pad_bignums(&[a.clone(), b.clone()], len); + let mut memory = pad_bignums(&[a, b], len); memory.splice(len..len, vec![0.into(); 2].iter().cloned()); let a_start_loc = 0; @@ -203,7 +203,7 @@ fn test_addmul_bignum(a: BigUint, b: BigUint, c: u128, expected_output: BigUint) fn test_mul_bignum(a: BigUint, b: BigUint, expected_output: BigUint) -> Result<()> { let len = bignum_len(&a).max(bignum_len(&b)); let output_len = len * 2; - let memory = pad_bignums(&[a.clone(), b.clone()], len); + let memory = pad_bignums(&[a, b], len); let a_start_loc = 0; let b_start_loc = len; From 062eb82a8b185c4d4bd64bac536cf95d093ac243 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Thu, 16 Mar 2023 11:28:56 -0700 Subject: [PATCH 085/121] cleanup --- evm/src/cpu/kernel/tests/bignum/mod.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/evm/src/cpu/kernel/tests/bignum/mod.rs b/evm/src/cpu/kernel/tests/bignum/mod.rs index b9f1d22e..26c6d8b1 100644 --- a/evm/src/cpu/kernel/tests/bignum/mod.rs +++ b/evm/src/cpu/kernel/tests/bignum/mod.rs @@ -274,12 +274,10 @@ fn test_cmp_bignum_all() -> Result<()> { for bit_size in BIT_SIZES_TO_TEST { let a = gen_bignum(bit_size); let b = gen_bignum(bit_size); - let output = if a < b { - MINUS_ONE - } else if a == b { - 0.into() - } else { - 1.into() + let output = match a.cmp(&b) { + Ordering::Less => U256::MINUS_ONE, + Ordering::Equal => 0.into(), + Ordering::Greater => 1.into(), }; test_cmp_bignum(a, b, output)?; From f1ad3da8ebf56cff9d62da24eb960f6083390864 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Thu, 16 Mar 2023 11:29:37 -0700 Subject: [PATCH 086/121] fix --- evm/src/cpu/kernel/tests/bignum/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/evm/src/cpu/kernel/tests/bignum/mod.rs b/evm/src/cpu/kernel/tests/bignum/mod.rs index 26c6d8b1..67240d70 100644 --- a/evm/src/cpu/kernel/tests/bignum/mod.rs +++ b/evm/src/cpu/kernel/tests/bignum/mod.rs @@ -1,3 +1,4 @@ +use std::cmp::Ordering; use std::fs::File; use std::io::{BufRead, BufReader}; use std::path::PathBuf; @@ -275,7 +276,7 @@ fn test_cmp_bignum_all() -> Result<()> { let a = gen_bignum(bit_size); let b = gen_bignum(bit_size); let output = match a.cmp(&b) { - Ordering::Less => U256::MINUS_ONE, + Ordering::Less => MINUS_ONE, Ordering::Equal => 0.into(), Ordering::Greater => 1.into(), }; From b62bc35d646d0d64050e4cc66d4eeb1e2f8117c9 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Thu, 16 Mar 2023 11:39:19 -0700 Subject: [PATCH 087/121] fixes --- evm/src/cpu/kernel/asm/bignum/cmp.asm | 5 +++++ evm/src/cpu/kernel/tests/bignum/mod.rs | 4 +++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/evm/src/cpu/kernel/asm/bignum/cmp.asm b/evm/src/cpu/kernel/asm/bignum/cmp.asm index ff8fb3e6..840fceff 100644 --- a/evm/src/cpu/kernel/asm/bignum/cmp.asm +++ b/evm/src/cpu/kernel/asm/bignum/cmp.asm @@ -4,6 +4,11 @@ // Compares two bignums of the same given length. Assumes that len > 0. // Returns 1 if a > b, 0 if a == b, and -1 (that is, 2^256 - 1) if a < b. global cmp_bignum: + // stack: len, a_start_loc, b_start_loc, retdest + DUP1 + // stack: len, len, a_start_loc, b_start_loc, retdest + ISZERO + %jumpi(equal) // stack: len, a_start_loc, b_start_loc, retdest SWAP1 // stack: a_start_loc, len, b_start_loc, retdest diff --git a/evm/src/cpu/kernel/tests/bignum/mod.rs b/evm/src/cpu/kernel/tests/bignum/mod.rs index 67240d70..12772db7 100644 --- a/evm/src/cpu/kernel/tests/bignum/mod.rs +++ b/evm/src/cpu/kernel/tests/bignum/mod.rs @@ -171,7 +171,9 @@ fn test_add_bignum(a: BigUint, b: BigUint, expected_output: BigUint) -> Result<( if carry_limb > 0.into() { new_memory[len] = carry_limb; } - let output = mem_vec_to_biguint(&new_memory[a_start_loc..a_start_loc + len]); + + let expected_output = biguint_to_mem_vec(expected_output); + let output = &new_memory[a_start_loc..a_start_loc + expected_output.len()]; assert_eq!(output, expected_output); Ok(()) From c59b979cdf8351a2ce01597a627bcb44a75f32b3 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Thu, 16 Mar 2023 11:42:39 -0700 Subject: [PATCH 088/121] addmul fix --- evm/src/cpu/kernel/tests/bignum/mod.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/evm/src/cpu/kernel/tests/bignum/mod.rs b/evm/src/cpu/kernel/tests/bignum/mod.rs index 12772db7..14de0945 100644 --- a/evm/src/cpu/kernel/tests/bignum/mod.rs +++ b/evm/src/cpu/kernel/tests/bignum/mod.rs @@ -197,7 +197,9 @@ fn test_addmul_bignum(a: BigUint, b: BigUint, c: u128, expected_output: BigUint) if carry_limb > 0.into() { new_memory[len] = carry_limb; } - let output = mem_vec_to_biguint(&new_memory[a_start_loc..a_start_loc + len]); + + let expected_output = biguint_to_mem_vec(expected_output); + let output = &new_memory[a_start_loc..a_start_loc + expected_output.len()]; assert_eq!(output, expected_output); Ok(()) From cecbfa9b591ef2a797a5df04f2ac5e2c145085ba Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Thu, 16 Mar 2023 11:46:01 -0700 Subject: [PATCH 089/121] fit --- evm/src/cpu/kernel/tests/bignum/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/evm/src/cpu/kernel/tests/bignum/mod.rs b/evm/src/cpu/kernel/tests/bignum/mod.rs index 14de0945..a83a063c 100644 --- a/evm/src/cpu/kernel/tests/bignum/mod.rs +++ b/evm/src/cpu/kernel/tests/bignum/mod.rs @@ -171,7 +171,7 @@ fn test_add_bignum(a: BigUint, b: BigUint, expected_output: BigUint) -> Result<( if carry_limb > 0.into() { new_memory[len] = carry_limb; } - + let expected_output = biguint_to_mem_vec(expected_output); let output = &new_memory[a_start_loc..a_start_loc + expected_output.len()]; assert_eq!(output, expected_output); @@ -197,7 +197,7 @@ fn test_addmul_bignum(a: BigUint, b: BigUint, c: u128, expected_output: BigUint) if carry_limb > 0.into() { new_memory[len] = carry_limb; } - + let expected_output = biguint_to_mem_vec(expected_output); let output = &new_memory[a_start_loc..a_start_loc + expected_output.len()]; assert_eq!(output, expected_output); From 9534762179f17a30bcd7cbc0c9030190b273ddb4 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Thu, 16 Mar 2023 11:56:39 -0700 Subject: [PATCH 090/121] div instead of shr --- evm/src/cpu/kernel/asm/hash/sha2/main.asm | 2 +- evm/src/cpu/kernel/asm/hash/sha2/ops.asm | 2 +- evm/src/cpu/kernel/asm/hash/sha2/write_length.asm | 14 +++++++------- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/evm/src/cpu/kernel/asm/hash/sha2/main.asm b/evm/src/cpu/kernel/asm/hash/sha2/main.asm index e47d1838..1deab294 100644 --- a/evm/src/cpu/kernel/asm/hash/sha2/main.asm +++ b/evm/src/cpu/kernel/asm/hash/sha2/main.asm @@ -31,7 +31,7 @@ global sha2_pad: DUP1 // stack: num_bytes, num_bytes, retdest %add_const(8) - %shr_const(6) + %div_const(64) %increment // stack: num_blocks = (num_bytes+8)//64 + 1, num_bytes, retdest diff --git a/evm/src/cpu/kernel/asm/hash/sha2/ops.asm b/evm/src/cpu/kernel/asm/hash/sha2/ops.asm index d50e5c9a..6a4c5e3b 100644 --- a/evm/src/cpu/kernel/asm/hash/sha2/ops.asm +++ b/evm/src/cpu/kernel/asm/hash/sha2/ops.asm @@ -34,7 +34,7 @@ // stack: rotr(x, 18), x, rotr(x, 7) SWAP1 // stack: x, rotr(x, 18), rotr(x, 7) - %shr_const(3) + %div_const(8) // equivalent to %shr_const(3) // stack: shr(x, 3), rotr(x, 18), rotr(x, 7) XOR XOR diff --git a/evm/src/cpu/kernel/asm/hash/sha2/write_length.asm b/evm/src/cpu/kernel/asm/hash/sha2/write_length.asm index 5727498c..bb7a01a8 100644 --- a/evm/src/cpu/kernel/asm/hash/sha2/write_length.asm +++ b/evm/src/cpu/kernel/asm/hash/sha2/write_length.asm @@ -15,7 +15,7 @@ %decrement SWAP1 // stack: length, last_addr - 1 - %shr_const(8) + %div_const(256) // equivalent to %shr_const(8) // stack: length >> 8, last_addr - 1 DUP1 // stack: length >> 8, length >> 8, last_addr - 1 @@ -30,7 +30,7 @@ %decrement SWAP1 // stack: length >> 8, last_addr - 2 - %shr_const(8) + %div_const(256) // equivalent to %shr_const(8) // stack: length >> 16, last_addr - 2 DUP1 // stack: length >> 16, length >> 16, last_addr - 2 @@ -45,7 +45,7 @@ %decrement SWAP1 // stack: length >> 16, last_addr - 3 - %shr_const(8) + %div_const(256) // equivalent to %shr_const(8) // stack: length >> 24, last_addr - 3 DUP1 // stack: length >> 24, length >> 24, last_addr - 3 @@ -60,7 +60,7 @@ %decrement SWAP1 // stack: length >> 24, last_addr - 4 - %shr_const(8) + %div_const(256) // equivalent to %shr_const(8) // stack: length >> 32, last_addr - 4 DUP1 // stack: length >> 32, length >> 32, last_addr - 4 @@ -75,7 +75,7 @@ %decrement SWAP1 // stack: length >> 32, last_addr - 5 - %shr_const(8) + %div_const(256) // equivalent to %shr_const(8) // stack: length >> 40, last_addr - 5 DUP1 // stack: length >> 40, length >> 40, last_addr - 5 @@ -90,7 +90,7 @@ %decrement SWAP1 // stack: length >> 40, last_addr - 6 - %shr_const(8) + %div_const(256) // equivalent to %shr_const(8) // stack: length >> 48, last_addr - 6 DUP1 // stack: length >> 48, length >> 48, last_addr - 6 @@ -105,7 +105,7 @@ %decrement SWAP1 // stack: length >> 48, last_addr - 7 - %shr_const(8) + %div_const(256) // equivalent to %shr_const(8) // stack: length >> 56, last_addr - 7 DUP1 // stack: length >> 56, length >> 56, last_addr - 7 From c8d591f6da8e9281e2ba6f976e418804496808c0 Mon Sep 17 00:00:00 2001 From: Daniel Lubarov Date: Thu, 16 Mar 2023 13:32:34 -0700 Subject: [PATCH 091/121] Add a `prove_with_outputs` method Which returns information about the post-state after execution. This is useful for debugging purposes. --- .../cpu/kernel/asm/core/create_addresses.asm | 19 ++++ evm/src/generation/mod.rs | 35 +++---- evm/src/generation/outputs.rs | 99 +++++++++++++++++++ evm/src/generation/state.rs | 32 +++++- evm/src/generation/trie_extractor.rs | 50 +++++----- evm/src/prover.rs | 28 +++++- evm/src/witness/memory.rs | 9 ++ evm/src/witness/operation.rs | 4 +- 8 files changed, 223 insertions(+), 53 deletions(-) create mode 100644 evm/src/generation/outputs.rs diff --git a/evm/src/cpu/kernel/asm/core/create_addresses.asm b/evm/src/cpu/kernel/asm/core/create_addresses.asm index 2d94ee94..67fd65a6 100644 --- a/evm/src/cpu/kernel/asm/core/create_addresses.asm +++ b/evm/src/cpu/kernel/asm/core/create_addresses.asm @@ -8,6 +8,8 @@ global get_create_address: // TODO: Replace with actual implementation. %pop2 PUSH 123 + // stack: address, retdest + %observe_new_address SWAP1 JUMP @@ -21,5 +23,22 @@ global get_create2_address: // TODO: Replace with actual implementation. %pop3 PUSH 123 + // stack: address, retdest + %observe_new_address SWAP1 JUMP + +// This should be called whenever a new address is created. This is only for debugging. It does +// nothing, but just provides a single hook where code can react to newly created addresses. +global observe_new_address: + // stack: address, retdest + SWAP1 + // stack: retdest, address + JUMP + +// Convenience macro to call observe_new_address and return where we left off. +%macro observe_new_address + %stack (address) -> (address, %%after) + %jump(observe_new_address) +%%after: +%endmacro diff --git a/evm/src/generation/mod.rs b/evm/src/generation/mod.rs index c01e8af1..63da3d1c 100644 --- a/evm/src/generation/mod.rs +++ b/evm/src/generation/mod.rs @@ -18,25 +18,24 @@ use crate::config::StarkConfig; use crate::cpu::bootstrap_kernel::generate_bootstrap_kernel; use crate::cpu::kernel::aggregator::KERNEL; use crate::cpu::kernel::constants::global_metadata::GlobalMetadata; -use crate::cpu::kernel::constants::global_metadata::GlobalMetadata::StateTrieRoot; -use crate::generation::mpt::AccountRlp; +use crate::generation::outputs::{get_outputs, GenerationOutputs}; use crate::generation::state::GenerationState; -use crate::generation::trie_extractor::read_state_trie_value; use crate::memory::segments::Segment; use crate::proof::{BlockMetadata, PublicValues, TrieRoots}; use crate::witness::memory::{MemoryAddress, MemoryChannel}; use crate::witness::transition::transition; pub mod mpt; +pub mod outputs; pub(crate) mod prover_input; pub(crate) mod rlp; pub(crate) mod state; mod trie_extractor; -use crate::generation::trie_extractor::read_trie; + use crate::witness::util::mem_write_log; -#[derive(Clone, Debug, Deserialize, Serialize, Default)] /// Inputs needed for trace generation. +#[derive(Clone, Debug, Deserialize, Serialize, Default)] pub struct GenerationInputs { pub signed_txns: Vec>, @@ -104,7 +103,11 @@ pub(crate) fn generate_traces, const D: usize>( inputs: GenerationInputs, config: &StarkConfig, timing: &mut TimingTree, -) -> anyhow::Result<([Vec>; NUM_TABLES], PublicValues)> { +) -> anyhow::Result<( + [Vec>; NUM_TABLES], + PublicValues, + GenerationOutputs, +)> { let mut state = GenerationState::::new(inputs.clone(), &KERNEL.code); apply_metadata_memops(&mut state, &inputs.block_metadata); @@ -118,23 +121,9 @@ pub(crate) fn generate_traces, const D: usize>( state.traces.checkpoint() ); - let read_metadata = |field| { - state.memory.get(MemoryAddress::new( - 0, - Segment::GlobalMetadata, - field as usize, - )) - }; - - log::debug!( - "Updated state trie:\n{:#?}", - read_trie::( - &state.memory, - read_metadata(StateTrieRoot).as_usize(), - read_state_trie_value - ) - ); + let outputs = get_outputs(&mut state); + let read_metadata = |field| state.memory.read_global_metadata(field); let trie_roots_before = TrieRoots { state_root: H256::from_uint(&read_metadata(StateTrieRootDigestBefore)), transactions_root: H256::from_uint(&read_metadata(TransactionTrieRootDigestBefore)), @@ -157,7 +146,7 @@ pub(crate) fn generate_traces, const D: usize>( "convert trace data to tables", state.traces.into_tables(all_stark, config, timing) ); - Ok((tables, public_values)) + Ok((tables, public_values, outputs)) } fn simulate_cpu, const D: usize>( diff --git a/evm/src/generation/outputs.rs b/evm/src/generation/outputs.rs new file mode 100644 index 00000000..a7e1a3f4 --- /dev/null +++ b/evm/src/generation/outputs.rs @@ -0,0 +1,99 @@ +use std::collections::HashMap; + +use ethereum_types::{Address, BigEndianHash, H256, U256}; +use plonky2::field::types::Field; + +use crate::cpu::kernel::constants::global_metadata::GlobalMetadata::StateTrieRoot; +use crate::generation::state::GenerationState; +use crate::generation::trie_extractor::{ + read_state_trie_value, read_storage_trie_value, read_trie, AccountTrieRecord, +}; + +/// The post-state after trace generation; intended for debugging. +#[derive(Clone, Debug)] +pub struct GenerationOutputs { + pub accounts: HashMap, +} + +#[derive(Clone, Eq, PartialEq, Hash, Debug)] +pub enum AddressOrStateKey { + Address(Address), + StateKey(H256), +} + +#[derive(Clone, Debug)] +pub struct AccountOutput { + pub balance: U256, + pub nonce: u64, + pub code: Vec, + pub storage: HashMap, +} + +pub(crate) fn get_outputs(state: &mut GenerationState) -> GenerationOutputs { + let account_map = read_trie::( + &state.memory, + state.memory.read_global_metadata(StateTrieRoot).as_usize(), + read_state_trie_value, + ); + + let accounts = account_map + .into_iter() + .map(|(state_key_nibbles, account)| { + assert_eq!( + state_key_nibbles.count, 64, + "Each state key should have 64 nibbles = 256 bits" + ); + let state_key_h256 = H256::from_uint(&state_key_nibbles.packed); + + let addr_or_state_key = + if let Some(address) = state.state_key_to_address.get(&state_key_h256) { + AddressOrStateKey::Address(*address) + } else { + AddressOrStateKey::StateKey(state_key_h256) + }; + + let account_output = account_trie_record_to_output(state, account); + (addr_or_state_key, account_output) + }) + .collect(); + + GenerationOutputs { accounts } +} + +fn account_trie_record_to_output( + state: &GenerationState, + account: AccountTrieRecord, +) -> AccountOutput { + let storage = get_storage(state, account.storage_ptr); + + // TODO: This won't work if the account was created during the txn. + // Need to track changes to code, similar to how we track addresses + // with observe_new_address. + let code = state + .inputs + .contract_code + .get(&account.code_hash) + .expect("Code not found") + .clone(); + + AccountOutput { + balance: account.balance, + nonce: account.nonce, + storage, + code, + } +} + +/// Get an account's storage trie, given a pointer to its root. +fn get_storage(state: &GenerationState, storage_ptr: usize) -> HashMap { + read_trie::(&state.memory, storage_ptr, read_storage_trie_value) + .into_iter() + .map(|(storage_key_nibbles, value)| { + assert_eq!( + storage_key_nibbles.count, 64, + "Each storage key should have 64 nibbles = 256 bits" + ); + (storage_key_nibbles.packed, value) + }) + .collect() +} diff --git a/evm/src/generation/state.rs b/evm/src/generation/state.rs index 88f17ade..95de3279 100644 --- a/evm/src/generation/state.rs +++ b/evm/src/generation/state.rs @@ -1,12 +1,17 @@ -use ethereum_types::U256; +use std::collections::HashMap; + +use ethereum_types::{Address, H160, H256, U256}; +use keccak_hash::keccak; use plonky2::field::types::Field; +use crate::cpu::kernel::aggregator::KERNEL; use crate::generation::mpt::all_mpt_prover_inputs_reversed; use crate::generation::rlp::all_rlp_prover_inputs_reversed; use crate::generation::GenerationInputs; use crate::witness::memory::MemoryState; use crate::witness::state::RegistersState; use crate::witness::traces::{TraceCheckpoint, Traces}; +use crate::witness::util::stack_peek; pub(crate) struct GenerationStateCheckpoint { pub(crate) registers: RegistersState, @@ -29,6 +34,11 @@ pub(crate) struct GenerationState { /// Prover inputs containing RLP data, in reverse order so that the next input can be obtained /// via `pop()`. pub(crate) rlp_prover_inputs: Vec, + + /// The state trie only stores state keys, which are hashes of addresses, but sometimes it is + /// useful to see the actual addresses for debugging. Here we store the mapping for all known + /// addresses. + pub(crate) state_key_to_address: HashMap, } impl GenerationState { @@ -53,9 +63,29 @@ impl GenerationState { next_txn_index: 0, mpt_prover_inputs, rlp_prover_inputs, + state_key_to_address: HashMap::new(), } } + /// Updates `program_counter`, and potentially adds some extra handling if we're jumping to a + /// special location. + pub fn jump_to(&mut self, dst: usize) { + self.registers.program_counter = dst; + if dst == KERNEL.global_labels["observe_new_address"] { + let address = stack_peek(self, 0).expect("Empty stack"); + let mut address_bytes = [0; 20]; + address.to_big_endian(&mut address_bytes); + self.observe_address(H160(address_bytes)); + } + } + + /// Observe the given address, so that we will be able to recognize the associated state key. + /// This is just for debugging purposes. + pub fn observe_address(&mut self, address: Address) { + let state_key = keccak(address.0); + self.state_key_to_address.insert(state_key, address); + } + pub fn checkpoint(&self) -> GenerationStateCheckpoint { GenerationStateCheckpoint { registers: self.registers, diff --git a/evm/src/generation/trie_extractor.rs b/evm/src/generation/trie_extractor.rs index d35d67eb..a7f01c97 100644 --- a/evm/src/generation/trie_extractor.rs +++ b/evm/src/generation/trie_extractor.rs @@ -1,50 +1,56 @@ +//! Code for extracting trie data after witness generation. This is intended only for debugging. + use std::collections::HashMap; use eth_trie_utils::partial_trie::Nibbles; use ethereum_types::{BigEndianHash, H256, U256}; -use plonky2::field::extension::Extendable; -use plonky2::hash::hash_types::RichField; use crate::cpu::kernel::constants::trie_type::PartialTrieType; -use crate::generation::mpt::AccountRlp; use crate::memory::segments::Segment; use crate::witness::memory::{MemoryAddress, MemoryState}; -pub(crate) fn read_state_trie_value(slice: &[U256]) -> AccountRlp { - AccountRlp { - nonce: slice[0], +/// Account data as it's stored in the state trie, with a pointer to the storage trie. +pub(crate) struct AccountTrieRecord { + pub(crate) nonce: u64, + pub(crate) balance: U256, + pub(crate) storage_ptr: usize, + pub(crate) code_hash: H256, +} + +pub(crate) fn read_state_trie_value(slice: &[U256]) -> AccountTrieRecord { + AccountTrieRecord { + nonce: slice[0].as_u64(), balance: slice[1], - storage_root: H256::from_uint(&slice[2]), + storage_ptr: slice[2].as_usize(), code_hash: H256::from_uint(&slice[3]), } } -pub(crate) fn read_trie( +pub(crate) fn read_storage_trie_value(slice: &[U256]) -> U256 { + slice[0] +} + +pub(crate) fn read_trie( memory: &MemoryState, ptr: usize, read_value: fn(&[U256]) -> V, -) -> HashMap -where - F: RichField + Extendable, -{ +) -> HashMap { let mut res = HashMap::new(); let empty_nibbles = Nibbles { count: 0, packed: U256::zero(), }; - read_trie_helper::(memory, ptr, read_value, empty_nibbles, &mut res); + read_trie_helper::(memory, ptr, read_value, empty_nibbles, &mut res); res } -pub(crate) fn read_trie_helper( +pub(crate) fn read_trie_helper( memory: &MemoryState, ptr: usize, read_value: fn(&[U256]) -> V, prefix: Nibbles, res: &mut HashMap, -) where - F: RichField + Extendable, -{ +) { let load = |offset| memory.get(MemoryAddress::new(0, Segment::TrieData, offset)); let load_slice_from = |init_offset| { &memory.contexts[0].segments[Segment::TrieData as usize].content[init_offset..] @@ -58,13 +64,7 @@ pub(crate) fn read_trie_helper( let ptr_payload = ptr + 1; for i in 0u8..16 { let child_ptr = load(ptr_payload + i as usize).as_usize(); - read_trie_helper::( - memory, - child_ptr, - read_value, - prefix.merge_nibble(i), - res, - ); + read_trie_helper::(memory, child_ptr, read_value, prefix.merge_nibble(i), res); } let value_ptr = load(ptr_payload + 16).as_usize(); if value_ptr != 0 { @@ -76,7 +76,7 @@ pub(crate) fn read_trie_helper( let packed = load(ptr + 2); let nibbles = Nibbles { count, packed }; let child_ptr = load(ptr + 3).as_usize(); - read_trie_helper::( + read_trie_helper::( memory, child_ptr, read_value, diff --git a/evm/src/prover.rs b/evm/src/prover.rs index 9e26218a..97b28a4b 100644 --- a/evm/src/prover.rs +++ b/evm/src/prover.rs @@ -25,6 +25,7 @@ use crate::constraint_consumer::ConstraintConsumer; use crate::cpu::cpu_stark::CpuStark; use crate::cpu::kernel::aggregator::KERNEL; use crate::cross_table_lookup::{cross_table_lookup_data, CtlCheckVars, CtlData}; +use crate::generation::outputs::GenerationOutputs; use crate::generation::{generate_traces, GenerationInputs}; use crate::keccak::keccak_stark::KeccakStark; use crate::keccak_sponge::keccak_sponge_stark::KeccakSpongeStark; @@ -46,6 +47,28 @@ pub fn prove( inputs: GenerationInputs, timing: &mut TimingTree, ) -> Result> +where + F: RichField + Extendable, + C: GenericConfig, + [(); C::Hasher::HASH_SIZE]:, + [(); CpuStark::::COLUMNS]:, + [(); KeccakStark::::COLUMNS]:, + [(); KeccakSpongeStark::::COLUMNS]:, + [(); LogicStark::::COLUMNS]:, + [(); MemoryStark::::COLUMNS]:, +{ + let (proof, _outputs) = prove_with_outputs(all_stark, config, inputs, timing)?; + Ok(proof) +} + +/// Generate traces, then create all STARK proofs. Returns information about the post-state, +/// intended for debugging, in addition to the proof. +pub fn prove_with_outputs( + all_stark: &AllStark, + config: &StarkConfig, + inputs: GenerationInputs, + timing: &mut TimingTree, +) -> Result<(AllProof, GenerationOutputs)> where F: RichField + Extendable, C: GenericConfig, @@ -57,12 +80,13 @@ where [(); MemoryStark::::COLUMNS]:, { timed!(timing, "build kernel", Lazy::force(&KERNEL)); - let (traces, public_values) = timed!( + let (traces, public_values, outputs) = timed!( timing, "generate all traces", generate_traces(all_stark, inputs, config, timing)? ); - prove_with_traces(all_stark, config, traces, public_values, timing) + let proof = prove_with_traces(all_stark, config, traces, public_values, timing)?; + Ok((proof, outputs)) } /// Compute all STARK proofs. diff --git a/evm/src/witness/memory.rs b/evm/src/witness/memory.rs index f42dcaac..a2885796 100644 --- a/evm/src/witness/memory.rs +++ b/evm/src/witness/memory.rs @@ -10,6 +10,7 @@ pub enum MemoryChannel { use MemoryChannel::{Code, GeneralPurpose}; +use crate::cpu::kernel::constants::global_metadata::GlobalMetadata; use crate::memory::segments::Segment; impl MemoryChannel { @@ -173,6 +174,14 @@ impl MemoryState { ); self.contexts[address.context].segments[address.segment].set(address.virt, val); } + + pub(crate) fn read_global_metadata(&self, field: GlobalMetadata) -> U256 { + self.get(MemoryAddress::new( + 0, + Segment::GlobalMetadata, + field as usize, + )) + } } impl Default for MemoryState { diff --git a/evm/src/witness/operation.rs b/evm/src/witness/operation.rs index 3d1dddde..035ce6e2 100644 --- a/evm/src/witness/operation.rs +++ b/evm/src/witness/operation.rs @@ -200,7 +200,7 @@ pub(crate) fn generate_jump( state.traces.push_memory(log_in0); state.traces.push_cpu(row); - state.registers.program_counter = dst as usize; + state.jump_to(dst as usize); Ok(()) } @@ -224,7 +224,7 @@ pub(crate) fn generate_jumpi( let dst: u32 = dst .try_into() .map_err(|_| ProgramError::InvalidJumpiDestination)?; - state.registers.program_counter = dst as usize; + state.jump_to(dst as usize); } else { row.general.jumps_mut().should_jump = F::ZERO; row.general.jumps_mut().cond_sum_pinv = F::ZERO; From 44c77f5583d8a2d6f31ecfaf35748a7955abc428 Mon Sep 17 00:00:00 2001 From: Daniel Lubarov Date: Thu, 16 Mar 2023 14:08:31 -0700 Subject: [PATCH 092/121] Input addresses --- evm/src/generation/mod.rs | 7 +++++++ evm/src/generation/outputs.rs | 5 +++++ evm/tests/basic_smart_contract.rs | 1 + evm/tests/empty_txn_list.rs | 1 + evm/tests/simple_transfer.rs | 1 + 5 files changed, 15 insertions(+) diff --git a/evm/src/generation/mod.rs b/evm/src/generation/mod.rs index 63da3d1c..aa17b9c9 100644 --- a/evm/src/generation/mod.rs +++ b/evm/src/generation/mod.rs @@ -46,6 +46,13 @@ pub struct GenerationInputs { pub contract_code: HashMap>, pub block_metadata: BlockMetadata, + + /// A list of known addresses in the input state trie (which itself doesn't hold addresses, + /// only state keys). This is only useful for debugging, so that we can return addresses in the + /// post-state rather than state keys. (See `GenerationOutputs`, and in particular + /// `AddressOrStateKey`.) If the caller is not interested in the post-state, this can be left + /// empty. + pub addresses: Vec
, } #[derive(Clone, Debug, Deserialize, Serialize, Default)] diff --git a/evm/src/generation/outputs.rs b/evm/src/generation/outputs.rs index a7e1a3f4..a197b1b6 100644 --- a/evm/src/generation/outputs.rs +++ b/evm/src/generation/outputs.rs @@ -30,6 +30,11 @@ pub struct AccountOutput { } pub(crate) fn get_outputs(state: &mut GenerationState) -> GenerationOutputs { + // First observe all addresses passed in the by caller. + for address in state.inputs.addresses.clone() { + state.observe_address(address); + } + let account_map = read_trie::( &state.memory, state.memory.read_global_metadata(StateTrieRoot).as_usize(), diff --git a/evm/tests/basic_smart_contract.rs b/evm/tests/basic_smart_contract.rs index 71d11933..ed326bfd 100644 --- a/evm/tests/basic_smart_contract.rs +++ b/evm/tests/basic_smart_contract.rs @@ -101,6 +101,7 @@ fn test_basic_smart_contract() -> anyhow::Result<()> { tries: tries_before, contract_code, block_metadata, + addresses: vec![], }; let mut timing = TimingTree::new("prove", log::Level::Debug); diff --git a/evm/tests/empty_txn_list.rs b/evm/tests/empty_txn_list.rs index 2bd9a116..19330417 100644 --- a/evm/tests/empty_txn_list.rs +++ b/evm/tests/empty_txn_list.rs @@ -48,6 +48,7 @@ fn test_empty_txn_list() -> anyhow::Result<()> { }, contract_code: HashMap::new(), block_metadata, + addresses: vec![], }; let mut timing = TimingTree::new("prove", log::Level::Debug); diff --git a/evm/tests/simple_transfer.rs b/evm/tests/simple_transfer.rs index 094bc070..d6e1a65f 100644 --- a/evm/tests/simple_transfer.rs +++ b/evm/tests/simple_transfer.rs @@ -75,6 +75,7 @@ fn test_simple_transfer() -> anyhow::Result<()> { tries: tries_before, contract_code: HashMap::new(), block_metadata, + addresses: vec![], }; let mut timing = TimingTree::new("prove", log::Level::Debug); From 373421a1d1d13f714b8ceb369c2e337998195edc Mon Sep 17 00:00:00 2001 From: Daniel Lubarov Date: Thu, 16 Mar 2023 14:11:40 -0700 Subject: [PATCH 093/121] Fix tests - need to supply empty code --- evm/tests/basic_smart_contract.rs | 2 ++ evm/tests/empty_txn_list.rs | 6 +++++- evm/tests/simple_transfer.rs | 5 ++++- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/evm/tests/basic_smart_contract.rs b/evm/tests/basic_smart_contract.rs index ed326bfd..4809ea93 100644 --- a/evm/tests/basic_smart_contract.rs +++ b/evm/tests/basic_smart_contract.rs @@ -95,7 +95,9 @@ fn test_basic_smart_contract() -> anyhow::Result<()> { }; let mut contract_code = HashMap::new(); + contract_code.insert(keccak(vec![]), vec![]); contract_code.insert(code_hash, code.to_vec()); + let inputs = GenerationInputs { signed_txns: vec![txn.to_vec()], tries: tries_before, diff --git a/evm/tests/empty_txn_list.rs b/evm/tests/empty_txn_list.rs index 19330417..a0148e74 100644 --- a/evm/tests/empty_txn_list.rs +++ b/evm/tests/empty_txn_list.rs @@ -3,6 +3,7 @@ use std::time::Duration; use env_logger::{try_init_from_env, Env, DEFAULT_FILTER_ENV}; use eth_trie_utils::partial_trie::PartialTrie; +use keccak_hash::keccak; use plonky2::field::goldilocks_field::GoldilocksField; use plonky2::plonk::config::PoseidonGoldilocksConfig; use plonky2::util::timing::TimingTree; @@ -38,6 +39,9 @@ fn test_empty_txn_list() -> anyhow::Result<()> { let txns_trie_root = transactions_trie.calc_hash(); let receipts_trie_root = receipts_trie.calc_hash(); + let mut contract_code = HashMap::new(); + contract_code.insert(keccak(vec![]), vec![]); + let inputs = GenerationInputs { signed_txns: vec![], tries: TrieInputs { @@ -46,7 +50,7 @@ fn test_empty_txn_list() -> anyhow::Result<()> { receipts_trie, storage_tries, }, - contract_code: HashMap::new(), + contract_code, block_metadata, addresses: vec![], }; diff --git a/evm/tests/simple_transfer.rs b/evm/tests/simple_transfer.rs index d6e1a65f..ff2bed31 100644 --- a/evm/tests/simple_transfer.rs +++ b/evm/tests/simple_transfer.rs @@ -70,10 +70,13 @@ fn test_simple_transfer() -> anyhow::Result<()> { ..BlockMetadata::default() }; + let mut contract_code = HashMap::new(); + contract_code.insert(keccak(vec![]), vec![]); + let inputs = GenerationInputs { signed_txns: vec![txn.to_vec()], tries: tries_before, - contract_code: HashMap::new(), + contract_code, block_metadata, addresses: vec![], }; From 38f79e4991ef69cefac987722ed40e244e2568f6 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Thu, 16 Mar 2023 14:58:31 -0700 Subject: [PATCH 094/121] optimizations with rep --- .../cpu/kernel/asm/hash/sha2/compression.asm | 52 +------- .../cpu/kernel/asm/hash/sha2/write_length.asm | 120 +++--------------- 2 files changed, 22 insertions(+), 150 deletions(-) diff --git a/evm/src/cpu/kernel/asm/hash/sha2/compression.asm b/evm/src/cpu/kernel/asm/hash/sha2/compression.asm index 0bceb715..8f7d942c 100644 --- a/evm/src/cpu/kernel/asm/hash/sha2/compression.asm +++ b/evm/src/cpu/kernel/asm/hash/sha2/compression.asm @@ -132,53 +132,11 @@ compression_end_block: // stack: a[64], b[64], c[64], d[64], e[64], f[64], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0], b[0], c[0], d[0], e[0], f[0], g[0], h[0], retdest PUSH 0 // stack: 0, a[64], b[64], c[64], d[64], e[64], f[64], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0], b[0], c[0], d[0], e[0], f[0], g[0], h[0], retdest - SWAP13 - // stack: a[0], a[64], b[64], c[64], d[64], e[64], f[64], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, 0, b[0], c[0], d[0], e[0], f[0], g[0], h[0], retdest - %add_u32 - // stack: a[0]+a[64], b[64], c[64], d[64], e[64], f[64], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, 0, b[0], c[0], d[0], e[0], f[0], g[0], h[0], retdest - SWAP12 - // stack: 0, b[64], c[64], d[64], e[64], f[64], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]+a[64], b[0], c[0], d[0], e[0], f[0], g[0], h[0], retdest - SWAP13 - // stack: b[0], b[64], c[64], d[64], e[64], f[64], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]+a[64], 0, c[0], d[0], e[0], f[0], g[0], h[0], retdest - %add_u32 - // stack: b[0]+b[64], c[64], d[64], e[64], f[64], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]+a[64], 0, c[0], d[0], e[0], f[0], g[0], h[0], retdest - SWAP12 - // stack: 0, c[64], d[64], e[64], f[64], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]+a[64], b[0]+b[64], c[0], d[0], e[0], f[0], g[0], h[0], retdest - SWAP13 - // stack: c[0], c[64], d[64], e[64], f[64], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]+a[64], b[0]+b[64], 0, d[0], e[0], f[0], g[0], h[0], retdest - %add_u32 - // stack: c[0]+c[64], d[64], e[64], f[64], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]+a[64], b[0]+b[64], 0, d[0], e[0], f[0], g[0], h[0], retdest - SWAP12 - // stack: 0, d[64], e[64], f[64], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0], e[0], f[0], g[0], h[0], retdest - SWAP13 - // stack: d[0], d[64], e[64], f[64], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]+a[64], b[0]+b[64], c[0]+c[64], 0, e[0], f[0], g[0], h[0], retdest - %add_u32 - // stack: d[0]+d[64], e[64], f[64], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]+a[64], b[0]+b[64], c[0]+c[64], 0, e[0], f[0], g[0], h[0], retdest - SWAP12 - // stack: 0, e[64], f[64], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], e[0], f[0], g[0], h[0], retdest - SWAP13 - // stack: e[0], e[64], f[64], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], 0, f[0], g[0], h[0], retdest - %add_u32 - // stack: e[0]+e[64], f[64], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], 0, f[0], g[0], h[0], retdest - SWAP12 - // stack: 0, f[64], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], e[0]+e[64], f[0], g[0], h[0], retdest - SWAP13 - // stack: f[0], f[64], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], e[0]+e[64], 0, g[0], h[0], retdest - %add_u32 - // stack: f[0]+f[64], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], e[0]+e[64], 0, g[0], h[0], retdest - SWAP12 - // stack: 0, g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], e[0]+e[64], f[0]+f[64], g[0], h[0], retdest - SWAP13 - // stack: g[0], g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], e[0]+e[64], f[0]+f[64], 0, h[0], retdest - %add_u32 - // stack: g[0]+g[64], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], e[0]+e[64], f[0]+f[64], 0, h[0], retdest - SWAP12 - // stack: 0, h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], e[0]+e[64], f[0]+f[64], g[0]+g[64], h[0], retdest - SWAP13 - // stack: h[0], h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], e[0]+e[64], f[0]+f[64], g[0]+g[64], 0, retdest - %add_u32 - // stack: h[0]+h[64], num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], e[0]+e[64], f[0]+f[64], g[0]+g[64], 0, retdest - SWAP12 + %rep 8 + SWAP13 + %add_u32 + SWAP12 + %endrep // stack: 0, num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], e[0]+e[64], f[0]+f[64], g[0]+g[64], h[0]+h[64], retdest POP // stack: num_blocks, scratch_space_addr, message_schedule_addr, i, a[0]+a[64], b[0]+b[64], c[0]+c[64], d[0]+d[64], e[0]+e[64], f[0]+f[64], g[0]+g[64], h[0]+h[64], retdest diff --git a/evm/src/cpu/kernel/asm/hash/sha2/write_length.asm b/evm/src/cpu/kernel/asm/hash/sha2/write_length.asm index bb7a01a8..4f73fa79 100644 --- a/evm/src/cpu/kernel/asm/hash/sha2/write_length.asm +++ b/evm/src/cpu/kernel/asm/hash/sha2/write_length.asm @@ -10,110 +10,24 @@ // stack: last_addr, length % (1 << 8), length, last_addr %mstore_kernel_general - // stack: length, last_addr - SWAP1 - %decrement - SWAP1 - // stack: length, last_addr - 1 - %div_const(256) // equivalent to %shr_const(8) - // stack: length >> 8, last_addr - 1 - DUP1 - // stack: length >> 8, length >> 8, last_addr - 1 - %and_const(0xff) - // stack: (length >> 8) % (1 << 8), length >> 8, last_addr - 1 - DUP3 - // stack: last_addr - 1, (length >> 8) % (1 << 8), length >> 8, last_addr - 1 - %mstore_kernel_general - - // stack: length >> 8, last_addr - 1 - SWAP1 - %decrement - SWAP1 - // stack: length >> 8, last_addr - 2 - %div_const(256) // equivalent to %shr_const(8) - // stack: length >> 16, last_addr - 2 - DUP1 - // stack: length >> 16, length >> 16, last_addr - 2 - %and_const(0xff) - // stack: (length >> 16) % (1 << 8), length >> 16, last_addr - 2 - DUP3 - // stack: last_addr - 2, (length >> 16) % (1 << 8), length >> 16, last_addr - 2 - %mstore_kernel_general + %rep 7 + // For i = 0 to 6 + // stack: length >> (8 * i), last_addr - i - 1 + SWAP1 + %decrement + SWAP1 + // stack: length >> (8 * i), last_addr - i - 2 + %div_const(256) // equivalent to %shr_const(8) + // stack: length >> (8 * (i + 1)), last_addr - i - 2 + DUP1 + // stack: length >> (8 * (i + 1)), length >> (8 * (i + 1)), last_addr - i - 2 + %mod_const(256) + // stack: (length >> (8 * (i + 1))) % (1 << 8), length >> (8 * (i + 1)), last_addr - i - 2 + DUP3 + // stack: last_addr - i - 2, (length >> (8 * (i + 1))) % (1 << 8), length >> (8 * (i + 1)), last_addr - i - 2 + %mstore_kernel_general + %endrep - // stack: length >> 16, last_addr - 2 - SWAP1 - %decrement - SWAP1 - // stack: length >> 16, last_addr - 3 - %div_const(256) // equivalent to %shr_const(8) - // stack: length >> 24, last_addr - 3 - DUP1 - // stack: length >> 24, length >> 24, last_addr - 3 - %and_const(0xff) - // stack: (length >> 24) % (1 << 8), length >> 24, last_addr - 3 - DUP3 - // stack: last_addr - 3, (length >> 24) % (1 << 8), length >> 24, last_addr - 3 - %mstore_kernel_general - - // stack: length >> 24, last_addr - 3 - SWAP1 - %decrement - SWAP1 - // stack: length >> 24, last_addr - 4 - %div_const(256) // equivalent to %shr_const(8) - // stack: length >> 32, last_addr - 4 - DUP1 - // stack: length >> 32, length >> 32, last_addr - 4 - %and_const(0xff) - // stack: (length >> 32) % (1 << 8), length >> 32, last_addr - 4 - DUP3 - // stack: last_addr - 4, (length >> 32) % (1 << 8), length >> 32, last_addr - 4 - %mstore_kernel_general - - // stack: length >> 32, last_addr - 4 - SWAP1 - %decrement - SWAP1 - // stack: length >> 32, last_addr - 5 - %div_const(256) // equivalent to %shr_const(8) - // stack: length >> 40, last_addr - 5 - DUP1 - // stack: length >> 40, length >> 40, last_addr - 5 - %and_const(0xff) - // stack: (length >> 40) % (1 << 8), length >> 40, last_addr - 5 - DUP3 - // stack: last_addr - 5, (length >> 40) % (1 << 8), length >> 40, last_addr - 5 - %mstore_kernel_general - - // stack: length >> 40, last_addr - 5 - SWAP1 - %decrement - SWAP1 - // stack: length >> 40, last_addr - 6 - %div_const(256) // equivalent to %shr_const(8) - // stack: length >> 48, last_addr - 6 - DUP1 - // stack: length >> 48, length >> 48, last_addr - 6 - %and_const(0xff) - // stack: (length >> 48) % (1 << 8), length >> 48, last_addr - 6 - DUP3 - // stack: last_addr - 6, (length >> 48) % (1 << 8), length >> 48, last_addr - 6 - %mstore_kernel_general - - // stack: length >> 48, last_addr - 6 - SWAP1 - %decrement - SWAP1 - // stack: length >> 48, last_addr - 7 - %div_const(256) // equivalent to %shr_const(8) - // stack: length >> 56, last_addr - 7 - DUP1 - // stack: length >> 56, length >> 56, last_addr - 7 - %and_const(0xff) - // stack: (length >> 56) % (1 << 8), length >> 56, last_addr - 7 - DUP3 - // stack: last_addr - 7, (length >> 56) % (1 << 8), length >> 56, last_addr - 7 - %mstore_kernel_general %pop2 // stack: (empty) %endmacro From 5720cf8a77003319b886d580f06c76a31e97422e Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Thu, 16 Mar 2023 15:40:40 -0700 Subject: [PATCH 095/121] updated function name --- evm/src/cpu/kernel/tests/bignum/mod.rs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/evm/src/cpu/kernel/tests/bignum/mod.rs b/evm/src/cpu/kernel/tests/bignum/mod.rs index a83a063c..7fc676ef 100644 --- a/evm/src/cpu/kernel/tests/bignum/mod.rs +++ b/evm/src/cpu/kernel/tests/bignum/mod.rs @@ -36,7 +36,7 @@ fn full_path(filename: &str) -> PathBuf { path } -fn test_data(filename: &str) -> Vec { +fn test_data_biguint(filename: &str) -> Vec { let file = File::open(full_path(filename)).unwrap(); let lines = BufReader::new(file).lines(); lines @@ -242,8 +242,8 @@ fn test_shr_bignum_all() -> Result<()> { test_shr_bignum(input, output)?; } - let inputs = test_data(TEST_DATA_BIGNUM_INPUTS); - let shr_outputs = test_data(TEST_DATA_SHR_OUTPUTS); + let inputs = test_data_biguint(TEST_DATA_BIGNUM_INPUTS); + let shr_outputs = test_data_biguint(TEST_DATA_SHR_OUTPUTS); for (input, output) in inputs.iter().zip(shr_outputs.iter()) { test_shr_bignum(input.clone(), output.clone())?; } @@ -263,7 +263,7 @@ fn test_iszero_bignum_all() -> Result<()> { test_iszero_bignum(input, output.into())?; } - let inputs = test_data(TEST_DATA_BIGNUM_INPUTS); + let inputs = test_data_biguint(TEST_DATA_BIGNUM_INPUTS); let iszero_outputs = test_data_u256(TEST_DATA_ISZERO_OUTPUTS); let mut iszero_outputs_iter = iszero_outputs.iter(); for input in inputs { @@ -292,7 +292,7 @@ fn test_cmp_bignum_all() -> Result<()> { test_cmp_bignum(a, b, output)?; } - let inputs = test_data(TEST_DATA_BIGNUM_INPUTS); + let inputs = test_data_biguint(TEST_DATA_BIGNUM_INPUTS); let cmp_outputs = test_data_u256(TEST_DATA_CMP_OUTPUTS); let mut cmp_outputs_iter = cmp_outputs.iter(); for a in inputs.clone() { @@ -319,8 +319,8 @@ fn test_add_bignum_all() -> Result<()> { test_add_bignum(a, b, output)?; } - let inputs = test_data(TEST_DATA_BIGNUM_INPUTS); - let add_outputs = test_data(TEST_DATA_ADD_OUTPUTS); + let inputs = test_data_biguint(TEST_DATA_BIGNUM_INPUTS); + let add_outputs = test_data_biguint(TEST_DATA_ADD_OUTPUTS); let mut add_outputs_iter = add_outputs.iter(); for a in inputs.clone() { for b in inputs.clone() { @@ -350,9 +350,9 @@ fn test_addmul_bignum_all() -> Result<()> { test_addmul_bignum(a, b, c, output)?; } - let inputs = test_data(TEST_DATA_BIGNUM_INPUTS); + let inputs = test_data_biguint(TEST_DATA_BIGNUM_INPUTS); let u128_inputs = test_data_u128(TEST_DATA_U128_INPUTS); - let addmul_outputs = test_data(TEST_DATA_ADDMUL_OUTPUTS); + let addmul_outputs = test_data_biguint(TEST_DATA_ADDMUL_OUTPUTS); let mut addmul_outputs_iter = addmul_outputs.iter(); for a in inputs.clone() { for b in inputs.clone() { @@ -380,8 +380,8 @@ fn test_mul_bignum_all() -> Result<()> { test_mul_bignum(a, b, output)?; } - let inputs = test_data(TEST_DATA_BIGNUM_INPUTS); - let mul_outputs = test_data(TEST_DATA_MUL_OUTPUTS); + let inputs = test_data_biguint(TEST_DATA_BIGNUM_INPUTS); + let mul_outputs = test_data_biguint(TEST_DATA_MUL_OUTPUTS); let mut mul_outputs_iter = mul_outputs.iter(); for a in inputs.clone() { for b in inputs.clone() { From 8c692b72b00a6cbd587436d46c0f889e55a45886 Mon Sep 17 00:00:00 2001 From: Daniel Lubarov Date: Fri, 17 Mar 2023 13:10:58 -0700 Subject: [PATCH 096/121] Fix account cloning --- evm/src/cpu/kernel/asm/core/transfer.asm | 3 ++- evm/src/cpu/kernel/asm/mpt/accounts.asm | 4 ++-- evm/src/cpu/kernel/constants/trie_type.rs | 2 +- evm/src/generation/mod.rs | 5 +++++ evm/src/generation/outputs.rs | 2 +- evm/src/generation/trie_extractor.rs | 1 + 6 files changed, 12 insertions(+), 5 deletions(-) diff --git a/evm/src/cpu/kernel/asm/core/transfer.asm b/evm/src/cpu/kernel/asm/core/transfer.asm index 05582e6e..8ae2d854 100644 --- a/evm/src/cpu/kernel/asm/core/transfer.asm +++ b/evm/src/cpu/kernel/asm/core/transfer.asm @@ -38,6 +38,7 @@ global transfer_eth_failure: // Returns 0 on success, or 1 if addr has insufficient balance. Panics if addr isn't found in the trie. // Pre stack: addr, amount, retdest // Post stack: status (0 indicates success) +// TODO: Should it be copy-on-write (with make_account_copy) instead of mutating the trie? global deduct_eth: // stack: addr, amount, retdest %mpt_read_state_trie @@ -73,7 +74,7 @@ global deduct_eth_insufficient_balance: // Pre stack: addr, amount, redest // Post stack: (empty) -// TODO: Should it be copy-on-write instead of mutating the trie? +// TODO: Should it be copy-on-write (with make_account_copy) instead of mutating the trie? global add_eth: // stack: addr, amount, retdest DUP1 %mpt_read_state_trie diff --git a/evm/src/cpu/kernel/asm/mpt/accounts.asm b/evm/src/cpu/kernel/asm/mpt/accounts.asm index 08291048..050dbb41 100644 --- a/evm/src/cpu/kernel/asm/mpt/accounts.asm +++ b/evm/src/cpu/kernel/asm/mpt/accounts.asm @@ -38,8 +38,8 @@ global make_account_copy: DUP2 %mload_trie_data %append_to_trie_data DUP2 %add_const(1) %mload_trie_data %append_to_trie_data - DUP2 %add_const(3) %mload_trie_data %append_to_trie_data - SWAP1 %add_const(4) %mload_trie_data %append_to_trie_data + DUP2 %add_const(2) %mload_trie_data %append_to_trie_data + SWAP1 %add_const(3) %mload_trie_data %append_to_trie_data // stack: new_account_ptr, retdest SWAP1 diff --git a/evm/src/cpu/kernel/constants/trie_type.rs b/evm/src/cpu/kernel/constants/trie_type.rs index 30f4802b..fc71c1f4 100644 --- a/evm/src/cpu/kernel/constants/trie_type.rs +++ b/evm/src/cpu/kernel/constants/trie_type.rs @@ -1,6 +1,6 @@ use eth_trie_utils::partial_trie::PartialTrie; -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub(crate) enum PartialTrieType { Empty = 0, Hash = 1, diff --git a/evm/src/generation/mod.rs b/evm/src/generation/mod.rs index aa17b9c9..2c786d8f 100644 --- a/evm/src/generation/mod.rs +++ b/evm/src/generation/mod.rs @@ -123,6 +123,11 @@ pub(crate) fn generate_traces, const D: usize>( timed!(timing, "simulate CPU", simulate_cpu(&mut state)?); + assert!( + state.mpt_prover_inputs.is_empty(), + "All MPT data should have been consumed" + ); + log::info!( "Trace lengths (before padding): {:?}", state.traces.checkpoint() diff --git a/evm/src/generation/outputs.rs b/evm/src/generation/outputs.rs index a197b1b6..b6da3576 100644 --- a/evm/src/generation/outputs.rs +++ b/evm/src/generation/outputs.rs @@ -78,7 +78,7 @@ fn account_trie_record_to_output( .inputs .contract_code .get(&account.code_hash) - .expect("Code not found") + .unwrap_or_else(|| panic!("Code not found: {:?}", account.code_hash)) .clone(); AccountOutput { diff --git a/evm/src/generation/trie_extractor.rs b/evm/src/generation/trie_extractor.rs index a7f01c97..66174419 100644 --- a/evm/src/generation/trie_extractor.rs +++ b/evm/src/generation/trie_extractor.rs @@ -10,6 +10,7 @@ use crate::memory::segments::Segment; use crate::witness::memory::{MemoryAddress, MemoryState}; /// Account data as it's stored in the state trie, with a pointer to the storage trie. +#[derive(Debug)] pub(crate) struct AccountTrieRecord { pub(crate) nonce: u64, pub(crate) balance: U256, From a05ed9fc3a1e92c03f2c132e822fd3143bb549d0 Mon Sep 17 00:00:00 2001 From: Daniel Lubarov Date: Sat, 18 Mar 2023 09:29:31 -0700 Subject: [PATCH 097/121] Fix clobbering of RLP data memory --- evm/src/cpu/kernel/asm/mpt/hash/hash.asm | 136 +++++++++-------- .../asm/mpt/hash/hash_trie_specific.asm | 17 +++ evm/src/cpu/kernel/asm/mpt/util.asm | 17 +++ evm/src/cpu/kernel/asm/rlp/encode.asm | 73 +++++---- .../cpu/kernel/asm/transactions/type_0.asm | 36 ++--- .../cpu/kernel/constants/global_metadata.rs | 11 +- evm/src/cpu/kernel/interpreter.rs | 3 +- evm/src/cpu/kernel/tests/packing.rs | 12 +- evm/src/cpu/kernel/tests/rlp/encode.rs | 6 +- evm/tests/add11_yml.rs | 139 ++++++++++++++++++ 10 files changed, 321 insertions(+), 129 deletions(-) create mode 100644 evm/tests/add11_yml.rs diff --git a/evm/src/cpu/kernel/asm/mpt/hash/hash.asm b/evm/src/cpu/kernel/asm/mpt/hash/hash.asm index 0c8beae7..4209f06c 100644 --- a/evm/src/cpu/kernel/asm/mpt/hash/hash.asm +++ b/evm/src/cpu/kernel/asm/mpt/hash/hash.asm @@ -118,16 +118,19 @@ global encode_node_empty: // stack: node_type, node_payload_ptr, encode_value, retdest %pop3 // stack: retdest - // An empty node is encoded as a single byte, 0x80, which is the RLP - // encoding of the empty string. Write this byte to RLP[0] and return - // (0, 1). + // An empty node is encoded as a single byte, 0x80, which is the RLP encoding of the empty string. + // TODO: Write this byte just once to RLP memory, then we can always return (0, 1). + %alloc_rlp_block + // stack: rlp_pos, retdest PUSH 0x80 - PUSH 0 + // stack: 0x80, rlp_pos, retdest + DUP2 + // stack: rlp_pos, 0x80, rlp_pos, retdest %mstore_rlp - %stack (retdest) -> (retdest, 0, 1) + %stack (rlp_pos, retdest) -> (retdest, rlp_pos, 1) JUMP -encode_node_branch: +global encode_node_branch: // stack: node_type, node_payload_ptr, encode_value, retdest POP // stack: node_payload_ptr, encode_value, retdest @@ -135,6 +138,7 @@ encode_node_branch: // Get the next unused offset within the encoded child buffers. // Then immediately increment the next unused offset by 16, so any // recursive calls will use nonoverlapping offsets. + // TODO: Allocate a block of RLP memory instead? %mload_global_metadata(@GLOBAL_METADATA_TRIE_ENCODED_CHILD_SIZE) DUP1 %add_const(16) %mstore_global_metadata(@GLOBAL_METADATA_TRIE_ENCODED_CHILD_SIZE) @@ -150,41 +154,41 @@ encode_node_branch: // stack: base_offset, node_payload_ptr, encode_value, retdest // Now, append each child to our RLP tape. - PUSH 9 // rlp_pos; we start at 9 to leave room to prepend a list prefix + %alloc_rlp_block DUP1 + // stack: rlp_pos, rlp_start, base_offset, node_payload_ptr, encode_value, retdest %append_child(0) %append_child(1) %append_child(2) %append_child(3) %append_child(4) %append_child(5) %append_child(6) %append_child(7) %append_child(8) %append_child(9) %append_child(10) %append_child(11) %append_child(12) %append_child(13) %append_child(14) %append_child(15) - // stack: rlp_pos', base_offset, node_payload_ptr, encode_value, retdest + // stack: rlp_pos', rlp_start, base_offset, node_payload_ptr, encode_value, retdest - // We no longer need base_offset. - SWAP1 - POP - - // stack: rlp_pos', node_payload_ptr, encode_value, retdest - SWAP1 + %stack (rlp_pos, rlp_start, base_offset, node_payload_ptr) + -> (node_payload_ptr, rlp_pos, rlp_start) %add_const(16) - // stack: value_ptr_ptr, rlp_pos', encode_value, retdest + // stack: value_ptr_ptr, rlp_pos', rlp_start, encode_value, retdest %mload_trie_data - // stack: value_ptr, rlp_pos', encode_value, retdest + // stack: value_ptr, rlp_pos', rlp_start, encode_value, retdest DUP1 %jumpi(encode_node_branch_with_value) + // No value; append the empty string (0x80). - // stack: value_ptr, rlp_pos', encode_value, retdest - %stack (value_ptr, rlp_pos, encode_value) -> (rlp_pos, 0x80, rlp_pos) + // stack: value_ptr, rlp_pos', rlp_start, encode_value, retdest + %stack (value_ptr, rlp_pos, rlp_start, encode_value) -> (rlp_pos, 0x80, rlp_pos, rlp_start) %mstore_rlp - // stack: rlp_pos', retdest + // stack: rlp_pos', rlp_start, retdest %increment - // stack: rlp_pos'', retdest + // stack: rlp_pos'', rlp_start, retdest %jump(encode_node_branch_prepend_prefix) encode_node_branch_with_value: - // stack: value_ptr, rlp_pos', encode_value, retdest - %stack (value_ptr, rlp_pos, encode_value) - -> (encode_value, rlp_pos, value_ptr, encode_node_branch_prepend_prefix) + // stack: value_ptr, rlp_pos', rlp_start, encode_value, retdest + %stack (value_ptr, rlp_pos, rlp_start, encode_value) + -> (encode_value, rlp_pos, value_ptr, encode_node_branch_prepend_prefix, rlp_start) JUMP // call encode_value encode_node_branch_prepend_prefix: - // stack: rlp_pos'', retdest + // stack: rlp_pos'', rlp_start, retdest %prepend_rlp_list_prefix - %stack (start_pos, rlp_len, retdest) -> (retdest, start_pos, rlp_len) + // stack: rlp_prefix_start, rlp_len, retdest + %stack (rlp_prefix_start, rlp_len, retdest) + -> (retdest, rlp_prefix_start, rlp_len) JUMP // Part of the encode_node_branch function. Encodes the i'th child. @@ -208,27 +212,28 @@ encode_node_branch_prepend_prefix: // Part of the encode_node_branch function. Appends the i'th child's RLP. %macro append_child(i) - // stack: rlp_pos, base_offset, node_payload_ptr, encode_value, retdest - DUP2 %add_const($i) %mload_kernel(@SEGMENT_TRIE_ENCODED_CHILD) // load result - DUP3 %add_const($i) %mload_kernel(@SEGMENT_TRIE_ENCODED_CHILD_LEN) // load result_len - // stack: result_len, result, rlp_pos, base_offset, node_payload_ptr, encode_value, retdest + // stack: rlp_pos, rlp_start, base_offset, node_payload_ptr, encode_value, retdest + DUP3 %add_const($i) %mload_kernel(@SEGMENT_TRIE_ENCODED_CHILD) // load result + DUP4 %add_const($i) %mload_kernel(@SEGMENT_TRIE_ENCODED_CHILD_LEN) // load result_len + // stack: result_len, result, rlp_pos, rlp_start, base_offset, node_payload_ptr, encode_value, retdest // If result_len != 32, result is raw RLP, with an appropriate RLP prefix already. DUP1 %sub_const(32) %jumpi(%%unpack) // Otherwise, result is a hash, and we need to add the prefix 0x80 + 32 = 160. - // stack: result_len, result, rlp_pos, base_offset, node_payload_ptr, encode_value, retdest + // stack: result_len, result, rlp_pos, rlp_start, base_offset, node_payload_ptr, encode_value, retdest PUSH 160 DUP4 // rlp_pos %mstore_rlp SWAP2 %increment SWAP2 // rlp_pos += 1 %%unpack: - %stack (result_len, result, rlp_pos, base_offset, node_payload_ptr, encode_value, retdest) - -> (rlp_pos, result, result_len, %%after_unpacking, base_offset, node_payload_ptr, encode_value, retdest) + %stack (result_len, result, rlp_pos, rlp_start, base_offset, node_payload_ptr, encode_value, retdest) + -> (rlp_pos, result, result_len, %%after_unpacking, + rlp_start, base_offset, node_payload_ptr, encode_value, retdest) %jump(mstore_unpacking_rlp) %%after_unpacking: - // stack: rlp_pos', base_offset, node_payload_ptr, encode_value, retdest + // stack: rlp_pos', rlp_start, base_offset, node_payload_ptr, encode_value, retdest %endmacro -encode_node_extension: +global encode_node_extension: // stack: node_type, node_payload_ptr, encode_value, retdest %stack (node_type, node_payload_ptr, encode_value) -> (node_payload_ptr, encode_value, encode_node_extension_after_encode_child, node_payload_ptr) @@ -237,61 +242,66 @@ encode_node_extension: %jump(encode_or_hash_node) encode_node_extension_after_encode_child: // stack: result, result_len, node_payload_ptr, retdest + %alloc_rlp_block + // stack: rlp_start, result, result_len, node_payload_ptr, retdest PUSH encode_node_extension_after_hex_prefix // retdest PUSH 0 // terminated - // stack: terminated, encode_node_extension_after_hex_prefix, result, result_len, node_payload_ptr, retdest - DUP5 %increment %mload_trie_data // Load the packed_nibbles field, which is at index 1. - // stack: packed_nibbles, terminated, encode_node_extension_after_hex_prefix, result, result_len, node_payload_ptr, retdest - DUP6 %mload_trie_data // Load the num_nibbles field, which is at index 0. - // stack: num_nibbles, packed_nibbles, terminated, encode_node_extension_after_hex_prefix, result, result_len, node_payload_ptr, retdest - PUSH 9 // We start at 9 to leave room to prepend the largest possible RLP list header. - // stack: rlp_start, num_nibbles, packed_nibbles, terminated, encode_node_extension_after_hex_prefix, result, result_len, node_payload_ptr, retdest + // stack: terminated, encode_node_extension_after_hex_prefix, rlp_start, result, result_len, node_payload_ptr, retdest + DUP6 %increment %mload_trie_data // Load the packed_nibbles field, which is at index 1. + // stack: packed_nibbles, terminated, encode_node_extension_after_hex_prefix, rlp_start, result, result_len, node_payload_ptr, retdest + DUP7 %mload_trie_data // Load the num_nibbles field, which is at index 0. + // stack: num_nibbles, packed_nibbles, terminated, encode_node_extension_after_hex_prefix, rlp_start, result, result_len, node_payload_ptr, retdest + DUP5 + // stack: rlp_start, num_nibbles, packed_nibbles, terminated, encode_node_extension_after_hex_prefix, rlp_start, result, result_len, node_payload_ptr, retdest %jump(hex_prefix_rlp) encode_node_extension_after_hex_prefix: - // stack: rlp_pos, result, result_len, node_payload_ptr, retdest + // stack: rlp_pos, rlp_start, result, result_len, node_payload_ptr, retdest // If result_len != 32, result is raw RLP, with an appropriate RLP prefix already. - DUP3 %sub_const(32) %jumpi(encode_node_extension_unpack) + DUP4 %sub_const(32) %jumpi(encode_node_extension_unpack) // Otherwise, result is a hash, and we need to add the prefix 0x80 + 32 = 160. PUSH 160 DUP2 // rlp_pos %mstore_rlp %increment // rlp_pos += 1 encode_node_extension_unpack: - %stack (rlp_pos, result, result_len, node_payload_ptr) - -> (rlp_pos, result, result_len, encode_node_extension_after_unpacking) + %stack (rlp_pos, rlp_start, result, result_len, node_payload_ptr) + -> (rlp_pos, result, result_len, encode_node_extension_after_unpacking, rlp_start) %jump(mstore_unpacking_rlp) encode_node_extension_after_unpacking: - // stack: rlp_end_pos, retdest + // stack: rlp_pos, rlp_start, retdest %prepend_rlp_list_prefix - %stack (rlp_start_pos, rlp_len, retdest) -> (retdest, rlp_start_pos, rlp_len) + %stack (rlp_prefix_start_pos, rlp_len, retdest) + -> (retdest, rlp_prefix_start_pos, rlp_len) JUMP -encode_node_leaf: +global encode_node_leaf: // stack: node_type, node_payload_ptr, encode_value, retdest POP // stack: node_payload_ptr, encode_value, retdest + %alloc_rlp_block PUSH encode_node_leaf_after_hex_prefix // retdest PUSH 1 // terminated - // stack: terminated, encode_node_leaf_after_hex_prefix, node_payload_ptr, encode_value, retdest - DUP3 %increment %mload_trie_data // Load the packed_nibbles field, which is at index 1. - // stack: packed_nibbles, terminated, encode_node_leaf_after_hex_prefix, node_payload_ptr, encode_value, retdest - DUP4 %mload_trie_data // Load the num_nibbles field, which is at index 0. - // stack: num_nibbles, packed_nibbles, terminated, encode_node_leaf_after_hex_prefix, node_payload_ptr, encode_value, retdest - PUSH 9 // We start at 9 to leave room to prepend the largest possible RLP list header. - // stack: rlp_start, num_nibbles, packed_nibbles, terminated, encode_node_leaf_after_hex_prefix, node_payload_ptr, encode_value, retdest + // stack: terminated, encode_node_leaf_after_hex_prefix, rlp_start, node_payload_ptr, encode_value, retdest + DUP4 %increment %mload_trie_data // Load the packed_nibbles field, which is at index 1. + // stack: packed_nibbles, terminated, encode_node_leaf_after_hex_prefix, rlp_start, node_payload_ptr, encode_value, retdest + DUP5 %mload_trie_data // Load the num_nibbles field, which is at index 0. + // stack: num_nibbles, packed_nibbles, terminated, encode_node_leaf_after_hex_prefix, rlp_start, node_payload_ptr, encode_value, retdest + DUP5 + // stack: rlp_start, num_nibbles, packed_nibbles, terminated, encode_node_leaf_after_hex_prefix, rlp_start, node_payload_ptr, encode_value, retdest %jump(hex_prefix_rlp) encode_node_leaf_after_hex_prefix: - // stack: rlp_pos, node_payload_ptr, encode_value, retdest - SWAP1 + // stack: rlp_pos, rlp_start, node_payload_ptr, encode_value, retdest + SWAP2 %add_const(2) // The value pointer starts at index 3, after num_nibbles and packed_nibbles. - // stack: value_ptr_ptr, rlp_pos, encode_value, retdest + // stack: value_ptr_ptr, rlp_start, rlp_pos, encode_value, retdest %mload_trie_data - // stack: value_ptr, rlp_pos, encode_value, retdest - %stack (value_ptr, rlp_pos, encode_value, retdest) - -> (encode_value, rlp_pos, value_ptr, encode_node_leaf_after_encode_value, retdest) + // stack: value_ptr, rlp_start, rlp_pos, encode_value, retdest + %stack (value_ptr, rlp_start, rlp_pos, encode_value, retdest) + -> (encode_value, rlp_pos, value_ptr, encode_node_leaf_after_encode_value, rlp_start, retdest) JUMP encode_node_leaf_after_encode_value: - // stack: rlp_end_pos, retdest + // stack: rlp_end_pos, rlp_start, retdest %prepend_rlp_list_prefix - %stack (rlp_start_pos, rlp_len, retdest) -> (retdest, rlp_start_pos, rlp_len) + %stack (rlp_prefix_start_pos, rlp_len, retdest) + -> (retdest, rlp_prefix_start_pos, rlp_len) JUMP diff --git a/evm/src/cpu/kernel/asm/mpt/hash/hash_trie_specific.asm b/evm/src/cpu/kernel/asm/mpt/hash/hash_trie_specific.asm index 15f33cee..3662ee04 100644 --- a/evm/src/cpu/kernel/asm/mpt/hash/hash_trie_specific.asm +++ b/evm/src/cpu/kernel/asm/mpt/hash/hash_trie_specific.asm @@ -13,6 +13,17 @@ global mpt_hash_state_trie: %%after: %endmacro +global mpt_hash_storage_trie: + // stack: node_ptr, retdest + %stack (node_ptr) -> (node_ptr, encode_storage_value) + %jump(mpt_hash) + +%macro mpt_hash_storage_trie + PUSH %%after + %jump(mpt_hash_storage_trie) +%%after: +%endmacro + global mpt_hash_txn_trie: // stack: retdest PUSH encode_txn @@ -96,6 +107,12 @@ global encode_receipt: global encode_storage_value: // stack: rlp_pos, value_ptr, retdest + SWAP1 %mload_trie_data SWAP1 + // stack: rlp_pos, value, retdest + // The YP says storage trie is a map "... to the RLP-encoded 256-bit integer values" + // which seems to imply that this should be %encode_rlp_256. But %encode_rlp_scalar + // causes the tests to pass, so it seems storage values should be treated as variable- + // length after all. %encode_rlp_scalar // stack: rlp_pos', retdest SWAP1 diff --git a/evm/src/cpu/kernel/asm/mpt/util.asm b/evm/src/cpu/kernel/asm/mpt/util.asm index 0f7689e1..c7662c41 100644 --- a/evm/src/cpu/kernel/asm/mpt/util.asm +++ b/evm/src/cpu/kernel/asm/mpt/util.asm @@ -10,6 +10,23 @@ // stack: (empty) %endmacro +%macro alloc_rlp_block + // stack: (empty) + %mload_global_metadata(@GLOBAL_METADATA_RLP_DATA_SIZE) + // stack: block_start + // In our model it's fine to use memory in a sparse way, as long as the gaps aren't larger than + // 2^16 or so. So instead of the caller specifying the size of the block they need, we'll just + // allocate 0x10000 = 2^16 bytes, much larger than any RLP blob the EVM could possibly create. + DUP1 %add_const(0x10000) + // stack: block_end, block_start + %mstore_global_metadata(@GLOBAL_METADATA_RLP_DATA_SIZE) + // stack: block_start + // We leave an extra 9 bytes, so that callers can later prepend a prefix before block_start. + // (9 is the length of the longest possible RLP list prefix.) + %add_const(9) + // stack: block_start +%endmacro + %macro get_trie_data_size // stack: (empty) %mload_global_metadata(@GLOBAL_METADATA_TRIE_DATA_SIZE) diff --git a/evm/src/cpu/kernel/asm/rlp/encode.asm b/evm/src/cpu/kernel/asm/rlp/encode.asm index bc69f444..8254e3e8 100644 --- a/evm/src/cpu/kernel/asm/rlp/encode.asm +++ b/evm/src/cpu/kernel/asm/rlp/encode.asm @@ -196,66 +196,65 @@ encode_rlp_list_prefix_large_done_writing_len: %%after: %endmacro -// Given an RLP list payload which starts at position 9 and ends at the given -// position, prepend the appropriate RLP list prefix. Returns the updated start -// position, as well as the length of the RLP data (including the newly-added -// prefix). +// Given an RLP list payload which starts and ends at the given positions, +// prepend the appropriate RLP list prefix. Returns the updated start position, +// as well as the length of the RLP data (including the newly-added prefix). // -// (We sometimes start list payloads at position 9 because 9 is the length of -// the longest possible RLP list prefix.) -// -// Pre stack: end_pos, retdest -// Post stack: start_pos, rlp_len +// Pre stack: end_pos, start_pos, retdest +// Post stack: prefix_start_pos, rlp_len global prepend_rlp_list_prefix: - // stack: end_pos, retdest - // Since the list payload starts at position 9, payload_len = end_pos - 9. - PUSH 9 DUP2 SUB - // stack: payload_len, end_pos, retdest + // stack: end_pos, start_pos, retdest + DUP2 DUP2 SUB // end_pos - start_pos + // stack: payload_len, end_pos, start_pos, retdest DUP1 %gt_const(55) %jumpi(prepend_rlp_list_prefix_big) // If we got here, we have a small list, so we prepend 0xc0 + len at position 8. - // stack: payload_len, end_pos, retdest - %add_const(0xc0) - // stack: prefix_byte, end_pos, retdest - PUSH 8 // offset + // stack: payload_len, end_pos, start_pos, retdest + DUP1 %add_const(0xc0) + // stack: prefix_byte, payload_len, end_pos, start_pos, retdest + DUP4 %decrement // offset of prefix %mstore_rlp - // stack: end_pos, retdest - %sub_const(8) - // stack: rlp_len, retdest - PUSH 8 // start_pos - %stack (start_pos, rlp_len, retdest) -> (retdest, start_pos, rlp_len) + // stack: payload_len, end_pos, start_pos, retdest + %increment + // stack: rlp_len, end_pos, start_pos, retdest + SWAP2 %decrement + // stack: prefix_start_pos, end_pos, rlp_len, retdest + %stack (prefix_start_pos, end_pos, rlp_len, retdest) -> (retdest, prefix_start_pos, rlp_len) JUMP prepend_rlp_list_prefix_big: // We have a large list, so we prepend 0xf7 + len_of_len at position - // 8 - len_of_len, followed by the length itself. - // stack: payload_len, end_pos, retdest + // prefix_start_pos = start_pos - 1 - len_of_len + // followed by the length itself. + // stack: payload_len, end_pos, start_pos, retdest DUP1 %num_bytes - // stack: len_of_len, payload_len, end_pos, retdest + // stack: len_of_len, payload_len, end_pos, start_pos, retdest DUP1 - PUSH 8 + DUP5 %decrement // start_pos - 1 SUB - // stack: start_pos, len_of_len, payload_len, end_pos, retdest - DUP2 %add_const(0xf7) DUP2 %mstore_rlp // rlp[start_pos] = 0xf7 + len_of_len - DUP1 %increment // start_len_pos = start_pos + 1 - %stack (start_len_pos, start_pos, len_of_len, payload_len, end_pos, retdest) + // stack: prefix_start_pos, len_of_len, payload_len, end_pos, start_pos, retdest + DUP2 %add_const(0xf7) DUP2 %mstore_rlp // rlp[prefix_start_pos] = 0xf7 + len_of_len + // stack: prefix_start_pos, len_of_len, payload_len, end_pos, start_pos, retdest + DUP1 %increment // start_len_pos = prefix_start_pos + 1 + %stack (start_len_pos, prefix_start_pos, len_of_len, payload_len, end_pos, start_pos, retdest) -> (start_len_pos, payload_len, len_of_len, prepend_rlp_list_prefix_big_done_writing_len, - start_pos, end_pos, retdest) + prefix_start_pos, end_pos, retdest) %jump(mstore_unpacking_rlp) prepend_rlp_list_prefix_big_done_writing_len: - // stack: 9, start_pos, end_pos, retdest - %stack (_9, start_pos, end_pos) -> (end_pos, start_pos, start_pos) - // stack: end_pos, start_pos, start_pos, retdest + // stack: start_pos, prefix_start_pos, end_pos, retdest + %stack (start_pos, prefix_start_pos, end_pos) + -> (end_pos, prefix_start_pos, prefix_start_pos) + // stack: end_pos, prefix_start_pos, prefix_start_pos, retdest SUB - // stack: rlp_len, start_pos, retdest - %stack (rlp_len, start_pos, retdest) -> (retdest, start_pos, rlp_len) + // stack: rlp_len, prefix_start_pos, retdest + %stack (rlp_len, prefix_start_pos, retdest) -> (retdest, prefix_start_pos, rlp_len) JUMP // Convenience macro to call prepend_rlp_list_prefix and return where we left off. %macro prepend_rlp_list_prefix - %stack (end_pos) -> (end_pos, %%after) + %stack (end_pos, start_pos) -> (end_pos, start_pos, %%after) %jump(prepend_rlp_list_prefix) %%after: %endmacro diff --git a/evm/src/cpu/kernel/asm/transactions/type_0.asm b/evm/src/cpu/kernel/asm/transactions/type_0.asm index e9aedca0..d00b10d4 100644 --- a/evm/src/cpu/kernel/asm/transactions/type_0.asm +++ b/evm/src/cpu/kernel/asm/transactions/type_0.asm @@ -84,62 +84,64 @@ type_0_compute_signed_data: // otherwise, it is // keccak256(rlp([nonce, gas_price, gas_limit, to, value, data])) + %alloc_rlp_block + // stack: rlp_start, retdest %mload_txn_field(@TXN_FIELD_NONCE) - // stack: nonce, retdest - PUSH 9 // We start at 9 to leave room to prepend the largest possible RLP list header. - // stack: rlp_pos, nonce, retdest + // stack: nonce, rlp_start, retdest + DUP2 + // stack: rlp_pos, nonce, rlp_start, retdest %encode_rlp_scalar - // stack: rlp_pos, retdest + // stack: rlp_pos, rlp_start, retdest %mload_txn_field(@TXN_FIELD_MAX_FEE_PER_GAS) SWAP1 %encode_rlp_scalar - // stack: rlp_pos, retdest + // stack: rlp_pos, rlp_start, retdest %mload_txn_field(@TXN_FIELD_GAS_LIMIT) SWAP1 %encode_rlp_scalar - // stack: rlp_pos, retdest + // stack: rlp_pos, rlp_start, retdest %mload_txn_field(@TXN_FIELD_TO) SWAP1 %encode_rlp_160 - // stack: rlp_pos, retdest + // stack: rlp_pos, rlp_start, retdest %mload_txn_field(@TXN_FIELD_VALUE) SWAP1 %encode_rlp_scalar - // stack: rlp_pos, retdest + // stack: rlp_pos, rlp_start, retdest // Encode txn data. %mload_txn_field(@TXN_FIELD_DATA_LEN) PUSH 0 // ADDR.virt PUSH @SEGMENT_TXN_DATA PUSH 0 // ADDR.context - // stack: ADDR: 3, len, rlp_pos, retdest + // stack: ADDR: 3, len, rlp_pos, rlp_start, retdest PUSH after_serializing_txn_data - // stack: after_serializing_txn_data, ADDR: 3, len, rlp_pos, retdest + // stack: after_serializing_txn_data, ADDR: 3, len, rlp_pos, rlp_start, retdest SWAP5 - // stack: rlp_pos, ADDR: 3, len, after_serializing_txn_data, retdest + // stack: rlp_pos, ADDR: 3, len, after_serializing_txn_data, rlp_start, retdest %jump(encode_rlp_string) after_serializing_txn_data: - // stack: rlp_pos, retdest + // stack: rlp_pos, rlp_start, retdest %mload_txn_field(@TXN_FIELD_CHAIN_ID_PRESENT) ISZERO %jumpi(finish_rlp_list) - // stack: rlp_pos, retdest + // stack: rlp_pos, rlp_start, retdest %mload_txn_field(@TXN_FIELD_CHAIN_ID) SWAP1 %encode_rlp_scalar - // stack: rlp_pos, retdest + // stack: rlp_pos, rlp_start, retdest PUSH 0 SWAP1 %encode_rlp_scalar - // stack: rlp_pos, retdest + // stack: rlp_pos, rlp_start, retdest PUSH 0 SWAP1 %encode_rlp_scalar - // stack: rlp_pos, retdest + // stack: rlp_pos, rlp_start, retdest finish_rlp_list: %prepend_rlp_list_prefix - // stack: start_pos, rlp_len, retdest + // stack: prefix_start_pos, rlp_len, retdest PUSH @SEGMENT_RLP_RAW PUSH 0 // context // stack: ADDR: 3, rlp_len, retdest diff --git a/evm/src/cpu/kernel/constants/global_metadata.rs b/evm/src/cpu/kernel/constants/global_metadata.rs index cee02e86..e9d694eb 100644 --- a/evm/src/cpu/kernel/constants/global_metadata.rs +++ b/evm/src/cpu/kernel/constants/global_metadata.rs @@ -6,10 +6,13 @@ pub(crate) enum GlobalMetadata { /// give each new context a unique ID, so that its memory will be zero-initialized. LargestContext = 0, /// The size of active memory, in bytes. - MemorySize = 2, + MemorySize = 1, /// The size of the `TrieData` segment, in bytes. In other words, the next address available for /// appending additional trie data. - TrieDataSize = 3, + TrieDataSize = 2, + /// The size of the `TrieData` segment, in bytes. In other words, the next address available for + /// appending additional trie data. + RlpDataSize = 3, /// A pointer to the root of the state trie within the `TrieData` buffer. StateTrieRoot = 4, /// A pointer to the root of the transaction trie within the `TrieData` buffer. @@ -45,13 +48,14 @@ pub(crate) enum GlobalMetadata { } impl GlobalMetadata { - pub(crate) const COUNT: usize = 21; + pub(crate) const COUNT: usize = 22; pub(crate) fn all() -> [Self; Self::COUNT] { [ Self::LargestContext, Self::MemorySize, Self::TrieDataSize, + Self::RlpDataSize, Self::StateTrieRoot, Self::TransactionTrieRoot, Self::ReceiptTrieRoot, @@ -79,6 +83,7 @@ impl GlobalMetadata { Self::LargestContext => "GLOBAL_METADATA_LARGEST_CONTEXT", Self::MemorySize => "GLOBAL_METADATA_MEMORY_SIZE", Self::TrieDataSize => "GLOBAL_METADATA_TRIE_DATA_SIZE", + Self::RlpDataSize => "GLOBAL_METADATA_RLP_DATA_SIZE", Self::StateTrieRoot => "GLOBAL_METADATA_STATE_TRIE_ROOT", Self::TransactionTrieRoot => "GLOBAL_METADATA_TXN_TRIE_ROOT", Self::ReceiptTrieRoot => "GLOBAL_METADATA_RECEIPT_TRIE_ROOT", diff --git a/evm/src/cpu/kernel/interpreter.rs b/evm/src/cpu/kernel/interpreter.rs index 52876c97..79c4ba93 100644 --- a/evm/src/cpu/kernel/interpreter.rs +++ b/evm/src/cpu/kernel/interpreter.rs @@ -279,6 +279,7 @@ impl<'a> Interpreter<'a> { .byte(0); self.opcode_count[opcode as usize] += 1; self.incr(1); + match opcode { 0x00 => self.run_stop(), // "STOP", 0x01 => self.run_add(), // "ADD", @@ -356,7 +357,7 @@ impl<'a> Interpreter<'a> { 0xa2 => todo!(), // "LOG2", 0xa3 => todo!(), // "LOG3", 0xa4 => todo!(), // "LOG4", - 0xa5 => bail!("Executed PANIC"), // "PANIC", + 0xa5 => bail!("Executed PANIC, stack={:?}", self.stack()), // "PANIC", 0xf0 => todo!(), // "CREATE", 0xf1 => todo!(), // "CALL", 0xf2 => todo!(), // "CALLCODE", diff --git a/evm/src/cpu/kernel/tests/packing.rs b/evm/src/cpu/kernel/tests/packing.rs index 71f66e6d..43ca9b5f 100644 --- a/evm/src/cpu/kernel/tests/packing.rs +++ b/evm/src/cpu/kernel/tests/packing.rs @@ -7,7 +7,7 @@ use crate::memory::segments::Segment; #[test] fn test_mload_packing_1_byte() -> Result<()> { - let mstore_unpacking = KERNEL.global_labels["mload_packing"]; + let mload_packing = KERNEL.global_labels["mload_packing"]; let retdest = 0xDEADBEEFu32.into(); let len = 1.into(); @@ -16,7 +16,7 @@ fn test_mload_packing_1_byte() -> Result<()> { let context = 0.into(); let initial_stack = vec![retdest, len, offset, segment, context]; - let mut interpreter = Interpreter::new_with_kernel(mstore_unpacking, initial_stack); + let mut interpreter = Interpreter::new_with_kernel(mload_packing, initial_stack); interpreter.set_rlp_memory(vec![0, 0, 0xAB]); interpreter.run()?; @@ -27,7 +27,7 @@ fn test_mload_packing_1_byte() -> Result<()> { #[test] fn test_mload_packing_3_bytes() -> Result<()> { - let mstore_unpacking = KERNEL.global_labels["mload_packing"]; + let mload_packing = KERNEL.global_labels["mload_packing"]; let retdest = 0xDEADBEEFu32.into(); let len = 3.into(); @@ -36,7 +36,7 @@ fn test_mload_packing_3_bytes() -> Result<()> { let context = 0.into(); let initial_stack = vec![retdest, len, offset, segment, context]; - let mut interpreter = Interpreter::new_with_kernel(mstore_unpacking, initial_stack); + let mut interpreter = Interpreter::new_with_kernel(mload_packing, initial_stack); interpreter.set_rlp_memory(vec![0, 0, 0xAB, 0xCD, 0xEF]); interpreter.run()?; @@ -47,7 +47,7 @@ fn test_mload_packing_3_bytes() -> Result<()> { #[test] fn test_mload_packing_32_bytes() -> Result<()> { - let mstore_unpacking = KERNEL.global_labels["mload_packing"]; + let mload_packing = KERNEL.global_labels["mload_packing"]; let retdest = 0xDEADBEEFu32.into(); let len = 32.into(); @@ -56,7 +56,7 @@ fn test_mload_packing_32_bytes() -> Result<()> { let context = 0.into(); let initial_stack = vec![retdest, len, offset, segment, context]; - let mut interpreter = Interpreter::new_with_kernel(mstore_unpacking, initial_stack); + let mut interpreter = Interpreter::new_with_kernel(mload_packing, initial_stack); interpreter.set_rlp_memory(vec![0xFF; 32]); interpreter.run()?; diff --git a/evm/src/cpu/kernel/tests/rlp/encode.rs b/evm/src/cpu/kernel/tests/rlp/encode.rs index 4e04b248..2771dea0 100644 --- a/evm/src/cpu/kernel/tests/rlp/encode.rs +++ b/evm/src/cpu/kernel/tests/rlp/encode.rs @@ -86,8 +86,9 @@ fn test_prepend_rlp_list_prefix_small() -> Result<()> { let prepend_rlp_list_prefix = KERNEL.global_labels["prepend_rlp_list_prefix"]; let retdest = 0xDEADBEEFu32.into(); + let start_pos = 9.into(); let end_pos = (9 + 5).into(); - let initial_stack = vec![retdest, end_pos]; + let initial_stack = vec![retdest, start_pos, end_pos]; let mut interpreter = Interpreter::new_with_kernel(prepend_rlp_list_prefix, initial_stack); interpreter.set_rlp_memory(vec![ // Nine 0s to leave room for the longest possible RLP list prefix. @@ -114,8 +115,9 @@ fn test_prepend_rlp_list_prefix_large() -> Result<()> { let prepend_rlp_list_prefix = KERNEL.global_labels["prepend_rlp_list_prefix"]; let retdest = 0xDEADBEEFu32.into(); + let start_pos = 9.into(); let end_pos = (9 + 60).into(); - let initial_stack = vec![retdest, end_pos]; + let initial_stack = vec![retdest, start_pos, end_pos]; let mut interpreter = Interpreter::new_with_kernel(prepend_rlp_list_prefix, initial_stack); #[rustfmt::skip] diff --git a/evm/tests/add11_yml.rs b/evm/tests/add11_yml.rs new file mode 100644 index 00000000..4b1eba54 --- /dev/null +++ b/evm/tests/add11_yml.rs @@ -0,0 +1,139 @@ +use std::collections::HashMap; +use std::time::Duration; + +use env_logger::{try_init_from_env, Env, DEFAULT_FILTER_ENV}; +use eth_trie_utils::partial_trie::{Nibbles, PartialTrie}; +use ethereum_types::Address; +use hex_literal::hex; +use keccak_hash::keccak; +use plonky2::field::goldilocks_field::GoldilocksField; +use plonky2::plonk::config::PoseidonGoldilocksConfig; +use plonky2::util::timing::TimingTree; +use plonky2_evm::all_stark::AllStark; +use plonky2_evm::config::StarkConfig; +use plonky2_evm::generation::mpt::AccountRlp; +use plonky2_evm::generation::{GenerationInputs, TrieInputs}; +use plonky2_evm::proof::BlockMetadata; +use plonky2_evm::prover::prove; +use plonky2_evm::verifier::verify_proof; + +type F = GoldilocksField; +const D: usize = 2; +type C = PoseidonGoldilocksConfig; + +/// Test a simple token transfer to a new address. +#[test] +fn add11_yml() -> anyhow::Result<()> { + init_logger(); + + let all_stark = AllStark::::default(); + let config = StarkConfig::standard_fast_config(); + + let beneficiary = hex!("2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"); + let sender = hex!("a94f5374fce5edbc8e2a8697c15331677e6ebf0b"); + let to = hex!("095e7baea6a6c7c4c2dfeb977efac326af552d87"); + + let beneficiary_state_key = keccak(beneficiary); + let sender_state_key = keccak(sender); + let to_state_key = keccak(to); + + let beneficiary_nibbles = Nibbles::from_bytes_be(beneficiary_state_key.as_bytes()).unwrap(); + let sender_nibbles = Nibbles::from_bytes_be(sender_state_key.as_bytes()).unwrap(); + let to_nibbles = Nibbles::from_bytes_be(to_state_key.as_bytes()).unwrap(); + + let code = [0x60, 0x01, 0x60, 0x01, 0x01, 0x60, 0x00, 0x55, 0x00]; + let code_hash = keccak(code); + + let beneficiary_account_before = AccountRlp { + nonce: 1.into(), + ..AccountRlp::default() + }; + let sender_account_before = AccountRlp { + balance: 0x0de0b6b3a7640000u64.into(), + ..AccountRlp::default() + }; + let to_account_before = AccountRlp { + balance: 0x0de0b6b3a7640000u64.into(), + code_hash, + ..AccountRlp::default() + }; + + let mut state_trie_before = PartialTrie::Empty; + state_trie_before.insert( + beneficiary_nibbles, + rlp::encode(&beneficiary_account_before).to_vec(), + ); + state_trie_before.insert(sender_nibbles, rlp::encode(&sender_account_before).to_vec()); + state_trie_before.insert(to_nibbles, rlp::encode(&to_account_before).to_vec()); + + let tries_before = TrieInputs { + state_trie: state_trie_before, + transactions_trie: PartialTrie::Empty, + receipts_trie: PartialTrie::Empty, + storage_tries: vec![(Address::from_slice(&to), PartialTrie::Empty)], + }; + + let txn = hex!("f863800a83061a8094095e7baea6a6c7c4c2dfeb977efac326af552d87830186a0801ba0ffb600e63115a7362e7811894a91d8ba4330e526f22121c994c4692035dfdfd5a06198379fcac8de3dbfac48b165df4bf88e2088f294b61efb9a65fe2281c76e16"); + + let block_metadata = BlockMetadata { + block_beneficiary: Address::from(beneficiary), + block_base_fee: 0xa.into(), + ..BlockMetadata::default() + }; + + let mut contract_code = HashMap::new(); + contract_code.insert(keccak(vec![]), vec![]); + contract_code.insert(code_hash, code.to_vec()); + + let inputs = GenerationInputs { + signed_txns: vec![txn.to_vec()], + tries: tries_before, + contract_code, + block_metadata, + addresses: vec![], + }; + + let mut timing = TimingTree::new("prove", log::Level::Debug); + let proof = prove::(&all_stark, &config, inputs, &mut timing)?; + timing.filter(Duration::from_millis(100)).print(); + + let beneficiary_account_after = AccountRlp { + nonce: 1.into(), + ..AccountRlp::default() + }; + let sender_account_after = AccountRlp { + balance: 0xde0b6b3a75be550u64.into(), + nonce: 1.into(), + ..AccountRlp::default() + }; + let to_account_after = AccountRlp { + balance: 0xde0b6b3a76586a0u64.into(), + code_hash, + // Storage map: { 0 => 2 } + storage_root: PartialTrie::Leaf { + nibbles: Nibbles::from_h256_be(keccak([0u8; 32])), + value: vec![2], + } + .calc_hash(), + ..AccountRlp::default() + }; + + let mut expected_state_trie_after = PartialTrie::Empty; + expected_state_trie_after.insert( + beneficiary_nibbles, + rlp::encode(&beneficiary_account_after).to_vec(), + ); + expected_state_trie_after.insert(sender_nibbles, rlp::encode(&sender_account_after).to_vec()); + expected_state_trie_after.insert(to_nibbles, rlp::encode(&to_account_after).to_vec()); + + assert_eq!( + proof.public_values.trie_roots_after.state_root, + expected_state_trie_after.calc_hash() + ); + + verify_proof(&all_stark, proof, &config) +} + +fn init_logger() { + let _ = try_init_from_env(Env::default().filter_or(DEFAULT_FILTER_ENV, "info")); +} From 7ed53142a03fdc4e9443bdd8349665c2fb2c28a6 Mon Sep 17 00:00:00 2001 From: Daniel Lubarov Date: Sun, 19 Mar 2023 14:13:42 -0700 Subject: [PATCH 098/121] Fix reads from not-found ext nodes --- evm/src/cpu/kernel/asm/core/transfer.asm | 12 ------------ evm/src/cpu/kernel/asm/mpt/read.asm | 13 ++++++++----- evm/src/generation/state.rs | 3 ++- evm/src/witness/operation.rs | 2 +- 4 files changed, 11 insertions(+), 19 deletions(-) diff --git a/evm/src/cpu/kernel/asm/core/transfer.asm b/evm/src/cpu/kernel/asm/core/transfer.asm index 8ae2d854..c001e726 100644 --- a/evm/src/cpu/kernel/asm/core/transfer.asm +++ b/evm/src/cpu/kernel/asm/core/transfer.asm @@ -23,18 +23,6 @@ global transfer_eth_failure: %%after: %endmacro -// Pre stack: should_transfer, from, to, amount -// Post stack: (empty) -%macro maybe_transfer_eth - %jumpi(%%transfer) - // We're skipping the transfer, so just pop the arguments and return. - %pop3 - %jump(%%after) -%%transfer: - %transfer_eth -%%after: -%endmacro - // Returns 0 on success, or 1 if addr has insufficient balance. Panics if addr isn't found in the trie. // Pre stack: addr, amount, retdest // Post stack: status (0 indicates success) diff --git a/evm/src/cpu/kernel/asm/mpt/read.asm b/evm/src/cpu/kernel/asm/mpt/read.asm index 08aa02c3..94cfbaf5 100644 --- a/evm/src/cpu/kernel/asm/mpt/read.asm +++ b/evm/src/cpu/kernel/asm/mpt/read.asm @@ -23,6 +23,7 @@ global mpt_read_state_trie: // - the virtual address of the trie to search in // - the number of nibbles in the key (should start at 64) // - the key, as a U256 +// - return destination // // This function returns a pointer to the value, or 0 if the key is not found. global mpt_read: @@ -43,13 +44,13 @@ global mpt_read: // it means the prover failed to provide necessary Merkle data, so panic. PANIC -mpt_read_empty: +global mpt_read_empty: // Return 0 to indicate that the value was not found. %stack (node_type, node_payload_ptr, num_nibbles, key, retdest) -> (retdest, 0) JUMP -mpt_read_branch: +global mpt_read_branch: // stack: node_type, node_payload_ptr, num_nibbles, key, retdest POP // stack: node_payload_ptr, num_nibbles, key, retdest @@ -71,7 +72,7 @@ mpt_read_branch: // stack: child_ptr, num_nibbles, key, retdest %jump(mpt_read) // recurse -mpt_read_branch_end_of_key: +global mpt_read_branch_end_of_key: %stack (node_payload_ptr, num_nibbles, key, retdest) -> (node_payload_ptr, retdest) // stack: node_payload_ptr, retdest %add_const(16) // skip over the 16 child nodes @@ -81,7 +82,7 @@ mpt_read_branch_end_of_key: SWAP1 JUMP -mpt_read_extension: +global mpt_read_extension: // stack: node_type, node_payload_ptr, num_nibbles, key, retdest %stack (node_type, node_payload_ptr, num_nibbles, key) -> (num_nibbles, key, node_payload_ptr) @@ -100,8 +101,9 @@ mpt_read_extension: // stack: node_key, key_part, key_part, future_nibbles, key, node_payload_ptr, retdest EQ // does the first part of our key match the node's key? %jumpi(mpt_read_extension_found) +global mpt_read_extension_not_found: // Not found; return 0. - %stack (key_part, future_nibbles, node_payload_ptr, retdest) -> (retdest, 0) + %stack (key_part, future_nibbles, key, node_payload_ptr, retdest) -> (retdest, 0) JUMP mpt_read_extension_found: // stack: key_part, future_nibbles, key, node_payload_ptr, retdest @@ -135,6 +137,7 @@ mpt_read_leaf: AND // stack: keys_match && num_nibbles_match, node_payload_ptr, retdest %jumpi(mpt_read_leaf_found) +global mpt_read_leaf_not_found: // Not found; return 0. %stack (node_payload_ptr, retdest) -> (retdest, 0) JUMP diff --git a/evm/src/generation/state.rs b/evm/src/generation/state.rs index 2e3718bf..9399e4b6 100644 --- a/evm/src/generation/state.rs +++ b/evm/src/generation/state.rs @@ -99,7 +99,8 @@ impl GenerationState { } pub(crate) fn stack(&self) -> Vec { - (0..self.registers.stack_len) + const MAX_TO_SHOW: usize = 10; + (0..self.registers.stack_len.min(MAX_TO_SHOW)) .map(|i| stack_peek(self, i).unwrap()) .collect() } diff --git a/evm/src/witness/operation.rs b/evm/src/witness/operation.rs index 035ce6e2..6d42eb48 100644 --- a/evm/src/witness/operation.rs +++ b/evm/src/witness/operation.rs @@ -589,7 +589,7 @@ pub(crate) fn generate_exit_kernel( state.registers.gas_used = gas_used_val; log::debug!( "Exiting to {}, is_kernel={}", - KERNEL.offset_name(program_counter), + program_counter, is_kernel_mode ); From f717a40b85a1921296b45dbe7c48de347ffec496 Mon Sep 17 00:00:00 2001 From: Daniel Lubarov Date: Sun, 19 Mar 2023 20:17:30 -0700 Subject: [PATCH 099/121] Charge for memory expansion --- evm/src/cpu/kernel/asm/account_code.asm | 20 ++++-- evm/src/cpu/kernel/asm/core/syscall_stubs.asm | 2 - evm/src/cpu/kernel/asm/memory/core.asm | 18 ----- evm/src/cpu/kernel/asm/memory/metadata.asm | 72 +++++++++++++++---- evm/src/cpu/kernel/asm/memory/syscalls.asm | 18 +++++ evm/src/cpu/kernel/asm/util/basic_macros.asm | 22 +++--- .../cpu/kernel/constants/context_metadata.rs | 8 +-- evm/src/cpu/kernel/interpreter.rs | 2 +- 8 files changed, 110 insertions(+), 52 deletions(-) diff --git a/evm/src/cpu/kernel/asm/account_code.asm b/evm/src/cpu/kernel/asm/account_code.asm index f10fbc19..3b18e309 100644 --- a/evm/src/cpu/kernel/asm/account_code.asm +++ b/evm/src/cpu/kernel/asm/account_code.asm @@ -1,6 +1,12 @@ -retzero: - %stack (account_ptr, retdest) -> (retdest, 0) - JUMP +global sys_extcodehash: + // stack: kexit_info, address + // TODO: Charge gas. + SWAP1 + // stack: address, kexit_info + %extcodehash + // stack: hash, kexit_info + SWAP1 + EXIT_KERNEL global extcodehash: // stack: address, retdest @@ -12,6 +18,9 @@ global extcodehash: %mload_trie_data // stack: codehash, retdest SWAP1 JUMP +retzero: + %stack (account_ptr, retdest) -> (retdest, 0) + JUMP %macro extcodehash %stack (address) -> (address, %%after) @@ -32,6 +41,7 @@ global extcodehash: global sys_extcodesize: // stack: kexit_info, address + // TODO: Charge gas. SWAP1 // stack: address, kexit_info %extcodesize @@ -61,6 +71,8 @@ global extcodesize: // Pre stack: kexit_info, address, dest_offset, offset, size // Post stack: (empty) global sys_extcodecopy: + // TODO: Call %update_mem_bytes to expand memory. + // TODO: Charge other gas. %stack (kexit_info, address, dest_offset, offset, size) -> (address, dest_offset, offset, size, kexit_info) %extcodecopy @@ -104,7 +116,7 @@ extcodecopy_loop: // stack: opcode, offset, code_size, dest_offset, i, size, retdest DUP4 // stack: dest_offset, opcode, offset, code_size, dest_offset, i, size, retdest - %mstore_main + %mstore_current(@SEGMENT_MAIN_MEMORY) // stack: offset, code_size, dest_offset, i, size, retdest %increment // stack: offset+1, code_size, dest_offset, i, size, retdest diff --git a/evm/src/cpu/kernel/asm/core/syscall_stubs.asm b/evm/src/cpu/kernel/asm/core/syscall_stubs.asm index 6dcbbb6e..d7f29081 100644 --- a/evm/src/cpu/kernel/asm/core/syscall_stubs.asm +++ b/evm/src/cpu/kernel/asm/core/syscall_stubs.asm @@ -35,8 +35,6 @@ global sys_returndatasize: PANIC global sys_returndatacopy: PANIC -global sys_extcodehash: - PANIC global sys_blockhash: PANIC global sys_coinbase: diff --git a/evm/src/cpu/kernel/asm/memory/core.asm b/evm/src/cpu/kernel/asm/memory/core.asm index 8f59a128..24f35ada 100644 --- a/evm/src/cpu/kernel/asm/memory/core.asm +++ b/evm/src/cpu/kernel/asm/memory/core.asm @@ -419,21 +419,3 @@ %mstore_kernel_general_2 // stack: (empty) %endmacro - -%macro mload_main - // stack: offset - DUP1 - // stack: offset, offset - %update_msize - // stack: offset - %mload_current(@SEGMENT_MAIN_MEMORY) -%endmacro - -%macro mstore_main - // stack: offset, value - DUP1 - // stack: offset, offset, value - %update_msize - // stack: offset, value - %mstore_current(@SEGMENT_MAIN_MEMORY) -%endmacro diff --git a/evm/src/cpu/kernel/asm/memory/metadata.asm b/evm/src/cpu/kernel/asm/memory/metadata.asm index 7ea6d9e5..9b9ce7c2 100644 --- a/evm/src/cpu/kernel/asm/memory/metadata.asm +++ b/evm/src/cpu/kernel/asm/memory/metadata.asm @@ -78,8 +78,13 @@ global sys_callvalue: SWAP1 EXIT_KERNEL +%macro mem_words + %mload_context_metadata(@CTX_METADATA_MEM_WORDS) +%endmacro + %macro msize - %mload_context_metadata(@CTX_METADATA_MSIZE) + %mem_words + %mul_const(32) %endmacro global sys_msize: @@ -89,17 +94,56 @@ global sys_msize: SWAP1 EXIT_KERNEL -%macro update_msize - // stack: offset - %add_const(32) - // stack: 32 + offset - %div_const(32) - // stack: (offset+32)/32 = ceil_div_usize(offset+1, 32) - %mul_const(32) - // stack: ceil_div_usize(offset+1, 32) * 32 - %msize - // stack: current_msize, ceil_div_usize(offset+1, 32) * 32 - %max - // stack: new_msize - %mstore_context_metadata(@CTX_METADATA_MSIZE) +%macro update_mem_words + // stack: num_words, kexit_info + %mem_words + // stack: old_num_words, num_words, kexit_info + DUP2 DUP2 GT + // stack: old_num_words > num_words, old_num_words, num_words, kexit_info + %jumpi(%%end) + // stack: old_num_words, num_words, kexit_info + %memory_cost + // stack: old_cost, num_words, kexit_info + SWAP1 + // stack: num_words, old_cost, kexit_info + DUP1 %mstore_context_metadata(@CTX_METADATA_MEM_WORDS) + // stack: num_words, old_cost, kexit_info + %memory_cost + // stack: new_cost, old_cost, kexit_info + SUB + // stack: additional_cost, kexit_info + %charge_gas +%%end: + // stack: kexit_info +%endmacro + +%macro update_mem_bytes + // stack: num_bytes, kexit_info + %num_bytes_to_num_words + // stack: num_words, kexit_info + %update_mem_words + // stack: kexit_info +%endmacro + +%macro num_bytes_to_num_words + // stack: num_bytes + %add_const(31) + // stack: 31 + num_bytes + %div_const(32) + // stack: (num_bytes + 31) / 32 +%endmacro + +%macro memory_cost + // stack: num_words + DUP1 + // stack: num_words, msize + %mul_const(@GAS_MEMORY) + // stack: num_words * GAS_MEMORY, msize + SWAP1 + // stack: num_words, num_words * GAS_MEMORY + %square + %div_const(512) + // stack: num_words^2 / 512, num_words * GAS_MEMORY + ADD + // stack: cost = num_words^2 / 512 + num_words * GAS_MEMORY %endmacro diff --git a/evm/src/cpu/kernel/asm/memory/syscalls.asm b/evm/src/cpu/kernel/asm/memory/syscalls.asm index 3b56a7fd..03cf3421 100644 --- a/evm/src/cpu/kernel/asm/memory/syscalls.asm +++ b/evm/src/cpu/kernel/asm/memory/syscalls.asm @@ -1,4 +1,10 @@ global sys_mload: + // stack: kexit_info, offset + %charge_gas_const(@GAS_VERYLOW) + // stack: kexit_info, offset + DUP2 %add_const(32) + // stack: expanded_num_bytes, kexit_info, offset + %update_mem_bytes // stack: kexit_info, offset PUSH 0 // acc = 0 // stack: acc, kexit_info, offset @@ -38,6 +44,12 @@ global sys_mload: EXIT_KERNEL global sys_mstore: + // stack: kexit_info, offset, value + %charge_gas_const(@GAS_VERYLOW) + // stack: kexit_info, offset, value + DUP2 %add_const(32) + // stack: expanded_num_bytes, kexit_info, offset, value + %update_mem_bytes // stack: kexit_info, offset, value DUP3 PUSH 0 BYTE DUP3 %add_const( 0) %mstore_current(@SEGMENT_MAIN_MEMORY) DUP3 PUSH 1 BYTE DUP3 %add_const( 1) %mstore_current(@SEGMENT_MAIN_MEMORY) @@ -75,6 +87,12 @@ global sys_mstore: EXIT_KERNEL global sys_mstore8: + // stack: kexit_info, offset, value + %charge_gas_const(@GAS_VERYLOW) + // stack: kexit_info, offset, value + DUP2 %increment + // stack: expanded_num_bytes, kexit_info, offset, value + %update_mem_bytes // stack: kexit_info, offset, value %stack (kexit_info, offset, value) -> (offset, value, kexit_info) %mstore_current(@SEGMENT_MAIN_MEMORY) diff --git a/evm/src/cpu/kernel/asm/util/basic_macros.asm b/evm/src/cpu/kernel/asm/util/basic_macros.asm index e81993b0..50857eaa 100644 --- a/evm/src/cpu/kernel/asm/util/basic_macros.asm +++ b/evm/src/cpu/kernel/asm/util/basic_macros.asm @@ -347,22 +347,26 @@ %endmacro // Charge gas. -// Arguments: -// stack[0]: gas to be charged -// stack[1]: syscall info -// Returns: -// new syscall info %macro charge_gas + // stack: gas, kexit_info %shl_const(192) ADD + // stack: kexit_info' +%endmacro + +// Charge a constant amount of gas. +%macro charge_gas_const(gas) + // stack: kexit_info + PUSH $gas + // stack: gas, kexit_info + %charge_gas + // stack: kexit_info' %endmacro // Charge gas and exit kernel code. -// Arguments: -// stack[0]: gas to be charged -// stack[1]: syscall info -// Returns: nothing %macro charge_gas_and_exit + // stack: gas, kexit_info %charge_gas + // stack: kexit_info' EXIT_KERNEL %endmacro diff --git a/evm/src/cpu/kernel/constants/context_metadata.rs b/evm/src/cpu/kernel/constants/context_metadata.rs index 4e869661..32af6e35 100644 --- a/evm/src/cpu/kernel/constants/context_metadata.rs +++ b/evm/src/cpu/kernel/constants/context_metadata.rs @@ -23,8 +23,8 @@ pub(crate) enum ContextMetadata { /// Pointer to the initial version of the state trie, at the creation of this context. Used when /// we need to revert a context. StateTrieCheckpointPointer = 9, - /// Size of the active main memory. - MSize = 10, + /// Size of the active main memory, in (32 byte) words. + MemWords = 10, StackSize = 11, /// The gas limit for this call (not the entire transaction). GasLimit = 12, @@ -45,7 +45,7 @@ impl ContextMetadata { Self::CallValue, Self::Static, Self::StateTrieCheckpointPointer, - Self::MSize, + Self::MemWords, Self::StackSize, Self::GasLimit, ] @@ -64,7 +64,7 @@ impl ContextMetadata { ContextMetadata::CallValue => "CTX_METADATA_CALL_VALUE", ContextMetadata::Static => "CTX_METADATA_STATIC", ContextMetadata::StateTrieCheckpointPointer => "CTX_METADATA_STATE_TRIE_CHECKPOINT_PTR", - ContextMetadata::MSize => "CTX_METADATA_MSIZE", + ContextMetadata::MemWords => "CTX_METADATA_MEM_WORDS", ContextMetadata::StackSize => "CTX_METADATA_STACK_SIZE", ContextMetadata::GasLimit => "CTX_METADATA_GAS_LIMIT", } diff --git a/evm/src/cpu/kernel/interpreter.rs b/evm/src/cpu/kernel/interpreter.rs index 79c4ba93..7d30d7f2 100644 --- a/evm/src/cpu/kernel/interpreter.rs +++ b/evm/src/cpu/kernel/interpreter.rs @@ -709,7 +709,7 @@ impl<'a> Interpreter<'a> { self.push( self.generation_state.memory.contexts[self.context].segments [Segment::ContextMetadata as usize] - .get(ContextMetadata::MSize as usize), + .get(ContextMetadata::MemWords as usize), ) } From 47fac8e35b6d408dee568c2bf19f5cb8a0004454 Mon Sep 17 00:00:00 2001 From: Daniel Lubarov Date: Sun, 19 Mar 2023 22:35:53 -0700 Subject: [PATCH 100/121] Couple fixes & minor refactor --- evm/src/cpu/kernel/aggregator.rs | 1 + evm/src/cpu/kernel/asm/core/gas.asm | 49 +++++++++++++++++++ evm/src/cpu/kernel/asm/core/syscall_stubs.asm | 10 ---- evm/src/cpu/kernel/asm/core/terminate.asm | 2 +- .../kernel/asm/curve/secp256k1/ecrecover.asm | 14 +----- evm/src/cpu/kernel/asm/memory/metadata.asm | 13 +++++ evm/src/cpu/kernel/asm/memory/syscalls.asm | 6 +++ evm/src/cpu/kernel/asm/util/basic_macros.asm | 25 ---------- evm/src/cpu/kernel/asm/util/keccak.asm | 18 +++++++ 9 files changed, 89 insertions(+), 49 deletions(-) create mode 100644 evm/src/cpu/kernel/asm/core/gas.asm diff --git a/evm/src/cpu/kernel/aggregator.rs b/evm/src/cpu/kernel/aggregator.rs index 80dd9392..34e3ce43 100644 --- a/evm/src/cpu/kernel/aggregator.rs +++ b/evm/src/cpu/kernel/aggregator.rs @@ -17,6 +17,7 @@ pub(crate) fn combined_kernel() -> Kernel { include_str!("asm/core/call.asm"), include_str!("asm/core/create.asm"), include_str!("asm/core/create_addresses.asm"), + include_str!("asm/core/gas.asm"), include_str!("asm/core/intrinsic_gas.asm"), include_str!("asm/core/invalid.asm"), include_str!("asm/core/jumpdest_analysis.asm"), diff --git a/evm/src/cpu/kernel/asm/core/gas.asm b/evm/src/cpu/kernel/asm/core/gas.asm new file mode 100644 index 00000000..0cc62e4a --- /dev/null +++ b/evm/src/cpu/kernel/asm/core/gas.asm @@ -0,0 +1,49 @@ +global sys_gas: + // stack: kexit_info + %charge_gas_const(@GAS_BASE) + // stack: kexit_info + DUP1 %shr_const(192) + // stack: gas_used, kexit_info + %ctx_gas_limit + // stack: gas_limit, gas_used, kexit_info + SUB + // stack: gas_remaining, kexit_info + SWAP1 + EXIT_KERNEL + +%macro ctx_gas_limit + %mload_context_metadata(@CTX_METADATA_GAS_LIMIT) +%endmacro + +// Charge gas. Faults if we exceed the limit for the current context. +%macro charge_gas + // stack: gas, kexit_info + %shl_const(192) + ADD + // stack: kexit_info' + %ctx_gas_limit + // stack: gas_limit, kexit_info' + DUP2 %shr_const(192) + // stack: gas_used, gas_limit, kexit_info' + GT + // stack: out_of_gas, kexit_info' + %jumpi(fault_exception) + // stack: kexit_info' +%endmacro + +// Charge a constant amount of gas. +%macro charge_gas_const(gas) + // stack: kexit_info + PUSH $gas + // stack: gas, kexit_info + %charge_gas + // stack: kexit_info' +%endmacro + +// Charge gas and exit kernel code. +%macro charge_gas_and_exit + // stack: gas, kexit_info + %charge_gas + // stack: kexit_info' + EXIT_KERNEL +%endmacro diff --git a/evm/src/cpu/kernel/asm/core/syscall_stubs.asm b/evm/src/cpu/kernel/asm/core/syscall_stubs.asm index d7f29081..624bd9c6 100644 --- a/evm/src/cpu/kernel/asm/core/syscall_stubs.asm +++ b/evm/src/cpu/kernel/asm/core/syscall_stubs.asm @@ -60,16 +60,6 @@ global sys_selfbalance: PANIC global sys_basefee: PANIC -global sys_gas: - // stack: kexit_info - DUP1 %shr_const(192) - // stack: gas_used, kexit_info - %mload_context_metadata(@CTX_METADATA_GAS_LIMIT) - // stack: gas_limit, gas_used, kexit_info - SUB - // stack: gas_remaining, kexit_info - SWAP1 - EXIT_KERNEL global sys_log0: PANIC global sys_log1: diff --git a/evm/src/cpu/kernel/asm/core/terminate.asm b/evm/src/cpu/kernel/asm/core/terminate.asm index 341884ea..98c65253 100644 --- a/evm/src/cpu/kernel/asm/core/terminate.asm +++ b/evm/src/cpu/kernel/asm/core/terminate.asm @@ -37,7 +37,7 @@ global sys_revert: PUSH 0 // success %jump(terminate_common) -// The execution is in an exceptional halt-ing state if +// The execution is in an exceptional halting state if // - there is insufficient gas // - the instruction is invalid // - there are insufficient stack items diff --git a/evm/src/cpu/kernel/asm/curve/secp256k1/ecrecover.asm b/evm/src/cpu/kernel/asm/curve/secp256k1/ecrecover.asm index 11ec27c8..6e9df123 100644 --- a/evm/src/cpu/kernel/asm/curve/secp256k1/ecrecover.asm +++ b/evm/src/cpu/kernel/asm/curve/secp256k1/ecrecover.asm @@ -106,19 +106,7 @@ ecdsa_after_precompute_loop_end: // Take a public key (PKx, PKy) and return the associated address KECCAK256(PKx || PKy)[-20:]. pubkey_to_addr: // stack: PKx, PKy, retdest - PUSH 0 - // stack: 0, PKx, PKy, retdest - MSTORE // TODO: switch to kernel memory (like `%mstore_kernel(@SEGMENT_KERNEL_GENERAL)`). - // stack: PKy, retdest - PUSH 0x20 - // stack: 0x20, PKy, retdest - MSTORE - // stack: retdest - PUSH 0x40 - // stack: 0x40, retdest - PUSH 0 - // stack: 0, 0x40, retdest - KECCAK256 + %keccak256_u256_pair // stack: hash, retdest PUSH 0xffffffffffffffffffffffffffffffffffffffff // stack: 2^160-1, hash, retdest diff --git a/evm/src/cpu/kernel/asm/memory/metadata.asm b/evm/src/cpu/kernel/asm/memory/metadata.asm index 9b9ce7c2..55c8bebc 100644 --- a/evm/src/cpu/kernel/asm/memory/metadata.asm +++ b/evm/src/cpu/kernel/asm/memory/metadata.asm @@ -147,3 +147,16 @@ global sys_msize: ADD // stack: cost = num_words^2 / 512 + num_words * GAS_MEMORY %endmacro + +// Faults if the given offset is "unreasonable", i.e. the associated memory expansion cost +// would exceed any reasonable block limit. +// We do this to avoid overflows in future gas-related calculations. +%macro ensure_reasonable_offset + // stack: offset + // The memory expansion cost, (50000000 / 32)^2 / 512, is around 2^32 gas, + // i.e. greater than any reasonable block limit. + %gt_const(50000000) + // stack: is_unreasonable + %jumpi(fault_exception) + // stack: (empty) +%endmacro diff --git a/evm/src/cpu/kernel/asm/memory/syscalls.asm b/evm/src/cpu/kernel/asm/memory/syscalls.asm index 03cf3421..af8b6f27 100644 --- a/evm/src/cpu/kernel/asm/memory/syscalls.asm +++ b/evm/src/cpu/kernel/asm/memory/syscalls.asm @@ -1,4 +1,6 @@ global sys_mload: + // stack: kexit_info, offset + DUP2 %ensure_reasonable_offset // stack: kexit_info, offset %charge_gas_const(@GAS_VERYLOW) // stack: kexit_info, offset @@ -44,6 +46,8 @@ global sys_mload: EXIT_KERNEL global sys_mstore: + // stack: kexit_info, offset, value + DUP2 %ensure_reasonable_offset // stack: kexit_info, offset, value %charge_gas_const(@GAS_VERYLOW) // stack: kexit_info, offset, value @@ -87,6 +91,8 @@ global sys_mstore: EXIT_KERNEL global sys_mstore8: + // stack: kexit_info, offset, value + DUP2 %ensure_reasonable_offset // stack: kexit_info, offset, value %charge_gas_const(@GAS_VERYLOW) // stack: kexit_info, offset, value diff --git a/evm/src/cpu/kernel/asm/util/basic_macros.asm b/evm/src/cpu/kernel/asm/util/basic_macros.asm index 50857eaa..476f1c74 100644 --- a/evm/src/cpu/kernel/asm/util/basic_macros.asm +++ b/evm/src/cpu/kernel/asm/util/basic_macros.asm @@ -345,28 +345,3 @@ %endrep // stack: a || b || c || d %endmacro - -// Charge gas. -%macro charge_gas - // stack: gas, kexit_info - %shl_const(192) - ADD - // stack: kexit_info' -%endmacro - -// Charge a constant amount of gas. -%macro charge_gas_const(gas) - // stack: kexit_info - PUSH $gas - // stack: gas, kexit_info - %charge_gas - // stack: kexit_info' -%endmacro - -// Charge gas and exit kernel code. -%macro charge_gas_and_exit - // stack: gas, kexit_info - %charge_gas - // stack: kexit_info' - EXIT_KERNEL -%endmacro diff --git a/evm/src/cpu/kernel/asm/util/keccak.asm b/evm/src/cpu/kernel/asm/util/keccak.asm index 7922e8ce..5665ad3b 100644 --- a/evm/src/cpu/kernel/asm/util/keccak.asm +++ b/evm/src/cpu/kernel/asm/util/keccak.asm @@ -23,3 +23,21 @@ global sys_keccak256: %stack (offset) -> (0, @SEGMENT_KERNEL_GENERAL, 0, $num_bytes) // context, segment, offset, len KECCAK_GENERAL %endmacro + +// Computes Keccak256(a || b). Clobbers @SEGMENT_KERNEL_GENERAL. +// +// Pre stack: a, b +// Post stack: hash +%macro keccak256_u256_pair + // Since KECCAK_GENERAL takes its input from memory, we will first write + // a's bytes to @SEGMENT_KERNEL_GENERAL[0..32], then b's bytes to + // @SEGMENT_KERNEL_GENERAL[32..64]. + %stack (a) -> (0, @SEGMENT_KERNEL_GENERAL, 0, a, 32, %%after_mstore_a) + %jump(mstore_unpacking) +%%after_mstore_a: + %stack (offset, b) -> (0, @SEGMENT_KERNEL_GENERAL, 32, b, 32, %%after_mstore_b) + %jump(mstore_unpacking) +%%after_mstore_b: + %stack (offset) -> (0, @SEGMENT_KERNEL_GENERAL, 0, 64) // context, segment, offset, len + KECCAK_GENERAL +%endmacro From b80a28dbd18fba7446ba5e7a6ffb8f50f125ee65 Mon Sep 17 00:00:00 2001 From: Daniel Lubarov Date: Sun, 19 Mar 2023 22:52:44 -0700 Subject: [PATCH 101/121] Misc --- evm/src/cpu/kernel/asm/core/syscall_stubs.asm | 8 -------- evm/src/cpu/kernel/asm/memory/syscalls.asm | 14 ++++++++++++++ 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/evm/src/cpu/kernel/asm/core/syscall_stubs.asm b/evm/src/cpu/kernel/asm/core/syscall_stubs.asm index 624bd9c6..23363166 100644 --- a/evm/src/cpu/kernel/asm/core/syscall_stubs.asm +++ b/evm/src/cpu/kernel/asm/core/syscall_stubs.asm @@ -17,20 +17,12 @@ global sys_balance: PANIC global sys_origin: PANIC -global sys_calldataload: - PANIC global sys_calldatasize: PANIC global sys_calldatacopy: PANIC global sys_codecopy: PANIC -global sys_gasprice: - // stack: kexit_info - %mload_txn_field(@TXN_FIELD_COMPUTED_FEE_PER_GAS) - // stack: gas_price, kexit_info - SWAP1 - EXIT_KERNEL global sys_returndatasize: PANIC global sys_returndatacopy: diff --git a/evm/src/cpu/kernel/asm/memory/syscalls.asm b/evm/src/cpu/kernel/asm/memory/syscalls.asm index af8b6f27..3045be6d 100644 --- a/evm/src/cpu/kernel/asm/memory/syscalls.asm +++ b/evm/src/cpu/kernel/asm/memory/syscalls.asm @@ -104,3 +104,17 @@ global sys_mstore8: %mstore_current(@SEGMENT_MAIN_MEMORY) // stack: kexit_info EXIT_KERNEL + +global sys_calldataload: + // stack: kexit_info, i + %charge_gas_const(@GAS_VERYLOW) + // stack: kexit_info, i + %stack (kexit_info, i) -> (@SEGMENT_CALLDATA, i, 32, sys_calldataload_after_mload_packing, kexit_info) + GET_CONTEXT + // stack: ADDR: 3, 32, sys_calldataload_after_mload_packing, kexit_info + %jump(mload_packing) +sys_calldataload_after_mload_packing: + // stack: value, kexit_info + SWAP1 + EXIT_KERNEL + PANIC From bdf35374d5d37469c7123684bbe89a33ab03b42d Mon Sep 17 00:00:00 2001 From: Daniel Lubarov Date: Sun, 19 Mar 2023 23:22:33 -0700 Subject: [PATCH 102/121] Misc --- evm/src/cpu/kernel/asm/core/call.asm | 4 ++ evm/src/cpu/kernel/asm/core/create.asm | 47 ++++++++++++++----- evm/src/cpu/kernel/asm/core/gas.asm | 9 ++++ evm/src/cpu/kernel/asm/core/syscall_stubs.asm | 2 + evm/src/cpu/kernel/asm/core/terminate.asm | 1 + evm/src/cpu/kernel/asm/memory/metadata.asm | 10 ++++ .../kernel/asm/mpt/storage/storage_read.asm | 1 + evm/src/cpu/kernel/asm/util/keccak.asm | 1 + 8 files changed, 63 insertions(+), 12 deletions(-) diff --git a/evm/src/cpu/kernel/asm/core/call.asm b/evm/src/cpu/kernel/asm/core/call.asm index cb66b7fa..103977b2 100644 --- a/evm/src/cpu/kernel/asm/core/call.asm +++ b/evm/src/cpu/kernel/asm/core/call.asm @@ -3,6 +3,7 @@ // Creates a new sub context and executes the code of the given account. global sys_call: // stack: kexit_info, gas, address, value, args_offset, args_size, ret_offset, ret_size + // TODO: Charge gas. %create_context // stack: new_ctx, kexit_info, gas, address, value, args_offset, args_size, ret_offset, ret_size @@ -27,6 +28,7 @@ global sys_call: // given account. In particular the storage remains the same. global sys_callcode: // stack: kexit_info, gas, address, value, args_offset, args_size, ret_offset, ret_size + // TODO: Charge gas. %create_context // stack: new_ctx, kexit_info, gas, address, value, args_offset, args_size, ret_offset, ret_size @@ -50,6 +52,7 @@ global sys_callcode: // CALL if the value sent is not 0. global sys_staticcall: // stack: kexit_info, gas, address, args_offset, args_size, ret_offset, ret_size + // TODO: Charge gas. %create_context // stack: new_ctx, kexit_info, gas, address, args_offset, args_size, ret_offset, ret_size @@ -70,6 +73,7 @@ global sys_staticcall: // value remain the same. global sys_delegatecall: // stack: kexit_info, gas, address, args_offset, args_size, ret_offset, ret_size + // TODO: Charge gas. %create_context // stack: new_ctx, kexit_info, gas, address, args_offset, args_size, ret_offset, ret_size diff --git a/evm/src/cpu/kernel/asm/core/create.asm b/evm/src/cpu/kernel/asm/core/create.asm index eb0f821e..cc37f832 100644 --- a/evm/src/cpu/kernel/asm/core/create.asm +++ b/evm/src/cpu/kernel/asm/core/create.asm @@ -1,21 +1,30 @@ // The CREATE syscall. // -// Pre stack: value, CODE_ADDR, code_len, retdest +// Pre stack: kexit_info, value, code_offset, code_len // Post stack: address global sys_create: + // TODO: Charge gas. + %stack (kexit_info, value, code_offset, code_len) + -> (value, 0, @SEGMENT_MAIN_MEMORY, code_offset, code_len) %address + // stack: sender, value, CODE_ADDR: 3, code_len, sys_create_finish, kexit_info %jump(create) +sys_create_finish: + // stack: address, kexit_info + SWAP1 + EXIT_KERNEL // Create a new contract account with the traditional address scheme, i.e. // address = KEC(RLP(sender, nonce))[12:] // This can be used both for the CREATE instruction and for contract-creation // transactions. // -// Pre stack: sender, endowment, CODE_ADDR, code_len, retdest +// Pre stack: sender, endowment, CODE_ADDR: 3, code_len, retdest // Post stack: address // Note: CODE_ADDR refers to a (context, segment, offset) tuple. global create: // stack: sender, endowment, CODE_ADDR, code_len, retdest + // TODO: Charge gas. DUP1 %get_nonce // stack: nonce, sender, endowment, CODE_ADDR, code_len, retdest // Call get_create_address and have it return to create_inner. @@ -26,20 +35,34 @@ global create: // CREATE2; see EIP-1014. Address will be // address = KEC(0xff || sender || salt || code_hash)[12:] // -// Pre stack: sender, endowment, salt, CODE_ADDR: 3, code_len, retdest +// Pre stack: kexit_info, value, code_offset, code_len, salt // Post stack: address -// Note: CODE_ADDR refers to a (context, segment, offset) tuple. global sys_create2: - // stack: sender, endowment, salt, CODE_ADDR: 3, code_len, retdest - DUP7 DUP7 DUP7 DUP7 // CODE_ADDR: 3, code_len + // stack: kexit_info, value, code_offset, code_len, salt + // TODO: Charge gas. + SWAP4 + %stack (salt) -> (salt, sys_create2_got_address) + // stack: salt, sys_create2_got_address, value, code_offset, code_len, kexit_info + DUP4 // code_len + DUP4 // code_offset + PUSH @SEGMENT_MAIN_MEMORY + PUSH 0 // context KECCAK_GENERAL - // stack: code_hash, sender, endowment, salt, CODE_ADDR: 3, code_len, retdest - - // Call get_create2_address and have it return to create_inner. - %stack (code_hash, sender, endowment, salt) - -> (sender, salt, code_hash, create_inner, sender, endowment) - // stack: sender, salt, CODE_ADDR, code_len, create_inner, sender, endowment, CODE_ADDR, code_len, retdest + // stack: hash, salt, sys_create2_got_address, value, code_offset, code_len, kexit_info + %address + // stack: sender, hash, salt, sys_create2_got_address, value, code_offset, code_len, kexit_info %jump(get_create2_address) +sys_create2_got_address: + // stack: address, value, code_offset, code_len, kexit_info + %address + %stack (sender, address, value, code_offset, code_len, kexit_info) + -> (address, sender, value, 0, @SEGMENT_MAIN_MEMORY, code_offset, code_len, + sys_create2_finish, kexit_info) + %jump(create_inner) +sys_create2_finish: + // stack: address, kexit_info + SWAP1 + EXIT_KERNEL // Pre stack: address, sender, endowment, CODE_ADDR, code_len, retdest // Post stack: address diff --git a/evm/src/cpu/kernel/asm/core/gas.asm b/evm/src/cpu/kernel/asm/core/gas.asm index 0cc62e4a..78cc065c 100644 --- a/evm/src/cpu/kernel/asm/core/gas.asm +++ b/evm/src/cpu/kernel/asm/core/gas.asm @@ -47,3 +47,12 @@ global sys_gas: // stack: kexit_info' EXIT_KERNEL %endmacro + +global sys_gasprice: + // stack: kexit_info + %charge_gas_const(@GAS_BASE) + // stack: kexit_info + %mload_txn_field(@TXN_FIELD_COMPUTED_FEE_PER_GAS) + // stack: gas_price, kexit_info + SWAP1 + EXIT_KERNEL diff --git a/evm/src/cpu/kernel/asm/core/syscall_stubs.asm b/evm/src/cpu/kernel/asm/core/syscall_stubs.asm index 23363166..26281eea 100644 --- a/evm/src/cpu/kernel/asm/core/syscall_stubs.asm +++ b/evm/src/cpu/kernel/asm/core/syscall_stubs.asm @@ -44,6 +44,8 @@ global sys_gaslimit: global sys_chainid: // TODO: Return the block's chain ID instead of the txn's, even though they should match. // stack: kexit_info + %charge_gas_const(@GAS_BASE) + // stack: kexit_info %mload_txn_field(@TXN_FIELD_CHAIN_ID) // stack: chain_id, kexit_info SWAP1 diff --git a/evm/src/cpu/kernel/asm/core/terminate.asm b/evm/src/cpu/kernel/asm/core/terminate.asm index 98c65253..4a3fbf02 100644 --- a/evm/src/cpu/kernel/asm/core/terminate.asm +++ b/evm/src/cpu/kernel/asm/core/terminate.asm @@ -20,6 +20,7 @@ global sys_return: global sys_selfdestruct: // stack: kexit_info + // TODO: Charge gas. %consume_gas_const(@GAS_SELFDESTRUCT) %leftover_gas // stack: leftover_gas diff --git a/evm/src/cpu/kernel/asm/memory/metadata.asm b/evm/src/cpu/kernel/asm/memory/metadata.asm index 55c8bebc..89b39707 100644 --- a/evm/src/cpu/kernel/asm/memory/metadata.asm +++ b/evm/src/cpu/kernel/asm/memory/metadata.asm @@ -39,6 +39,8 @@ %endmacro global sys_address: + // stack: kexit_info + %charge_gas_const(@GAS_BASE) // stack: kexit_info %address // stack: address, kexit_info @@ -50,6 +52,8 @@ global sys_address: %endmacro global sys_caller: + // stack: kexit_info + %charge_gas_const(@GAS_BASE) // stack: kexit_info %caller // stack: caller, kexit_info @@ -65,6 +69,8 @@ global sys_caller: %endmacro global sys_codesize: + // stack: kexit_info + %charge_gas_const(@GAS_BASE) // stack: kexit_info %codesize // stack: codesize, kexit_info @@ -72,6 +78,8 @@ global sys_codesize: EXIT_KERNEL global sys_callvalue: + // stack: kexit_info + %charge_gas_const(@GAS_BASE) // stack: kexit_info %callvalue // stack: callvalue, kexit_info @@ -88,6 +96,8 @@ global sys_callvalue: %endmacro global sys_msize: + // stack: kexit_info + %charge_gas_const(@GAS_BASE) // stack: kexit_info %msize // stack: msize, kexit_info diff --git a/evm/src/cpu/kernel/asm/mpt/storage/storage_read.asm b/evm/src/cpu/kernel/asm/mpt/storage/storage_read.asm index e93b333f..cf7ed1e9 100644 --- a/evm/src/cpu/kernel/asm/mpt/storage/storage_read.asm +++ b/evm/src/cpu/kernel/asm/mpt/storage/storage_read.asm @@ -5,6 +5,7 @@ global sys_sload: // stack: kexit_info, slot + // TODO: Charge gas. SWAP1 // stack: slot, kexit_info %stack (slot) -> (slot, after_storage_read) diff --git a/evm/src/cpu/kernel/asm/util/keccak.asm b/evm/src/cpu/kernel/asm/util/keccak.asm index 5665ad3b..280a4047 100644 --- a/evm/src/cpu/kernel/asm/util/keccak.asm +++ b/evm/src/cpu/kernel/asm/util/keccak.asm @@ -1,5 +1,6 @@ global sys_keccak256: // stack: kexit_info, offset, len + // TODO: Charge gas. %stack (kexit_info, offset, len) -> (offset, len, kexit_info) PUSH @SEGMENT_MAIN_MEMORY GET_CONTEXT From 692575a24bf190267c38db561dad78121cddfaee Mon Sep 17 00:00:00 2001 From: Hamish Ivey-Law <426294+unzvfu@users.noreply.github.com> Date: Tue, 21 Mar 2023 02:20:11 +1100 Subject: [PATCH 103/121] Bump eth_trie_utils version. (#923) --- evm/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/evm/Cargo.toml b/evm/Cargo.toml index d9de1d16..37333027 100644 --- a/evm/Cargo.toml +++ b/evm/Cargo.toml @@ -13,7 +13,7 @@ edition = "2021" anyhow = "1.0.40" blake2 = "0.10.5" env_logger = "0.10.0" -eth_trie_utils = "0.4.0" +eth_trie_utils = "0.4.1" ethereum-types = "0.14.0" hex = { version = "0.4.3", optional = true } hex-literal = "0.3.4" From 25575df57c95fa61e3be96c0ba885e221c65fda6 Mon Sep 17 00:00:00 2001 From: Dmitry Vagner Date: Mon, 20 Mar 2023 11:49:13 -0700 Subject: [PATCH 104/121] cleanup --- evm/src/bls381_arithmetic.rs | 76 ++++++++++++++++++++---------------- 1 file changed, 42 insertions(+), 34 deletions(-) diff --git a/evm/src/bls381_arithmetic.rs b/evm/src/bls381_arithmetic.rs index f3217639..f47467c7 100644 --- a/evm/src/bls381_arithmetic.rs +++ b/evm/src/bls381_arithmetic.rs @@ -1,9 +1,8 @@ use std::ops::{Add, Div, Mul, Neg, Sub}; use ethereum_types::U512; - -// use rand::distributions::{Distribution, Standard}; -// use rand::Rng; +use rand::distributions::{Distribution, Standard}; +use rand::Rng; pub trait FieldExt: Sized @@ -43,14 +42,14 @@ impl Fp { } } -// impl Distribution for Standard { -// fn sample(&self, rng: &mut R) -> Fp { -// let xs = rng.gen::<[u64; 8]>(); -// Fp { -// val: U512(xs) % BLS_BASE, -// } -// } -// } +impl Distribution for Standard { + fn sample(&self, rng: &mut R) -> Fp { + let xs = rng.gen::<[u64; 8]>(); + Fp { + val: U512(xs) % BLS_BASE, + } + } +} impl Add for Fp { type Output = Self; @@ -105,11 +104,11 @@ impl Mul for Fp { type Output = Self; fn mul(self, other: Self) -> Self { - // x1, y1 are at most (q-1) // 2^256 < 2^125 - let x1 = U512(self.val.0[..4].try_into().unwrap()); - let x0 = U512(self.val.0[4..].try_into().unwrap()); - let y1 = U512(other.val.0[..4].try_into().unwrap()); - let y0 = U512(other.val.0[4..].try_into().unwrap()); + // x1, y1 are at most ((q-1) // 2^256) < 2^125 + let x0 = U512(self.val.0[..4].try_into().unwrap()); + let x1 = U512(self.val.0[4..].try_into().unwrap()); + let y0 = U512(other.val.0[..4].try_into().unwrap()); + let y1 = U512(other.val.0[4..].try_into().unwrap()); let z00 = Fp { val: x0.saturating_mul(y0) % BLS_BASE, @@ -169,12 +168,15 @@ where pub im: T, } -// impl> Distribution> for Standard { -// fn sample(&self, rng: &mut R) -> Fp2 { -// let (re, im) = rng.gen::<(T, T)>(); -// Fp2 { re, im } -// } -// } +impl + FieldExt> Distribution> for Standard +where + Standard: Distribution, +{ + fn sample(&self, rng: &mut R) -> Fp2 { + let (re, im) = rng.gen::<(T, T)>(); + Fp2 { re, im } + } +} impl Add for Fp2 { type Output = Self; @@ -300,12 +302,15 @@ where pub t2: Fp2, } -// impl> Distribution> for Standard { -// fn sample(&self, rng: &mut R) -> Fp6 { -// let (t0, t1, t2) = rng.gen::<(Fp2, Fp2, Fp2)>(); -// Fp6 { t0, t1, t2 } -// } -// } +impl + FieldExt> Distribution> for Standard +where + Standard: Distribution, +{ + fn sample(&self, rng: &mut R) -> Fp6 { + let (t0, t1, t2) = rng.gen::<(Fp2, Fp2, Fp2)>(); + Fp6 { t0, t1, t2 } + } +} impl Add for Fp6 { type Output = Self; @@ -506,12 +511,15 @@ impl FieldExt for Fp12 { } } -// impl> Distribution> for Standard { -// fn sample(&self, rng: &mut R) -> Fp12 { -// let (z0, z1) = rng.gen::<(Fp6, Fp6)>(); -// Fp12 { z0, z1 } -// } -// } +impl + FieldExt> Distribution> for Standard +where + Standard: Distribution, +{ + fn sample(&self, rng: &mut R) -> Fp12 { + let (z0, z1) = rng.gen::<(Fp6, Fp6)>(); + Fp12 { z0, z1 } + } +} impl Add for Fp12 { type Output = Self; From 503880731a871ea6f90f751b9e7eb5d2f57ae0b7 Mon Sep 17 00:00:00 2001 From: Dmitry Vagner Date: Mon, 20 Mar 2023 11:55:43 -0700 Subject: [PATCH 105/121] rename --- evm/src/bls381_pairing.rs | 0 evm/src/{bls381_arithmetic.rs => extension_tower.rs} | 0 evm/src/lib.rs | 2 +- 3 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 evm/src/bls381_pairing.rs rename evm/src/{bls381_arithmetic.rs => extension_tower.rs} (100%) diff --git a/evm/src/bls381_pairing.rs b/evm/src/bls381_pairing.rs deleted file mode 100644 index e69de29b..00000000 diff --git a/evm/src/bls381_arithmetic.rs b/evm/src/extension_tower.rs similarity index 100% rename from evm/src/bls381_arithmetic.rs rename to evm/src/extension_tower.rs diff --git a/evm/src/lib.rs b/evm/src/lib.rs index 61c5a07c..fa48d8dc 100644 --- a/evm/src/lib.rs +++ b/evm/src/lib.rs @@ -8,13 +8,13 @@ pub mod all_stark; pub mod arithmetic; -pub mod bls381_arithmetic; pub mod bn254_arithmetic; pub mod bn254_pairing; pub mod config; pub mod constraint_consumer; pub mod cpu; pub mod cross_table_lookup; +pub mod extension_tower; pub mod fixed_recursive_verifier; pub mod generation; mod get_challenges; From 5e98a5f90722d5594357b818daac5ba0ef3a18ef Mon Sep 17 00:00:00 2001 From: Dmitry Vagner Date: Mon, 20 Mar 2023 12:25:23 -0700 Subject: [PATCH 106/121] adj trait --- evm/src/extension_tower.rs | 183 ++++++++++++++++++++++++++----------- 1 file changed, 131 insertions(+), 52 deletions(-) diff --git a/evm/src/extension_tower.rs b/evm/src/extension_tower.rs index f47467c7..3a8d7443 100644 --- a/evm/src/extension_tower.rs +++ b/evm/src/extension_tower.rs @@ -30,77 +30,77 @@ pub const BLS_BASE: U512 = U512([ ]); #[derive(Debug, Copy, Clone, PartialEq)] -pub struct Fp { +pub struct Fp381 { pub val: U512, } -impl Fp { - pub fn new(val: usize) -> Fp { - Fp { +impl Fp381 { + pub fn new(val: usize) -> Fp381 { + Fp381 { val: U512::from(val), } } } -impl Distribution for Standard { - fn sample(&self, rng: &mut R) -> Fp { +impl Distribution for Standard { + fn sample(&self, rng: &mut R) -> Fp381 { let xs = rng.gen::<[u64; 8]>(); - Fp { + Fp381 { val: U512(xs) % BLS_BASE, } } } -impl Add for Fp { +impl Add for Fp381 { type Output = Self; fn add(self, other: Self) -> Self { - Fp { + Fp381 { val: (self.val + other.val) % BLS_BASE, } } } -impl Neg for Fp { +impl Neg for Fp381 { type Output = Self; fn neg(self) -> Self::Output { - Fp { + Fp381 { val: (BLS_BASE - self.val) % BLS_BASE, } } } -impl Sub for Fp { +impl Sub for Fp381 { type Output = Self; fn sub(self, other: Self) -> Self { - Fp { + Fp381 { val: (BLS_BASE + self.val - other.val) % BLS_BASE, } } } -impl Fp { - fn lsh_128(self) -> Fp { +impl Fp381 { + fn lsh_128(self) -> Fp381 { let b128: U512 = U512([0, 0, 1, 0, 0, 0, 0, 0]); // since BLS_BASE < 2^384, multiplying by 2^128 doesn't overflow the U512 - Fp { + Fp381 { val: self.val.saturating_mul(b128) % BLS_BASE, } } - fn lsh_256(self) -> Fp { + fn lsh_256(self) -> Fp381 { self.lsh_128().lsh_128() } - fn lsh_512(self) -> Fp { + fn lsh_512(self) -> Fp381 { self.lsh_256().lsh_256() } } #[allow(clippy::suspicious_arithmetic_impl)] -impl Mul for Fp { +impl Mul for Fp381 { type Output = Self; fn mul(self, other: Self) -> Self { @@ -110,16 +110,16 @@ impl Mul for Fp { let y0 = U512(other.val.0[..4].try_into().unwrap()); let y1 = U512(other.val.0[4..].try_into().unwrap()); - let z00 = Fp { + let z00 = Fp381 { val: x0.saturating_mul(y0) % BLS_BASE, }; - let z01 = Fp { + let z01 = Fp381 { val: x0.saturating_mul(y1), }; - let z10 = Fp { + let z10 = Fp381 { val: x1.saturating_mul(y0), }; - let z11 = Fp { + let z11 = Fp381 { val: x1.saturating_mul(y1), }; @@ -127,16 +127,16 @@ impl Mul for Fp { } } -impl FieldExt for Fp { - const ZERO: Self = Fp { val: U512::zero() }; - const UNIT: Self = Fp { val: U512::one() }; - fn inv(self) -> Fp { +impl FieldExt for Fp381 { + const ZERO: Self = Fp381 { val: U512::zero() }; + const UNIT: Self = Fp381 { val: U512::one() }; + fn inv(self) -> Fp381 { exp_fp(self, BLS_BASE - 2) } } #[allow(clippy::suspicious_arithmetic_impl)] -impl Div for Fp { +impl Div for Fp381 { type Output = Self; fn div(self, rhs: Self) -> Self::Output { @@ -144,9 +144,9 @@ impl Div for Fp { } } -fn exp_fp(x: Fp, e: U512) -> Fp { +fn exp_fp(x: Fp381, e: U512) -> Fp381 { let mut current = x; - let mut product = Fp { val: U512::one() }; + let mut product = Fp381 { val: U512::one() }; for j in 0..512 { if e.bit(j) { @@ -168,8 +168,9 @@ where pub im: T, } -impl + FieldExt> Distribution> for Standard +impl Distribution> for Standard where + T: Distribution + FieldExt, Standard: Distribution, { fn sample(&self, rng: &mut R) -> Fp2 { @@ -281,7 +282,7 @@ pub trait Adj { /// Helper function which multiplies by the Fp2 element /// whose cube root we will adjoin in the next extension -impl Adj for Fp2 { +impl Adj for Fp2 { fn mul_adj(self) -> Self { Fp2 { re: self.re - self.im, @@ -296,14 +297,17 @@ impl Adj for Fp2 { pub struct Fp6 where T: FieldExt, + Fp2: Adj, { pub t0: Fp2, pub t1: Fp2, pub t2: Fp2, } -impl + FieldExt> Distribution> for Standard +impl Distribution> for Standard where + T: Distribution + FieldExt, + Fp2: Adj, Standard: Distribution, { fn sample(&self, rng: &mut R) -> Fp6 { @@ -312,7 +316,11 @@ where } } -impl Add for Fp6 { +impl Add for Fp6 +where + T: FieldExt, + Fp2: Adj, +{ type Output = Self; fn add(self, other: Self) -> Self { @@ -324,7 +332,11 @@ impl Add for Fp6 { } } -impl Neg for Fp6 { +impl Neg for Fp6 +where + T: FieldExt, + Fp2: Adj, +{ type Output = Self; fn neg(self) -> Self::Output { @@ -336,7 +348,11 @@ impl Neg for Fp6 { } } -impl Sub for Fp6 { +impl Sub for Fp6 +where + T: FieldExt, + Fp2: Adj, +{ type Output = Self; fn sub(self, other: Self) -> Self { @@ -348,7 +364,11 @@ impl Sub for Fp6 { } } -impl Mul for Fp6 { +impl Mul for Fp6 +where + T: FieldExt, + Fp2: Adj, +{ type Output = Self; fn mul(self, other: Self) -> Self { @@ -360,7 +380,11 @@ impl Mul for Fp6 { } } -impl Fp6 { +impl Fp6 +where + T: FieldExt, + Fp2: Adj, +{ // This function scalar multiplies an Fp6 by an Fp2 fn scale(self, x: Fp2) -> Fp6 { Fp6 { @@ -371,7 +395,11 @@ impl Fp6 { } } -impl Fp6 { +impl Fp6 +where + T: FieldExt, + Fp2: Adj, +{ /// This function multiplies an Fp6 element by t, and hence shifts the bases, /// where the t^2 coefficient picks up a factor of 1+i as the 1 coefficient of the output fn sh(self) -> Fp6 { @@ -383,12 +411,20 @@ impl Fp6 { } } -impl Fp6 { +impl Fp6 +where + T: FieldExt, + Fp2: Adj, +{ const FROB_T: [[Fp2; 6]; 2] = [[Fp2::::ZERO; 6]; 2]; const FROB_Z: [Fp2; 12] = [Fp2::::ZERO; 12]; } -impl Fp6 { +impl Fp6 +where + T: FieldExt, + Fp2: Adj, +{ /// The nth frobenius endomorphism of a p^q field is given by mapping /// x to x^(p^n) /// which sends a + bt + ct^2: Fp6 to @@ -418,7 +454,11 @@ impl Fp6 { } } -impl FieldExt for Fp6 { +impl FieldExt for Fp6 +where + T: FieldExt, + Fp2: Adj, +{ const ZERO: Fp6 = Fp6 { t0: Fp2::::ZERO, t1: Fp2::::ZERO, @@ -457,7 +497,11 @@ impl FieldExt for Fp6 { } #[allow(clippy::suspicious_arithmetic_impl)] -impl Div for Fp6 { +impl Div for Fp6 +where + T: FieldExt, + Fp2: Adj, +{ type Output = Self; fn div(self, rhs: Self) -> Self::Output { @@ -471,12 +515,17 @@ impl Div for Fp6 { pub struct Fp12 where T: FieldExt, + Fp2: Adj, { pub z0: Fp6, pub z1: Fp6, } -impl FieldExt for Fp12 { +impl FieldExt for Fp12 +where + T: FieldExt, + Fp2: Adj, +{ const ZERO: Fp12 = Fp12 { z0: Fp6::::ZERO, z1: Fp6::::ZERO, @@ -511,8 +560,10 @@ impl FieldExt for Fp12 { } } -impl + FieldExt> Distribution> for Standard +impl Distribution> for Standard where + T: Distribution + FieldExt, + Fp2: Adj, Standard: Distribution, { fn sample(&self, rng: &mut R) -> Fp12 { @@ -521,7 +572,11 @@ where } } -impl Add for Fp12 { +impl Add for Fp12 +where + T: FieldExt, + Fp2: Adj, +{ type Output = Self; fn add(self, other: Self) -> Self { @@ -532,7 +587,11 @@ impl Add for Fp12 { } } -impl Neg for Fp12 { +impl Neg for Fp12 +where + T: FieldExt, + Fp2: Adj, +{ type Output = Self; fn neg(self) -> Self::Output { @@ -543,7 +602,11 @@ impl Neg for Fp12 { } } -impl Sub for Fp12 { +impl Sub for Fp12 +where + T: FieldExt, + Fp2: Adj, +{ type Output = Self; fn sub(self, other: Self) -> Self { @@ -554,7 +617,11 @@ impl Sub for Fp12 { } } -impl Mul for Fp12 { +impl Mul for Fp12 +where + T: FieldExt, + Fp2: Adj, +{ type Output = Self; fn mul(self, other: Self) -> Self { @@ -568,7 +635,11 @@ impl Mul for Fp12 { } } -impl Fp12 { +impl Fp12 +where + T: FieldExt, + Fp2: Adj, +{ // This function scalar multiplies an Fp12 by an Fp6 fn scale(self, x: Fp6) -> Fp12 { Fp12 { @@ -585,7 +656,11 @@ impl Fp12 { } } -impl Fp12 { +impl Fp12 +where + T: FieldExt, + Fp2: Adj, +{ /// The nth frobenius endomorphism of a p^q field is given by mapping /// x to x^(p^n) /// which sends a + bz: Fp12 to @@ -601,7 +676,11 @@ impl Fp12 { } #[allow(clippy::suspicious_arithmetic_impl)] -impl Div for Fp12 { +impl Div for Fp12 +where + T: FieldExt, + Fp2: Adj, +{ type Output = Self; fn div(self, rhs: Self) -> Self::Output { From 2752456e5d803bb8972807d41e3b4306eaef2070 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Mon, 20 Mar 2023 12:31:36 -0700 Subject: [PATCH 107/121] addressed comments --- evm/src/cpu/kernel/tests/bignum/mod.rs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/evm/src/cpu/kernel/tests/bignum/mod.rs b/evm/src/cpu/kernel/tests/bignum/mod.rs index 7fc676ef..57038e69 100644 --- a/evm/src/cpu/kernel/tests/bignum/mod.rs +++ b/evm/src/cpu/kernel/tests/bignum/mod.rs @@ -27,7 +27,7 @@ const TEST_DATA_ADD_OUTPUTS: &str = "add_outputs"; const TEST_DATA_ADDMUL_OUTPUTS: &str = "addmul_outputs"; const TEST_DATA_MUL_OUTPUTS: &str = "mul_outputs"; -const BIT_SIZES_TO_TEST: [usize; 4] = [128, 256, 512, 1000]; +const BIT_SIZES_TO_TEST: [usize; 15] = [0, 1, 2, 127, 128, 129, 255, 256, 257, 512, 1000, 1023, 1024, 1025, 31415]; fn full_path(filename: &str) -> PathBuf { let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); @@ -259,7 +259,7 @@ fn test_iszero_bignum_all() -> Result<()> { test_iszero_bignum(input, output.into())?; let input = max_bignum(bit_size); - let output = 0; + let output = bit_size.is_zero() as u8; test_iszero_bignum(input, output.into())?; } @@ -295,8 +295,8 @@ fn test_cmp_bignum_all() -> Result<()> { let inputs = test_data_biguint(TEST_DATA_BIGNUM_INPUTS); let cmp_outputs = test_data_u256(TEST_DATA_CMP_OUTPUTS); let mut cmp_outputs_iter = cmp_outputs.iter(); - for a in inputs.clone() { - for b in inputs.clone() { + for a in &inputs { + for b in &inputs { let output = cmp_outputs_iter.next().unwrap(); test_cmp_bignum(a.clone(), b.clone(), *output)?; } @@ -322,8 +322,8 @@ fn test_add_bignum_all() -> Result<()> { let inputs = test_data_biguint(TEST_DATA_BIGNUM_INPUTS); let add_outputs = test_data_biguint(TEST_DATA_ADD_OUTPUTS); let mut add_outputs_iter = add_outputs.iter(); - for a in inputs.clone() { - for b in inputs.clone() { + for a in &inputs { + for b in &inputs { let output = add_outputs_iter.next().unwrap(); test_add_bignum(a.clone(), b.clone(), output.clone())?; } @@ -354,11 +354,11 @@ fn test_addmul_bignum_all() -> Result<()> { let u128_inputs = test_data_u128(TEST_DATA_U128_INPUTS); let addmul_outputs = test_data_biguint(TEST_DATA_ADDMUL_OUTPUTS); let mut addmul_outputs_iter = addmul_outputs.iter(); - for a in inputs.clone() { - for b in inputs.clone() { - for c in u128_inputs.clone() { + for a in &inputs { + for b in &inputs { + for c in &u128_inputs { let output = addmul_outputs_iter.next().unwrap(); - test_addmul_bignum(a.clone(), b.clone(), c, output.clone())?; + test_addmul_bignum(a.clone(), b.clone(), c.clone(), output.clone())?; } } } @@ -383,8 +383,8 @@ fn test_mul_bignum_all() -> Result<()> { let inputs = test_data_biguint(TEST_DATA_BIGNUM_INPUTS); let mul_outputs = test_data_biguint(TEST_DATA_MUL_OUTPUTS); let mut mul_outputs_iter = mul_outputs.iter(); - for a in inputs.clone() { - for b in inputs.clone() { + for a in &inputs { + for b in &inputs { let output = mul_outputs_iter.next().unwrap(); test_mul_bignum(a.clone(), b.clone(), output.clone())?; } From 72b5bb0eac6c1559efa5124ad0c8bb8abbdb0dad Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Mon, 20 Mar 2023 12:31:41 -0700 Subject: [PATCH 108/121] fmt --- evm/src/cpu/kernel/tests/bignum/mod.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/evm/src/cpu/kernel/tests/bignum/mod.rs b/evm/src/cpu/kernel/tests/bignum/mod.rs index 57038e69..a689b352 100644 --- a/evm/src/cpu/kernel/tests/bignum/mod.rs +++ b/evm/src/cpu/kernel/tests/bignum/mod.rs @@ -27,7 +27,9 @@ const TEST_DATA_ADD_OUTPUTS: &str = "add_outputs"; const TEST_DATA_ADDMUL_OUTPUTS: &str = "addmul_outputs"; const TEST_DATA_MUL_OUTPUTS: &str = "mul_outputs"; -const BIT_SIZES_TO_TEST: [usize; 15] = [0, 1, 2, 127, 128, 129, 255, 256, 257, 512, 1000, 1023, 1024, 1025, 31415]; +const BIT_SIZES_TO_TEST: [usize; 15] = [ + 0, 1, 2, 127, 128, 129, 255, 256, 257, 512, 1000, 1023, 1024, 1025, 31415, +]; fn full_path(filename: &str) -> PathBuf { let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); From f6b9d6ee2e57b1622010dd3bafbd2e43451947d1 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Mon, 20 Mar 2023 12:36:07 -0700 Subject: [PATCH 109/121] addressed comments --- evm/src/cpu/kernel/asm/util/basic_macros.asm | 8 -------- evm/src/cpu/kernel/tests/bignum/mod.rs | 2 +- plonky2/src/fri/recursive_verifier.rs | 8 ++++++-- plonky2/src/gadgets/split_base.rs | 3 ++- plonky2/src/gates/random_access.rs | 4 +++- plonky2/src/hash/merkle_tree.rs | 4 +++- plonky2/src/iop/generator.rs | 3 ++- plonky2/src/iop/witness.rs | 6 ++++-- 8 files changed, 21 insertions(+), 17 deletions(-) diff --git a/evm/src/cpu/kernel/asm/util/basic_macros.asm b/evm/src/cpu/kernel/asm/util/basic_macros.asm index 3f4c4c69..50857eaa 100644 --- a/evm/src/cpu/kernel/asm/util/basic_macros.asm +++ b/evm/src/cpu/kernel/asm/util/basic_macros.asm @@ -50,14 +50,6 @@ %endrep %endmacro -%macro neq - // stack: x, y - EQ - // stack: x == y - ISZERO - // stack: x != y -%endmacro - %macro and_const(c) // stack: input, ... PUSH $c diff --git a/evm/src/cpu/kernel/tests/bignum/mod.rs b/evm/src/cpu/kernel/tests/bignum/mod.rs index a689b352..4b1a7460 100644 --- a/evm/src/cpu/kernel/tests/bignum/mod.rs +++ b/evm/src/cpu/kernel/tests/bignum/mod.rs @@ -360,7 +360,7 @@ fn test_addmul_bignum_all() -> Result<()> { for b in &inputs { for c in &u128_inputs { let output = addmul_outputs_iter.next().unwrap(); - test_addmul_bignum(a.clone(), b.clone(), c.clone(), output.clone())?; + test_addmul_bignum(a.clone(), b.clone(), *c, output.clone())?; } } } diff --git a/plonky2/src/fri/recursive_verifier.rs b/plonky2/src/fri/recursive_verifier.rs index 307c4785..8e9329d5 100644 --- a/plonky2/src/fri/recursive_verifier.rs +++ b/plonky2/src/fri/recursive_verifier.rs @@ -78,12 +78,16 @@ impl, const D: usize> CircuitBuilder { assert!( self.config.num_wires >= min_wires, - "To efficiently perform FRI checks with an arity of 2^{max_fri_arity_bits}, at least {min_wires} wires are needed. Consider reducing arity." + "To efficiently perform FRI checks with an arity of 2^{}, at least {} wires are needed. Consider reducing arity.", + max_fri_arity_bits, + min_wires ); assert!( self.config.num_routed_wires >= min_routed_wires, - "To efficiently perform FRI checks with an arity of 2^{max_fri_arity_bits}, at least {min_routed_wires} routed wires are needed. Consider reducing arity." + "To efficiently perform FRI checks with an arity of 2^{}, at least {} routed wires are needed. Consider reducing arity.", + max_fri_arity_bits, + min_routed_wires ); } diff --git a/plonky2/src/gadgets/split_base.rs b/plonky2/src/gadgets/split_base.rs index 7558be3d..dd0edf5d 100644 --- a/plonky2/src/gadgets/split_base.rs +++ b/plonky2/src/gadgets/split_base.rs @@ -38,7 +38,8 @@ impl, const D: usize> CircuitBuilder { let num_bits = bits.len(); assert!( num_bits <= log_floor(F::ORDER, 2), - "{num_bits} bits may overflow the field" + "{} bits may overflow the field", + num_bits ); if num_bits == 0 { return self.zero(); diff --git a/plonky2/src/gates/random_access.rs b/plonky2/src/gates/random_access.rs index b74b1169..80874505 100644 --- a/plonky2/src/gates/random_access.rs +++ b/plonky2/src/gates/random_access.rs @@ -361,7 +361,9 @@ impl, const D: usize> SimpleGenerator let access_index = access_index_f.to_canonical_u64() as usize; debug_assert!( access_index < vec_size, - "Access index {access_index} is larger than the vector size {vec_size}" + "Access index {} is larger than the vector size {}", + access_index, + vec_size ); set_local_wire( diff --git a/plonky2/src/hash/merkle_tree.rs b/plonky2/src/hash/merkle_tree.rs index beb22b07..e884554f 100644 --- a/plonky2/src/hash/merkle_tree.rs +++ b/plonky2/src/hash/merkle_tree.rs @@ -136,7 +136,9 @@ impl> MerkleTree { let log2_leaves_len = log2_strict(leaves.len()); assert!( cap_height <= log2_leaves_len, - "cap_height={cap_height} should be at most log2(leaves.len())={log2_leaves_len}" + "cap_height={} should be at most log2(leaves.len())={}", + cap_height, + log2_leaves_len ); let num_digests = 2 * (leaves.len() - (1 << cap_height)); diff --git a/plonky2/src/iop/generator.rs b/plonky2/src/iop/generator.rs index 80eb0094..a65d1748 100644 --- a/plonky2/src/iop/generator.rs +++ b/plonky2/src/iop/generator.rs @@ -89,7 +89,8 @@ pub(crate) fn generate_partial_witness< assert_eq!( remaining_generators, 0, - "{remaining_generators} generators weren't run", + "{} generators weren't run", + remaining_generators, ); witness diff --git a/plonky2/src/iop/witness.rs b/plonky2/src/iop/witness.rs index d0e3e7e4..14213d0d 100644 --- a/plonky2/src/iop/witness.rs +++ b/plonky2/src/iop/witness.rs @@ -284,7 +284,8 @@ impl WitnessWrite for PartialWitness { if let Some(old_value) = opt_old_value { assert_eq!( value, old_value, - "Target {target:?} was set twice with different values: {old_value} != {value}" + "Target {:?} was set twice with different values: {} != {}", + target, old_value, value ); } } @@ -324,7 +325,8 @@ impl<'a, F: Field> PartitionWitness<'a, F> { if let Some(old_value) = *rep_value { assert_eq!( value, old_value, - "Partition containing {target:?} was set twice with different values: {old_value} != {value}" + "Partition containing {:?} was set twice with different values: {} != {}", + target, old_value, value ); None } else { From a5fad9ebc078f15b279c7bc0af789dd2934275b2 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Mon, 20 Mar 2023 12:36:48 -0700 Subject: [PATCH 110/121] addressed comments --- evm/src/keccak/keccak_stark.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/evm/src/keccak/keccak_stark.rs b/evm/src/keccak/keccak_stark.rs index 61651dd5..c8fe8086 100644 --- a/evm/src/keccak/keccak_stark.rs +++ b/evm/src/keccak/keccak_stark.rs @@ -68,7 +68,7 @@ impl, const D: usize> KeccakStark { let pad_rows = self.generate_trace_rows_for_perm([0; NUM_INPUTS]); while rows.len() < num_rows { - rows.extend(pad_rows.clone()); + rows.extend(&pad_rows); } rows.drain(num_rows..); rows From 652b2bedad1eccc64853dae17acab6bdb9230b59 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Mon, 20 Mar 2023 12:37:37 -0700 Subject: [PATCH 111/121] allow empty stack replacement --- evm/src/cpu/kernel/evm_asm.pest | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/evm/src/cpu/kernel/evm_asm.pest b/evm/src/cpu/kernel/evm_asm.pest index e7337430..3243aecc 100644 --- a/evm/src/cpu/kernel/evm_asm.pest +++ b/evm/src/cpu/kernel/evm_asm.pest @@ -26,7 +26,7 @@ stack = { ^"%stack" ~ stack_placeholders ~ "->" ~ stack_replacements } stack_placeholders = { "(" ~ (stack_placeholder ~ ("," ~ stack_placeholder)*)? ~ ")" } stack_placeholder = { stack_block | identifier } stack_block = { identifier ~ ":" ~ literal_decimal } -stack_replacements = { "(" ~ stack_replacement ~ ("," ~ stack_replacement)* ~ ")" } +stack_replacements = { "(" ~ (stack_replacement ~ ("," ~ stack_replacement)*)? ~ ")" } stack_replacement = { literal | identifier | constant | macro_label | variable } global_label_decl = ${ ^"GLOBAL " ~ identifier ~ ":" } From 3c4bc1d8246107060b0008255f31a4aa2ff286b1 Mon Sep 17 00:00:00 2001 From: Daniel Lubarov Date: Mon, 20 Mar 2023 18:02:20 -0700 Subject: [PATCH 112/121] Fix GAS and implement storage value parsing --- evm/src/cpu/kernel/asm/mpt/load/load_trie_specific.asm | 5 ++++- evm/src/witness/transition.rs | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/evm/src/cpu/kernel/asm/mpt/load/load_trie_specific.asm b/evm/src/cpu/kernel/asm/mpt/load/load_trie_specific.asm index b93b36e4..80c6dbbe 100644 --- a/evm/src/cpu/kernel/asm/mpt/load/load_trie_specific.asm +++ b/evm/src/cpu/kernel/asm/mpt/load/load_trie_specific.asm @@ -37,4 +37,7 @@ global mpt_load_receipt_trie_value: global mpt_load_storage_trie_value: // stack: retdest - PANIC // TODO + PROVER_INPUT(mpt) + %append_to_trie_data + // stack: retdest + JUMP diff --git a/evm/src/witness/transition.rs b/evm/src/witness/transition.rs index d48561db..be6aba94 100644 --- a/evm/src/witness/transition.rs +++ b/evm/src/witness/transition.rs @@ -108,6 +108,7 @@ fn decode(registers: RegistersState, opcode: u8) -> Result Ok(Operation::Jumpi), (0x58, _) => Ok(Operation::Pc), (0x59, _) => Ok(Operation::Syscall(opcode)), + (0x5a, _) => Ok(Operation::Syscall(opcode)), (0x5b, _) => Ok(Operation::Jumpdest), (0x60..=0x7f, _) => Ok(Operation::Push(opcode & 0x1f)), (0x80..=0x8f, _) => Ok(Operation::Dup(opcode & 0xf)), From 893b88c309e073bc370b439c26da8f0f9d01f6c1 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Tue, 21 Mar 2023 05:54:29 +0100 Subject: [PATCH 113/121] Implement syscalls for BALANCE and SELFBALANCE (#922) * Implement syscalls for BALANCE and SELFBALANCE * Remove stubs --- evm/src/cpu/kernel/asm/balance.asm | 35 +++++++++++++++---- evm/src/cpu/kernel/asm/core/syscall_stubs.asm | 4 --- 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/evm/src/cpu/kernel/asm/balance.asm b/evm/src/cpu/kernel/asm/balance.asm index 6ce88cc4..1c7fb400 100644 --- a/evm/src/cpu/kernel/asm/balance.asm +++ b/evm/src/cpu/kernel/asm/balance.asm @@ -1,3 +1,20 @@ +global sys_balance: + // stack: kexit_info, address + // TODO: assuming a cold account access for now. + %charge_gas_const(@GAS_COLDACCOUNTACCESS) + SWAP1 + // stack: address, kexit_info + %balance + // stack: balance, kexit_info + SWAP1 + EXIT_KERNEL + +%macro balance + %stack (address) -> (address, %%after) + %jump(balance) +%%after: +%endmacro + global balance: // stack: address, retdest %mpt_read_state_trie @@ -13,11 +30,17 @@ retzero: %stack (account_ptr, retdest) -> (retdest, 0) JUMP +global sys_selfbalance: + // stack: kexit_info + %charge_gas_const(@GAS_LOW) + %selfbalance + // stack: balance, kexit_info + SWAP1 + EXIT_KERNEL -global selfbalance: - // stack: retdest +%macro selfbalance + PUSH %%after %address - PUSH balance - // stack: balance, address, retdest - JUMP - + %jump(balance) +%%after: +%endmacro \ No newline at end of file diff --git a/evm/src/cpu/kernel/asm/core/syscall_stubs.asm b/evm/src/cpu/kernel/asm/core/syscall_stubs.asm index 26281eea..610c7502 100644 --- a/evm/src/cpu/kernel/asm/core/syscall_stubs.asm +++ b/evm/src/cpu/kernel/asm/core/syscall_stubs.asm @@ -13,8 +13,6 @@ global sys_sgt: PANIC global sys_sar: PANIC -global sys_balance: - PANIC global sys_origin: PANIC global sys_calldatasize: @@ -50,8 +48,6 @@ global sys_chainid: // stack: chain_id, kexit_info SWAP1 EXIT_KERNEL -global sys_selfbalance: - PANIC global sys_basefee: PANIC global sys_log0: From afded1682b13c1d8adf45d7c4ebb2cc94b4ac4e3 Mon Sep 17 00:00:00 2001 From: Daniel Lubarov Date: Mon, 20 Mar 2023 21:40:58 -0700 Subject: [PATCH 114/121] Contract creation fixes --- evm/src/cpu/kernel/asm/balance.asm | 2 +- evm/src/cpu/kernel/asm/core/create.asm | 14 ++- .../cpu/kernel/asm/core/create_addresses.asm | 24 +++- evm/src/cpu/kernel/asm/core/nonce.asm | 26 +++-- evm/src/cpu/kernel/asm/core/process_txn.asm | 103 ++++++++++++++---- evm/src/cpu/kernel/asm/core/terminate.asm | 11 +- .../asm/mpt/insert/insert_trie_specific.asm | 6 + .../cpu/kernel/asm/transactions/type_0.asm | 2 +- evm/src/generation/state.rs | 10 +- 9 files changed, 149 insertions(+), 49 deletions(-) diff --git a/evm/src/cpu/kernel/asm/balance.asm b/evm/src/cpu/kernel/asm/balance.asm index 1c7fb400..1c6429d2 100644 --- a/evm/src/cpu/kernel/asm/balance.asm +++ b/evm/src/cpu/kernel/asm/balance.asm @@ -43,4 +43,4 @@ global sys_selfbalance: %address %jump(balance) %%after: -%endmacro \ No newline at end of file +%endmacro diff --git a/evm/src/cpu/kernel/asm/core/create.asm b/evm/src/cpu/kernel/asm/core/create.asm index cc37f832..d7e6eed2 100644 --- a/evm/src/cpu/kernel/asm/core/create.asm +++ b/evm/src/cpu/kernel/asm/core/create.asm @@ -1,3 +1,7 @@ +// TODO: This file needs to be cleaned up. +// `create` is no longer being used for contract-creation txns, +// so it can be inlined. Also need to set metadata on new ctx. + // The CREATE syscall. // // Pre stack: kexit_info, value, code_offset, code_len @@ -24,8 +28,8 @@ sys_create_finish: // Note: CODE_ADDR refers to a (context, segment, offset) tuple. global create: // stack: sender, endowment, CODE_ADDR, code_len, retdest - // TODO: Charge gas. - DUP1 %get_nonce + DUP1 %nonce + // stack: nonce, sender, endowment, CODE_ADDR, code_len, retdest // Call get_create_address and have it return to create_inner. %stack (nonce, sender) @@ -67,12 +71,14 @@ sys_create2_finish: // Pre stack: address, sender, endowment, CODE_ADDR, code_len, retdest // Post stack: address // Note: CODE_ADDR refers to a (context, segment, offset) tuple. -create_inner: +global create_inner: // stack: address, sender, endowment, CODE_ADDR, code_len, retdest %stack (address, sender, endowment) -> (sender, address, endowment, sender, address) - // TODO: Need to handle insufficient balance failure. + %transfer_eth + // stack: transfer_eth_status, sender, address, CODE_ADDR, code_len, retdest + %jumpi(fault_exception) // stack: sender, address, CODE_ADDR, code_len, retdest %increment_nonce diff --git a/evm/src/cpu/kernel/asm/core/create_addresses.asm b/evm/src/cpu/kernel/asm/core/create_addresses.asm index 67fd65a6..8aad8e28 100644 --- a/evm/src/cpu/kernel/asm/core/create_addresses.asm +++ b/evm/src/cpu/kernel/asm/core/create_addresses.asm @@ -5,14 +5,32 @@ // Post stack: address global get_create_address: // stack: sender, nonce, retdest - // TODO: Replace with actual implementation. - %pop2 - PUSH 123 + %alloc_rlp_block + // stack: rlp_start, sender, nonce, retdest + %stack (rlp_start, sender, nonce) -> (rlp_start, sender, nonce, rlp_start) + // stack: rlp_start, sender, nonce, rlp_start, retdest + %encode_rlp_160 // TODO: or encode_rlp_scalar? + // stack: rlp_pos, nonce, rlp_start, retdest + %encode_rlp_scalar + // stack: rlp_pos, rlp_start, retdest + %prepend_rlp_list_prefix + // stack: rlp_prefix_start, rlp_len, retdest + PUSH @SEGMENT_RLP_RAW + PUSH 0 // context + // stack: RLP_ADDR: 3, rlp_len, retdest + KECCAK_GENERAL // stack: address, retdest %observe_new_address SWAP1 JUMP +// Convenience macro to call get_create_address and return where we left off. +%macro get_create_address + %stack (sender, nonce) -> (sender, nonce, %%after) + %jump(get_create_address) +%%after: +%endmacro + // Computes the address for a contract based on the CREATE2 rule, i.e. // address = KEC(0xff || sender || salt || code_hash)[12:] // diff --git a/evm/src/cpu/kernel/asm/core/nonce.asm b/evm/src/cpu/kernel/asm/core/nonce.asm index 042d81f3..973a032d 100644 --- a/evm/src/cpu/kernel/asm/core/nonce.asm +++ b/evm/src/cpu/kernel/asm/core/nonce.asm @@ -1,17 +1,21 @@ -// Increment the nonce of the given account. +// Get the nonce of the given account. // Pre stack: address, retdest // Post stack: (empty) - -global get_nonce: +global nonce: // stack: address, retdest - // TODO: Replace with actual implementation. - POP - JUMP + %mpt_read_state_trie + // stack: account_ptr, retdest + // The nonce is the first account field, so we deref the account pointer itself. + // Note: We don't need to handle account_ptr=0, as trie_data[0] = 0, + // so the deref will give 0 (the default nonce) as desired. + %mload_trie_data + // stack: nonce, retdest + SWAP1 JUMP -// Convenience macro to call get_nonce and return where we left off. -%macro get_nonce +// Convenience macro to call nonce and return where we left off. +%macro nonce %stack (address) -> (address, %%after) - %jump(get_nonce) + %jump(nonce) %%after: %endmacro @@ -20,7 +24,7 @@ global increment_nonce: // stack: address, retdest %mpt_read_state_trie // stack: account_ptr, retdest - DUP1 ISZERO %jumpi(panic) + DUP1 ISZERO %jumpi(increment_nonce_no_such_account) // stack: nonce_ptr, retdest DUP1 %mload_trie_data // stack: nonce, nonce_ptr, retdest @@ -30,6 +34,8 @@ global increment_nonce: %mstore_trie_data // stack: retdest JUMP +global increment_nonce_no_such_account: + PANIC // Convenience macro to call increment_nonce and return where we left off. %macro increment_nonce diff --git a/evm/src/cpu/kernel/asm/core/process_txn.asm b/evm/src/cpu/kernel/asm/core/process_txn.asm index 9629d647..acce98f9 100644 --- a/evm/src/cpu/kernel/asm/core/process_txn.asm +++ b/evm/src/cpu/kernel/asm/core/process_txn.asm @@ -50,23 +50,76 @@ global process_based_on_type: global process_contract_creation_txn: // stack: retdest - PUSH process_contract_creation_txn_after_create - // stack: process_contract_creation_txn_after_create, retdest - %mload_txn_field(@TXN_FIELD_DATA_LEN) - // stack: code_len, process_contract_creation_txn_after_create, retdest - PUSH 0 - // stack: code_offset, code_len, process_contract_creation_txn_after_create, retdest - PUSH @SEGMENT_TXN_DATA - // stack: code_segment, code_offset, code_len, process_contract_creation_txn_after_create, retdest - PUSH 0 // context - // stack: CODE_ADDR, code_len, process_contract_creation_txn_after_create, retdest + + %mload_txn_field(@TXN_FIELD_ORIGIN) + // stack: origin, retdest + DUP1 %nonce + // stack: origin_nonce, origin, retdest + SWAP1 + // stack: origin, origin_nonce, retdest + %get_create_address + // stack: address, retdest + + // Deduct value from caller. %mload_txn_field(@TXN_FIELD_VALUE) %mload_txn_field(@TXN_FIELD_ORIGIN) - // stack: sender, endowment, CODE_ADDR, code_len, process_contract_creation_txn_after_create, retdest - %jump(create) + %deduct_eth + // stack: deduct_eth_status, address, retdest + %jumpi(panic) + // stack: address, retdest -global process_contract_creation_txn_after_create: - // stack: new_address, retdest + // Write the new account's data to MPT data, and get a pointer to it. + %get_trie_data_size + // stack: account_ptr, address, retdest + PUSH 1 %append_to_trie_data // nonce = 1 + // stack: account_ptr, address, retdest + DUP2 %balance %mload_txn_field(@TXN_FIELD_VALUE) ADD %append_to_trie_data // balance = old_balance + txn_value + // stack: account_ptr, address, retdest + PUSH 0 %append_to_trie_data // storage_root = nil + // stack: account_ptr, address, retdest + PUSH @EMPTY_STRING_HASH %append_to_trie_data // code_hash = keccak('') + // stack: account_ptr, address, retdest + DUP2 + // stack: address, account_ptr, address, retdest + %mpt_insert_state_trie + // stack: address, retdest + + %create_context + // stack: new_ctx, address, retdest + + // Copy the code from txdata to the new context's code segment. + PUSH process_contract_creation_txn_after_code_loaded + %mload_txn_field(@TXN_FIELD_DATA_LEN) + PUSH 0 // SRC.offset + PUSH @SEGMENT_TXN_DATA // SRC.segment + PUSH 0 // SRC.context + PUSH 0 // DST.offset + PUSH @SEGMENT_CODE // DST.segment + DUP7 // DST.context = new_ctx + %jump(memcpy) + +process_contract_creation_txn_after_code_loaded: + // stack: new_ctx, address, retdest + + // Each line in the block below does not change the stack. + DUP2 %set_new_ctx_addr + %mload_txn_field(@TXN_FIELD_ORIGIN) %set_new_ctx_caller + %mload_txn_field(@TXN_FIELD_VALUE) %set_new_ctx_value + %set_new_ctx_parent_ctx + %set_new_ctx_parent_pc(process_contract_creation_txn_after_constructor) + %non_intrinisic_gas %set_new_ctx_gas_limit + // stack: new_ctx, address, retdest + + %enter_new_ctx + // (Old context) stack: new_ctx, address, retdest + +global process_contract_creation_txn_after_constructor: + // stack: success, leftover_gas, new_ctx, address, retdest + POP // TODO: Success will go into the receipt when we support that. + // stack: leftover_gas, new_ctx, address, retdest + %pay_coinbase_and_refund_sender + // stack: new_ctx, address, retdest + POP POP JUMP @@ -105,9 +158,8 @@ global process_message_txn_insufficient_balance: global process_message_txn_return: // stack: retdest - %mload_txn_field(@TXN_FIELD_INTRINSIC_GAS) - %mload_txn_field(@TXN_FIELD_GAS_LIMIT) - SUB + // Since no code was executed, the leftover gas is the non-intrinsic gas. + %non_intrinisic_gas // stack: leftover_gas, retdest %pay_coinbase_and_refund_sender // stack: retdest @@ -124,18 +176,13 @@ global process_message_txn_code_loaded: %mload_txn_field(@TXN_FIELD_VALUE) %set_new_ctx_value %set_new_ctx_parent_ctx %set_new_ctx_parent_pc(process_message_txn_after_call) - // stack: new_ctx, retdest - - // The gas provided to the callee is gas_limit - intrinsic_gas. - %mload_txn_field(@TXN_FIELD_INTRINSIC_GAS) - %mload_txn_field(@TXN_FIELD_GAS_LIMIT) - SUB - %set_new_ctx_gas_limit + %non_intrinisic_gas %set_new_ctx_gas_limit // stack: new_ctx, retdest // TODO: Copy TXN_DATA to CALLDATA %enter_new_ctx + // (Old context) stack: new_ctx, retdest global process_message_txn_after_call: // stack: success, leftover_gas, new_ctx, retdest @@ -206,3 +253,11 @@ global process_message_txn_after_call: %mstore_txn_field(@TXN_FIELD_COMPUTED_PRIORITY_FEE_PER_GAS) // stack: (empty) %endmacro + +%macro non_intrinisic_gas + // stack: (empty) + %mload_txn_field(@TXN_FIELD_INTRINSIC_GAS) + %mload_txn_field(@TXN_FIELD_GAS_LIMIT) + SUB + // stack: gas_limit - intrinsic_gas +%endmacro diff --git a/evm/src/cpu/kernel/asm/core/terminate.asm b/evm/src/cpu/kernel/asm/core/terminate.asm index 4a3fbf02..26fb113c 100644 --- a/evm/src/cpu/kernel/asm/core/terminate.asm +++ b/evm/src/cpu/kernel/asm/core/terminate.asm @@ -97,6 +97,15 @@ global terminate_common: %shr_const(192) // stack: gas_used %mload_context_metadata(@CTX_METADATA_GAS_LIMIT) + // stack: gas_limit, gas_used + SWAP1 + // stack: gas_used, gas_limit + DUP2 DUP2 LT + // stack: gas_used < gas_limit, gas_used, gas_limit + SWAP2 + // stack: gas_limit, gas_used, gas_used < gas_limit SUB - // stack: leftover_gas + // stack: gas_limit - gas_used, gas_used < gas_limit + MUL + // stack: leftover_gas = (gas_limit - gas_used) * (gas_used < gas_limit) %endmacro diff --git a/evm/src/cpu/kernel/asm/mpt/insert/insert_trie_specific.asm b/evm/src/cpu/kernel/asm/mpt/insert/insert_trie_specific.asm index 225f3cc0..60df845e 100644 --- a/evm/src/cpu/kernel/asm/mpt/insert/insert_trie_specific.asm +++ b/evm/src/cpu/kernel/asm/mpt/insert/insert_trie_specific.asm @@ -15,3 +15,9 @@ mpt_insert_state_trie_save: // stack: updated_node_ptr, retdest %mstore_global_metadata(@GLOBAL_METADATA_STATE_TRIE_ROOT) JUMP + +%macro mpt_insert_state_trie + %stack (key, value_ptr) -> (key, value_ptr, %%after) + %jump(mpt_insert_state_trie) +%%after: +%endmacro diff --git a/evm/src/cpu/kernel/asm/transactions/type_0.asm b/evm/src/cpu/kernel/asm/transactions/type_0.asm index d00b10d4..45c57361 100644 --- a/evm/src/cpu/kernel/asm/transactions/type_0.asm +++ b/evm/src/cpu/kernel/asm/transactions/type_0.asm @@ -102,7 +102,7 @@ type_0_compute_signed_data: // stack: rlp_pos, rlp_start, retdest %mload_txn_field(@TXN_FIELD_TO) - SWAP1 %encode_rlp_160 + SWAP1 %encode_rlp_scalar // stack: rlp_pos, rlp_start, retdest %mload_txn_field(@TXN_FIELD_VALUE) diff --git a/evm/src/generation/state.rs b/evm/src/generation/state.rs index 9399e4b6..26a0ac81 100644 --- a/evm/src/generation/state.rs +++ b/evm/src/generation/state.rs @@ -1,6 +1,6 @@ use std::collections::HashMap; -use ethereum_types::{Address, H160, H256, U256}; +use ethereum_types::{Address, BigEndianHash, H160, H256, U256}; use keccak_hash::keccak; use plonky2::field::types::Field; @@ -72,10 +72,10 @@ impl GenerationState { pub fn jump_to(&mut self, dst: usize) { self.registers.program_counter = dst; if dst == KERNEL.global_labels["observe_new_address"] { - let address = stack_peek(self, 0).expect("Empty stack"); - let mut address_bytes = [0; 20]; - address.to_big_endian(&mut address_bytes); - self.observe_address(H160(address_bytes)); + let tip_u256 = stack_peek(self, 0).expect("Empty stack"); + let tip_h256 = H256::from_uint(&tip_u256); + let tip_h160 = H160::from(tip_h256); + self.observe_address(tip_h160); } } From e1ae539271827e091819f83abc4d7ff8fe1a7faf Mon Sep 17 00:00:00 2001 From: Daniel Lubarov Date: Mon, 20 Mar 2023 23:57:44 -0700 Subject: [PATCH 115/121] Fix test --- evm/src/cpu/kernel/asm/core/create_addresses.asm | 1 + evm/src/cpu/kernel/tests/core/create_addresses.rs | 10 ++++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/evm/src/cpu/kernel/asm/core/create_addresses.asm b/evm/src/cpu/kernel/asm/core/create_addresses.asm index 8aad8e28..7dd4e889 100644 --- a/evm/src/cpu/kernel/asm/core/create_addresses.asm +++ b/evm/src/cpu/kernel/asm/core/create_addresses.asm @@ -19,6 +19,7 @@ global get_create_address: PUSH 0 // context // stack: RLP_ADDR: 3, rlp_len, retdest KECCAK_GENERAL + %mod_const(0x10000000000000000000000000000000000000000) // 2^160 // stack: address, retdest %observe_new_address SWAP1 diff --git a/evm/src/cpu/kernel/tests/core/create_addresses.rs b/evm/src/cpu/kernel/tests/core/create_addresses.rs index 047ddc00..03d780d8 100644 --- a/evm/src/cpu/kernel/tests/core/create_addresses.rs +++ b/evm/src/cpu/kernel/tests/core/create_addresses.rs @@ -1,4 +1,6 @@ use anyhow::Result; +use ethereum_types::U256; +use hex_literal::hex; use crate::cpu::kernel::aggregator::KERNEL; use crate::cpu::kernel::interpreter::Interpreter; @@ -7,11 +9,11 @@ use crate::cpu::kernel::interpreter::Interpreter; fn test_get_create_address() -> Result<()> { let get_create_address = KERNEL.global_labels["get_create_address"]; - // TODO: Replace with real data once we have a real implementation. + // This is copied from OpenEthereum's `test_contract_address`. let retaddr = 0xdeadbeefu32.into(); - let nonce = 5.into(); - let sender = 0.into(); - let expected_addr = 123.into(); + let nonce = 88.into(); + let sender = U256::from_big_endian(&hex!("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6")); + let expected_addr = U256::from_big_endian(&hex!("3f09c73a5ed19289fb9bdc72f1742566df146f56")); let initial_stack = vec![retaddr, nonce, sender]; let mut interpreter = Interpreter::new_with_kernel(get_create_address, initial_stack); From caaf3b4a34538db00abbfe80a786c742779ce76c Mon Sep 17 00:00:00 2001 From: Dmitry Vagner Date: Tue, 21 Mar 2023 11:42:46 -0700 Subject: [PATCH 116/121] merge fields --- evm/src/extension_tower.rs | 195 ++++++++++++++++++++++++++++--------- 1 file changed, 149 insertions(+), 46 deletions(-) diff --git a/evm/src/extension_tower.rs b/evm/src/extension_tower.rs index 3a8d7443..c95cb24e 100644 --- a/evm/src/extension_tower.rs +++ b/evm/src/extension_tower.rs @@ -1,6 +1,6 @@ use std::ops::{Add, Div, Mul, Neg, Sub}; -use ethereum_types::U512; +use ethereum_types::{U256, U512}; use rand::distributions::{Distribution, Standard}; use rand::Rng; @@ -18,6 +18,102 @@ pub trait FieldExt: fn inv(self) -> Self; } +pub const BN_BASE: U256 = U256([ + 0x3c208c16d87cfd47, + 0x97816a916871ca8d, + 0xb85045b68181585d, + 0x30644e72e131a029, +]); + +#[derive(Debug, Copy, Clone, PartialEq)] +pub struct BN254 { + pub val: U256, +} + +impl BN254 { + pub fn new(val: usize) -> BN254 { + BN254 { + val: U256::from(val), + } + } +} + +impl Distribution for Standard { + fn sample(&self, rng: &mut R) -> BN254 { + let xs = rng.gen::<[u64; 4]>(); + BN254 { + val: U256(xs) % BN_BASE, + } + } +} + +impl Add for BN254 { + type Output = Self; + + fn add(self, other: Self) -> Self { + BN254 { + val: (self.val + other.val) % BN_BASE, + } + } +} + +impl Neg for BN254 { + type Output = Self; + + fn neg(self) -> Self::Output { + BN254 { + val: (BN_BASE - self.val) % BN_BASE, + } + } +} + +impl Sub for BN254 { + type Output = Self; + + fn sub(self, other: Self) -> Self { + BN254 { + val: (BN_BASE + self.val - other.val) % BN_BASE, + } + } +} + +#[allow(clippy::suspicious_arithmetic_impl)] +impl Mul for BN254 { + type Output = Self; + + fn mul(self, other: Self) -> Self { + BN254 { + val: U256::try_from((self.val).full_mul(other.val) % BN_BASE).unwrap(), + } + } +} + +impl FieldExt for BN254 { + const ZERO: Self = BN254 { val: U256::zero() }; + const UNIT: Self = BN254 { val: U256::one() }; + fn inv(self) -> BN254 { + let exp = BN_BASE - 2; + let mut current = self; + let mut product = BN254 { val: U256::one() }; + for j in 0..256 { + if exp.bit(j) { + product = product * current; + } + current = current * current; + } + product + } +} + +#[allow(clippy::suspicious_arithmetic_impl)] +impl Div for BN254 { + type Output = Self; + + fn div(self, rhs: Self) -> Self::Output { + self * rhs.inv() + } +} + pub const BLS_BASE: U512 = U512([ 0xb9feffffffffaaab, 0x1eabfffeb153ffff, @@ -30,77 +126,77 @@ pub const BLS_BASE: U512 = U512([ ]); #[derive(Debug, Copy, Clone, PartialEq)] -pub struct Fp381 { +pub struct BLS381 { pub val: U512, } -impl Fp381 { - pub fn new(val: usize) -> Fp381 { - Fp381 { +impl BLS381 { + pub fn new(val: usize) -> BLS381 { + BLS381 { val: U512::from(val), } } } -impl Distribution for Standard { - fn sample(&self, rng: &mut R) -> Fp381 { +impl Distribution for Standard { + fn sample(&self, rng: &mut R) -> BLS381 { let xs = rng.gen::<[u64; 8]>(); - Fp381 { + BLS381 { val: U512(xs) % BLS_BASE, } } } -impl Add for Fp381 { +impl Add for BLS381 { type Output = Self; fn add(self, other: Self) -> Self { - Fp381 { + BLS381 { val: (self.val + other.val) % BLS_BASE, } } } -impl Neg for Fp381 { +impl Neg for BLS381 { type Output = Self; fn neg(self) -> Self::Output { - Fp381 { + BLS381 { val: (BLS_BASE - self.val) % BLS_BASE, } } } -impl Sub for Fp381 { +impl Sub for BLS381 { type Output = Self; fn sub(self, other: Self) -> Self { - Fp381 { + BLS381 { val: (BLS_BASE + self.val - other.val) % BLS_BASE, } } } -impl Fp381 { - fn lsh_128(self) -> Fp381 { +impl BLS381 { + fn lsh_128(self) -> BLS381 { let b128: U512 = U512([0, 0, 1, 0, 0, 0, 0, 0]); // since BLS_BASE < 2^384, multiplying by 2^128 doesn't overflow the U512 - Fp381 { + BLS381 { val: self.val.saturating_mul(b128) % BLS_BASE, } } - fn lsh_256(self) -> Fp381 { + fn lsh_256(self) -> BLS381 { self.lsh_128().lsh_128() } - fn lsh_512(self) -> Fp381 { + fn lsh_512(self) -> BLS381 { self.lsh_256().lsh_256() } } #[allow(clippy::suspicious_arithmetic_impl)] -impl Mul for Fp381 { +impl Mul for BLS381 { type Output = Self; fn mul(self, other: Self) -> Self { @@ -110,16 +206,16 @@ impl Mul for Fp381 { let y0 = U512(other.val.0[..4].try_into().unwrap()); let y1 = U512(other.val.0[4..].try_into().unwrap()); - let z00 = Fp381 { + let z00 = BLS381 { val: x0.saturating_mul(y0) % BLS_BASE, }; - let z01 = Fp381 { + let z01 = BLS381 { val: x0.saturating_mul(y1), }; - let z10 = Fp381 { + let z10 = BLS381 { val: x1.saturating_mul(y0), }; - let z11 = Fp381 { + let z11 = BLS381 { val: x1.saturating_mul(y1), }; @@ -127,16 +223,26 @@ impl Mul for Fp381 { } } -impl FieldExt for Fp381 { - const ZERO: Self = Fp381 { val: U512::zero() }; - const UNIT: Self = Fp381 { val: U512::one() }; - fn inv(self) -> Fp381 { - exp_fp(self, BLS_BASE - 2) +impl FieldExt for BLS381 { + const ZERO: Self = BLS381 { val: U512::zero() }; + const UNIT: Self = BLS381 { val: U512::one() }; + fn inv(self) -> BLS381 { + let exp = BLS_BASE - 2; + let mut current = self; + let mut product = BLS381 { val: U512::one() }; + + for j in 0..512 { + if exp.bit(j) { + product = product * current; + } + current = current * current; + } + product } } #[allow(clippy::suspicious_arithmetic_impl)] -impl Div for Fp381 { +impl Div for BLS381 { type Output = Self; fn div(self, rhs: Self) -> Self::Output { @@ -144,19 +250,6 @@ impl Div for Fp381 { } } -fn exp_fp(x: Fp381, e: U512) -> Fp381 { - let mut current = x; - let mut product = Fp381 { val: U512::one() }; - - for j in 0..512 { - if e.bit(j) { - product = product * current; - } - current = current * current; - } - product -} - /// The degree 2 field extension Fp2 is given by adjoining i, the square root of -1, to Fp /// The arithmetic in this extension is standard complex arithmetic #[derive(Debug, Copy, Clone, PartialEq)] @@ -276,13 +369,23 @@ impl Div for Fp2 { } } +/// Helper function which multiplies by the Fp2 element +/// whose cube root we will adjoin in the next extension pub trait Adj { fn mul_adj(self) -> Self; } -/// Helper function which multiplies by the Fp2 element -/// whose cube root we will adjoin in the next extension -impl Adj for Fp2 { +impl Adj for Fp2 { + fn mul_adj(self) -> Self { + let nine = BN254::new(9); + Fp2 { + re: nine * self.re - self.im, + im: self.re + nine * self.im, + } + } +} + +impl Adj for Fp2 { fn mul_adj(self) -> Self { Fp2 { re: self.re - self.im, From a79271a8ec541e8abd343c7c4a955c529cd4c15d Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Tue, 21 Mar 2023 20:15:30 +0100 Subject: [PATCH 117/121] Minor account code fixes (#929) * Fixes * Fix * Newline --- evm/src/cpu/kernel/asm/account_code.asm | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/evm/src/cpu/kernel/asm/account_code.asm b/evm/src/cpu/kernel/asm/account_code.asm index 3b18e309..9f8cafcb 100644 --- a/evm/src/cpu/kernel/asm/account_code.asm +++ b/evm/src/cpu/kernel/asm/account_code.asm @@ -63,7 +63,7 @@ global extcodesize: %macro extcodecopy // stack: address, dest_offset, offset, size - %stack (dest_offset, offset, size) -> (dest_offset, offset, size, %%after) + %stack (address, dest_offset, offset, size) -> (address, dest_offset, offset, size, %%after) %jump(extcodecopy) %%after: %endmacro @@ -145,6 +145,7 @@ global load_code: JUMP load_code_ctd: // stack: codehash, ctx, segment, retdest + DUP1 ISZERO %jumpi(load_code_non_existent_account) PROVER_INPUT(account_code::length) // stack: code_size, codehash, ctx, segment, retdest PUSH 0 @@ -177,3 +178,7 @@ load_code_check: // stack: shouldbecodehash, codehash, retdest, code_size %assert_eq JUMP + +load_code_non_existent_account: + %stack (codehash, ctx, segment, retdest) -> (retdest, 0) + JUMP From 2df1439d351c874196d393032ba2d169c6cd977c Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Tue, 21 Mar 2023 20:15:46 +0100 Subject: [PATCH 118/121] Return error instead of panic in memory operation (#928) --- evm/src/witness/errors.rs | 11 +++++++++++ evm/src/witness/memory.rs | 29 +++++++++++++++++++---------- evm/src/witness/operation.rs | 4 ++-- 3 files changed, 32 insertions(+), 12 deletions(-) diff --git a/evm/src/witness/errors.rs b/evm/src/witness/errors.rs index 53263675..e28e7d0f 100644 --- a/evm/src/witness/errors.rs +++ b/evm/src/witness/errors.rs @@ -1,3 +1,5 @@ +use ethereum_types::U256; + #[allow(dead_code)] #[derive(Debug)] pub enum ProgramError { @@ -8,4 +10,13 @@ pub enum ProgramError { InvalidJumpiDestination, StackOverflow, KernelPanic, + MemoryError(MemoryError), +} + +#[allow(clippy::enum_variant_names)] +#[derive(Debug)] +pub enum MemoryError { + ContextTooLarge { context: U256 }, + SegmentTooLarge { segment: U256 }, + VirtTooLarge { virt: U256 }, } diff --git a/evm/src/witness/memory.rs b/evm/src/witness/memory.rs index a2885796..127aac33 100644 --- a/evm/src/witness/memory.rs +++ b/evm/src/witness/memory.rs @@ -12,6 +12,9 @@ use MemoryChannel::{Code, GeneralPurpose}; use crate::cpu::kernel::constants::global_metadata::GlobalMetadata; use crate::memory::segments::Segment; +use crate::witness::errors::MemoryError::{ContextTooLarge, SegmentTooLarge, VirtTooLarge}; +use crate::witness::errors::ProgramError; +use crate::witness::errors::ProgramError::MemoryError; impl MemoryChannel { pub fn index(&self) -> usize { @@ -41,19 +44,25 @@ impl MemoryAddress { } } - pub(crate) fn new_u256s(context: U256, segment: U256, virt: U256) -> Self { - assert!(context.bits() <= 32, "context too large: {}", context); - assert!( - segment < Segment::COUNT.into(), - "segment too large: {}", - segment - ); - assert!(virt.bits() <= 32, "virt too large: {}", virt); - Self { + pub(crate) fn new_u256s( + context: U256, + segment: U256, + virt: U256, + ) -> Result { + if context.bits() > 32 { + return Err(MemoryError(ContextTooLarge { context })); + } + if segment >= Segment::COUNT.into() { + return Err(MemoryError(SegmentTooLarge { segment })); + } + if virt.bits() > 32 { + return Err(MemoryError(VirtTooLarge { virt })); + } + Ok(Self { context: context.as_usize(), segment: segment.as_usize(), virt: virt.as_usize(), - } + }) } pub(crate) fn increment(&mut self) { diff --git a/evm/src/witness/operation.rs b/evm/src/witness/operation.rs index 6d42eb48..43576ff4 100644 --- a/evm/src/witness/operation.rs +++ b/evm/src/witness/operation.rs @@ -111,7 +111,7 @@ pub(crate) fn generate_keccak_general( stack_pop_with_log_and_fill::<4, _>(state, &mut row)?; let len = len.as_usize(); - let base_address = MemoryAddress::new_u256s(context, segment, base_virt); + let base_address = MemoryAddress::new_u256s(context, segment, base_virt)?; let input = (0..len) .map(|i| { let address = MemoryAddress { @@ -608,7 +608,7 @@ pub(crate) fn generate_mload_general( let (val, log_read) = mem_read_gp_with_log_and_fill( 3, - MemoryAddress::new_u256s(context, segment, virt), + MemoryAddress::new_u256s(context, segment, virt)?, state, &mut row, ); From 4d83c58d1f801ddd807292f32ddc296972f5c972 Mon Sep 17 00:00:00 2001 From: Dmitry Vagner Date: Tue, 21 Mar 2023 13:51:11 -0700 Subject: [PATCH 119/121] frob works --- evm/src/cpu/kernel/tests/bn254.rs | 403 +++++++++++++-------------- evm/src/extension_tower.rs | 440 ++++++++++++++++++++++++++++-- 2 files changed, 617 insertions(+), 226 deletions(-) diff --git a/evm/src/cpu/kernel/tests/bn254.rs b/evm/src/cpu/kernel/tests/bn254.rs index badfb472..7195fc73 100644 --- a/evm/src/cpu/kernel/tests/bn254.rs +++ b/evm/src/cpu/kernel/tests/bn254.rs @@ -2,13 +2,14 @@ use anyhow::Result; use ethereum_types::U256; use rand::Rng; -use crate::bn254_arithmetic::{Fp, Fp12, Fp2, Fp6}; -use crate::bn254_pairing::{ - gen_fp12_sparse, invariant_exponent, miller_loop, tate, Curve, TwistedCurve, -}; use crate::cpu::kernel::interpreter::{ run_interpreter_with_memory, Interpreter, InterpreterMemoryInitialization, }; +// use crate::bn254_arithmetic::{Fp, Fp12, Fp2, Fp6}; +// use crate::bn254_pairing::{ +// gen_fp12_sparse, invariant_exponent, miller_loop, tate, Curve, TwistedCurve, +// }; +use crate::extension_tower::{Fp12, Stack, BN254}; use crate::memory::segments::Segment::BnPairing; fn extract_stack(interpreter: Interpreter<'static>) -> Vec { @@ -20,48 +21,48 @@ fn extract_stack(interpreter: Interpreter<'static>) -> Vec { .collect::>() } -fn setup_mul_fp6_test(f: Fp6, g: Fp6, label: &str) -> InterpreterMemoryInitialization { - let mut stack = f.on_stack(); - if label == "mul_fp254_6" { - stack.extend(g.on_stack()); - } - stack.push(U256::from(0xdeadbeefu32)); - InterpreterMemoryInitialization { - label: label.to_string(), - stack, - segment: BnPairing, - memory: vec![], - } -} +// fn setup_mul_fp6_test(f: Fp6, g: Fp6, label: &str) -> InterpreterMemoryInitialization { +// let mut stack = f.on_stack(); +// if label == "mul_fp254_6" { +// stack.extend(g.on_stack()); +// } +// stack.push(U256::from(0xdeadbeefu32)); +// InterpreterMemoryInitialization { +// label: label.to_string(), +// stack, +// segment: BnPairing, +// memory: vec![], +// } +// } -#[test] -fn test_mul_fp6() -> Result<()> { - let mut rng = rand::thread_rng(); - let f: Fp6 = rng.gen::(); - let g: Fp6 = rng.gen::(); +// #[test] +// fn test_mul_fp6() -> Result<()> { +// let mut rng = rand::thread_rng(); +// let f: Fp6 = rng.gen::(); +// let g: Fp6 = rng.gen::(); - let setup_normal: InterpreterMemoryInitialization = setup_mul_fp6_test(f, g, "mul_fp254_6"); - let setup_square: InterpreterMemoryInitialization = setup_mul_fp6_test(f, f, "square_fp254_6"); +// let setup_normal: InterpreterMemoryInitialization = setup_mul_fp6_test(f, g, "mul_fp254_6"); +// let setup_square: InterpreterMemoryInitialization = setup_mul_fp6_test(f, f, "square_fp254_6"); - let intrptr_normal: Interpreter = run_interpreter_with_memory(setup_normal).unwrap(); - let intrptr_square: Interpreter = run_interpreter_with_memory(setup_square).unwrap(); +// let intrptr_normal: Interpreter = run_interpreter_with_memory(setup_normal).unwrap(); +// let intrptr_square: Interpreter = run_interpreter_with_memory(setup_square).unwrap(); - let out_normal: Vec = extract_stack(intrptr_normal); - let out_square: Vec = extract_stack(intrptr_square); +// let out_normal: Vec = extract_stack(intrptr_normal); +// let out_square: Vec = extract_stack(intrptr_square); - let exp_normal: Vec = (f * g).on_stack(); - let exp_square: Vec = (f * f).on_stack(); +// let exp_normal: Vec = (f * g).on_stack(); +// let exp_square: Vec = (f * f).on_stack(); - assert_eq!(out_normal, exp_normal); - assert_eq!(out_square, exp_square); +// assert_eq!(out_normal, exp_normal); +// assert_eq!(out_square, exp_square); - Ok(()) -} +// Ok(()) +// } fn setup_mul_fp12_test( out: usize, - f: Fp12, - g: Fp12, + f: Fp12, + g: Fp12, label: &str, ) -> InterpreterMemoryInitialization { let in0: usize = 200; @@ -89,60 +90,60 @@ fn test_mul_fp12() -> Result<()> { let out: usize = 224; let mut rng = rand::thread_rng(); - let f: Fp12 = rng.gen::(); - let g: Fp12 = rng.gen::(); - let h: Fp12 = gen_fp12_sparse(&mut rng); + let f: Fp12 = rng.gen::>(); + let g: Fp12 = rng.gen::>(); + // let h: Fp12 = gen_fp12_sparse(&mut rng); let setup_normal: InterpreterMemoryInitialization = setup_mul_fp12_test(out, f, g, "mul_fp254_12"); - let setup_sparse: InterpreterMemoryInitialization = - setup_mul_fp12_test(out, f, h, "mul_fp254_12_sparse"); + // let setup_sparse: InterpreterMemoryInitialization = + // setup_mul_fp12_test(out, f, h, "mul_fp254_12_sparse"); let setup_square: InterpreterMemoryInitialization = setup_mul_fp12_test(out, f, f, "square_fp254_12"); let intrptr_normal: Interpreter = run_interpreter_with_memory(setup_normal).unwrap(); - let intrptr_sparse: Interpreter = run_interpreter_with_memory(setup_sparse).unwrap(); + // let intrptr_sparse: Interpreter = run_interpreter_with_memory(setup_sparse).unwrap(); let intrptr_square: Interpreter = run_interpreter_with_memory(setup_square).unwrap(); let out_normal: Vec = intrptr_normal.extract_kernel_memory(BnPairing, out..out + 12); - let out_sparse: Vec = intrptr_sparse.extract_kernel_memory(BnPairing, out..out + 12); + // let out_sparse: Vec = intrptr_sparse.extract_kernel_memory(BnPairing, out..out + 12); let out_square: Vec = intrptr_square.extract_kernel_memory(BnPairing, out..out + 12); let exp_normal: Vec = (f * g).on_stack(); - let exp_sparse: Vec = (f * h).on_stack(); + // let exp_sparse: Vec = (f * h).on_stack(); let exp_square: Vec = (f * f).on_stack(); assert_eq!(out_normal, exp_normal); - assert_eq!(out_sparse, exp_sparse); + // assert_eq!(out_sparse, exp_sparse); assert_eq!(out_square, exp_square); Ok(()) } -fn setup_frob_fp6_test(f: Fp6, n: usize) -> InterpreterMemoryInitialization { - InterpreterMemoryInitialization { - label: String::from("test_frob_fp254_6_") + &(n.to_string()), - stack: f.on_stack(), - segment: BnPairing, - memory: vec![], - } -} +// fn setup_frob_fp6_test(f: Fp6, n: usize) -> InterpreterMemoryInitialization { +// InterpreterMemoryInitialization { +// label: String::from("test_frob_fp254_6_") + &(n.to_string()), +// stack: f.on_stack(), +// segment: BnPairing, +// memory: vec![], +// } +// } -#[test] -fn test_frob_fp6() -> Result<()> { - let mut rng = rand::thread_rng(); - let f: Fp6 = rng.gen::(); - for n in 1..4 { - let setup_frob = setup_frob_fp6_test(f, n); - let intrptr_frob: Interpreter = run_interpreter_with_memory(setup_frob).unwrap(); - let out_frob: Vec = extract_stack(intrptr_frob); - let exp_frob: Vec = f.frob(n).on_stack(); - assert_eq!(out_frob, exp_frob); - } - Ok(()) -} +// #[test] +// fn test_frob_fp6() -> Result<()> { +// let mut rng = rand::thread_rng(); +// let f: Fp6 = rng.gen::(); +// for n in 1..4 { +// let setup_frob = setup_frob_fp6_test(f, n); +// let intrptr_frob: Interpreter = run_interpreter_with_memory(setup_frob).unwrap(); +// let out_frob: Vec = extract_stack(intrptr_frob); +// let exp_frob: Vec = f.frob(n).on_stack(); +// assert_eq!(out_frob, exp_frob); +// } +// Ok(()) +// } -fn setup_frob_fp12_test(ptr: usize, f: Fp12, n: usize) -> InterpreterMemoryInitialization { +fn setup_frob_fp12_test(ptr: usize, f: Fp12, n: usize) -> InterpreterMemoryInitialization { InterpreterMemoryInitialization { label: String::from("test_frob_fp254_12_") + &(n.to_string()), stack: vec![U256::from(ptr)], @@ -155,7 +156,7 @@ fn setup_frob_fp12_test(ptr: usize, f: Fp12, n: usize) -> InterpreterMemoryIniti fn test_frob_fp12() -> Result<()> { let ptr: usize = 200; let mut rng = rand::thread_rng(); - let f: Fp12 = rng.gen::(); + let f: Fp12 = rng.gen::>(); for n in [1, 2, 3, 6] { let setup_frob = setup_frob_fp12_test(ptr, f, n); let intrptr_frob: Interpreter = run_interpreter_with_memory(setup_frob).unwrap(); @@ -166,154 +167,154 @@ fn test_frob_fp12() -> Result<()> { Ok(()) } -#[test] -fn test_inv_fp12() -> Result<()> { - let ptr: usize = 200; - let inv: usize = 212; - let mut rng = rand::thread_rng(); - let f: Fp12 = rng.gen::(); +// #[test] +// fn test_inv_fp12() -> Result<()> { +// let ptr: usize = 200; +// let inv: usize = 212; +// let mut rng = rand::thread_rng(); +// let f: Fp12 = rng.gen::(); - let setup = InterpreterMemoryInitialization { - label: "inv_fp254_12".to_string(), - stack: vec![U256::from(ptr), U256::from(inv), U256::from(0xdeadbeefu32)], - segment: BnPairing, - memory: vec![(ptr, f.on_stack())], - }; - let interpreter: Interpreter = run_interpreter_with_memory(setup).unwrap(); - let output: Vec = interpreter.extract_kernel_memory(BnPairing, inv..inv + 12); - let expected: Vec = f.inv().on_stack(); +// let setup = InterpreterMemoryInitialization { +// label: "inv_fp254_12".to_string(), +// stack: vec![U256::from(ptr), U256::from(inv), U256::from(0xdeadbeefu32)], +// segment: BnPairing, +// memory: vec![(ptr, f.on_stack())], +// }; +// let interpreter: Interpreter = run_interpreter_with_memory(setup).unwrap(); +// let output: Vec = interpreter.extract_kernel_memory(BnPairing, inv..inv + 12); +// let expected: Vec = f.inv().on_stack(); - assert_eq!(output, expected); +// assert_eq!(output, expected); - Ok(()) -} +// Ok(()) +// } -#[test] -fn test_invariant_exponent() -> Result<()> { - let ptr: usize = 200; - let mut rng = rand::thread_rng(); - let f: Fp12 = rng.gen::(); +// #[test] +// fn test_invariant_exponent() -> Result<()> { +// let ptr: usize = 200; +// let mut rng = rand::thread_rng(); +// let f: Fp12 = rng.gen::(); - let setup = InterpreterMemoryInitialization { - label: "bn254_invariant_exponent".to_string(), - stack: vec![U256::from(ptr), U256::from(0xdeadbeefu32)], - segment: BnPairing, - memory: vec![(ptr, f.on_stack())], - }; +// let setup = InterpreterMemoryInitialization { +// label: "bn254_invariant_exponent".to_string(), +// stack: vec![U256::from(ptr), U256::from(0xdeadbeefu32)], +// segment: BnPairing, +// memory: vec![(ptr, f.on_stack())], +// }; - let interpreter: Interpreter = run_interpreter_with_memory(setup).unwrap(); - let output: Vec = interpreter.extract_kernel_memory(BnPairing, ptr..ptr + 12); - let expected: Vec = invariant_exponent(f).on_stack(); +// let interpreter: Interpreter = run_interpreter_with_memory(setup).unwrap(); +// let output: Vec = interpreter.extract_kernel_memory(BnPairing, ptr..ptr + 12); +// let expected: Vec = invariant_exponent(f).on_stack(); - assert_eq!(output, expected); +// assert_eq!(output, expected); - Ok(()) -} +// Ok(()) +// } -// The curve is cyclic with generator (1, 2) -pub const CURVE_GENERATOR: Curve = { - Curve { - x: Fp { val: U256::one() }, - y: Fp { - val: U256([2, 0, 0, 0]), - }, - } -}; +// // The curve is cyclic with generator (1, 2) +// pub const CURVE_GENERATOR: Curve = { +// Curve { +// x: Fp { val: U256::one() }, +// y: Fp { +// val: U256([2, 0, 0, 0]), +// }, +// } +// }; -// The twisted curve is cyclic with generator (x, y) as follows -pub const TWISTED_GENERATOR: TwistedCurve = { - TwistedCurve { - x: Fp2 { - re: Fp { - val: U256([ - 0x46debd5cd992f6ed, - 0x674322d4f75edadd, - 0x426a00665e5c4479, - 0x1800deef121f1e76, - ]), - }, - im: Fp { - val: U256([ - 0x97e485b7aef312c2, - 0xf1aa493335a9e712, - 0x7260bfb731fb5d25, - 0x198e9393920d483a, - ]), - }, - }, - y: Fp2 { - re: Fp { - val: U256([ - 0x4ce6cc0166fa7daa, - 0xe3d1e7690c43d37b, - 0x4aab71808dcb408f, - 0x12c85ea5db8c6deb, - ]), - }, - im: Fp { - val: U256([ - 0x55acdadcd122975b, - 0xbc4b313370b38ef3, - 0xec9e99ad690c3395, - 0x090689d0585ff075, - ]), - }, - }, - } -}; +// // The twisted curve is cyclic with generator (x, y) as follows +// pub const TWISTED_GENERATOR: TwistedCurve = { +// TwistedCurve { +// x: Fp2 { +// re: Fp { +// val: U256([ +// 0x46debd5cd992f6ed, +// 0x674322d4f75edadd, +// 0x426a00665e5c4479, +// 0x1800deef121f1e76, +// ]), +// }, +// im: Fp { +// val: U256([ +// 0x97e485b7aef312c2, +// 0xf1aa493335a9e712, +// 0x7260bfb731fb5d25, +// 0x198e9393920d483a, +// ]), +// }, +// }, +// y: Fp2 { +// re: Fp { +// val: U256([ +// 0x4ce6cc0166fa7daa, +// 0xe3d1e7690c43d37b, +// 0x4aab71808dcb408f, +// 0x12c85ea5db8c6deb, +// ]), +// }, +// im: Fp { +// val: U256([ +// 0x55acdadcd122975b, +// 0xbc4b313370b38ef3, +// 0xec9e99ad690c3395, +// 0x090689d0585ff075, +// ]), +// }, +// }, +// } +// }; -#[test] -fn test_miller() -> Result<()> { - let ptr: usize = 200; - let out: usize = 206; - let inputs: Vec = vec![ - CURVE_GENERATOR.x.val, - CURVE_GENERATOR.y.val, - TWISTED_GENERATOR.x.re.val, - TWISTED_GENERATOR.x.im.val, - TWISTED_GENERATOR.y.re.val, - TWISTED_GENERATOR.y.im.val, - ]; +// #[test] +// fn test_miller() -> Result<()> { +// let ptr: usize = 200; +// let out: usize = 206; +// let inputs: Vec = vec![ +// CURVE_GENERATOR.x.val, +// CURVE_GENERATOR.y.val, +// TWISTED_GENERATOR.x.re.val, +// TWISTED_GENERATOR.x.im.val, +// TWISTED_GENERATOR.y.re.val, +// TWISTED_GENERATOR.y.im.val, +// ]; - let setup = InterpreterMemoryInitialization { - label: "bn254_miller".to_string(), - stack: vec![U256::from(ptr), U256::from(out), U256::from(0xdeadbeefu32)], - segment: BnPairing, - memory: vec![(ptr, inputs)], - }; - let interpreter = run_interpreter_with_memory(setup).unwrap(); - let output: Vec = interpreter.extract_kernel_memory(BnPairing, out..out + 12); - let expected = miller_loop(CURVE_GENERATOR, TWISTED_GENERATOR).on_stack(); +// let setup = InterpreterMemoryInitialization { +// label: "bn254_miller".to_string(), +// stack: vec![U256::from(ptr), U256::from(out), U256::from(0xdeadbeefu32)], +// segment: BnPairing, +// memory: vec![(ptr, inputs)], +// }; +// let interpreter = run_interpreter_with_memory(setup).unwrap(); +// let output: Vec = interpreter.extract_kernel_memory(BnPairing, out..out + 12); +// let expected = miller_loop(CURVE_GENERATOR, TWISTED_GENERATOR).on_stack(); - assert_eq!(output, expected); +// assert_eq!(output, expected); - Ok(()) -} +// Ok(()) +// } -#[test] -fn test_tate() -> Result<()> { - let ptr: usize = 200; - let out: usize = 206; - let inputs: Vec = vec![ - CURVE_GENERATOR.x.val, - CURVE_GENERATOR.y.val, - TWISTED_GENERATOR.x.re.val, - TWISTED_GENERATOR.x.im.val, - TWISTED_GENERATOR.y.re.val, - TWISTED_GENERATOR.y.im.val, - ]; +// #[test] +// fn test_tate() -> Result<()> { +// let ptr: usize = 200; +// let out: usize = 206; +// let inputs: Vec = vec![ +// CURVE_GENERATOR.x.val, +// CURVE_GENERATOR.y.val, +// TWISTED_GENERATOR.x.re.val, +// TWISTED_GENERATOR.x.im.val, +// TWISTED_GENERATOR.y.re.val, +// TWISTED_GENERATOR.y.im.val, +// ]; - let setup = InterpreterMemoryInitialization { - label: "bn254_tate".to_string(), - stack: vec![U256::from(ptr), U256::from(out), U256::from(0xdeadbeefu32)], - segment: BnPairing, - memory: vec![(ptr, inputs)], - }; - let interpreter = run_interpreter_with_memory(setup).unwrap(); - let output: Vec = interpreter.extract_kernel_memory(BnPairing, out..out + 12); - let expected = tate(CURVE_GENERATOR, TWISTED_GENERATOR).on_stack(); +// let setup = InterpreterMemoryInitialization { +// label: "bn254_tate".to_string(), +// stack: vec![U256::from(ptr), U256::from(out), U256::from(0xdeadbeefu32)], +// segment: BnPairing, +// memory: vec![(ptr, inputs)], +// }; +// let interpreter = run_interpreter_with_memory(setup).unwrap(); +// let output: Vec = interpreter.extract_kernel_memory(BnPairing, out..out + 12); +// let expected = tate(CURVE_GENERATOR, TWISTED_GENERATOR).on_stack(); - assert_eq!(output, expected); +// assert_eq!(output, expected); - Ok(()) -} +// Ok(()) +// } diff --git a/evm/src/extension_tower.rs b/evm/src/extension_tower.rs index c95cb24e..15d21907 100644 --- a/evm/src/extension_tower.rs +++ b/evm/src/extension_tower.rs @@ -1,3 +1,4 @@ +use std::mem::transmute; use std::ops::{Add, Div, Mul, Neg, Sub}; use ethereum_types::{U256, U512}; @@ -250,7 +251,7 @@ impl Div for BLS381 { } } -/// The degree 2 field extension Fp2 is given by adjoining i, the square root of -1, to Fp +/// The degree 2 field extension Fp2 is given by adjoining i, the square root of -1, to BN254 /// The arithmetic in this extension is standard complex arithmetic #[derive(Debug, Copy, Clone, PartialEq)] pub struct Fp2 @@ -263,7 +264,7 @@ where impl Distribution> for Standard where - T: Distribution + FieldExt, + T: FieldExt, Standard: Distribution, { fn sample(&self, rng: &mut R) -> Fp2 { @@ -317,7 +318,7 @@ impl Mul for Fp2 { } impl Fp2 { - /// This function scalar multiplies an Fp2 by an Fp + /// This function scalar multiplies an Fp2 by an BN254 pub fn scale(self, x: T) -> Self { Fp2 { re: x * self.re, @@ -371,8 +372,10 @@ impl Div for Fp2 { /// Helper function which multiplies by the Fp2 element /// whose cube root we will adjoin in the next extension -pub trait Adj { +pub trait Adj: Sized { fn mul_adj(self) -> Self; + const FROB_T: [[Self; 6]; 2]; + const FROB_Z: [Self; 12]; } impl Adj for Fp2 { @@ -383,6 +386,393 @@ impl Adj for Fp2 { im: self.re + nine * self.im, } } + + const FROB_T: [[Fp2; 6]; 2] = [ + [ + Fp2 { + re: BN254 { val: U256::one() }, + im: BN254 { val: U256::zero() }, + }, + Fp2 { + re: BN254 { + val: U256([ + 0x99e39557176f553d, + 0xb78cc310c2c3330c, + 0x4c0bec3cf559b143, + 0x2fb347984f7911f7, + ]), + }, + im: BN254 { + val: U256([ + 0x1665d51c640fcba2, + 0x32ae2a1d0b7c9dce, + 0x4ba4cc8bd75a0794, + 0x16c9e55061ebae20, + ]), + }, + }, + Fp2 { + re: BN254 { + val: U256([ + 0xe4bd44e5607cfd48, + 0xc28f069fbb966e3d, + 0x5e6dd9e7e0acccb0, + 0x30644e72e131a029, + ]), + }, + im: BN254 { val: U256::zero() }, + }, + Fp2 { + re: BN254 { + val: U256([ + 0x7b746ee87bdcfb6d, + 0x805ffd3d5d6942d3, + 0xbaff1c77959f25ac, + 0x0856e078b755ef0a, + ]), + }, + im: BN254 { + val: U256([ + 0x380cab2baaa586de, + 0x0fdf31bf98ff2631, + 0xa9f30e6dec26094f, + 0x04f1de41b3d1766f, + ]), + }, + }, + Fp2 { + re: BN254 { + val: U256([ + 0x5763473177fffffe, + 0xd4f263f1acdb5c4f, + 0x59e26bcea0d48bac, + 0x0, + ]), + }, + im: BN254 { val: U256::zero() }, + }, + Fp2 { + re: BN254 { + val: U256([ + 0x62e913ee1dada9e4, + 0xf71614d4b0b71f3a, + 0x699582b87809d9ca, + 0x28be74d4bb943f51, + ]), + }, + im: BN254 { + val: U256([ + 0xedae0bcec9c7aac7, + 0x54f40eb4c3f6068d, + 0xc2b86abcbe01477a, + 0x14a88ae0cb747b99, + ]), + }, + }, + ], + [ + Fp2 { + re: BN254 { val: U256::one() }, + im: BN254 { val: U256::zero() }, + }, + Fp2 { + re: { + BN254 { + val: U256([ + 0x848a1f55921ea762, + 0xd33365f7be94ec72, + 0x80f3c0b75a181e84, + 0x05b54f5e64eea801, + ]), + } + }, + im: { + BN254 { + val: U256([ + 0xc13b4711cd2b8126, + 0x3685d2ea1bdec763, + 0x9f3a80b03b0b1c92, + 0x2c145edbe7fd8aee, + ]), + } + }, + }, + Fp2 { + re: { + BN254 { + val: U256([ + 0x5763473177fffffe, + 0xd4f263f1acdb5c4f, + 0x59e26bcea0d48bac, + 0x0, + ]), + } + }, + im: { BN254 { val: U256::zero() } }, + }, + Fp2 { + re: { + BN254 { + val: U256([ + 0x0e1a92bc3ccbf066, + 0xe633094575b06bcb, + 0x19bee0f7b5b2444e, + 0xbc58c6611c08dab, + ]), + } + }, + im: { + BN254 { + val: U256([ + 0x5fe3ed9d730c239f, + 0xa44a9e08737f96e5, + 0xfeb0f6ef0cd21d04, + 0x23d5e999e1910a12, + ]), + } + }, + }, + Fp2 { + re: { + BN254 { + val: U256([ + 0xe4bd44e5607cfd48, + 0xc28f069fbb966e3d, + 0x5e6dd9e7e0acccb0, + 0x30644e72e131a029, + ]), + } + }, + im: { BN254 { val: U256::zero() } }, + }, + Fp2 { + re: { + BN254 { + val: U256([ + 0xa97bda050992657f, + 0xde1afb54342c724f, + 0x1d9da40771b6f589, + 0x1ee972ae6a826a7d, + ]), + } + }, + im: { + BN254 { + val: U256([ + 0x5721e37e70c255c9, + 0x54326430418536d1, + 0xd2b513cdbb257724, + 0x10de546ff8d4ab51, + ]), + } + }, + }, + ], + ]; + + const FROB_Z: [Fp2; 12] = [ + Fp2 { + re: { BN254 { val: U256::one() } }, + im: { BN254 { val: U256::zero() } }, + }, + Fp2 { + re: { + BN254 { + val: U256([ + 0xd60b35dadcc9e470, + 0x5c521e08292f2176, + 0xe8b99fdd76e68b60, + 0x1284b71c2865a7df, + ]), + } + }, + im: { + BN254 { + val: U256([ + 0xca5cf05f80f362ac, + 0x747992778eeec7e5, + 0xa6327cfe12150b8e, + 0x246996f3b4fae7e6, + ]), + } + }, + }, + Fp2 { + re: { + BN254 { + val: U256([ + 0xe4bd44e5607cfd49, + 0xc28f069fbb966e3d, + 0x5e6dd9e7e0acccb0, + 0x30644e72e131a029, + ]), + } + }, + im: { BN254 { val: U256::zero() } }, + }, + Fp2 { + re: { + BN254 { + val: U256([ + 0xe86f7d391ed4a67f, + 0x894cb38dbe55d24a, + 0xefe9608cd0acaa90, + 0x19dc81cfcc82e4bb, + ]), + } + }, + im: { + BN254 { + val: U256([ + 0x7694aa2bf4c0c101, + 0x7f03a5e397d439ec, + 0x06cbeee33576139d, + 0xabf8b60be77d73, + ]), + } + }, + }, + Fp2 { + re: { + BN254 { + val: U256([ + 0xe4bd44e5607cfd48, + 0xc28f069fbb966e3d, + 0x5e6dd9e7e0acccb0, + 0x30644e72e131a029, + ]), + } + }, + im: { BN254 { val: U256::zero() } }, + }, + Fp2 { + re: { + BN254 { + val: U256([ + 0x1264475e420ac20f, + 0x2cfa95859526b0d4, + 0x072fc0af59c61f30, + 0x757cab3a41d3cdc, + ]), + } + }, + im: { + BN254 { + val: U256([ + 0xe85845e34c4a5b9c, + 0xa20b7dfd71573c93, + 0x18e9b79ba4e2606c, + 0xca6b035381e35b6, + ]), + } + }, + }, + Fp2 { + re: { + BN254 { + val: U256([ + 0x3c208c16d87cfd46, + 0x97816a916871ca8d, + 0xb85045b68181585d, + 0x30644e72e131a029, + ]), + } + }, + im: { BN254 { val: U256::zero() } }, + }, + Fp2 { + re: { + BN254 { + val: U256([ + 0x6615563bfbb318d7, + 0x3b2f4c893f42a916, + 0xcf96a5d90a9accfd, + 0x1ddf9756b8cbf849, + ]), + } + }, + im: { + BN254 { + val: U256([ + 0x71c39bb757899a9b, + 0x2307d819d98302a7, + 0x121dc8b86f6c4ccf, + 0x0bfab77f2c36b843, + ]), + } + }, + }, + Fp2 { + re: { + BN254 { + val: U256([ + 0x5763473177fffffe, + 0xd4f263f1acdb5c4f, + 0x59e26bcea0d48bac, + 0x0, + ]), + } + }, + im: { BN254 { val: U256::zero() } }, + }, + Fp2 { + re: { + BN254 { + val: U256([ + 0x53b10eddb9a856c8, + 0x0e34b703aa1bf842, + 0xc866e529b0d4adcd, + 0x1687cca314aebb6d, + ]), + } + }, + im: { + BN254 { + val: U256([ + 0xc58be1eae3bc3c46, + 0x187dc4add09d90a0, + 0xb18456d34c0b44c0, + 0x2fb855bcd54a22b6, + ]), + } + }, + }, + Fp2 { + re: { + BN254 { + val: U256([ + 0x5763473177ffffff, + 0xd4f263f1acdb5c4f, + 0x59e26bcea0d48bac, + 0x0, + ]), + } + }, + im: { BN254 { val: U256::zero() } }, + }, + Fp2 { + re: { + BN254 { + val: U256([ + 0x29bc44b896723b38, + 0x6a86d50bd34b19b9, + 0xb120850727bb392d, + 0x290c83bf3d14634d, + ]), + } + }, + im: { + BN254 { + val: U256([ + 0x53c846338c32a1ab, + 0xf575ec93f71a8df9, + 0x9f668e1adc9ef7f0, + 0x23bd9e3da9136a73, + ]), + } + }, + }, + ]; } impl Adj for Fp2 { @@ -392,6 +782,8 @@ impl Adj for Fp2 { im: self.re + self.im, } } + const FROB_T: [[Fp2; 6]; 2] = [[Fp2::::ZERO; 6]; 2]; + const FROB_Z: [Fp2; 12] = [Fp2::::ZERO; 12]; } /// The degree 3 field extension Fp6 over Fp2 is given by adjoining t, where t^3 = 1 + i @@ -409,7 +801,7 @@ where impl Distribution> for Standard where - T: Distribution + FieldExt, + T: FieldExt, Fp2: Adj, Standard: Distribution, { @@ -514,15 +906,6 @@ where } } -impl Fp6 -where - T: FieldExt, - Fp2: Adj, -{ - const FROB_T: [[Fp2; 6]; 2] = [[Fp2::::ZERO; 6]; 2]; - const FROB_Z: [Fp2; 12] = [Fp2::::ZERO; 12]; -} - impl Fp6 where T: FieldExt, @@ -538,8 +921,8 @@ where /// are precomputed in the constant arrays FROB_T1 and FROB_T2 pub fn frob(self, n: usize) -> Fp6 { let n = n % 6; - let frob_t1 = Fp6::::FROB_T[0][n]; - let frob_t2 = Fp6::::FROB_T[1][n]; + let frob_t1 = Fp2::::FROB_T[0][n]; + let frob_t2 = Fp2::::FROB_T[1][n]; if n % 2 != 0 { Fp6 { @@ -579,7 +962,7 @@ where /// (x_n)_m = (x^(p^n))^(p^m) = x^(p^n * p^m) = x^(p^(n+m)) = x_{n+m} /// By Galois Theory, given x: Fp6, the product /// phi = x_0 * x_1 * x_2 * x_3 * x_4 * x_5 - /// lands in Fp, and hence the inverse of x is given by + /// lands in BN254, and hence the inverse of x is given by /// (x_1 * x_2 * x_3 * x_4 * x_5) / phi /// We can save compute by rearranging the numerator: /// (x_1 * x_3) * x_5 * (x_1 * x_3)_1 @@ -612,8 +995,8 @@ where } } -/// The degree 2 field extension Fp12 over Fp6 is given by adjoining z, where z^2 = t. -/// It thus has basis 1, z over Fp6 +/// The degree 2 field extension Fp12 over Fp6 is given by +/// adjoining z, where z^2 = t. It thus has basis 1, z over Fp6 #[derive(Debug, Copy, Clone, PartialEq)] pub struct Fp12 where @@ -641,7 +1024,7 @@ where /// By Galois Theory, given x: Fp12, the product /// phi = Prod_{i=0}^11 x_i - /// lands in Fp, and hence the inverse of x is given by + /// lands in BN254, and hence the inverse of x is given by /// (Prod_{i=1}^11 x_i) / phi /// The 6th Frob map is nontrivial but leaves Fp6 fixed and hence must be the conjugate: /// x_6 = (a + bz)_6 = a - bz = x.conj() @@ -665,7 +1048,7 @@ where impl Distribution> for Standard where - T: Distribution + FieldExt, + T: FieldExt, Fp2: Adj, Standard: Distribution, { @@ -773,7 +1156,7 @@ where let n = n % 12; Fp12 { z0: self.z0.frob(n), - z1: self.z1.frob(n).scale(Fp6::::FROB_Z[n]), + z1: self.z1.frob(n).scale(Fp2::::FROB_Z[n]), } } } @@ -791,6 +1174,13 @@ where } } -// trait Stack { -// fn on_stack(self) -> Vec; -// } +pub trait Stack { + fn on_stack(self) -> Vec; +} + +impl Stack for Fp12 { + fn on_stack(self) -> Vec { + let f: [U256; 12] = unsafe { transmute(self) }; + f.into_iter().collect() + } +} From fc72ce46c56986772ac84d4a6b7be6a910978421 Mon Sep 17 00:00:00 2001 From: Dmitry Vagner Date: Tue, 21 Mar 2023 13:55:51 -0700 Subject: [PATCH 120/121] fp6 works --- evm/src/cpu/kernel/tests/bn254.rs | 108 ++++++++++++++++-------------- evm/src/extension_tower.rs | 7 ++ 2 files changed, 63 insertions(+), 52 deletions(-) diff --git a/evm/src/cpu/kernel/tests/bn254.rs b/evm/src/cpu/kernel/tests/bn254.rs index 7195fc73..1840a3c2 100644 --- a/evm/src/cpu/kernel/tests/bn254.rs +++ b/evm/src/cpu/kernel/tests/bn254.rs @@ -9,7 +9,7 @@ use crate::cpu::kernel::interpreter::{ // use crate::bn254_pairing::{ // gen_fp12_sparse, invariant_exponent, miller_loop, tate, Curve, TwistedCurve, // }; -use crate::extension_tower::{Fp12, Stack, BN254}; +use crate::extension_tower::{Fp12, Fp6, Stack, BN254}; use crate::memory::segments::Segment::BnPairing; fn extract_stack(interpreter: Interpreter<'static>) -> Vec { @@ -21,43 +21,47 @@ fn extract_stack(interpreter: Interpreter<'static>) -> Vec { .collect::>() } -// fn setup_mul_fp6_test(f: Fp6, g: Fp6, label: &str) -> InterpreterMemoryInitialization { -// let mut stack = f.on_stack(); -// if label == "mul_fp254_6" { -// stack.extend(g.on_stack()); -// } -// stack.push(U256::from(0xdeadbeefu32)); -// InterpreterMemoryInitialization { -// label: label.to_string(), -// stack, -// segment: BnPairing, -// memory: vec![], -// } -// } +fn setup_mul_fp6_test( + f: Fp6, + g: Fp6, + label: &str, +) -> InterpreterMemoryInitialization { + let mut stack = f.on_stack(); + if label == "mul_fp254_6" { + stack.extend(g.on_stack()); + } + stack.push(U256::from(0xdeadbeefu32)); + InterpreterMemoryInitialization { + label: label.to_string(), + stack, + segment: BnPairing, + memory: vec![], + } +} -// #[test] -// fn test_mul_fp6() -> Result<()> { -// let mut rng = rand::thread_rng(); -// let f: Fp6 = rng.gen::(); -// let g: Fp6 = rng.gen::(); +#[test] +fn test_mul_fp6() -> Result<()> { + let mut rng = rand::thread_rng(); + let f: Fp6 = rng.gen::>(); + let g: Fp6 = rng.gen::>(); -// let setup_normal: InterpreterMemoryInitialization = setup_mul_fp6_test(f, g, "mul_fp254_6"); -// let setup_square: InterpreterMemoryInitialization = setup_mul_fp6_test(f, f, "square_fp254_6"); + let setup_normal: InterpreterMemoryInitialization = setup_mul_fp6_test(f, g, "mul_fp254_6"); + let setup_square: InterpreterMemoryInitialization = setup_mul_fp6_test(f, f, "square_fp254_6"); -// let intrptr_normal: Interpreter = run_interpreter_with_memory(setup_normal).unwrap(); -// let intrptr_square: Interpreter = run_interpreter_with_memory(setup_square).unwrap(); + let intrptr_normal: Interpreter = run_interpreter_with_memory(setup_normal).unwrap(); + let intrptr_square: Interpreter = run_interpreter_with_memory(setup_square).unwrap(); -// let out_normal: Vec = extract_stack(intrptr_normal); -// let out_square: Vec = extract_stack(intrptr_square); + let out_normal: Vec = extract_stack(intrptr_normal); + let out_square: Vec = extract_stack(intrptr_square); -// let exp_normal: Vec = (f * g).on_stack(); -// let exp_square: Vec = (f * f).on_stack(); + let exp_normal: Vec = (f * g).on_stack(); + let exp_square: Vec = (f * f).on_stack(); -// assert_eq!(out_normal, exp_normal); -// assert_eq!(out_square, exp_square); + assert_eq!(out_normal, exp_normal); + assert_eq!(out_square, exp_square); -// Ok(()) -// } + Ok(()) +} fn setup_mul_fp12_test( out: usize, @@ -120,28 +124,28 @@ fn test_mul_fp12() -> Result<()> { Ok(()) } -// fn setup_frob_fp6_test(f: Fp6, n: usize) -> InterpreterMemoryInitialization { -// InterpreterMemoryInitialization { -// label: String::from("test_frob_fp254_6_") + &(n.to_string()), -// stack: f.on_stack(), -// segment: BnPairing, -// memory: vec![], -// } -// } +fn setup_frob_fp6_test(f: Fp6, n: usize) -> InterpreterMemoryInitialization { + InterpreterMemoryInitialization { + label: String::from("test_frob_fp254_6_") + &(n.to_string()), + stack: f.on_stack(), + segment: BnPairing, + memory: vec![], + } +} -// #[test] -// fn test_frob_fp6() -> Result<()> { -// let mut rng = rand::thread_rng(); -// let f: Fp6 = rng.gen::(); -// for n in 1..4 { -// let setup_frob = setup_frob_fp6_test(f, n); -// let intrptr_frob: Interpreter = run_interpreter_with_memory(setup_frob).unwrap(); -// let out_frob: Vec = extract_stack(intrptr_frob); -// let exp_frob: Vec = f.frob(n).on_stack(); -// assert_eq!(out_frob, exp_frob); -// } -// Ok(()) -// } +#[test] +fn test_frob_fp6() -> Result<()> { + let mut rng = rand::thread_rng(); + let f: Fp6 = rng.gen::>(); + for n in 1..4 { + let setup_frob = setup_frob_fp6_test(f, n); + let intrptr_frob: Interpreter = run_interpreter_with_memory(setup_frob).unwrap(); + let out_frob: Vec = extract_stack(intrptr_frob); + let exp_frob: Vec = f.frob(n).on_stack(); + assert_eq!(out_frob, exp_frob); + } + Ok(()) +} fn setup_frob_fp12_test(ptr: usize, f: Fp12, n: usize) -> InterpreterMemoryInitialization { InterpreterMemoryInitialization { diff --git a/evm/src/extension_tower.rs b/evm/src/extension_tower.rs index 15d21907..00e396b4 100644 --- a/evm/src/extension_tower.rs +++ b/evm/src/extension_tower.rs @@ -1178,6 +1178,13 @@ pub trait Stack { fn on_stack(self) -> Vec; } +impl Stack for Fp6 { + fn on_stack(self) -> Vec { + let f: [U256; 6] = unsafe { transmute(self) }; + f.into_iter().collect() + } +} + impl Stack for Fp12 { fn on_stack(self) -> Vec { let f: [U256; 12] = unsafe { transmute(self) }; From 143225f449c8365b3cc09bc4b16a4477c3928dfc Mon Sep 17 00:00:00 2001 From: Dmitry Vagner Date: Tue, 21 Mar 2023 19:19:02 -0700 Subject: [PATCH 121/121] finish --- evm/src/arithmetic/mod.rs | 2 +- evm/src/bn254_arithmetic.rs | 876 ----------------------------- evm/src/bn254_pairing.rs | 62 +- evm/src/cpu/kernel/interpreter.rs | 2 +- evm/src/cpu/kernel/tests/bn254.rs | 289 +++++----- evm/src/generation/prover_input.rs | 4 +- evm/src/lib.rs | 1 - 7 files changed, 181 insertions(+), 1055 deletions(-) delete mode 100644 evm/src/bn254_arithmetic.rs diff --git a/evm/src/arithmetic/mod.rs b/evm/src/arithmetic/mod.rs index 8d9592b7..c6987ed7 100644 --- a/evm/src/arithmetic/mod.rs +++ b/evm/src/arithmetic/mod.rs @@ -1,7 +1,7 @@ use ethereum_types::U256; use plonky2::field::types::PrimeField64; -use crate::bn254_arithmetic::BN_BASE; +use crate::extension_tower::BN_BASE; use crate::util::{addmod, mulmod, submod}; mod addcy; diff --git a/evm/src/bn254_arithmetic.rs b/evm/src/bn254_arithmetic.rs deleted file mode 100644 index c2f1e3d4..00000000 --- a/evm/src/bn254_arithmetic.rs +++ /dev/null @@ -1,876 +0,0 @@ -use std::mem::transmute; -use std::ops::{Add, Div, Mul, Neg, Sub}; - -use ethereum_types::U256; -use rand::distributions::{Distribution, Standard}; -use rand::Rng; - -pub const BN_BASE: U256 = U256([ - 0x3c208c16d87cfd47, - 0x97816a916871ca8d, - 0xb85045b68181585d, - 0x30644e72e131a029, -]); - -#[derive(Debug, Copy, Clone, PartialEq)] -pub struct Fp { - pub val: U256, -} - -impl Fp { - pub fn new(val: usize) -> Fp { - Fp { - val: U256::from(val), - } - } -} - -impl Distribution for Standard { - fn sample(&self, rng: &mut R) -> Fp { - let xs = rng.gen::<[u64; 4]>(); - Fp { - val: U256(xs) % BN_BASE, - } - } -} - -impl Add for Fp { - type Output = Self; - - fn add(self, other: Self) -> Self { - Fp { - val: (self.val + other.val) % BN_BASE, - } - } -} - -impl Neg for Fp { - type Output = Self; - - fn neg(self) -> Self::Output { - Fp { - val: (BN_BASE - self.val) % BN_BASE, - } - } -} - -impl Sub for Fp { - type Output = Self; - - fn sub(self, other: Self) -> Self { - Fp { - val: (BN_BASE + self.val - other.val) % BN_BASE, - } - } -} - -#[allow(clippy::suspicious_arithmetic_impl)] -impl Mul for Fp { - type Output = Self; - - fn mul(self, other: Self) -> Self { - Fp { - val: U256::try_from((self.val).full_mul(other.val) % BN_BASE).unwrap(), - } - } -} - -impl Fp { - pub fn inv(self) -> Fp { - exp_fp(self, BN_BASE - 2) - } -} - -#[allow(clippy::suspicious_arithmetic_impl)] -impl Div for Fp { - type Output = Self; - - fn div(self, rhs: Self) -> Self::Output { - self * rhs.inv() - } -} - -pub const ZERO_FP: Fp = Fp { val: U256::zero() }; -pub const UNIT_FP: Fp = Fp { val: U256::one() }; - -fn exp_fp(x: Fp, e: U256) -> Fp { - let mut current = x; - let mut product = Fp { val: U256::one() }; - - for j in 0..256 { - if e.bit(j) { - product = product * current; - } - current = current * current; - } - product -} - -/// The degree 2 field extension Fp2 is given by adjoining i, the square root of -1, to Fp -/// The arithmetic in this extension is standard complex arithmetic -#[derive(Debug, Copy, Clone, PartialEq)] -pub struct Fp2 { - pub re: Fp, - pub im: Fp, -} - -pub const ZERO_FP2: Fp2 = Fp2 { - re: ZERO_FP, - im: ZERO_FP, -}; - -pub const UNIT_FP2: Fp2 = Fp2 { - re: UNIT_FP, - im: ZERO_FP, -}; - -impl Distribution for Standard { - fn sample(&self, rng: &mut R) -> Fp2 { - let (re, im) = rng.gen::<(Fp, Fp)>(); - Fp2 { re, im } - } -} - -impl Add for Fp2 { - type Output = Self; - - fn add(self, other: Self) -> Self { - Fp2 { - re: self.re + other.re, - im: self.im + other.im, - } - } -} - -impl Neg for Fp2 { - type Output = Self; - - fn neg(self) -> Self::Output { - Fp2 { - re: -self.re, - im: -self.im, - } - } -} - -impl Sub for Fp2 { - type Output = Self; - - fn sub(self, other: Self) -> Self { - Fp2 { - re: self.re - other.re, - im: self.im - other.im, - } - } -} - -impl Mul for Fp2 { - type Output = Self; - - fn mul(self, other: Self) -> Self { - Fp2 { - re: self.re * other.re - self.im * other.im, - im: self.re * other.im + self.im * other.re, - } - } -} - -impl Fp2 { - // We preemptively define a helper function which multiplies an Fp2 element by 9 + i - fn i9(self) -> Fp2 { - let nine = Fp::new(9); - Fp2 { - re: nine * self.re - self.im, - im: self.re + nine * self.im, - } - } - - // This function scalar multiplies an Fp2 by an Fp - pub fn scale(self, x: Fp) -> Fp2 { - Fp2 { - re: x * self.re, - im: x * self.im, - } - } - - /// Return the complex conjugate z' of z: Fp2 - /// This also happens to be the frobenius map - /// z -> z^p - /// since p == 3 mod 4 and hence - /// i^p = i^3 = -i - fn conj(self) -> Fp2 { - Fp2 { - re: self.re, - im: -self.im, - } - } - - // Return the magnitude squared of a complex number - fn norm_sq(self) -> Fp { - self.re * self.re + self.im * self.im - } - - /// The inverse of z is given by z'/||z||^2 since ||z||^2 = zz' - pub fn inv(self) -> Fp2 { - let norm_sq = self.norm_sq(); - self.conj().scale(norm_sq.inv()) - } -} - -#[allow(clippy::suspicious_arithmetic_impl)] -impl Div for Fp2 { - type Output = Self; - - fn div(self, rhs: Self) -> Self::Output { - self * rhs.inv() - } -} - -/// The degree 3 field extension Fp6 over Fp2 is given by adjoining t, where t^3 = 9 + i -// Fp6 has basis 1, t, t^2 over Fp2 -#[derive(Debug, Copy, Clone, PartialEq)] -pub struct Fp6 { - pub t0: Fp2, - pub t1: Fp2, - pub t2: Fp2, -} - -pub const ZERO_FP6: Fp6 = Fp6 { - t0: ZERO_FP2, - t1: ZERO_FP2, - t2: ZERO_FP2, -}; - -pub const UNIT_FP6: Fp6 = Fp6 { - t0: UNIT_FP2, - t1: ZERO_FP2, - t2: ZERO_FP2, -}; - -impl Distribution for Standard { - fn sample(&self, rng: &mut R) -> Fp6 { - let (t0, t1, t2) = rng.gen::<(Fp2, Fp2, Fp2)>(); - Fp6 { t0, t1, t2 } - } -} - -impl Add for Fp6 { - type Output = Self; - - fn add(self, other: Self) -> Self { - Fp6 { - t0: self.t0 + other.t0, - t1: self.t1 + other.t1, - t2: self.t2 + other.t2, - } - } -} - -impl Neg for Fp6 { - type Output = Self; - - fn neg(self) -> Self::Output { - Fp6 { - t0: -self.t0, - t1: -self.t1, - t2: -self.t2, - } - } -} - -impl Sub for Fp6 { - type Output = Self; - - fn sub(self, other: Self) -> Self { - Fp6 { - t0: self.t0 - other.t0, - t1: self.t1 - other.t1, - t2: self.t2 - other.t2, - } - } -} - -impl Mul for Fp6 { - type Output = Self; - - fn mul(self, other: Self) -> Self { - Fp6 { - t0: self.t0 * other.t0 + (self.t1 * other.t2 + self.t2 * other.t1).i9(), - t1: self.t0 * other.t1 + self.t1 * other.t0 + (self.t2 * other.t2).i9(), - t2: self.t0 * other.t2 + self.t1 * other.t1 + self.t2 * other.t0, - } - } -} - -impl Fp6 { - // This function scalar multiplies an Fp6 by an Fp2 - fn scale(self, x: Fp2) -> Fp6 { - Fp6 { - t0: x * self.t0, - t1: x * self.t1, - t2: x * self.t2, - } - } - - /// This function multiplies an Fp6 element by t, and hence shifts the bases, - /// where the t^2 coefficient picks up a factor of 9+i as the 1 coefficient of the output - fn sh(self) -> Fp6 { - Fp6 { - t0: self.t2.i9(), - t1: self.t0, - t2: self.t1, - } - } - - /// The nth frobenius endomorphism of a p^q field is given by mapping - /// x to x^(p^n) - /// which sends a + bt + ct^2: Fp6 to - /// a^(p^n) + b^(p^n) * t^(p^n) + c^(p^n) * t^(2p^n) - /// The Fp2 coefficients are determined by the comment in the conj method, - /// while the values of - /// t^(p^n) and t^(2p^n) - /// are precomputed in the constant arrays FROB_T1 and FROB_T2 - pub fn frob(self, n: usize) -> Fp6 { - let n = n % 6; - let frob_t1 = FROB_T1[n]; - let frob_t2 = FROB_T2[n]; - - if n % 2 != 0 { - Fp6 { - t0: self.t0.conj(), - t1: frob_t1 * self.t1.conj(), - t2: frob_t2 * self.t2.conj(), - } - } else { - Fp6 { - t0: self.t0, - t1: frob_t1 * self.t1, - t2: frob_t2 * self.t2, - } - } - } - - /// Let x_n = x^(p^n) and note that - /// x_0 = x^(p^0) = x^1 = x - /// (x_n)_m = (x^(p^n))^(p^m) = x^(p^n * p^m) = x^(p^(n+m)) = x_{n+m} - /// By Galois Theory, given x: Fp6, the product - /// phi = x_0 * x_1 * x_2 * x_3 * x_4 * x_5 - /// lands in Fp, and hence the inverse of x is given by - /// (x_1 * x_2 * x_3 * x_4 * x_5) / phi - /// We can save compute by rearranging the numerator: - /// (x_1 * x_3) * x_5 * (x_1 * x_3)_1 - /// By Galois theory, the following are in Fp2 and are complex conjugates - /// x_1 * x_3 * x_5, x_0 * x_2 * x_4 - /// and therefore - /// phi = ||x_1 * x_3 * x_5||^2 - /// and hence the inverse is given by - /// ([x_1 * x_3] * x_5) * [x_1 * x_3]_1 / ||[x_1 * x_3] * x_5||^2 - pub fn inv(self) -> Fp6 { - let prod_13 = self.frob(1) * self.frob(3); - let prod_135 = (prod_13 * self.frob(5)).t0; - let phi = prod_135.norm_sq(); - let prod_odds_over_phi = prod_135.scale(phi.inv()); - let prod_24 = prod_13.frob(1); - prod_24.scale(prod_odds_over_phi) - } - - pub fn on_stack(self) -> Vec { - let f: [U256; 6] = unsafe { transmute(self) }; - f.into_iter().collect() - } -} - -#[allow(clippy::suspicious_arithmetic_impl)] -impl Div for Fp6 { - type Output = Self; - - fn div(self, rhs: Self) -> Self::Output { - self * rhs.inv() - } -} - -/// The degree 2 field extension Fp12 over Fp6 is given by adjoining z, where z^2 = t. -/// It thus has basis 1, z over Fp6 -#[derive(Debug, Copy, Clone, PartialEq)] -pub struct Fp12 { - pub z0: Fp6, - pub z1: Fp6, -} - -pub const UNIT_FP12: Fp12 = Fp12 { - z0: UNIT_FP6, - z1: ZERO_FP6, -}; - -impl Distribution for Standard { - fn sample(&self, rng: &mut R) -> Fp12 { - let (z0, z1) = rng.gen::<(Fp6, Fp6)>(); - Fp12 { z0, z1 } - } -} - -impl Mul for Fp12 { - type Output = Self; - - fn mul(self, other: Self) -> Self { - let h0 = self.z0 * other.z0; - let h1 = self.z1 * other.z1; - let h01 = (self.z0 + self.z1) * (other.z0 + other.z1); - Fp12 { - z0: h0 + h1.sh(), - z1: h01 - (h0 + h1), - } - } -} - -impl Fp12 { - // This function scalar multiplies an Fp12 by an Fp6 - fn scale(self, x: Fp6) -> Fp12 { - Fp12 { - z0: x * self.z0, - z1: x * self.z1, - } - } - - fn conj(self) -> Fp12 { - Fp12 { - z0: self.z0, - z1: -self.z1, - } - } - /// The nth frobenius endomorphism of a p^q field is given by mapping - /// x to x^(p^n) - /// which sends a + bz: Fp12 to - /// a^(p^n) + b^(p^n) * z^(p^n) - /// where the values of z^(p^n) are precomputed in the constant array FROB_Z - pub fn frob(self, n: usize) -> Fp12 { - let n = n % 12; - Fp12 { - z0: self.z0.frob(n), - z1: self.z1.frob(n).scale(FROB_Z[n]), - } - } - - /// By Galois Theory, given x: Fp12, the product - /// phi = Prod_{i=0}^11 x_i - /// lands in Fp, and hence the inverse of x is given by - /// (Prod_{i=1}^11 x_i) / phi - /// The 6th Frob map is nontrivial but leaves Fp6 fixed and hence must be the conjugate: - /// x_6 = (a + bz)_6 = a - bz = x.conj() - /// Letting prod_17 = x_1 * x_7, the remaining factors in the numerator can be expresed as: - /// [(prod_17) * (prod_17)_2] * (prod_17)_4 * [(prod_17) * (prod_17)_2]_1 - /// By Galois theory, both the following are in Fp2 and are complex conjugates - /// prod_odds, prod_evens - /// Thus phi = ||prod_odds||^2, and hence the inverse is given by - /// prod_odds * prod_evens_except_six * x.conj() / ||prod_odds||^2 - pub fn inv(self) -> Fp12 { - let prod_17 = (self.frob(1) * self.frob(7)).z0; - let prod_1379 = prod_17 * prod_17.frob(2); - let prod_odds = (prod_1379 * prod_17.frob(4)).t0; - let phi = prod_odds.norm_sq(); - let prod_odds_over_phi = prod_odds.scale(phi.inv()); - let prod_evens_except_six = prod_1379.frob(1); - let prod_except_six = prod_evens_except_six.scale(prod_odds_over_phi); - self.conj().scale(prod_except_six) - } - - pub fn on_stack(self) -> Vec { - let f: [U256; 12] = unsafe { transmute(self) }; - f.into_iter().collect() - } -} - -#[allow(clippy::suspicious_arithmetic_impl)] -impl Div for Fp12 { - type Output = Self; - - fn div(self, rhs: Self) -> Self::Output { - self * rhs.inv() - } -} - -const FROB_T1: [Fp2; 6] = [ - Fp2 { - re: Fp { val: U256::one() }, - im: Fp { val: U256::zero() }, - }, - Fp2 { - re: Fp { - val: U256([ - 0x99e39557176f553d, - 0xb78cc310c2c3330c, - 0x4c0bec3cf559b143, - 0x2fb347984f7911f7, - ]), - }, - im: Fp { - val: U256([ - 0x1665d51c640fcba2, - 0x32ae2a1d0b7c9dce, - 0x4ba4cc8bd75a0794, - 0x16c9e55061ebae20, - ]), - }, - }, - Fp2 { - re: Fp { - val: U256([ - 0xe4bd44e5607cfd48, - 0xc28f069fbb966e3d, - 0x5e6dd9e7e0acccb0, - 0x30644e72e131a029, - ]), - }, - im: Fp { val: U256::zero() }, - }, - Fp2 { - re: Fp { - val: U256([ - 0x7b746ee87bdcfb6d, - 0x805ffd3d5d6942d3, - 0xbaff1c77959f25ac, - 0x0856e078b755ef0a, - ]), - }, - im: Fp { - val: U256([ - 0x380cab2baaa586de, - 0x0fdf31bf98ff2631, - 0xa9f30e6dec26094f, - 0x04f1de41b3d1766f, - ]), - }, - }, - Fp2 { - re: Fp { - val: U256([ - 0x5763473177fffffe, - 0xd4f263f1acdb5c4f, - 0x59e26bcea0d48bac, - 0x0, - ]), - }, - im: Fp { val: U256::zero() }, - }, - Fp2 { - re: Fp { - val: U256([ - 0x62e913ee1dada9e4, - 0xf71614d4b0b71f3a, - 0x699582b87809d9ca, - 0x28be74d4bb943f51, - ]), - }, - im: Fp { - val: U256([ - 0xedae0bcec9c7aac7, - 0x54f40eb4c3f6068d, - 0xc2b86abcbe01477a, - 0x14a88ae0cb747b99, - ]), - }, - }, -]; - -const FROB_T2: [Fp2; 6] = [ - Fp2 { - re: Fp { val: U256::one() }, - im: Fp { val: U256::zero() }, - }, - Fp2 { - re: { - Fp { - val: U256([ - 0x848a1f55921ea762, - 0xd33365f7be94ec72, - 0x80f3c0b75a181e84, - 0x05b54f5e64eea801, - ]), - } - }, - im: { - Fp { - val: U256([ - 0xc13b4711cd2b8126, - 0x3685d2ea1bdec763, - 0x9f3a80b03b0b1c92, - 0x2c145edbe7fd8aee, - ]), - } - }, - }, - Fp2 { - re: { - Fp { - val: U256([ - 0x5763473177fffffe, - 0xd4f263f1acdb5c4f, - 0x59e26bcea0d48bac, - 0x0, - ]), - } - }, - im: { Fp { val: U256::zero() } }, - }, - Fp2 { - re: { - Fp { - val: U256([ - 0x0e1a92bc3ccbf066, - 0xe633094575b06bcb, - 0x19bee0f7b5b2444e, - 0xbc58c6611c08dab, - ]), - } - }, - im: { - Fp { - val: U256([ - 0x5fe3ed9d730c239f, - 0xa44a9e08737f96e5, - 0xfeb0f6ef0cd21d04, - 0x23d5e999e1910a12, - ]), - } - }, - }, - Fp2 { - re: { - Fp { - val: U256([ - 0xe4bd44e5607cfd48, - 0xc28f069fbb966e3d, - 0x5e6dd9e7e0acccb0, - 0x30644e72e131a029, - ]), - } - }, - im: { Fp { val: U256::zero() } }, - }, - Fp2 { - re: { - Fp { - val: U256([ - 0xa97bda050992657f, - 0xde1afb54342c724f, - 0x1d9da40771b6f589, - 0x1ee972ae6a826a7d, - ]), - } - }, - im: { - Fp { - val: U256([ - 0x5721e37e70c255c9, - 0x54326430418536d1, - 0xd2b513cdbb257724, - 0x10de546ff8d4ab51, - ]), - } - }, - }, -]; - -const FROB_Z: [Fp2; 12] = [ - Fp2 { - re: { Fp { val: U256::one() } }, - im: { Fp { val: U256::zero() } }, - }, - Fp2 { - re: { - Fp { - val: U256([ - 0xd60b35dadcc9e470, - 0x5c521e08292f2176, - 0xe8b99fdd76e68b60, - 0x1284b71c2865a7df, - ]), - } - }, - im: { - Fp { - val: U256([ - 0xca5cf05f80f362ac, - 0x747992778eeec7e5, - 0xa6327cfe12150b8e, - 0x246996f3b4fae7e6, - ]), - } - }, - }, - Fp2 { - re: { - Fp { - val: U256([ - 0xe4bd44e5607cfd49, - 0xc28f069fbb966e3d, - 0x5e6dd9e7e0acccb0, - 0x30644e72e131a029, - ]), - } - }, - im: { Fp { val: U256::zero() } }, - }, - Fp2 { - re: { - Fp { - val: U256([ - 0xe86f7d391ed4a67f, - 0x894cb38dbe55d24a, - 0xefe9608cd0acaa90, - 0x19dc81cfcc82e4bb, - ]), - } - }, - im: { - Fp { - val: U256([ - 0x7694aa2bf4c0c101, - 0x7f03a5e397d439ec, - 0x06cbeee33576139d, - 0xabf8b60be77d73, - ]), - } - }, - }, - Fp2 { - re: { - Fp { - val: U256([ - 0xe4bd44e5607cfd48, - 0xc28f069fbb966e3d, - 0x5e6dd9e7e0acccb0, - 0x30644e72e131a029, - ]), - } - }, - im: { Fp { val: U256::zero() } }, - }, - Fp2 { - re: { - Fp { - val: U256([ - 0x1264475e420ac20f, - 0x2cfa95859526b0d4, - 0x072fc0af59c61f30, - 0x757cab3a41d3cdc, - ]), - } - }, - im: { - Fp { - val: U256([ - 0xe85845e34c4a5b9c, - 0xa20b7dfd71573c93, - 0x18e9b79ba4e2606c, - 0xca6b035381e35b6, - ]), - } - }, - }, - Fp2 { - re: { - Fp { - val: U256([ - 0x3c208c16d87cfd46, - 0x97816a916871ca8d, - 0xb85045b68181585d, - 0x30644e72e131a029, - ]), - } - }, - im: { Fp { val: U256::zero() } }, - }, - Fp2 { - re: { - Fp { - val: U256([ - 0x6615563bfbb318d7, - 0x3b2f4c893f42a916, - 0xcf96a5d90a9accfd, - 0x1ddf9756b8cbf849, - ]), - } - }, - im: { - Fp { - val: U256([ - 0x71c39bb757899a9b, - 0x2307d819d98302a7, - 0x121dc8b86f6c4ccf, - 0x0bfab77f2c36b843, - ]), - } - }, - }, - Fp2 { - re: { - Fp { - val: U256([ - 0x5763473177fffffe, - 0xd4f263f1acdb5c4f, - 0x59e26bcea0d48bac, - 0x0, - ]), - } - }, - im: { Fp { val: U256::zero() } }, - }, - Fp2 { - re: { - Fp { - val: U256([ - 0x53b10eddb9a856c8, - 0x0e34b703aa1bf842, - 0xc866e529b0d4adcd, - 0x1687cca314aebb6d, - ]), - } - }, - im: { - Fp { - val: U256([ - 0xc58be1eae3bc3c46, - 0x187dc4add09d90a0, - 0xb18456d34c0b44c0, - 0x2fb855bcd54a22b6, - ]), - } - }, - }, - Fp2 { - re: { - Fp { - val: U256([ - 0x5763473177ffffff, - 0xd4f263f1acdb5c4f, - 0x59e26bcea0d48bac, - 0x0, - ]), - } - }, - im: { Fp { val: U256::zero() } }, - }, - Fp2 { - re: { - Fp { - val: U256([ - 0x29bc44b896723b38, - 0x6a86d50bd34b19b9, - 0xb120850727bb392d, - 0x290c83bf3d14634d, - ]), - } - }, - im: { - Fp { - val: U256([ - 0x53c846338c32a1ab, - 0xf575ec93f71a8df9, - 0x9f668e1adc9ef7f0, - 0x23bd9e3da9136a73, - ]), - } - }, - }, -]; diff --git a/evm/src/bn254_pairing.rs b/evm/src/bn254_pairing.rs index bf5db74a..08eb614c 100644 --- a/evm/src/bn254_pairing.rs +++ b/evm/src/bn254_pairing.rs @@ -2,13 +2,13 @@ use std::ops::Add; use rand::Rng; -use crate::bn254_arithmetic::{Fp, Fp12, Fp2, Fp6, UNIT_FP12, ZERO_FP, ZERO_FP2}; +use crate::extension_tower::{FieldExt, Fp12, Fp2, Fp6, BN254}; -// The curve consists of pairs (x, y): (Fp, Fp) | y^2 = x^3 + 2 +// The curve consists of pairs (x, y): (BN254, BN254) | y^2 = x^3 + 2 #[derive(Debug, Copy, Clone, PartialEq)] pub struct Curve { - pub x: Fp, - pub y: Fp, + pub x: BN254, + pub y: BN254, } /// Standard addition formula for elliptic curves, restricted to the cases @@ -19,7 +19,7 @@ impl Add for Curve { fn add(self, other: Self) -> Self { let m = if self == other { - Fp::new(3) * self.x * self.x / (Fp::new(2) * self.y) + BN254::new(3) * self.x * self.x / (BN254::new(2) * self.y) } else { (other.y - self.y) / (other.x - self.x) }; @@ -34,12 +34,12 @@ impl Add for Curve { // The twisted curve consists of pairs (x, y): (Fp2, Fp2) | y^2 = x^3 + 3/(9 + i) #[derive(Debug, Copy, Clone, PartialEq)] pub struct TwistedCurve { - pub x: Fp2, - pub y: Fp2, + pub x: Fp2, + pub y: Fp2, } // The tate pairing takes a point each from the curve and its twist and outputs an Fp12 element -pub fn tate(p: Curve, q: TwistedCurve) -> Fp12 { +pub fn tate(p: Curve, q: TwistedCurve) -> Fp12 { let miller_output = miller_loop(p, q); invariant_exponent(miller_output) } @@ -47,10 +47,10 @@ pub fn tate(p: Curve, q: TwistedCurve) -> Fp12 { /// Standard code for miller loop, can be found on page 99 at this url: /// https://static1.squarespace.com/static/5fdbb09f31d71c1227082339/t/5ff394720493bd28278889c6/1609798774687/PairingsForBeginners.pdf#page=107 /// where EXP is a hardcoding of the array of Booleans that the loop traverses -pub fn miller_loop(p: Curve, q: TwistedCurve) -> Fp12 { +pub fn miller_loop(p: Curve, q: TwistedCurve) -> Fp12 { let mut r = p; - let mut acc = UNIT_FP12; - let mut line; + let mut acc: Fp12 = Fp12::::UNIT; + let mut line: Fp12; for i in EXP { line = tangent(r, q); @@ -66,14 +66,14 @@ pub fn miller_loop(p: Curve, q: TwistedCurve) -> Fp12 { } /// The sloped line function for doubling a point -pub fn tangent(p: Curve, q: TwistedCurve) -> Fp12 { - let cx = -Fp::new(3) * p.x * p.x; - let cy = Fp::new(2) * p.y; - sparse_embed(p.y * p.y - Fp::new(9), q.x.scale(cx), q.y.scale(cy)) +pub fn tangent(p: Curve, q: TwistedCurve) -> Fp12 { + let cx = -BN254::new(3) * p.x * p.x; + let cy = BN254::new(2) * p.y; + sparse_embed(p.y * p.y - BN254::new(9), q.x.scale(cx), q.y.scale(cy)) } /// The sloped line function for adding two points -pub fn cord(p1: Curve, p2: Curve, q: TwistedCurve) -> Fp12 { +pub fn cord(p1: Curve, p2: Curve, q: TwistedCurve) -> Fp12 { let cx = p2.y - p1.y; let cy = p1.x - p2.x; sparse_embed(p1.y * p2.x - p2.y * p1.x, q.x.scale(cx), q.y.scale(cy)) @@ -81,27 +81,31 @@ pub fn cord(p1: Curve, p2: Curve, q: TwistedCurve) -> Fp12 { /// The tangent and cord functions output sparse Fp12 elements. /// This map embeds the nonzero coefficients into an Fp12. -pub fn sparse_embed(g000: Fp, g01: Fp2, g11: Fp2) -> Fp12 { +pub fn sparse_embed(g000: BN254, g01: Fp2, g11: Fp2) -> Fp12 { let g0 = Fp6 { t0: Fp2 { re: g000, - im: ZERO_FP, + im: BN254::ZERO, }, t1: g01, - t2: ZERO_FP2, + t2: Fp2::::ZERO, }; let g1 = Fp6 { - t0: ZERO_FP2, + t0: Fp2::::ZERO, t1: g11, - t2: ZERO_FP2, + t2: Fp2::::ZERO, }; Fp12 { z0: g0, z1: g1 } } -pub fn gen_fp12_sparse(rng: &mut R) -> Fp12 { - sparse_embed(rng.gen::(), rng.gen::(), rng.gen::()) +pub fn gen_fp12_sparse(rng: &mut R) -> Fp12 { + sparse_embed( + rng.gen::(), + rng.gen::>(), + rng.gen::>(), + ) } /// The output y of the miller loop is not an invariant, @@ -116,7 +120,7 @@ pub fn gen_fp12_sparse(rng: &mut R) -> Fp12 { /// (p^4 - p^2 + 1)/N = p^3 + (a2)p^2 - (a1)p - a0 /// where 0 < a0, a1, a2 < p. Then the final power is given by /// y = y_3 * (y^a2)_2 * (y^-a1)_1 * (y^-a0) -pub fn invariant_exponent(f: Fp12) -> Fp12 { +pub fn invariant_exponent(f: Fp12) -> Fp12 { let mut y = f.frob(6) / f; y = y.frob(2) * y; let (y_a2, y_a1, y_a0) = get_custom_powers(y); @@ -134,11 +138,11 @@ pub fn invariant_exponent(f: Fp12) -> Fp12 { /// EXPS4 = [(a4[i], a2[i], a0[i]) for i in 0..len(a4)] /// EXPS2 = [ (a2[i], a0[i]) for i in len(a4)..len(a2)] /// EXPS0 = [ a0[i] for i in len(a2)..len(a0)] -fn get_custom_powers(f: Fp12) -> (Fp12, Fp12, Fp12) { - let mut sq: Fp12 = f; - let mut y0: Fp12 = UNIT_FP12; - let mut y2: Fp12 = UNIT_FP12; - let mut y4: Fp12 = UNIT_FP12; +fn get_custom_powers(f: Fp12) -> (Fp12, Fp12, Fp12) { + let mut sq: Fp12 = f; + let mut y0: Fp12 = Fp12::::UNIT; + let mut y2: Fp12 = Fp12::::UNIT; + let mut y4: Fp12 = Fp12::::UNIT; // proceed via standard squaring algorithm for exponentiation diff --git a/evm/src/cpu/kernel/interpreter.rs b/evm/src/cpu/kernel/interpreter.rs index 1693f490..408671ba 100644 --- a/evm/src/cpu/kernel/interpreter.rs +++ b/evm/src/cpu/kernel/interpreter.rs @@ -8,11 +8,11 @@ use ethereum_types::{U256, U512}; use keccak_hash::keccak; use plonky2::field::goldilocks_field::GoldilocksField; -use crate::bn254_arithmetic::BN_BASE; use crate::cpu::kernel::aggregator::KERNEL; use crate::cpu::kernel::constants::context_metadata::ContextMetadata; use crate::cpu::kernel::constants::global_metadata::GlobalMetadata; use crate::cpu::kernel::constants::txn_fields::NormalizedTxnField; +use crate::extension_tower::BN_BASE; use crate::generation::prover_input::ProverInputFn; use crate::generation::state::GenerationState; use crate::generation::GenerationInputs; diff --git a/evm/src/cpu/kernel/tests/bn254.rs b/evm/src/cpu/kernel/tests/bn254.rs index 1840a3c2..8e71ffd6 100644 --- a/evm/src/cpu/kernel/tests/bn254.rs +++ b/evm/src/cpu/kernel/tests/bn254.rs @@ -2,14 +2,13 @@ use anyhow::Result; use ethereum_types::U256; use rand::Rng; +use crate::bn254_pairing::{ + gen_fp12_sparse, invariant_exponent, miller_loop, tate, Curve, TwistedCurve, +}; use crate::cpu::kernel::interpreter::{ run_interpreter_with_memory, Interpreter, InterpreterMemoryInitialization, }; -// use crate::bn254_arithmetic::{Fp, Fp12, Fp2, Fp6}; -// use crate::bn254_pairing::{ -// gen_fp12_sparse, invariant_exponent, miller_loop, tate, Curve, TwistedCurve, -// }; -use crate::extension_tower::{Fp12, Fp6, Stack, BN254}; +use crate::extension_tower::{FieldExt, Fp12, Fp2, Fp6, Stack, BN254}; use crate::memory::segments::Segment::BnPairing; fn extract_stack(interpreter: Interpreter<'static>) -> Vec { @@ -96,29 +95,29 @@ fn test_mul_fp12() -> Result<()> { let mut rng = rand::thread_rng(); let f: Fp12 = rng.gen::>(); let g: Fp12 = rng.gen::>(); - // let h: Fp12 = gen_fp12_sparse(&mut rng); + let h: Fp12 = gen_fp12_sparse(&mut rng); let setup_normal: InterpreterMemoryInitialization = setup_mul_fp12_test(out, f, g, "mul_fp254_12"); - // let setup_sparse: InterpreterMemoryInitialization = - // setup_mul_fp12_test(out, f, h, "mul_fp254_12_sparse"); + let setup_sparse: InterpreterMemoryInitialization = + setup_mul_fp12_test(out, f, h, "mul_fp254_12_sparse"); let setup_square: InterpreterMemoryInitialization = setup_mul_fp12_test(out, f, f, "square_fp254_12"); let intrptr_normal: Interpreter = run_interpreter_with_memory(setup_normal).unwrap(); - // let intrptr_sparse: Interpreter = run_interpreter_with_memory(setup_sparse).unwrap(); + let intrptr_sparse: Interpreter = run_interpreter_with_memory(setup_sparse).unwrap(); let intrptr_square: Interpreter = run_interpreter_with_memory(setup_square).unwrap(); let out_normal: Vec = intrptr_normal.extract_kernel_memory(BnPairing, out..out + 12); - // let out_sparse: Vec = intrptr_sparse.extract_kernel_memory(BnPairing, out..out + 12); + let out_sparse: Vec = intrptr_sparse.extract_kernel_memory(BnPairing, out..out + 12); let out_square: Vec = intrptr_square.extract_kernel_memory(BnPairing, out..out + 12); let exp_normal: Vec = (f * g).on_stack(); - // let exp_sparse: Vec = (f * h).on_stack(); + let exp_sparse: Vec = (f * h).on_stack(); let exp_square: Vec = (f * f).on_stack(); assert_eq!(out_normal, exp_normal); - // assert_eq!(out_sparse, exp_sparse); + assert_eq!(out_sparse, exp_sparse); assert_eq!(out_square, exp_square); Ok(()) @@ -171,154 +170,154 @@ fn test_frob_fp12() -> Result<()> { Ok(()) } -// #[test] -// fn test_inv_fp12() -> Result<()> { -// let ptr: usize = 200; -// let inv: usize = 212; -// let mut rng = rand::thread_rng(); -// let f: Fp12 = rng.gen::(); +#[test] +fn test_inv_fp12() -> Result<()> { + let ptr: usize = 200; + let inv: usize = 212; + let mut rng = rand::thread_rng(); + let f: Fp12 = rng.gen::>(); -// let setup = InterpreterMemoryInitialization { -// label: "inv_fp254_12".to_string(), -// stack: vec![U256::from(ptr), U256::from(inv), U256::from(0xdeadbeefu32)], -// segment: BnPairing, -// memory: vec![(ptr, f.on_stack())], -// }; -// let interpreter: Interpreter = run_interpreter_with_memory(setup).unwrap(); -// let output: Vec = interpreter.extract_kernel_memory(BnPairing, inv..inv + 12); -// let expected: Vec = f.inv().on_stack(); + let setup = InterpreterMemoryInitialization { + label: "inv_fp254_12".to_string(), + stack: vec![U256::from(ptr), U256::from(inv), U256::from(0xdeadbeefu32)], + segment: BnPairing, + memory: vec![(ptr, f.on_stack())], + }; + let interpreter: Interpreter = run_interpreter_with_memory(setup).unwrap(); + let output: Vec = interpreter.extract_kernel_memory(BnPairing, inv..inv + 12); + let expected: Vec = f.inv().on_stack(); -// assert_eq!(output, expected); + assert_eq!(output, expected); -// Ok(()) -// } + Ok(()) +} -// #[test] -// fn test_invariant_exponent() -> Result<()> { -// let ptr: usize = 200; -// let mut rng = rand::thread_rng(); -// let f: Fp12 = rng.gen::(); +#[test] +fn test_invariant_exponent() -> Result<()> { + let ptr: usize = 200; + let mut rng = rand::thread_rng(); + let f: Fp12 = rng.gen::>(); -// let setup = InterpreterMemoryInitialization { -// label: "bn254_invariant_exponent".to_string(), -// stack: vec![U256::from(ptr), U256::from(0xdeadbeefu32)], -// segment: BnPairing, -// memory: vec![(ptr, f.on_stack())], -// }; + let setup = InterpreterMemoryInitialization { + label: "bn254_invariant_exponent".to_string(), + stack: vec![U256::from(ptr), U256::from(0xdeadbeefu32)], + segment: BnPairing, + memory: vec![(ptr, f.on_stack())], + }; -// let interpreter: Interpreter = run_interpreter_with_memory(setup).unwrap(); -// let output: Vec = interpreter.extract_kernel_memory(BnPairing, ptr..ptr + 12); -// let expected: Vec = invariant_exponent(f).on_stack(); + let interpreter: Interpreter = run_interpreter_with_memory(setup).unwrap(); + let output: Vec = interpreter.extract_kernel_memory(BnPairing, ptr..ptr + 12); + let expected: Vec = invariant_exponent(f).on_stack(); -// assert_eq!(output, expected); + assert_eq!(output, expected); -// Ok(()) -// } + Ok(()) +} -// // The curve is cyclic with generator (1, 2) -// pub const CURVE_GENERATOR: Curve = { -// Curve { -// x: Fp { val: U256::one() }, -// y: Fp { -// val: U256([2, 0, 0, 0]), -// }, -// } -// }; +// The curve is cyclic with generator (1, 2) +pub const CURVE_GENERATOR: Curve = { + Curve { + x: BN254 { val: U256::one() }, + y: BN254 { + val: U256([2, 0, 0, 0]), + }, + } +}; -// // The twisted curve is cyclic with generator (x, y) as follows -// pub const TWISTED_GENERATOR: TwistedCurve = { -// TwistedCurve { -// x: Fp2 { -// re: Fp { -// val: U256([ -// 0x46debd5cd992f6ed, -// 0x674322d4f75edadd, -// 0x426a00665e5c4479, -// 0x1800deef121f1e76, -// ]), -// }, -// im: Fp { -// val: U256([ -// 0x97e485b7aef312c2, -// 0xf1aa493335a9e712, -// 0x7260bfb731fb5d25, -// 0x198e9393920d483a, -// ]), -// }, -// }, -// y: Fp2 { -// re: Fp { -// val: U256([ -// 0x4ce6cc0166fa7daa, -// 0xe3d1e7690c43d37b, -// 0x4aab71808dcb408f, -// 0x12c85ea5db8c6deb, -// ]), -// }, -// im: Fp { -// val: U256([ -// 0x55acdadcd122975b, -// 0xbc4b313370b38ef3, -// 0xec9e99ad690c3395, -// 0x090689d0585ff075, -// ]), -// }, -// }, -// } -// }; +// The twisted curve is cyclic with generator (x, y) as follows +pub const TWISTED_GENERATOR: TwistedCurve = { + TwistedCurve { + x: Fp2 { + re: BN254 { + val: U256([ + 0x46debd5cd992f6ed, + 0x674322d4f75edadd, + 0x426a00665e5c4479, + 0x1800deef121f1e76, + ]), + }, + im: BN254 { + val: U256([ + 0x97e485b7aef312c2, + 0xf1aa493335a9e712, + 0x7260bfb731fb5d25, + 0x198e9393920d483a, + ]), + }, + }, + y: Fp2 { + re: BN254 { + val: U256([ + 0x4ce6cc0166fa7daa, + 0xe3d1e7690c43d37b, + 0x4aab71808dcb408f, + 0x12c85ea5db8c6deb, + ]), + }, + im: BN254 { + val: U256([ + 0x55acdadcd122975b, + 0xbc4b313370b38ef3, + 0xec9e99ad690c3395, + 0x090689d0585ff075, + ]), + }, + }, + } +}; -// #[test] -// fn test_miller() -> Result<()> { -// let ptr: usize = 200; -// let out: usize = 206; -// let inputs: Vec = vec![ -// CURVE_GENERATOR.x.val, -// CURVE_GENERATOR.y.val, -// TWISTED_GENERATOR.x.re.val, -// TWISTED_GENERATOR.x.im.val, -// TWISTED_GENERATOR.y.re.val, -// TWISTED_GENERATOR.y.im.val, -// ]; +#[test] +fn test_miller() -> Result<()> { + let ptr: usize = 200; + let out: usize = 206; + let inputs: Vec = vec![ + CURVE_GENERATOR.x.val, + CURVE_GENERATOR.y.val, + TWISTED_GENERATOR.x.re.val, + TWISTED_GENERATOR.x.im.val, + TWISTED_GENERATOR.y.re.val, + TWISTED_GENERATOR.y.im.val, + ]; -// let setup = InterpreterMemoryInitialization { -// label: "bn254_miller".to_string(), -// stack: vec![U256::from(ptr), U256::from(out), U256::from(0xdeadbeefu32)], -// segment: BnPairing, -// memory: vec![(ptr, inputs)], -// }; -// let interpreter = run_interpreter_with_memory(setup).unwrap(); -// let output: Vec = interpreter.extract_kernel_memory(BnPairing, out..out + 12); -// let expected = miller_loop(CURVE_GENERATOR, TWISTED_GENERATOR).on_stack(); + let setup = InterpreterMemoryInitialization { + label: "bn254_miller".to_string(), + stack: vec![U256::from(ptr), U256::from(out), U256::from(0xdeadbeefu32)], + segment: BnPairing, + memory: vec![(ptr, inputs)], + }; + let interpreter = run_interpreter_with_memory(setup).unwrap(); + let output: Vec = interpreter.extract_kernel_memory(BnPairing, out..out + 12); + let expected = miller_loop(CURVE_GENERATOR, TWISTED_GENERATOR).on_stack(); -// assert_eq!(output, expected); + assert_eq!(output, expected); -// Ok(()) -// } + Ok(()) +} -// #[test] -// fn test_tate() -> Result<()> { -// let ptr: usize = 200; -// let out: usize = 206; -// let inputs: Vec = vec![ -// CURVE_GENERATOR.x.val, -// CURVE_GENERATOR.y.val, -// TWISTED_GENERATOR.x.re.val, -// TWISTED_GENERATOR.x.im.val, -// TWISTED_GENERATOR.y.re.val, -// TWISTED_GENERATOR.y.im.val, -// ]; +#[test] +fn test_tate() -> Result<()> { + let ptr: usize = 200; + let out: usize = 206; + let inputs: Vec = vec![ + CURVE_GENERATOR.x.val, + CURVE_GENERATOR.y.val, + TWISTED_GENERATOR.x.re.val, + TWISTED_GENERATOR.x.im.val, + TWISTED_GENERATOR.y.re.val, + TWISTED_GENERATOR.y.im.val, + ]; -// let setup = InterpreterMemoryInitialization { -// label: "bn254_tate".to_string(), -// stack: vec![U256::from(ptr), U256::from(out), U256::from(0xdeadbeefu32)], -// segment: BnPairing, -// memory: vec![(ptr, inputs)], -// }; -// let interpreter = run_interpreter_with_memory(setup).unwrap(); -// let output: Vec = interpreter.extract_kernel_memory(BnPairing, out..out + 12); -// let expected = tate(CURVE_GENERATOR, TWISTED_GENERATOR).on_stack(); + let setup = InterpreterMemoryInitialization { + label: "bn254_tate".to_string(), + stack: vec![U256::from(ptr), U256::from(out), U256::from(0xdeadbeefu32)], + segment: BnPairing, + memory: vec![(ptr, inputs)], + }; + let interpreter = run_interpreter_with_memory(setup).unwrap(); + let output: Vec = interpreter.extract_kernel_memory(BnPairing, out..out + 12); + let expected = tate(CURVE_GENERATOR, TWISTED_GENERATOR).on_stack(); -// assert_eq!(output, expected); + assert_eq!(output, expected); -// Ok(()) -// } + Ok(()) +} diff --git a/evm/src/generation/prover_input.rs b/evm/src/generation/prover_input.rs index 1313de83..7f62acda 100644 --- a/evm/src/generation/prover_input.rs +++ b/evm/src/generation/prover_input.rs @@ -5,7 +5,7 @@ use anyhow::{bail, Error}; use ethereum_types::{BigEndianHash, H256, U256}; use plonky2::field::types::Field; -use crate::bn254_arithmetic::Fp12; +use crate::extension_tower::{FieldExt, Fp12, BN254}; use crate::generation::prover_input::EvmField::{ Bn254Base, Bn254Scalar, Secp256k1Base, Secp256k1Scalar, }; @@ -207,7 +207,7 @@ impl EvmField { } fn field_extension_inverse(&self, n: usize, f: [U256; 12]) -> U256 { - let f: Fp12 = unsafe { transmute(f) }; + let f: Fp12 = unsafe { transmute(f) }; let f_inv: [U256; 12] = unsafe { transmute(f.inv()) }; f_inv[n] } diff --git a/evm/src/lib.rs b/evm/src/lib.rs index fa48d8dc..dc2204df 100644 --- a/evm/src/lib.rs +++ b/evm/src/lib.rs @@ -8,7 +8,6 @@ pub mod all_stark; pub mod arithmetic; -pub mod bn254_arithmetic; pub mod bn254_pairing; pub mod config; pub mod constraint_consumer;