From 191ddf7bc1012dc98beaf10bac1ebe5a225f8af1 Mon Sep 17 00:00:00 2001 From: Jacqueline Nabaglo Date: Thu, 23 Jun 2022 15:33:55 -0700 Subject: [PATCH] Exponentiation kernel function (#574) * Exponentiation kernel function * Exponentiation: Hamish comments --- evm/src/cpu/kernel/aggregator.rs | 1 + evm/src/cpu/kernel/asm/exp.asm | 81 ++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 evm/src/cpu/kernel/asm/exp.asm diff --git a/evm/src/cpu/kernel/aggregator.rs b/evm/src/cpu/kernel/aggregator.rs index 514712e4..aeb29c3e 100644 --- a/evm/src/cpu/kernel/aggregator.rs +++ b/evm/src/cpu/kernel/aggregator.rs @@ -8,6 +8,7 @@ use crate::cpu::kernel::parser::parse; #[allow(dead_code)] // TODO: Should be used once witness generation is done. pub(crate) fn combined_kernel() -> Kernel { let files = vec![ + include_str!("asm/exp.asm"), include_str!("asm/storage_read.asm"), include_str!("asm/storage_write.asm"), ]; diff --git a/evm/src/cpu/kernel/asm/exp.asm b/evm/src/cpu/kernel/asm/exp.asm new file mode 100644 index 00000000..8103b015 --- /dev/null +++ b/evm/src/cpu/kernel/asm/exp.asm @@ -0,0 +1,81 @@ +/// Recursive implementation of exp. +/// Equivalent to: +/// def exp(x, e): +/// if e == 0: +/// # The path where JUMPI does not jump to `step_case` +/// return 1 +/// else: +/// # This is under the `step_case` label +/// return (x if e % 2 else 1) * exp(x * x, e // 2) +/// Note that this correctly handles exp(0, 0) == 1. + +global exp: +// We don't seem to handle global labels yet, so this function has a local label too for now: +exp: + // stack: x, e, retdest + dup2 + // stack: e, x, e, retdest + push step_case + // stack: step_case, e, x, e, retdest + jumpi + // stack: x, e, retdest + pop + // stack: e, retdest + pop + // stack: retdest + push 1 + // stack: 1, retdest + swap1 + // stack: retdest, 1 + jump + +step_case: + // stack: x, e, retdest + push recursion_return + // stack: recursion_return, x, e, retdest + push 2 + // stack: 2, recursion_return, x, e, retdest + dup4 + // stack: e, 2, recursion_return, x, e, retdest + div + // stack: e / 2, recursion_return, x, e, retdest + dup3 + // stack: x, e / 2, recursion_return, x, e, retdest + dup1 + // stack: x, x, e / 2, recursion_return, x, e, retdest + mul + // stack: x * x, e / 2, recursion_return, x, e, retdest + push exp + // stack: exp, x * x, e / 2, recursion_return, x, e, retdest + jump +recursion_return: + // stack: exp(x * x, e / 2), x, e, retdest + push 2 + // stack: 2, exp(x * x, e / 2), x, e, retdest + dup4 + // stack: e, 2, exp(x * x, e / 2), x, e, retdest + mod + // stack: e % 2, exp(x * x, e / 2), x, e, retdest + push 1 + // stack: 1, e % 2, exp(x * x, e / 2), x, e, retdest + dup4 + // stack: x, 1, e % 2, exp(x * x, e / 2), x, e, retdest + sub + // stack: x - 1, e % 2, exp(x * x, e / 2), x, e, retdest + mul + // stack: (x - 1) * (e % 2), exp(x * x, e / 2), x, e, retdest + push 1 + // stack: 1, (x - 1) * (e % 2), exp(x * x, e / 2), x, e, retdest + add + // stack: 1 + (x - 1) * (e % 2), exp(x * x, e / 2), x, e, retdest + mul + // stack: (1 + (x - 1) * (e % 2)) * exp(x * x, e / 2), x, e, retdest + swap3 + // stack: retdest, x, e, (1 + (x - 1) * (e % 2)) * exp(x * x, e / 2) + swap2 + // stack: e, x, retdest, (1 + (x - 1) * (e % 2)) * exp(x * x, e / 2) + pop + // stack: x, retdest, (1 + (x - 1) * (e % 2)) * exp(x * x, e / 2) + pop + // stack: retdest, (1 + (x - 1) * (e % 2)) * exp(x * x, e / 2) + jump