mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-05 15:23:06 +00:00
expmod precompile
This commit is contained in:
parent
11a03c5ebc
commit
dc91554da2
@ -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"),
|
||||
];
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
39
evm/src/cpu/kernel/asm/util/math.asm
Normal file
39
evm/src/cpu/kernel/asm/util/math.asm
Normal file
@ -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
|
||||
Loading…
x
Reference in New Issue
Block a user