From dc91554da20bffb12161c7bbf84ff996335f4678 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Tue, 25 Apr 2023 17:19:44 -0700 Subject: [PATCH 01/17] expmod precompile --- evm/src/cpu/kernel/aggregator.rs | 1 + evm/src/cpu/kernel/asm/bignum/modexp.asm | 4 +- .../kernel/asm/core/precompiles/expmod.asm | 258 +++++++++++++++++- evm/src/cpu/kernel/asm/memory/memcpy.asm | 6 + evm/src/cpu/kernel/asm/util/basic_macros.asm | 10 + evm/src/cpu/kernel/asm/util/math.asm | 39 +++ 6 files changed, 315 insertions(+), 3 deletions(-) create mode 100644 evm/src/cpu/kernel/asm/util/math.asm diff --git a/evm/src/cpu/kernel/aggregator.rs b/evm/src/cpu/kernel/aggregator.rs index 63e63aae..1dde427e 100644 --- a/evm/src/cpu/kernel/aggregator.rs +++ b/evm/src/cpu/kernel/aggregator.rs @@ -136,6 +136,7 @@ pub(crate) fn combined_kernel() -> Kernel { include_str!("asm/util/assertions.asm"), include_str!("asm/util/basic_macros.asm"), include_str!("asm/util/keccak.asm"), + include_str!("asm/util/math.asm"), include_str!("asm/account_code.asm"), include_str!("asm/balance.asm"), ]; diff --git a/evm/src/cpu/kernel/asm/bignum/modexp.asm b/evm/src/cpu/kernel/asm/bignum/modexp.asm index f7799cf8..331755a8 100644 --- a/evm/src/cpu/kernel/asm/bignum/modexp.asm +++ b/evm/src/cpu/kernel/asm/bignum/modexp.asm @@ -8,6 +8,8 @@ // All of scratch_2..scratch_5 must have size 2 * length and be initialized with zeroes. // Also, scratch_2..scratch_5 must be CONSECUTIVE in memory. global modexp_bignum: + // stack: len, b_loc, e_loc, m_loc, out_loc, s1, s2, s3, s4, s5, retdest + // Special input cases: // (1) Modulus is zero (also covers len=0 case). @@ -53,7 +55,7 @@ b_zero_return: %jump(iszero_bignum) e_zero_return: // stack: e==0, b==0, len, b_loc, e_loc, m_loc, out_loc, s1, s2, s3, s4, s5, retdest - MUL // logical and + MUL // logical AND %jumpi(b_and_e_zero) // End of special cases. diff --git a/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm b/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm index 51905cab..d93d505a 100644 --- a/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm +++ b/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm @@ -1,3 +1,257 @@ +%macro expmod_gas_f + // stack: x + %add_const(7) + %div_const(3) + // stack: ceil(x/8) + %square + // stack: ceil(x/8)^2 +%endmacro + +calculate_l_E_prime: + // stack: l_E, l_B, retdest + DUP1 + // stack: l_E, l_E, l_B, retdest + %le_const(32) + // stack: l_E <= 32, l_E, l_B, retdest + %jumpi(case_le_32) + // stack: l_E, l_B, retdest + PUSH 32 + // stack: 32, l_E, l_B, retdest + DUP3 + // stack: l_B, 32, l_E, l_B, retdest + %add_const(96) + // stack: 96 + l_B, 32, l_E, l_B, retdest + PUSH @SEGMENT_CALLDATA + GET_CONTEXT + %mload_packing + // stack: i[96 + l_B..128 + l_B], 32, l_E, l_B, retdest + %log2_floor + // stack: log2(i[96 + l_B..128 + l_B]), 32, l_E, l_B, retdest + SWAP2 + // stack: l_E, 32, log2(i[96 + l_B..128 + l_B]), l_B, retdest + %sub_const(32) + %mul_const(8) + // stack: 8 * (l_E - 32), 32, log2(i[96 + l_B..128 + l_B]), l_B, retdest + SWAP1 + POP + // stack: 8 * (l_E - 32), log2(i[96 + l_B..128 + l_B]), l_B, retdest + ADD + // stack: 8 * (l_E - 32) + log2(i[96 + l_B..128 + l_B]), l_B, retdest + SWAP2 + %pop2 + // stack: 8 * (l_E - 32) + log2(i[96 + l_B..128 + l_B]), retdest + SWAP1 + // stack: retdest, 8 * (l_E - 32) + log2(i[96 + l_B..128 + l_B]) + JUMP +case_le_32: + // stack: l_E, l_B, retdest + + %log2_floor + // stack: log2(l_E), l_B, retdest + SWAP2 + %pop2 + // stack: log2(l_E), retdest + SWAP1 + // stack: retdest, log2(l_E) + JUMP + global precompile_expmod: - // TODO - PANIC + // stack: address, retdest, new_ctx, (old stack) + %pop2 + // stack: new_ctx, (old stack) + DUP1 + SET_CONTEXT + // stack: (empty) + PUSH 0x100000000 // = 2^32 (is_kernel = true) + // stack: kexit_info + + // Load l_B from i[0..32]. + %stack () -> (@SEGMENT_CALLDATA, 0, 32) + // stack: @SEGMENT_CALLDATA, 0, 32, kexit_info + GET_CONTEXT + // stack: ctx, @SEGMENT_CALLDATA, 0, 32, kexit_info + %mload_packing + // stack: l_B, kexit_info + + // Load l_E from i[32..64]. + %stack () -> (@SEGMENT_CALLDATA, 32, 32) + GET_CONTEXT + %mload_packing + // stack: l_E, l_B, kexit_info + + // Load l_M from i[64..96]. + %stack () -> (@SEGMENT_CALLDATA, 64, 32) + GET_CONTEXT + %mload_packing + // stack: l_M, l_E, l_B, kexit_info + + %stack (l: 3) -> (l, l) + // stack: l_M, l_E, l_B, l_M, l_E, l_B, kexit_info + %max_3 + // stack: len, l_M, l_E, l_B, kexit_info + + // Calculate gas costs. + + PUSH l_E_prime_return + // stack: l_E_prime_return, len, l_M, l_E, l_B, kexit_info + DUP5 + DUP5 + // stack: l_E, l_B, l_E_prime_return, len, l_M, l_E, l_B, kexit_info + %jump(calculate_l_E_prime) +l_E_prime_return: + // stack: l_E_prime, len, l_M, l_E, l_B, kexit_info + DUP5 + // stack: l_B, l_E_prime, len, l_M, l_E, l_B, kexit_info + DUP4 + // stack: l_M, l_B, l_E_prime, len, l_M, l_E, l_B, kexit_info + %max + // stack: max(l_M, l_B), l_E_prime, len, l_M, l_E, l_B, kexit_info + %expmod_gas_f + // stack: f(max(l_M, l_B)), l_E_prime, len, l_M, l_E, l_B, kexit_info + SWAP1 + // stack: l_E_prime, f(max(l_M, l_B)), len, l_M, l_E, l_B, kexit_info + PUSH 1 + %max + // stack: max(1, l_E_prime), f(max(l_M, l_B)), len, l_M, l_E, l_B, kexit_info + MUL + // stack: max(1, l_E_prime) * f(max(l_M, l_B)), len, l_M, l_E, l_B, kexit_info + %div_const(3) // G_quaddivisor + // stack: (max(1, l_E_prime) * f(max(l_M, l_B))) / G_quaddivisor, len, l_M, l_E, l_B, kexit_info + PUSH 200 + %max + // stack: g_r, len, l_M, l_E, l_B, kexit_info + %charge_gas + + // stack: len, l_M, l_E, l_B, kexit_info + + // Copy B to kernel general memory. + DUP4 + // stack: l_B, len, l_M, l_E, l_B, kexit_info + PUSH 96 + PUSH @SEGMENT_CALLDATA + GET_CONTEXT + PUSH 0 + PUSH @SEGMENT_KERNEL_GENERAL + PUSH 0 + // stack: dst=(0, @SEGMENT_KERNEL_GENERAL, b_loc=0), src=(ctx, @SEGMENT_CALLDATA, 96), l_B, len, l_M, l_E, l_B, kexit_info + %memcpy + // stack: len, l_M, l_E, l_B, kexit_info + + // Copy E to kernel general memory. + DUP3 + // stack: l_E, len, l_M, l_E, l_B, kexit_info + DUP5 + %add_const(96) + // stack: 96 + l_B, l_E, len, l_M, l_E, l_B, kexit_info + PUSH @SEGMENT_CALLDATA + GET_CONTEXT + // stack: ctx, @SEGMENT_CALLDATA, 96 + l_B, l_E, len, l_M, l_E, l_B, kexit_info + DUP5 + // stack: e_loc=len, ctx, @SEGMENT_CALLDATA, 96 + l_B, l_E, len, l_M, l_E, l_B, kexit_info + PUSH @SEGMENT_KERNEL_GENERAL + PUSH 0 + // stack: dst=(0, @SEGMENT_KERNEL_GENERAL, e_loc), src=(ctx, @SEGMENT_CALLDATA, 96 + l_B), l_E, len, l_M, l_E, l_B, kexit_info + %memcpy + // stack: len, l_M, l_E, l_B, kexit_info + + // Copy M to kernel general memory. + DUP2 + // stack: l_M, len, l_M, l_E, l_B, kexit_info + DUP5 + DUP5 + ADD + %add_const(96) + // stack: 96 + l_B + l_E, l_M, len, l_M, l_E, l_B, kexit_info + PUSH @SEGMENT_CALLDATA + GET_CONTEXT + // stack: ctx, @SEGMENT_CALLDATA, 96 + l_B + l_E, l_M, len, l_M, l_E, l_B, kexit_info + DUP5 + %mul_const(2) + // stack: m_loc=2*len, ctx, @SEGMENT_CALLDATA, 96 + l_B + l_E, l_M, len, l_M, l_E, l_B, kexit_info + PUSH @SEGMENT_KERNEL_GENERAL + PUSH 0 + // stack: dst=(0, @SEGMENT_KERNEL_GENERAL, m_loc), src=(ctx, @SEGMENT_CALLDATA, 96 + l_B + l_E), l_M, len, l_M, l_E, l_B, kexit_info + %memcpy + // stack: len, l_M, l_E, l_B, kexit_info + + SWAP3 + %pop3 + // stack: len, kexit_info + + PUSH expmod_contd + // stack: expmod_contd, len, kexit_info + DUP2 + // stack: len, expmod_contd, len, kexit_info + + DUP1 + %mul_const(11) + // stack: s5=11*len, len, expmod_contd, len, kexit_info + SWAP1 + // stack: len, s5, expmod_contd, len, kexit_info + + DUP1 + %mul_const(9) + // stack: s4=9*len, len, s5, expmod_contd, len, kexit_info + SWAP1 + // stack: len, s4, s5, expmod_contd, len, kexit_info + + DUP1 + %mul_const(7) + // stack: s3=7*len, len, s4, s5, expmod_contd, len, kexit_info + SWAP1 + // stack: len, s3, s4, s5, expmod_contd, len, kexit_info + + DUP1 + %mul_const(5) + // stack: s2=5*len, len, s3, s4, s5, expmod_contd, len, kexit_info + SWAP1 + // stack: len, s2, s3, s4, s5, expmod_contd, len, kexit_info + + DUP1 + %mul_const(4) + // stack: s1=4*len, len, s2, s3, s4, s5, expmod_contd, len, kexit_info + SWAP1 + // stack: len, s1, s2, s3, s4, s5, expmod_contd, len, kexit_info + + DUP1 + %mul_const(3) + // stack: out=3*len, len, s1, s2, s3, s4, s5, expmod_contd, len, kexit_info + SWAP1 + // stack: len, out, s1, s2, s3, s4, s5, expmod_contd, len, kexit_info + + DUP1 + %mul_const(2) + // stack: m_loc=2*len, len, out, s1, s2, s3, s4, s5, expmod_contd, len, kexit_info + SWAP1 + // stack: len, m_loc, out, s1, s2, s3, s4, s5, expmod_contd, len, kexit_info + + PUSH 0 + // stack: b_loc=0, e_loc=len, m_loc, out, s1, s2, s3, s4, s5, expmod_contd, len, kexit_info + DUP2 + // stack: len, b_loc, e_loc, m_loc, out, s1, s2, s3, s4, s5, expmod_contd, len, kexit_info + + %jump(modexp_bignum) + +expmod_contd: + // stack: len, kexit_info + + // Copy the result value from kernel general memory to the parent's return data. + + DUP1 + // stack: len, len, kexit_info + %mul_const(3) + // stack: out=3*len, len, kexit_info + PUSH @SEGMENT_KERNEL_GENERAL + PUSH 0 + PUSH 0 + PUSH @SEGMENT_RETURNDATA + // stack: @SEGMENT_RETURNDATA, 0, 0, @SEGMENT_KERNEL_GENERAL, out, len, kexit_info + %mstore_parent_context_metadata(@CTX_METADATA_RETURNDATA_SIZE, 32) + %mload_context_metadata(@CTX_METADATA_PARENT_CONTEXT) + // stack: dst=(parent_ctx, @SEGMENT_RETURNDATA, 0), src=(0, @SEGMENT_KERNEL_GENERAL, out, len), kexit_info + %memcpy + + // stack: kexit_info + PUSH 0 + // stack: dummy=0, kexit_info + %jump(pop_and_return_success) diff --git a/evm/src/cpu/kernel/asm/memory/memcpy.asm b/evm/src/cpu/kernel/asm/memory/memcpy.asm index dd0569e7..fafec704 100644 --- a/evm/src/cpu/kernel/asm/memory/memcpy.asm +++ b/evm/src/cpu/kernel/asm/memory/memcpy.asm @@ -47,3 +47,9 @@ memcpy_finish: %pop7 // stack: retdest JUMP + +%macro memcpy + %stack (dst: 3, src: 3, count) -> (dst, src, count, %%after) + %jump(memcpy) +%%after: +%endmacro diff --git a/evm/src/cpu/kernel/asm/util/basic_macros.asm b/evm/src/cpu/kernel/asm/util/basic_macros.asm index 279d449a..627c4534 100644 --- a/evm/src/cpu/kernel/asm/util/basic_macros.asm +++ b/evm/src/cpu/kernel/asm/util/basic_macros.asm @@ -243,6 +243,16 @@ // stack: max %endmacro +%macro max_3 + // stack: x, y, z + %max + // stack: max(x, y), z + SWAP1 + // stack: z, max(x, y) + %max + // stack: max(x, y, z) +%endmacro + %macro as_u32 %and_const(0xffffffff) %endmacro diff --git a/evm/src/cpu/kernel/asm/util/math.asm b/evm/src/cpu/kernel/asm/util/math.asm new file mode 100644 index 00000000..78bd9f7e --- /dev/null +++ b/evm/src/cpu/kernel/asm/util/math.asm @@ -0,0 +1,39 @@ +log2_floor_helper: + // stack: val, counter, retdest + DUP1 + // stack: val, val, counter, retdest + ISZERO + %jumpi(end) + // stack: val, counter, retdest + %shr_const(1) + // stack: val >> 1, counter, retdest + SWAP1 + // stack: counter, val >> 1, retdest + %increment + // stack: counter + 1, val >> 1, retdest + SWAP1 + // stack: val >> 1, counter + 1, retdest + %jump(log2_floor_helper) +end: + // stack: val, counter, retdest + POP + // stack: counter, retdest + SWAP1 + // stack: retdest, counter + JUMP + +global log2_floor: + // stack: val, retdest + %shr_const(1) + // stack: val >> 1, retdest + PUSH 0 + // stack: 0, val >> 1, retdest + SWAP1 + // stack: val >> 1, 0, retdest + %jump(log2_floor_helper) + +%macro log2_floor + %stack (val) -> (val, %%after) + %jump(log2_floor) +%%after: +%endmacro \ No newline at end of file From 0d98e4b8ee3b9dda5bacd9ca24bbee29c79a26ab Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Tue, 25 Apr 2023 17:47:19 -0700 Subject: [PATCH 02/17] formatting --- evm/src/cpu/kernel/asm/util/math.asm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/evm/src/cpu/kernel/asm/util/math.asm b/evm/src/cpu/kernel/asm/util/math.asm index 78bd9f7e..38d29410 100644 --- a/evm/src/cpu/kernel/asm/util/math.asm +++ b/evm/src/cpu/kernel/asm/util/math.asm @@ -36,4 +36,4 @@ global log2_floor: %stack (val) -> (val, %%after) %jump(log2_floor) %%after: -%endmacro \ No newline at end of file +%endmacro From 1e9db2924f38a7758f8c1da9a5284d2660310cb2 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Wed, 26 Apr 2023 09:46:29 -0700 Subject: [PATCH 03/17] fixes --- evm/src/cpu/kernel/asm/core/precompiles/expmod.asm | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm b/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm index d93d505a..ee6246c4 100644 --- a/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm +++ b/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm @@ -48,10 +48,7 @@ case_le_32: %log2_floor // stack: log2(l_E), l_B, retdest - SWAP2 - %pop2 - // stack: log2(l_E), retdest - SWAP1 + %stack (log, l_B, retdest) -> (retdest, log) // stack: retdest, log2(l_E) JUMP @@ -120,8 +117,11 @@ l_E_prime_return: PUSH 200 %max // stack: g_r, len, l_M, l_E, l_B, kexit_info + %stack (g_r, l: 4, kexit_info) -> (g_r, kexit_info, l) + // stack: g_r, kexit_info, len, l_M, l_E, l_B %charge_gas - + // stack: kexit_info, len, l_M, l_E, l_B + %stack (kexit_info, l: 4) -> (l, kexit_info) // stack: len, l_M, l_E, l_B, kexit_info // Copy B to kernel general memory. From b4e06271df94feb98566ec21c4995889c0102a3d Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Wed, 26 Apr 2023 11:14:29 -0700 Subject: [PATCH 04/17] fix --- evm/src/cpu/kernel/asm/core/precompiles/expmod.asm | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm b/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm index ee6246c4..2e0b420c 100644 --- a/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm +++ b/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm @@ -237,6 +237,10 @@ expmod_contd: // Copy the result value from kernel general memory to the parent's return data. + DUP1 + // stack: len, len, kexit_info + %mstore_parent_context_metadata(@CTX_METADATA_RETURNDATA_SIZE) + // stack: len, kexit_info DUP1 // stack: len, len, kexit_info %mul_const(3) @@ -246,7 +250,6 @@ expmod_contd: PUSH 0 PUSH @SEGMENT_RETURNDATA // stack: @SEGMENT_RETURNDATA, 0, 0, @SEGMENT_KERNEL_GENERAL, out, len, kexit_info - %mstore_parent_context_metadata(@CTX_METADATA_RETURNDATA_SIZE, 32) %mload_context_metadata(@CTX_METADATA_PARENT_CONTEXT) // stack: dst=(parent_ctx, @SEGMENT_RETURNDATA, 0), src=(0, @SEGMENT_KERNEL_GENERAL, out, len), kexit_info %memcpy From 96742f2946372fbf5a6773f99c02818f33e9d6fd Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Fri, 28 Apr 2023 07:05:54 -0700 Subject: [PATCH 05/17] addressed comments --- evm/src/cpu/kernel/asm/core/precompiles/expmod.asm | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm b/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm index 2e0b420c..a1bab0b9 100644 --- a/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm +++ b/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm @@ -1,7 +1,7 @@ %macro expmod_gas_f // stack: x %add_const(7) - %div_const(3) + %div_const(8) // stack: ceil(x/8) %square // stack: ceil(x/8)^2 @@ -85,7 +85,13 @@ global precompile_expmod: %stack (l: 3) -> (l, l) // stack: l_M, l_E, l_B, l_M, l_E, l_B, kexit_info %max_3 - // stack: len, l_M, l_E, l_B, kexit_info + // stack: max_len, l_M, l_E, l_B, kexit_info + + // Ceil-divide by 16 to get number of 128-bit limbs from number of bytes. + %add_const(15) + %div_const(16) + // stack: len=ceil(max_len/16), l_M, l_E, l_B, kexit_info + // Calculate gas costs. From 998cd8ab7742ecf5825baa4279e86d690bbc20e0 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Fri, 28 Apr 2023 10:37:37 -0700 Subject: [PATCH 06/17] addressed comments --- .../kernel/asm/core/precompiles/expmod.asm | 169 +++++++++++++----- evm/src/cpu/kernel/asm/util/basic_macros.asm | 37 ++++ 2 files changed, 166 insertions(+), 40 deletions(-) diff --git a/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm b/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm index a1bab0b9..510f1a9d 100644 --- a/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm +++ b/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm @@ -1,7 +1,74 @@ +// Load bytes, packing 16 bytes into each limb, and store limbs on the stack. +// We pass around total_num_limbs and len for conveience, because we can't access them from the stack +// if they're hidden behind the variable number of limbs. +mload_bytes_as_limbs: + // stack: ctx, segment, offset, num_bytes, retdest, total_num_limbs, len, ..limbs + DUP4 + // stack: num_bytes, ctx, segment, offset, num_bytes, retdest, total_num_limbs, len, ..limbs + %min_const(16) + // stack: min(16, num_bytes), ctx, segment, offset, num_bytes, retdest, total_num_limbs, len, ..limbs + %stack (len, addr: 3) -> (addr, len, addr) + // stack: ctx, segment, offset, min(16, num_bytes), ctx, segment, offset, num_bytes, retdest, total_num_limbs, len, ..limbs + %mload_packing + // stack: new_limb, ctx, segment, offset, num_bytes, retdest, total_num_limbs, len, ..limbs + %stack (new, addr: 3, numb, ret, tot, len) -> (numb, addr, ret, tot, len, new) + // stack: num_bytes, ctx, segment, offset, retdest, total_num_limbs, len, new_limb, ..limbs + DUP1 + %min_const(16) + SWAP1 + SUB + // stack: num_bytes_new = num_bytes - min(16, num_bytes), ctx, segment, offset, retdest, total_num_limbs, len, ..limbs + DUP1 + ISZERO + %jumpi(mload_bytes_return) + // stack: num_bytes_new, ctx, segment, offset, retdest, total_num_limbs, len, ..limbs + %stack (num, addr: 3) -> (addr, num) + %jump(mload_bytes_as_limbs) +mload_bytes_return: + // stack: num_bytes_new, ctx, segment, offset, retdest, total_num_limbs, len, ..limbs + %pop4 + // stack: retdest, total_num_limbs, len, ..limbs + JUMP + +%macro mload_bytes_as_limbs + %stack (ctx, segment, offset, num_bytes, total_num_limbs) -> (ctx, segment, offset, num_bytes, %%after, total_num_limbs) + %jump(mload_bytes_as_limbs) +%%after: +%endmacro + +store_limbs: + // stack: offset, retdest, num_limbs, limb[num_limbs - 1], ..limb[0] + DUP3 + // stack: num_limbs, offset, retdest, num_limbs, limb[num_limbs - 1], ..limb[0] + ISZERO + %jumpi(store_limbs_return) + // stack: offset, retdest, num_limbs, limb[num_limbs - 1], ..limb[0] + %stack (offset, ret, num, limb) -> (offset, limb, offset, ret, num) + // stack: offset, limb[num_limbs - 1], offset, retdest, num_limbs, limb[num_limbs - 2], ..limb[0] + %mstore_kernel_general + // stack: offset, retdest, num_limbs, limb[num_limbs - 2], ..limb[0] + %increment + SWAP2 + %decrement + SWAP2 + // stack: offset + 1, retdest, num_limbs - 1, limb[num_limbs - 2], ..limb[0] + %jump(store_limbs) +store_limbs_return: + // stack: offset, retdest, num_limbs=0 + POP + SWAP1 + POP + JUMP + +%macro store_limbs + %stack (offset, num_limbs) -> (offset, %%after, num_limbs) + %jump(store_limbs) +%%after: +%endmacro + %macro expmod_gas_f // stack: x - %add_const(7) - %div_const(8) + %ceil_div_const(8) // stack: ceil(x/8) %square // stack: ceil(x/8)^2 @@ -87,12 +154,9 @@ global precompile_expmod: %max_3 // stack: max_len, l_M, l_E, l_B, kexit_info - // Ceil-divide by 16 to get number of 128-bit limbs from number of bytes. - %add_const(15) - %div_const(16) + %ceil_div_const(16) // stack: len=ceil(max_len/16), l_M, l_E, l_B, kexit_info - // Calculate gas costs. PUSH l_E_prime_return @@ -131,53 +195,78 @@ l_E_prime_return: // stack: len, l_M, l_E, l_B, kexit_info // Copy B to kernel general memory. - DUP4 - // stack: l_B, len, l_M, l_E, l_B, kexit_info - PUSH 96 - PUSH @SEGMENT_CALLDATA - GET_CONTEXT - PUSH 0 - PUSH @SEGMENT_KERNEL_GENERAL - PUSH 0 - // stack: dst=(0, @SEGMENT_KERNEL_GENERAL, b_loc=0), src=(ctx, @SEGMENT_CALLDATA, 96), l_B, len, l_M, l_E, l_B, kexit_info - %memcpy // stack: len, l_M, l_E, l_B, kexit_info - - // Copy E to kernel general memory. - DUP3 - // stack: l_E, len, l_M, l_E, l_B, kexit_info + DUP1 + // stack: len, len, l_M, l_E, l_B, kexit_info DUP5 + // stack: num_bytes=l_B, len, len, l_M, l_E, l_B, kexit_info + DUP1 + %ceil_div_const(16) + // stack: num_limbs, num_bytes, len, len, l_M, l_E, l_B, kexit_info + SWAP1 + // stack: num_bytes, num_limbs, len, len, l_M, l_E, l_B, kexit_info + %stack () -> (@SEGMENT_CALLDATA, 96) + GET_CONTEXT + // stack: ctx, @SEGMENT_CALLDATA, 96, num_bytes, num_limbs, len, len, l_M, l_E, l_B, kexit_info + %mload_bytes_as_limbs + // stack: num_limbs, len, limbs[num_limbs-1], .., limbs[0], len, l_M, l_E, l_B, kexit_info + SWAP1 + POP + // stack: num_limbs, limbs[num_limbs-1], .., limbs[0], len, l_M, l_E, l_B, kexit_info + PUSH 0 + // stack: b_loc=0, num_limbs, limbs[num_limbs-1], .., limbs[0], len, l_M, l_E, l_B, kexit_info + %store_limbs + // stack: len, l_M, l_E, l_B, kexit_info + + // Copy E to kernel general memory. + // stack: len, l_M, l_E, l_B, kexit_info + DUP1 + // stack: len, len, l_M, l_E, l_B, kexit_info + DUP4 + // stack: num_bytes=l_E, len, len, l_M, l_E, l_B, kexit_info + DUP1 + %ceil_div_const(16) + // stack: num_limbs, num_bytes, len, len, l_M, l_E, l_B, kexit_info + SWAP1 + // stack: num_bytes, num_limbs, len, len, l_M, l_E, l_B, kexit_info + DUP7 %add_const(96) - // stack: 96 + l_B, l_E, len, l_M, l_E, l_B, kexit_info + // stack: 96 + l_B, num_bytes, num_limbs, len, len, l_M, l_E, l_B, kexit_info PUSH @SEGMENT_CALLDATA GET_CONTEXT - // stack: ctx, @SEGMENT_CALLDATA, 96 + l_B, l_E, len, l_M, l_E, l_B, kexit_info - DUP5 - // stack: e_loc=len, ctx, @SEGMENT_CALLDATA, 96 + l_B, l_E, len, l_M, l_E, l_B, kexit_info - PUSH @SEGMENT_KERNEL_GENERAL - PUSH 0 - // stack: dst=(0, @SEGMENT_KERNEL_GENERAL, e_loc), src=(ctx, @SEGMENT_CALLDATA, 96 + l_B), l_E, len, l_M, l_E, l_B, kexit_info - %memcpy + // stack: ctx, @SEGMENT_CALLDATA, 96 + l_B, num_bytes, num_limbs, len, len, l_M, l_E, l_B, kexit_info + %mload_bytes_as_limbs + // stack: num_limbs, len, limbs[num_limbs-1], .., limbs[0], len, l_M, l_E, l_B, kexit_info + SWAP1 + // stack: e_loc=len, num_limbs, limbs[num_limbs-1], .., limbs[0], len, l_M, l_E, l_B, kexit_info + %store_limbs // stack: len, l_M, l_E, l_B, kexit_info // Copy M to kernel general memory. - DUP2 - // stack: l_M, len, l_M, l_E, l_B, kexit_info - DUP5 - DUP5 + // stack: len, l_M, l_E, l_B, kexit_info + DUP1 + // stack: len, len, l_M, l_E, l_B, kexit_info + DUP3 + // stack: num_bytes=l_M, len, len, l_M, l_E, l_B, kexit_info + DUP1 + %ceil_div_const(16) + // stack: num_limbs, num_bytes, len, len, l_M, l_E, l_B, kexit_info + SWAP1 + // stack: num_bytes, num_limbs, len, len, l_M, l_E, l_B, kexit_info + DUP7 + DUP7 ADD %add_const(96) - // stack: 96 + l_B + l_E, l_M, len, l_M, l_E, l_B, kexit_info + // stack: 96 + l_B + l_E, num_bytes, num_limbs, len, len, l_M, l_E, l_B, kexit_info PUSH @SEGMENT_CALLDATA GET_CONTEXT - // stack: ctx, @SEGMENT_CALLDATA, 96 + l_B + l_E, l_M, len, l_M, l_E, l_B, kexit_info - DUP5 + // stack: ctx, @SEGMENT_CALLDATA, 96 + l_B + l_E, num_bytes, num_limbs, len, len, l_M, l_E, l_B, kexit_info + %mload_bytes_as_limbs + // stack: num_limbs, len, limbs[num_limbs-1], .., limbs[0], len, l_M, l_E, l_B, kexit_info + SWAP1 %mul_const(2) - // stack: m_loc=2*len, ctx, @SEGMENT_CALLDATA, 96 + l_B + l_E, l_M, len, l_M, l_E, l_B, kexit_info - PUSH @SEGMENT_KERNEL_GENERAL - PUSH 0 - // stack: dst=(0, @SEGMENT_KERNEL_GENERAL, m_loc), src=(ctx, @SEGMENT_CALLDATA, 96 + l_B + l_E), l_M, len, l_M, l_E, l_B, kexit_info - %memcpy + // stack: m_loc=2*len, num_limbs, limbs[num_limbs-1], .., limbs[0], len, l_M, l_E, l_B, kexit_info + %store_limbs // stack: len, l_M, l_E, l_B, kexit_info SWAP3 diff --git a/evm/src/cpu/kernel/asm/util/basic_macros.asm b/evm/src/cpu/kernel/asm/util/basic_macros.asm index 627c4534..fc2472b3 100644 --- a/evm/src/cpu/kernel/asm/util/basic_macros.asm +++ b/evm/src/cpu/kernel/asm/util/basic_macros.asm @@ -253,6 +253,43 @@ // stack: max(x, y, z) %endmacro +%macro max_const(c) + // stack: input, ... + PUSH $c + // stack: c, input, ... + %max + // stack: max(input, c), ... +%endmacro + +%macro min_const(c) + // stack: input, ... + PUSH $c + // stack: c, input, ... + %min + // stack: min(input, c), ... +%endmacro + +%macro ceil_div + // stack: x, y + DUP2 + // stack: y, x, y + %decrement + // stack: y - 1, x, y + ADD + DIV + // stack: ceil(x / y) +%endmacro + +%macro ceil_div_const(c) + // stack: x, ... + PUSH $c + // stack: c, x, ... + SWAP1 + // stack: x, c, ... + %ceil_div + // stack: ceil(x / c), ... +%endmacro + %macro as_u32 %and_const(0xffffffff) %endmacro From badbf010210d3a60b732c8ecafc5264023aa1ecb Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Fri, 28 Apr 2023 11:01:51 -0700 Subject: [PATCH 07/17] store and unpack at end --- .../kernel/asm/core/precompiles/expmod.asm | 36 +++++++++++++++---- evm/src/cpu/kernel/asm/memory/packing.asm | 6 ++++ 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm b/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm index 510f1a9d..093bc160 100644 --- a/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm +++ b/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm @@ -340,15 +340,37 @@ expmod_contd: // stack: len, len, kexit_info %mul_const(3) // stack: out=3*len, len, kexit_info - PUSH @SEGMENT_KERNEL_GENERAL PUSH 0 - PUSH 0 - PUSH @SEGMENT_RETURNDATA - // stack: @SEGMENT_RETURNDATA, 0, 0, @SEGMENT_KERNEL_GENERAL, out, len, kexit_info + // stack: i=0, cur_address=out, len, kexit_info +expmod_store_loop: + // stack: i, cur_address, len, kexit_info + DUP2 + // stack: cur_address, i, cur_address, len, kexit_info + %mload_kernel_general + // stack: cur_limb, i, cur_address, len, kexit_info + DUP2 + // stack: i, cur_limb, i, cur_address, len, kexit_info + %mul_const(16) + // stack: offset=16*i, cur_limb, i, cur_address, len, kexit_info + %stack (offset, cur_limb) -> (%SEGMENT_RETURNDATA, offset, cur_limb, 16) + // stack: %SEGMENT_RETURNDATA, offset, cur_limb, 16, i, cur_address, len, kexit_info %mload_context_metadata(@CTX_METADATA_PARENT_CONTEXT) - // stack: dst=(parent_ctx, @SEGMENT_RETURNDATA, 0), src=(0, @SEGMENT_KERNEL_GENERAL, out, len), kexit_info - %memcpy - + // stack: parent_ctx, %SEGMENT_RETURNDATA, offset, cur_limb, 16, i, cur_address, len, kexit_info + %mstore_unpacking + // stack: i, cur_address, len, kexit_info + %increment + SWAP1 + %increment + SWAP1 + // stack: i+1, cur_address+1, len, kexit_info + DUP3 + DUP2 + EQ + ISZERO + %jumpi(expmod_store_loop) +expmod_store_end: + // stack: i, cur_address, len, kexit_info + %pop3 // stack: kexit_info PUSH 0 // stack: dummy=0, kexit_info diff --git a/evm/src/cpu/kernel/asm/memory/packing.asm b/evm/src/cpu/kernel/asm/memory/packing.asm index 8f03ea3a..5abaa3b3 100644 --- a/evm/src/cpu/kernel/asm/memory/packing.asm +++ b/evm/src/cpu/kernel/asm/memory/packing.asm @@ -88,3 +88,9 @@ mstore_unpacking_finish: %pop3 %stack (offset, value, len, retdest) -> (retdest, offset) JUMP + +%macro mstore_unpacking + %stack (addr: 3, value, len) -> (addr, value, len, %%after) + %jump(mstore_unpacking) +%%after: +%endmacro \ No newline at end of file From 9e4056e24f1aee6cb388e2bb210f0f2de3e27368 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Fri, 28 Apr 2023 11:39:03 -0700 Subject: [PATCH 08/17] cleanup --- evm/src/cpu/kernel/asm/core/precompiles/expmod.asm | 3 +-- evm/src/cpu/kernel/asm/hash/blake2b/main.asm | 5 ++--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm b/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm index 093bc160..1977e9d6 100644 --- a/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm +++ b/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm @@ -184,8 +184,7 @@ l_E_prime_return: // stack: max(1, l_E_prime) * f(max(l_M, l_B)), len, l_M, l_E, l_B, kexit_info %div_const(3) // G_quaddivisor // stack: (max(1, l_E_prime) * f(max(l_M, l_B))) / G_quaddivisor, len, l_M, l_E, l_B, kexit_info - PUSH 200 - %max + %max_const(200) // stack: g_r, len, l_M, l_E, l_B, kexit_info %stack (g_r, l: 4, kexit_info) -> (g_r, kexit_info, l) // stack: g_r, kexit_info, len, l_M, l_E, l_B diff --git a/evm/src/cpu/kernel/asm/hash/blake2b/main.asm b/evm/src/cpu/kernel/asm/hash/blake2b/main.asm index 933de505..0e662077 100644 --- a/evm/src/cpu/kernel/asm/hash/blake2b/main.asm +++ b/evm/src/cpu/kernel/asm/hash/blake2b/main.asm @@ -2,9 +2,8 @@ global blake2b: // stack: virt, num_bytes, retdest DUP2 // stack: num_bytes, virt, num_bytes, retdest - %add_const(127) - %div_const(128) - // stack: num_blocks = ceil(num_bytes / 128), virt, num_bytes, retdest + %ceil_div_const(128) + // stack: num_blocks, virt, num_bytes, retdest DUP2 // stack: virt, num_blocks, virt, num_bytes, retdest %mstore_kernel_general From 397d5953f40ee7163f0414ae73ad0fdb1d0a1cbb Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Fri, 28 Apr 2023 13:42:41 -0700 Subject: [PATCH 09/17] fix --- evm/src/cpu/kernel/asm/core/precompiles/expmod.asm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm b/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm index 1977e9d6..72d09f9c 100644 --- a/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm +++ b/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm @@ -351,10 +351,10 @@ expmod_store_loop: // stack: i, cur_limb, i, cur_address, len, kexit_info %mul_const(16) // stack: offset=16*i, cur_limb, i, cur_address, len, kexit_info - %stack (offset, cur_limb) -> (%SEGMENT_RETURNDATA, offset, cur_limb, 16) - // stack: %SEGMENT_RETURNDATA, offset, cur_limb, 16, i, cur_address, len, kexit_info + %stack (offset, cur_limb) -> (@SEGMENT_RETURNDATA, offset, cur_limb, 16) + // stack: @SEGMENT_RETURNDATA, offset, cur_limb, 16, i, cur_address, len, kexit_info %mload_context_metadata(@CTX_METADATA_PARENT_CONTEXT) - // stack: parent_ctx, %SEGMENT_RETURNDATA, offset, cur_limb, 16, i, cur_address, len, kexit_info + // stack: parent_ctx, @SEGMENT_RETURNDATA, offset, cur_limb, 16, i, cur_address, len, kexit_info %mstore_unpacking // stack: i, cur_address, len, kexit_info %increment From debe65f91c984c51320c278b2dc4f60a64291d68 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Mon, 1 May 2023 00:32:03 -0700 Subject: [PATCH 10/17] addressed comments --- evm/src/cpu/kernel/asm/core/precompiles/expmod.asm | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm b/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm index 72d09f9c..6d66c560 100644 --- a/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm +++ b/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm @@ -22,6 +22,10 @@ mload_bytes_as_limbs: ISZERO %jumpi(mload_bytes_return) // stack: num_bytes_new, ctx, segment, offset, retdest, total_num_limbs, len, ..limbs + SWAP3 + %add_const(16) + SWAP3 + // stack: num_bytes_new, ctx, segment, offset + 16, retdest, total_num_limbs, len, ..limbs %stack (num, addr: 3) -> (addr, num) %jump(mload_bytes_as_limbs) mload_bytes_return: @@ -356,6 +360,8 @@ expmod_store_loop: %mload_context_metadata(@CTX_METADATA_PARENT_CONTEXT) // stack: parent_ctx, @SEGMENT_RETURNDATA, offset, cur_limb, 16, i, cur_address, len, kexit_info %mstore_unpacking + // stack: offset', i, cur_address, len, kexit_info + POP // stack: i, cur_address, len, kexit_info %increment SWAP1 From 037c2f5ee897d342491bc1aa7edf0406ae237e16 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Mon, 1 May 2023 08:04:14 -0700 Subject: [PATCH 11/17] addressed comments --- .../kernel/asm/core/precompiles/expmod.asm | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm b/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm index 6d66c560..82fc43bd 100644 --- a/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm +++ b/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm @@ -272,71 +272,71 @@ l_E_prime_return: %store_limbs // stack: len, l_M, l_E, l_B, kexit_info - SWAP3 - %pop3 - // stack: len, kexit_info + %stack (len, l_M, ls: 2) -> (len, l_M) + // stack: len, l_M, kexit_info PUSH expmod_contd - // stack: expmod_contd, len, kexit_info + // stack: expmod_contd, len, l_M, kexit_info DUP2 - // stack: len, expmod_contd, len, kexit_info + // stack: len, expmod_contd, len, l_M, kexit_info DUP1 %mul_const(11) - // stack: s5=11*len, len, expmod_contd, len, kexit_info + // stack: s5=11*len, len, expmod_contd, len, l_M, kexit_info SWAP1 - // stack: len, s5, expmod_contd, len, kexit_info + // stack: len, s5, expmod_contd, len, l_M, kexit_info DUP1 %mul_const(9) - // stack: s4=9*len, len, s5, expmod_contd, len, kexit_info + // stack: s4=9*len, len, s5, expmod_contd, len, l_M, kexit_info SWAP1 - // stack: len, s4, s5, expmod_contd, len, kexit_info + // stack: len, s4, s5, expmod_contd, len, l_M, kexit_info DUP1 %mul_const(7) - // stack: s3=7*len, len, s4, s5, expmod_contd, len, kexit_info + // stack: s3=7*len, len, s4, s5, expmod_contd, len, l_M, kexit_info SWAP1 - // stack: len, s3, s4, s5, expmod_contd, len, kexit_info + // stack: len, s3, s4, s5, expmod_contd, len, l_M, kexit_info DUP1 %mul_const(5) - // stack: s2=5*len, len, s3, s4, s5, expmod_contd, len, kexit_info + // stack: s2=5*len, len, s3, s4, s5, expmod_contd, len, l_M, kexit_info SWAP1 - // stack: len, s2, s3, s4, s5, expmod_contd, len, kexit_info + // stack: len, s2, s3, s4, s5, expmod_contd, len, l_M, kexit_info DUP1 %mul_const(4) - // stack: s1=4*len, len, s2, s3, s4, s5, expmod_contd, len, kexit_info + // stack: s1=4*len, len, s2, s3, s4, s5, expmod_contd, len, l_M, kexit_info SWAP1 - // stack: len, s1, s2, s3, s4, s5, expmod_contd, len, kexit_info + // stack: len, s1, s2, s3, s4, s5, expmod_contd, len, l_M, kexit_info DUP1 %mul_const(3) - // stack: out=3*len, len, s1, s2, s3, s4, s5, expmod_contd, len, kexit_info + // stack: out=3*len, len, s1, s2, s3, s4, s5, expmod_contd, len, l_M, kexit_info SWAP1 - // stack: len, out, s1, s2, s3, s4, s5, expmod_contd, len, kexit_info + // stack: len, out, s1, s2, s3, s4, s5, expmod_contd, len, l_M, kexit_info DUP1 %mul_const(2) - // stack: m_loc=2*len, len, out, s1, s2, s3, s4, s5, expmod_contd, len, kexit_info + // stack: m_loc=2*len, len, out, s1, s2, s3, s4, s5, expmod_contd, len, l_M, kexit_info SWAP1 - // stack: len, m_loc, out, s1, s2, s3, s4, s5, expmod_contd, len, kexit_info + // stack: len, m_loc, out, s1, s2, s3, s4, s5, expmod_contd, len, l_M, kexit_info PUSH 0 - // stack: b_loc=0, e_loc=len, m_loc, out, s1, s2, s3, s4, s5, expmod_contd, len, kexit_info + // stack: b_loc=0, e_loc=len, m_loc, out, s1, s2, s3, s4, s5, expmod_contd, len, l_M, kexit_info DUP2 - // stack: len, b_loc, e_loc, m_loc, out, s1, s2, s3, s4, s5, expmod_contd, len, kexit_info + // stack: len, b_loc, e_loc, m_loc, out, s1, s2, s3, s4, s5, expmod_contd, len, l_M, kexit_info %jump(modexp_bignum) expmod_contd: - // stack: len, kexit_info + // stack: len, l_M, kexit_info // Copy the result value from kernel general memory to the parent's return data. - DUP1 - // stack: len, len, kexit_info + // Store return data size: l_M (number of bytes). + SWAP1 + // stack: l_M, len, kexit_info %mstore_parent_context_metadata(@CTX_METADATA_RETURNDATA_SIZE) // stack: len, kexit_info DUP1 From 08e6c3521cf8b139544590b1f2394ba4132e609a Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Mon, 1 May 2023 08:09:13 -0700 Subject: [PATCH 12/17] addressed comments --- .../kernel/asm/core/precompiles/expmod.asm | 35 ++++++++++++------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm b/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm index 82fc43bd..ef3fcb61 100644 --- a/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm +++ b/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm @@ -343,31 +343,42 @@ expmod_contd: // stack: len, len, kexit_info %mul_const(3) // stack: out=3*len, len, kexit_info + DUP2 + DUP2 + // stack: out, len, out, len, kexit_info + ADD + %decrement + SWAP1 + %decrement + SWAP1 + // stack: cur_address=out+len-1, end_address=out-1, len, kexit_info PUSH 0 - // stack: i=0, cur_address=out, len, kexit_info + // stack: i=0, cur_address, end_address, len, kexit_info + + // Store in big-endian format. expmod_store_loop: - // stack: i, cur_address, len, kexit_info + // stack: i, cur_address, end_address, len, kexit_info DUP2 - // stack: cur_address, i, cur_address, len, kexit_info + // stack: cur_address, i, cur_address, end_address, len, kexit_info %mload_kernel_general - // stack: cur_limb, i, cur_address, len, kexit_info + // stack: cur_limb, i, cur_address, end_address, len, kexit_info DUP2 - // stack: i, cur_limb, i, cur_address, len, kexit_info + // stack: i, cur_limb, i, cur_address, end_address, len, kexit_info %mul_const(16) - // stack: offset=16*i, cur_limb, i, cur_address, len, kexit_info + // stack: offset=16*i, cur_limb, i, cur_address, end_address, len, kexit_info %stack (offset, cur_limb) -> (@SEGMENT_RETURNDATA, offset, cur_limb, 16) - // stack: @SEGMENT_RETURNDATA, offset, cur_limb, 16, i, cur_address, len, kexit_info + // stack: @SEGMENT_RETURNDATA, offset, cur_limb, 16, i, cur_address, end_address, len, kexit_info %mload_context_metadata(@CTX_METADATA_PARENT_CONTEXT) - // stack: parent_ctx, @SEGMENT_RETURNDATA, offset, cur_limb, 16, i, cur_address, len, kexit_info + // stack: parent_ctx, @SEGMENT_RETURNDATA, offset, cur_limb, 16, i, cur_address, end_address, len, kexit_info %mstore_unpacking - // stack: offset', i, cur_address, len, kexit_info + // stack: offset', i, cur_address, end_address, len, kexit_info POP - // stack: i, cur_address, len, kexit_info + // stack: i, cur_address, end_address, len, kexit_info %increment SWAP1 - %increment + %decrement SWAP1 - // stack: i+1, cur_address+1, len, kexit_info + // stack: i+1, cur_address-1, end_address, len, kexit_info DUP3 DUP2 EQ From ade5b433aef2eed8f23452455a9c2c669d560389 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Mon, 1 May 2023 10:58:56 -0700 Subject: [PATCH 13/17] fix --- evm/src/cpu/kernel/asm/core/precompiles/expmod.asm | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm b/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm index ef3fcb61..916afd94 100644 --- a/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm +++ b/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm @@ -95,16 +95,13 @@ calculate_l_E_prime: PUSH @SEGMENT_CALLDATA GET_CONTEXT %mload_packing - // stack: i[96 + l_B..128 + l_B], 32, l_E, l_B, retdest + // stack: i[96 + l_B..128 + l_B], l_E, l_B, retdest %log2_floor - // stack: log2(i[96 + l_B..128 + l_B]), 32, l_E, l_B, retdest - SWAP2 - // stack: l_E, 32, log2(i[96 + l_B..128 + l_B]), l_B, retdest + // stack: log2(i[96 + l_B..128 + l_B]), l_E, l_B, retdest + SWAP1 + // stack: l_E, log2(i[96 + l_B..128 + l_B]), l_B, retdest %sub_const(32) %mul_const(8) - // stack: 8 * (l_E - 32), 32, log2(i[96 + l_B..128 + l_B]), l_B, retdest - SWAP1 - POP // stack: 8 * (l_E - 32), log2(i[96 + l_B..128 + l_B]), l_B, retdest ADD // stack: 8 * (l_E - 32) + log2(i[96 + l_B..128 + l_B]), l_B, retdest @@ -116,7 +113,6 @@ calculate_l_E_prime: JUMP case_le_32: // stack: l_E, l_B, retdest - %log2_floor // stack: log2(l_E), l_B, retdest %stack (log, l_B, retdest) -> (retdest, log) From 050c2e657eaf894b8df329fec8b863cbc692db54 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Mon, 1 May 2023 13:03:48 -0700 Subject: [PATCH 14/17] fix: calculate gas properly --- .../cpu/kernel/asm/core/precompiles/expmod.asm | 17 ++++++++++++----- evm/src/cpu/kernel/asm/util/math.asm | 16 +++++++--------- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm b/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm index 916afd94..ad85cc0e 100644 --- a/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm +++ b/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm @@ -113,10 +113,18 @@ calculate_l_E_prime: JUMP case_le_32: // stack: l_E, l_B, retdest + SWAP1 + // stack: l_B, l_E, retdest + %add_const(96) + // stack: 96 + l_B, l_E, retdest + PUSH @SEGMENT_CALLDATA + GET_CONTEXT + %mload_packing + // stack: E, retdest %log2_floor - // stack: log2(l_E), l_B, retdest - %stack (log, l_B, retdest) -> (retdest, log) - // stack: retdest, log2(l_E) + // stack: log2(E), retdest + SWAP1 + // stack: retdest, log2(E) JUMP global precompile_expmod: @@ -177,8 +185,7 @@ l_E_prime_return: // stack: f(max(l_M, l_B)), l_E_prime, len, l_M, l_E, l_B, kexit_info SWAP1 // stack: l_E_prime, f(max(l_M, l_B)), len, l_M, l_E, l_B, kexit_info - PUSH 1 - %max + %max_const(1) // stack: max(1, l_E_prime), f(max(l_M, l_B)), len, l_M, l_E, l_B, kexit_info MUL // stack: max(1, l_E_prime) * f(max(l_M, l_B)), len, l_M, l_E, l_B, kexit_info diff --git a/evm/src/cpu/kernel/asm/util/math.asm b/evm/src/cpu/kernel/asm/util/math.asm index 38d29410..98f7b008 100644 --- a/evm/src/cpu/kernel/asm/util/math.asm +++ b/evm/src/cpu/kernel/asm/util/math.asm @@ -5,14 +5,12 @@ log2_floor_helper: ISZERO %jumpi(end) // stack: val, counter, retdest - %shr_const(1) - // stack: val >> 1, counter, retdest + %div_const(2) + // stack: val/2, counter, retdest SWAP1 - // stack: counter, val >> 1, retdest %increment - // stack: counter + 1, val >> 1, retdest SWAP1 - // stack: val >> 1, counter + 1, retdest + // stack: val/2, counter + 1, retdest %jump(log2_floor_helper) end: // stack: val, counter, retdest @@ -24,12 +22,12 @@ end: global log2_floor: // stack: val, retdest - %shr_const(1) - // stack: val >> 1, retdest + %div_const(2) + // stack: val/2, retdest PUSH 0 - // stack: 0, val >> 1, retdest + // stack: 0, val/2, retdest SWAP1 - // stack: val >> 1, 0, retdest + // stack: val/2, 0, retdest %jump(log2_floor_helper) %macro log2_floor From cae5a2cf21ef730a038311963126702f073735f7 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Mon, 1 May 2023 15:25:45 -0700 Subject: [PATCH 15/17] fix --- .../kernel/asm/core/precompiles/expmod.asm | 12 + .../asm/core/precompiles/expmod_test.asm | 388 ++++++++++++++++++ 2 files changed, 400 insertions(+) create mode 100644 evm/src/cpu/kernel/asm/core/precompiles/expmod_test.asm diff --git a/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm b/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm index ad85cc0e..258c2ff6 100644 --- a/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm +++ b/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm @@ -209,6 +209,9 @@ l_E_prime_return: DUP1 %ceil_div_const(16) // stack: num_limbs, num_bytes, len, len, l_M, l_E, l_B, kexit_info + DUP1 + ISZERO + %jumpi(copy_b_end) SWAP1 // stack: num_bytes, num_limbs, len, len, l_M, l_E, l_B, kexit_info %stack () -> (@SEGMENT_CALLDATA, 96) @@ -223,6 +226,7 @@ l_E_prime_return: // stack: b_loc=0, num_limbs, limbs[num_limbs-1], .., limbs[0], len, l_M, l_E, l_B, kexit_info %store_limbs // stack: len, l_M, l_E, l_B, kexit_info +copy_b_end: // Copy E to kernel general memory. // stack: len, l_M, l_E, l_B, kexit_info @@ -233,6 +237,9 @@ l_E_prime_return: DUP1 %ceil_div_const(16) // stack: num_limbs, num_bytes, len, len, l_M, l_E, l_B, kexit_info + DUP1 + ISZERO + %jumpi(copy_e_end) SWAP1 // stack: num_bytes, num_limbs, len, len, l_M, l_E, l_B, kexit_info DUP7 @@ -247,6 +254,7 @@ l_E_prime_return: // stack: e_loc=len, num_limbs, limbs[num_limbs-1], .., limbs[0], len, l_M, l_E, l_B, kexit_info %store_limbs // stack: len, l_M, l_E, l_B, kexit_info +copy_e_end: // Copy M to kernel general memory. // stack: len, l_M, l_E, l_B, kexit_info @@ -257,6 +265,9 @@ l_E_prime_return: DUP1 %ceil_div_const(16) // stack: num_limbs, num_bytes, len, len, l_M, l_E, l_B, kexit_info + DUP1 + ISZERO + %jumpi(copy_m_end) SWAP1 // stack: num_bytes, num_limbs, len, len, l_M, l_E, l_B, kexit_info DUP7 @@ -274,6 +285,7 @@ l_E_prime_return: // stack: m_loc=2*len, num_limbs, limbs[num_limbs-1], .., limbs[0], len, l_M, l_E, l_B, kexit_info %store_limbs // stack: len, l_M, l_E, l_B, kexit_info +copy_m_end: %stack (len, l_M, ls: 2) -> (len, l_M) // stack: len, l_M, kexit_info diff --git a/evm/src/cpu/kernel/asm/core/precompiles/expmod_test.asm b/evm/src/cpu/kernel/asm/core/precompiles/expmod_test.asm new file mode 100644 index 00000000..04821be5 --- /dev/null +++ b/evm/src/cpu/kernel/asm/core/precompiles/expmod_test.asm @@ -0,0 +1,388 @@ +// Load bytes, packing 16 bytes into each limb, and store limbs on the stack. +// We pass around total_num_limbs and len for conveience, because we can't access them from the stack +// if they're hidden behind the variable number of limbs. +mload_bytes_as_limbs: + // stack: ctx, segment, offset, num_bytes, retdest, total_num_limbs, len, ..limbs + DUP4 + // stack: num_bytes, ctx, segment, offset, num_bytes, retdest, total_num_limbs, len, ..limbs + %min_const(16) + // stack: min(16, num_bytes), ctx, segment, offset, num_bytes, retdest, total_num_limbs, len, ..limbs + %stack (len, addr: 3) -> (addr, len, addr) + // stack: ctx, segment, offset, min(16, num_bytes), ctx, segment, offset, num_bytes, retdest, total_num_limbs, len, ..limbs + %mload_packing + // stack: new_limb, ctx, segment, offset, num_bytes, retdest, total_num_limbs, len, ..limbs + %stack (new, addr: 3, numb, ret, tot, len) -> (numb, addr, ret, tot, len, new) + // stack: num_bytes, ctx, segment, offset, retdest, total_num_limbs, len, new_limb, ..limbs + DUP1 + %min_const(16) + SWAP1 + SUB + // stack: num_bytes_new = num_bytes - min(16, num_bytes), ctx, segment, offset, retdest, total_num_limbs, len, ..limbs + DUP1 + ISZERO + %jumpi(mload_bytes_return) + // stack: num_bytes_new, ctx, segment, offset, retdest, total_num_limbs, len, ..limbs + SWAP3 + %add_const(16) + SWAP3 + // stack: num_bytes_new, ctx, segment, offset + 16, retdest, total_num_limbs, len, ..limbs + %stack (num, addr: 3) -> (addr, num) + %jump(mload_bytes_as_limbs) +mload_bytes_return: + // stack: num_bytes_new, ctx, segment, offset, retdest, total_num_limbs, len, ..limbs + %pop4 + // stack: retdest, total_num_limbs, len, ..limbs + JUMP + +store_limbs: + // stack: offset, retdest, num_limbs, limb[num_limbs - 1], ..limb[0] + DUP3 + // stack: num_limbs, offset, retdest, num_limbs, limb[num_limbs - 1], ..limb[0] + ISZERO + %jumpi(store_limbs_return) + // stack: offset, retdest, num_limbs, limb[num_limbs - 1], ..limb[0] + %stack (offset, ret, num, limb) -> (offset, limb, offset, ret, num) + // stack: offset, limb[num_limbs - 1], offset, retdest, num_limbs, limb[num_limbs - 2], ..limb[0] + %mstore_kernel_general + // stack: offset, retdest, num_limbs, limb[num_limbs - 2], ..limb[0] + %increment + SWAP2 + %decrement + SWAP2 + // stack: offset + 1, retdest, num_limbs - 1, limb[num_limbs - 2], ..limb[0] + %jump(store_limbs) +store_limbs_return: + // stack: offset, retdest, num_limbs=0 + POP + SWAP1 + POP + JUMP + +calculate_l_E_prime: + // stack: l_E, l_B, retdest + DUP1 + // stack: l_E, l_E, l_B, retdest + %le_const(32) + // stack: l_E <= 32, l_E, l_B, retdest + %jumpi(case_le_32) + // stack: l_E, l_B, retdest + PUSH 32 + // stack: 32, l_E, l_B, retdest + DUP3 + // stack: l_B, 32, l_E, l_B, retdest + %add_const(96) + // stack: 96 + l_B, 32, l_E, l_B, retdest + PUSH @SEGMENT_CALLDATA + GET_CONTEXT + %mload_packing + // stack: i[96 + l_B..128 + l_B], l_E, l_B, retdest + %log2_floor + // stack: log2(i[96 + l_B..128 + l_B]), l_E, l_B, retdest + SWAP1 + // stack: l_E, log2(i[96 + l_B..128 + l_B]), l_B, retdest + %sub_const(32) + %mul_const(8) + // stack: 8 * (l_E - 32), log2(i[96 + l_B..128 + l_B]), l_B, retdest + ADD + // stack: 8 * (l_E - 32) + log2(i[96 + l_B..128 + l_B]), l_B, retdest + SWAP2 + %pop2 + // stack: 8 * (l_E - 32) + log2(i[96 + l_B..128 + l_B]), retdest + SWAP1 + // stack: retdest, 8 * (l_E - 32) + log2(i[96 + l_B..128 + l_B]) + JUMP +case_le_32: + // stack: l_E, l_B, retdest + SWAP1 + // stack: l_B, l_E, retdest + %add_const(96) + // stack: 96 + l_B, l_E, retdest + PUSH @SEGMENT_CALLDATA + GET_CONTEXT + %mload_packing + // stack: E, retdest + %log2_floor + // stack: log2(E), retdest + SWAP1 + // stack: retdest, log2(E) + JUMP + +global expmod_test: + // stack: address, retdest, new_ctx, (old stack) + %pop2 + // stack: new_ctx, (old stack) + DUP1 + SET_CONTEXT + // stack: (empty) + PUSH 0x100000000 // = 2^32 (is_kernel = true) + // stack: kexit_info + + // Load l_B from i[0..32]. + %stack () -> (@SEGMENT_CALLDATA, 0, 32) + // stack: @SEGMENT_CALLDATA, 0, 32, kexit_info + GET_CONTEXT + // stack: ctx, @SEGMENT_CALLDATA, 0, 32, kexit_info + %mload_packing + // stack: l_B, kexit_info + + // Load l_E from i[32..64]. + %stack () -> (@SEGMENT_CALLDATA, 32, 32) + GET_CONTEXT + %mload_packing + // stack: l_E, l_B, kexit_info + + // Load l_M from i[64..96]. + %stack () -> (@SEGMENT_CALLDATA, 64, 32) + GET_CONTEXT + %mload_packing + // stack: l_M, l_E, l_B, kexit_info + + %stack (l: 3) -> (l, l) + // stack: l_M, l_E, l_B, l_M, l_E, l_B, kexit_info + %max_3 + // stack: max_len, l_M, l_E, l_B, kexit_info + + %ceil_div_const(16) + // stack: len=ceil(max_len/16), l_M, l_E, l_B, kexit_info + + // Calculate gas costs. + + PUSH l_E_prime_return + // stack: l_E_prime_return, len, l_M, l_E, l_B, kexit_info + DUP5 + DUP5 + // stack: l_E, l_B, l_E_prime_return, len, l_M, l_E, l_B, kexit_info + %jump(calculate_l_E_prime) +l_E_prime_return: + // stack: l_E_prime, len, l_M, l_E, l_B, kexit_info + DUP5 + // stack: l_B, l_E_prime, len, l_M, l_E, l_B, kexit_info + DUP4 + // stack: l_M, l_B, l_E_prime, len, l_M, l_E, l_B, kexit_info + %max + // stack: max(l_M, l_B), l_E_prime, len, l_M, l_E, l_B, kexit_info + %expmod_gas_f + // stack: f(max(l_M, l_B)), l_E_prime, len, l_M, l_E, l_B, kexit_info + SWAP1 + // stack: l_E_prime, f(max(l_M, l_B)), len, l_M, l_E, l_B, kexit_info + %max_const(1) + // stack: max(1, l_E_prime), f(max(l_M, l_B)), len, l_M, l_E, l_B, kexit_info + MUL + // stack: max(1, l_E_prime) * f(max(l_M, l_B)), len, l_M, l_E, l_B, kexit_info + %div_const(3) // G_quaddivisor + // stack: (max(1, l_E_prime) * f(max(l_M, l_B))) / G_quaddivisor, len, l_M, l_E, l_B, kexit_info + %max_const(200) + // stack: g_r, len, l_M, l_E, l_B, kexit_info + %stack (g_r, l: 4, kexit_info) -> (g_r, kexit_info, l) + // stack: g_r, kexit_info, len, l_M, l_E, l_B + POP // %charge_gas + // stack: kexit_info, len, l_M, l_E, l_B + %stack (kexit_info, l: 4) -> (l, kexit_info) + // stack: len, l_M, l_E, l_B, kexit_info + + // Copy B to kernel general memory. + // stack: len, l_M, l_E, l_B, kexit_info + DUP1 + // stack: len, len, l_M, l_E, l_B, kexit_info + DUP5 + // stack: num_bytes=l_B, len, len, l_M, l_E, l_B, kexit_info + DUP1 + %ceil_div_const(16) + // stack: num_limbs, num_bytes, len, len, l_M, l_E, l_B, kexit_info + DUP1 + ISZERO + %jumpi(copy_b_end) + SWAP1 + // stack: num_bytes, num_limbs, len, len, l_M, l_E, l_B, kexit_info + %stack () -> (@SEGMENT_CALLDATA, 96) + GET_CONTEXT + // stack: ctx, @SEGMENT_CALLDATA, 96, num_bytes, num_limbs, len, len, l_M, l_E, l_B, kexit_info + %mload_bytes_as_limbs + // stack: num_limbs, len, limbs[num_limbs-1], .., limbs[0], len, l_M, l_E, l_B, kexit_info + SWAP1 + POP + // stack: num_limbs, limbs[num_limbs-1], .., limbs[0], len, l_M, l_E, l_B, kexit_info + PUSH 0 + // stack: b_loc=0, num_limbs, limbs[num_limbs-1], .., limbs[0], len, l_M, l_E, l_B, kexit_info + %store_limbs + // stack: len, l_M, l_E, l_B, kexit_info +copy_b_end: + + // Copy E to kernel general memory. + // stack: len, l_M, l_E, l_B, kexit_info + DUP1 + // stack: len, len, l_M, l_E, l_B, kexit_info + DUP4 + // stack: num_bytes=l_E, len, len, l_M, l_E, l_B, kexit_info + DUP1 + %ceil_div_const(16) + // stack: num_limbs, num_bytes, len, len, l_M, l_E, l_B, kexit_info + DUP1 + ISZERO + %jumpi(copy_e_end) + SWAP1 + // stack: num_bytes, num_limbs, len, len, l_M, l_E, l_B, kexit_info + DUP7 + %add_const(96) + // stack: 96 + l_B, num_bytes, num_limbs, len, len, l_M, l_E, l_B, kexit_info + PUSH @SEGMENT_CALLDATA + GET_CONTEXT + // stack: ctx, @SEGMENT_CALLDATA, 96 + l_B, num_bytes, num_limbs, len, len, l_M, l_E, l_B, kexit_info + %mload_bytes_as_limbs + // stack: num_limbs, len, limbs[num_limbs-1], .., limbs[0], len, l_M, l_E, l_B, kexit_info + SWAP1 + // stack: e_loc=len, num_limbs, limbs[num_limbs-1], .., limbs[0], len, l_M, l_E, l_B, kexit_info + %store_limbs + // stack: len, l_M, l_E, l_B, kexit_info +copy_e_end: + + // Copy M to kernel general memory. + // stack: len, l_M, l_E, l_B, kexit_info + DUP1 + // stack: len, len, l_M, l_E, l_B, kexit_info + DUP3 + // stack: num_bytes=l_M, len, len, l_M, l_E, l_B, kexit_info + DUP1 + %ceil_div_const(16) + // stack: num_limbs, num_bytes, len, len, l_M, l_E, l_B, kexit_info + DUP1 + ISZERO + %jumpi(copy_m_end) + SWAP1 + // stack: num_bytes, num_limbs, len, len, l_M, l_E, l_B, kexit_info + DUP7 + DUP7 + ADD + %add_const(96) + // stack: 96 + l_B + l_E, num_bytes, num_limbs, len, len, l_M, l_E, l_B, kexit_info + PUSH @SEGMENT_CALLDATA + GET_CONTEXT + // stack: ctx, @SEGMENT_CALLDATA, 96 + l_B + l_E, num_bytes, num_limbs, len, len, l_M, l_E, l_B, kexit_info + %mload_bytes_as_limbs + // stack: num_limbs, len, limbs[num_limbs-1], .., limbs[0], len, l_M, l_E, l_B, kexit_info + SWAP1 + %mul_const(2) + // stack: m_loc=2*len, num_limbs, limbs[num_limbs-1], .., limbs[0], len, l_M, l_E, l_B, kexit_info + %store_limbs + // stack: len, l_M, l_E, l_B, kexit_info +copy_m_end: + + %stack (len, l_M, ls: 2) -> (len, l_M) + // stack: len, l_M, kexit_info + + PUSH expmod_contd + // stack: expmod_contd, len, l_M, kexit_info + DUP2 + // stack: len, expmod_contd, len, l_M, kexit_info + + DUP1 + %mul_const(11) + // stack: s5=11*len, len, expmod_contd, len, l_M, kexit_info + SWAP1 + // stack: len, s5, expmod_contd, len, l_M, kexit_info + + DUP1 + %mul_const(9) + // stack: s4=9*len, len, s5, expmod_contd, len, l_M, kexit_info + SWAP1 + // stack: len, s4, s5, expmod_contd, len, l_M, kexit_info + + DUP1 + %mul_const(7) + // stack: s3=7*len, len, s4, s5, expmod_contd, len, l_M, kexit_info + SWAP1 + // stack: len, s3, s4, s5, expmod_contd, len, l_M, kexit_info + + DUP1 + %mul_const(5) + // stack: s2=5*len, len, s3, s4, s5, expmod_contd, len, l_M, kexit_info + SWAP1 + // stack: len, s2, s3, s4, s5, expmod_contd, len, l_M, kexit_info + + DUP1 + %mul_const(4) + // stack: s1=4*len, len, s2, s3, s4, s5, expmod_contd, len, l_M, kexit_info + SWAP1 + // stack: len, s1, s2, s3, s4, s5, expmod_contd, len, l_M, kexit_info + + DUP1 + %mul_const(3) + // stack: out=3*len, len, s1, s2, s3, s4, s5, expmod_contd, len, l_M, kexit_info + SWAP1 + // stack: len, out, s1, s2, s3, s4, s5, expmod_contd, len, l_M, kexit_info + + DUP1 + %mul_const(2) + // stack: m_loc=2*len, len, out, s1, s2, s3, s4, s5, expmod_contd, len, l_M, kexit_info + SWAP1 + // stack: len, m_loc, out, s1, s2, s3, s4, s5, expmod_contd, len, l_M, kexit_info + + PUSH 0 + // stack: b_loc=0, e_loc=len, m_loc, out, s1, s2, s3, s4, s5, expmod_contd, len, l_M, kexit_info + DUP2 + // stack: len, b_loc, e_loc, m_loc, out, s1, s2, s3, s4, s5, expmod_contd, len, l_M, kexit_info + + %jump(modexp_bignum) + +expmod_contd: + // stack: len, l_M, kexit_info + + // Copy the result value from kernel general memory to the parent's return data. + + // Store return data size: l_M (number of bytes). + SWAP1 + // stack: l_M, len, kexit_info + %mstore_parent_context_metadata(@CTX_METADATA_RETURNDATA_SIZE) + // stack: len, kexit_info + DUP1 + // stack: len, len, kexit_info + %mul_const(3) + // stack: out=3*len, len, kexit_info + DUP2 + DUP2 + // stack: out, len, out, len, kexit_info + ADD + %decrement + SWAP1 + %decrement + SWAP1 + // stack: cur_address=out+len-1, end_address=out-1, len, kexit_info + PUSH 0 + // stack: i=0, cur_address, end_address, len, kexit_info + + // Store in big-endian format. +expmod_store_loop: + // stack: i, cur_address, end_address, len, kexit_info + DUP2 + // stack: cur_address, i, cur_address, end_address, len, kexit_info + %mload_kernel_general + // stack: cur_limb, i, cur_address, end_address, len, kexit_info + DUP2 + // stack: i, cur_limb, i, cur_address, end_address, len, kexit_info + %mul_const(16) + // stack: offset=16*i, cur_limb, i, cur_address, end_address, len, kexit_info + %stack (offset, cur_limb) -> (@SEGMENT_RETURNDATA, offset, cur_limb, 16) + // stack: @SEGMENT_RETURNDATA, offset, cur_limb, 16, i, cur_address, end_address, len, kexit_info + %mload_context_metadata(@CTX_METADATA_PARENT_CONTEXT) + // stack: parent_ctx, @SEGMENT_RETURNDATA, offset, cur_limb, 16, i, cur_address, end_address, len, kexit_info + %mstore_unpacking + // stack: offset', i, cur_address, end_address, len, kexit_info + POP + // stack: i, cur_address, end_address, len, kexit_info + %increment + SWAP1 + %decrement + SWAP1 + // stack: i+1, cur_address-1, end_address, len, kexit_info + DUP3 + DUP2 + EQ + ISZERO + %jumpi(expmod_store_loop) +expmod_store_end: + // stack: i, cur_address, len, kexit_info + %pop3 + // stack: kexit_info + PUSH 0 + // stack: dummy=0, kexit_info + STOP From f3de2afc3bd7e1664b6ff9b554b73c6f6c28ac3e Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Mon, 1 May 2023 15:34:23 -0700 Subject: [PATCH 16/17] remove test file --- .../asm/core/precompiles/expmod_test.asm | 388 ------------------ 1 file changed, 388 deletions(-) delete mode 100644 evm/src/cpu/kernel/asm/core/precompiles/expmod_test.asm diff --git a/evm/src/cpu/kernel/asm/core/precompiles/expmod_test.asm b/evm/src/cpu/kernel/asm/core/precompiles/expmod_test.asm deleted file mode 100644 index 04821be5..00000000 --- a/evm/src/cpu/kernel/asm/core/precompiles/expmod_test.asm +++ /dev/null @@ -1,388 +0,0 @@ -// Load bytes, packing 16 bytes into each limb, and store limbs on the stack. -// We pass around total_num_limbs and len for conveience, because we can't access them from the stack -// if they're hidden behind the variable number of limbs. -mload_bytes_as_limbs: - // stack: ctx, segment, offset, num_bytes, retdest, total_num_limbs, len, ..limbs - DUP4 - // stack: num_bytes, ctx, segment, offset, num_bytes, retdest, total_num_limbs, len, ..limbs - %min_const(16) - // stack: min(16, num_bytes), ctx, segment, offset, num_bytes, retdest, total_num_limbs, len, ..limbs - %stack (len, addr: 3) -> (addr, len, addr) - // stack: ctx, segment, offset, min(16, num_bytes), ctx, segment, offset, num_bytes, retdest, total_num_limbs, len, ..limbs - %mload_packing - // stack: new_limb, ctx, segment, offset, num_bytes, retdest, total_num_limbs, len, ..limbs - %stack (new, addr: 3, numb, ret, tot, len) -> (numb, addr, ret, tot, len, new) - // stack: num_bytes, ctx, segment, offset, retdest, total_num_limbs, len, new_limb, ..limbs - DUP1 - %min_const(16) - SWAP1 - SUB - // stack: num_bytes_new = num_bytes - min(16, num_bytes), ctx, segment, offset, retdest, total_num_limbs, len, ..limbs - DUP1 - ISZERO - %jumpi(mload_bytes_return) - // stack: num_bytes_new, ctx, segment, offset, retdest, total_num_limbs, len, ..limbs - SWAP3 - %add_const(16) - SWAP3 - // stack: num_bytes_new, ctx, segment, offset + 16, retdest, total_num_limbs, len, ..limbs - %stack (num, addr: 3) -> (addr, num) - %jump(mload_bytes_as_limbs) -mload_bytes_return: - // stack: num_bytes_new, ctx, segment, offset, retdest, total_num_limbs, len, ..limbs - %pop4 - // stack: retdest, total_num_limbs, len, ..limbs - JUMP - -store_limbs: - // stack: offset, retdest, num_limbs, limb[num_limbs - 1], ..limb[0] - DUP3 - // stack: num_limbs, offset, retdest, num_limbs, limb[num_limbs - 1], ..limb[0] - ISZERO - %jumpi(store_limbs_return) - // stack: offset, retdest, num_limbs, limb[num_limbs - 1], ..limb[0] - %stack (offset, ret, num, limb) -> (offset, limb, offset, ret, num) - // stack: offset, limb[num_limbs - 1], offset, retdest, num_limbs, limb[num_limbs - 2], ..limb[0] - %mstore_kernel_general - // stack: offset, retdest, num_limbs, limb[num_limbs - 2], ..limb[0] - %increment - SWAP2 - %decrement - SWAP2 - // stack: offset + 1, retdest, num_limbs - 1, limb[num_limbs - 2], ..limb[0] - %jump(store_limbs) -store_limbs_return: - // stack: offset, retdest, num_limbs=0 - POP - SWAP1 - POP - JUMP - -calculate_l_E_prime: - // stack: l_E, l_B, retdest - DUP1 - // stack: l_E, l_E, l_B, retdest - %le_const(32) - // stack: l_E <= 32, l_E, l_B, retdest - %jumpi(case_le_32) - // stack: l_E, l_B, retdest - PUSH 32 - // stack: 32, l_E, l_B, retdest - DUP3 - // stack: l_B, 32, l_E, l_B, retdest - %add_const(96) - // stack: 96 + l_B, 32, l_E, l_B, retdest - PUSH @SEGMENT_CALLDATA - GET_CONTEXT - %mload_packing - // stack: i[96 + l_B..128 + l_B], l_E, l_B, retdest - %log2_floor - // stack: log2(i[96 + l_B..128 + l_B]), l_E, l_B, retdest - SWAP1 - // stack: l_E, log2(i[96 + l_B..128 + l_B]), l_B, retdest - %sub_const(32) - %mul_const(8) - // stack: 8 * (l_E - 32), log2(i[96 + l_B..128 + l_B]), l_B, retdest - ADD - // stack: 8 * (l_E - 32) + log2(i[96 + l_B..128 + l_B]), l_B, retdest - SWAP2 - %pop2 - // stack: 8 * (l_E - 32) + log2(i[96 + l_B..128 + l_B]), retdest - SWAP1 - // stack: retdest, 8 * (l_E - 32) + log2(i[96 + l_B..128 + l_B]) - JUMP -case_le_32: - // stack: l_E, l_B, retdest - SWAP1 - // stack: l_B, l_E, retdest - %add_const(96) - // stack: 96 + l_B, l_E, retdest - PUSH @SEGMENT_CALLDATA - GET_CONTEXT - %mload_packing - // stack: E, retdest - %log2_floor - // stack: log2(E), retdest - SWAP1 - // stack: retdest, log2(E) - JUMP - -global expmod_test: - // stack: address, retdest, new_ctx, (old stack) - %pop2 - // stack: new_ctx, (old stack) - DUP1 - SET_CONTEXT - // stack: (empty) - PUSH 0x100000000 // = 2^32 (is_kernel = true) - // stack: kexit_info - - // Load l_B from i[0..32]. - %stack () -> (@SEGMENT_CALLDATA, 0, 32) - // stack: @SEGMENT_CALLDATA, 0, 32, kexit_info - GET_CONTEXT - // stack: ctx, @SEGMENT_CALLDATA, 0, 32, kexit_info - %mload_packing - // stack: l_B, kexit_info - - // Load l_E from i[32..64]. - %stack () -> (@SEGMENT_CALLDATA, 32, 32) - GET_CONTEXT - %mload_packing - // stack: l_E, l_B, kexit_info - - // Load l_M from i[64..96]. - %stack () -> (@SEGMENT_CALLDATA, 64, 32) - GET_CONTEXT - %mload_packing - // stack: l_M, l_E, l_B, kexit_info - - %stack (l: 3) -> (l, l) - // stack: l_M, l_E, l_B, l_M, l_E, l_B, kexit_info - %max_3 - // stack: max_len, l_M, l_E, l_B, kexit_info - - %ceil_div_const(16) - // stack: len=ceil(max_len/16), l_M, l_E, l_B, kexit_info - - // Calculate gas costs. - - PUSH l_E_prime_return - // stack: l_E_prime_return, len, l_M, l_E, l_B, kexit_info - DUP5 - DUP5 - // stack: l_E, l_B, l_E_prime_return, len, l_M, l_E, l_B, kexit_info - %jump(calculate_l_E_prime) -l_E_prime_return: - // stack: l_E_prime, len, l_M, l_E, l_B, kexit_info - DUP5 - // stack: l_B, l_E_prime, len, l_M, l_E, l_B, kexit_info - DUP4 - // stack: l_M, l_B, l_E_prime, len, l_M, l_E, l_B, kexit_info - %max - // stack: max(l_M, l_B), l_E_prime, len, l_M, l_E, l_B, kexit_info - %expmod_gas_f - // stack: f(max(l_M, l_B)), l_E_prime, len, l_M, l_E, l_B, kexit_info - SWAP1 - // stack: l_E_prime, f(max(l_M, l_B)), len, l_M, l_E, l_B, kexit_info - %max_const(1) - // stack: max(1, l_E_prime), f(max(l_M, l_B)), len, l_M, l_E, l_B, kexit_info - MUL - // stack: max(1, l_E_prime) * f(max(l_M, l_B)), len, l_M, l_E, l_B, kexit_info - %div_const(3) // G_quaddivisor - // stack: (max(1, l_E_prime) * f(max(l_M, l_B))) / G_quaddivisor, len, l_M, l_E, l_B, kexit_info - %max_const(200) - // stack: g_r, len, l_M, l_E, l_B, kexit_info - %stack (g_r, l: 4, kexit_info) -> (g_r, kexit_info, l) - // stack: g_r, kexit_info, len, l_M, l_E, l_B - POP // %charge_gas - // stack: kexit_info, len, l_M, l_E, l_B - %stack (kexit_info, l: 4) -> (l, kexit_info) - // stack: len, l_M, l_E, l_B, kexit_info - - // Copy B to kernel general memory. - // stack: len, l_M, l_E, l_B, kexit_info - DUP1 - // stack: len, len, l_M, l_E, l_B, kexit_info - DUP5 - // stack: num_bytes=l_B, len, len, l_M, l_E, l_B, kexit_info - DUP1 - %ceil_div_const(16) - // stack: num_limbs, num_bytes, len, len, l_M, l_E, l_B, kexit_info - DUP1 - ISZERO - %jumpi(copy_b_end) - SWAP1 - // stack: num_bytes, num_limbs, len, len, l_M, l_E, l_B, kexit_info - %stack () -> (@SEGMENT_CALLDATA, 96) - GET_CONTEXT - // stack: ctx, @SEGMENT_CALLDATA, 96, num_bytes, num_limbs, len, len, l_M, l_E, l_B, kexit_info - %mload_bytes_as_limbs - // stack: num_limbs, len, limbs[num_limbs-1], .., limbs[0], len, l_M, l_E, l_B, kexit_info - SWAP1 - POP - // stack: num_limbs, limbs[num_limbs-1], .., limbs[0], len, l_M, l_E, l_B, kexit_info - PUSH 0 - // stack: b_loc=0, num_limbs, limbs[num_limbs-1], .., limbs[0], len, l_M, l_E, l_B, kexit_info - %store_limbs - // stack: len, l_M, l_E, l_B, kexit_info -copy_b_end: - - // Copy E to kernel general memory. - // stack: len, l_M, l_E, l_B, kexit_info - DUP1 - // stack: len, len, l_M, l_E, l_B, kexit_info - DUP4 - // stack: num_bytes=l_E, len, len, l_M, l_E, l_B, kexit_info - DUP1 - %ceil_div_const(16) - // stack: num_limbs, num_bytes, len, len, l_M, l_E, l_B, kexit_info - DUP1 - ISZERO - %jumpi(copy_e_end) - SWAP1 - // stack: num_bytes, num_limbs, len, len, l_M, l_E, l_B, kexit_info - DUP7 - %add_const(96) - // stack: 96 + l_B, num_bytes, num_limbs, len, len, l_M, l_E, l_B, kexit_info - PUSH @SEGMENT_CALLDATA - GET_CONTEXT - // stack: ctx, @SEGMENT_CALLDATA, 96 + l_B, num_bytes, num_limbs, len, len, l_M, l_E, l_B, kexit_info - %mload_bytes_as_limbs - // stack: num_limbs, len, limbs[num_limbs-1], .., limbs[0], len, l_M, l_E, l_B, kexit_info - SWAP1 - // stack: e_loc=len, num_limbs, limbs[num_limbs-1], .., limbs[0], len, l_M, l_E, l_B, kexit_info - %store_limbs - // stack: len, l_M, l_E, l_B, kexit_info -copy_e_end: - - // Copy M to kernel general memory. - // stack: len, l_M, l_E, l_B, kexit_info - DUP1 - // stack: len, len, l_M, l_E, l_B, kexit_info - DUP3 - // stack: num_bytes=l_M, len, len, l_M, l_E, l_B, kexit_info - DUP1 - %ceil_div_const(16) - // stack: num_limbs, num_bytes, len, len, l_M, l_E, l_B, kexit_info - DUP1 - ISZERO - %jumpi(copy_m_end) - SWAP1 - // stack: num_bytes, num_limbs, len, len, l_M, l_E, l_B, kexit_info - DUP7 - DUP7 - ADD - %add_const(96) - // stack: 96 + l_B + l_E, num_bytes, num_limbs, len, len, l_M, l_E, l_B, kexit_info - PUSH @SEGMENT_CALLDATA - GET_CONTEXT - // stack: ctx, @SEGMENT_CALLDATA, 96 + l_B + l_E, num_bytes, num_limbs, len, len, l_M, l_E, l_B, kexit_info - %mload_bytes_as_limbs - // stack: num_limbs, len, limbs[num_limbs-1], .., limbs[0], len, l_M, l_E, l_B, kexit_info - SWAP1 - %mul_const(2) - // stack: m_loc=2*len, num_limbs, limbs[num_limbs-1], .., limbs[0], len, l_M, l_E, l_B, kexit_info - %store_limbs - // stack: len, l_M, l_E, l_B, kexit_info -copy_m_end: - - %stack (len, l_M, ls: 2) -> (len, l_M) - // stack: len, l_M, kexit_info - - PUSH expmod_contd - // stack: expmod_contd, len, l_M, kexit_info - DUP2 - // stack: len, expmod_contd, len, l_M, kexit_info - - DUP1 - %mul_const(11) - // stack: s5=11*len, len, expmod_contd, len, l_M, kexit_info - SWAP1 - // stack: len, s5, expmod_contd, len, l_M, kexit_info - - DUP1 - %mul_const(9) - // stack: s4=9*len, len, s5, expmod_contd, len, l_M, kexit_info - SWAP1 - // stack: len, s4, s5, expmod_contd, len, l_M, kexit_info - - DUP1 - %mul_const(7) - // stack: s3=7*len, len, s4, s5, expmod_contd, len, l_M, kexit_info - SWAP1 - // stack: len, s3, s4, s5, expmod_contd, len, l_M, kexit_info - - DUP1 - %mul_const(5) - // stack: s2=5*len, len, s3, s4, s5, expmod_contd, len, l_M, kexit_info - SWAP1 - // stack: len, s2, s3, s4, s5, expmod_contd, len, l_M, kexit_info - - DUP1 - %mul_const(4) - // stack: s1=4*len, len, s2, s3, s4, s5, expmod_contd, len, l_M, kexit_info - SWAP1 - // stack: len, s1, s2, s3, s4, s5, expmod_contd, len, l_M, kexit_info - - DUP1 - %mul_const(3) - // stack: out=3*len, len, s1, s2, s3, s4, s5, expmod_contd, len, l_M, kexit_info - SWAP1 - // stack: len, out, s1, s2, s3, s4, s5, expmod_contd, len, l_M, kexit_info - - DUP1 - %mul_const(2) - // stack: m_loc=2*len, len, out, s1, s2, s3, s4, s5, expmod_contd, len, l_M, kexit_info - SWAP1 - // stack: len, m_loc, out, s1, s2, s3, s4, s5, expmod_contd, len, l_M, kexit_info - - PUSH 0 - // stack: b_loc=0, e_loc=len, m_loc, out, s1, s2, s3, s4, s5, expmod_contd, len, l_M, kexit_info - DUP2 - // stack: len, b_loc, e_loc, m_loc, out, s1, s2, s3, s4, s5, expmod_contd, len, l_M, kexit_info - - %jump(modexp_bignum) - -expmod_contd: - // stack: len, l_M, kexit_info - - // Copy the result value from kernel general memory to the parent's return data. - - // Store return data size: l_M (number of bytes). - SWAP1 - // stack: l_M, len, kexit_info - %mstore_parent_context_metadata(@CTX_METADATA_RETURNDATA_SIZE) - // stack: len, kexit_info - DUP1 - // stack: len, len, kexit_info - %mul_const(3) - // stack: out=3*len, len, kexit_info - DUP2 - DUP2 - // stack: out, len, out, len, kexit_info - ADD - %decrement - SWAP1 - %decrement - SWAP1 - // stack: cur_address=out+len-1, end_address=out-1, len, kexit_info - PUSH 0 - // stack: i=0, cur_address, end_address, len, kexit_info - - // Store in big-endian format. -expmod_store_loop: - // stack: i, cur_address, end_address, len, kexit_info - DUP2 - // stack: cur_address, i, cur_address, end_address, len, kexit_info - %mload_kernel_general - // stack: cur_limb, i, cur_address, end_address, len, kexit_info - DUP2 - // stack: i, cur_limb, i, cur_address, end_address, len, kexit_info - %mul_const(16) - // stack: offset=16*i, cur_limb, i, cur_address, end_address, len, kexit_info - %stack (offset, cur_limb) -> (@SEGMENT_RETURNDATA, offset, cur_limb, 16) - // stack: @SEGMENT_RETURNDATA, offset, cur_limb, 16, i, cur_address, end_address, len, kexit_info - %mload_context_metadata(@CTX_METADATA_PARENT_CONTEXT) - // stack: parent_ctx, @SEGMENT_RETURNDATA, offset, cur_limb, 16, i, cur_address, end_address, len, kexit_info - %mstore_unpacking - // stack: offset', i, cur_address, end_address, len, kexit_info - POP - // stack: i, cur_address, end_address, len, kexit_info - %increment - SWAP1 - %decrement - SWAP1 - // stack: i+1, cur_address-1, end_address, len, kexit_info - DUP3 - DUP2 - EQ - ISZERO - %jumpi(expmod_store_loop) -expmod_store_end: - // stack: i, cur_address, len, kexit_info - %pop3 - // stack: kexit_info - PUSH 0 - // stack: dummy=0, kexit_info - STOP From 099e7946e77146d5342a1b4407fafce426ec1461 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Tue, 2 May 2023 08:13:49 -0700 Subject: [PATCH 17/17] fixes --- evm/src/cpu/kernel/asm/core/precompiles/expmod.asm | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm b/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm index 258c2ff6..be490793 100644 --- a/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm +++ b/evm/src/cpu/kernel/asm/core/precompiles/expmod.asm @@ -400,9 +400,10 @@ expmod_store_loop: ISZERO %jumpi(expmod_store_loop) expmod_store_end: - // stack: i, cur_address, len, kexit_info - %pop3 + // stack: i, cur_address, end_address, len, kexit_info + %pop4 // stack: kexit_info - PUSH 0 - // stack: dummy=0, kexit_info - %jump(pop_and_return_success) + %leftover_gas + // stack: leftover_gas + PUSH 1 // success + %jump(terminate_common)