diff --git a/benchmarks/bench_evm_modexp_dos.nim b/benchmarks/bench_evm_modexp_dos.nim index 6f18c221..312e36c6 100644 --- a/benchmarks/bench_evm_modexp_dos.nim +++ b/benchmarks/bench_evm_modexp_dos.nim @@ -10,9 +10,9 @@ proc report(op: string, elapsedNs: int64, elapsedCycles: int64, iters: int) = let cycles = elapsedCycles div iters let throughput = 1e9 / float64(ns) when SupportsGetTicks: - echo &"{op:<45} {throughput:>15.3f} ops/s {ns:>16} ns/op {cycles:>12} CPU cycles (approx)" + echo &"{op:<70} {throughput:>15.3f} ops/s {ns:>16} ns/op {cycles:>12} CPU cycles (approx)" else: - echo &"{op:<45} {throughput:>15.3f} ops/s {ns:>16} ns/op" + echo &"{op:<70} {throughput:>15.3f} ops/s {ns:>16} ns/op" template bench(fnCall: untyped, ticks, ns: var int64): untyped = block: @@ -366,6 +366,60 @@ proc dos2c() = report("EVM Modexp - 1,1,121 - exponent=7 and odd modulus", nanoseconds, ticks, execsEIP2565) echo "Total time: ", nanoseconds.float64 / 1e6, " ms for ", execsEIP2565, " iterations" +proc dos2d() = + # odd variation with no shortcut and power of 2 modulus + + let input = [ + # Length of base (1) + uint8 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + + # Length of exponent (1) + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + + # Length of modulus (121) + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, + + # Base + 0x33, + + # Exponent + 0x07, + + # Modulus + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ] + + var r = newSeq[byte](121) + var ticks, nanoseconds: int64 + + let (gasFeeEIP198, gasFeeEIP2565) = computeGasFee(input) + const blockSize = 30000000 + + let execsEIP198 = blockSize div gasFeeEIP198 + let execsEIP2565 = blockSize div gasFeeEIP2565 + + echo "Gas cost: ", gasFeeEIP198, " gas (EIP-198) - ", execsEIP198, " executions per block" + echo "Gas cost: ", gasFeeEIP2565, " gas (EIP-2565) - ", execsEIP2565, " executions per block" + + for i in 0 ..< execsEIP2565: + bench( + (let _ = r.eth_evm_modexp(input)), + ticks, nanoseconds) + + report("EVM Modexp - 1,1,121 - exponent=7 and power-of-2 modulus", nanoseconds, ticks, execsEIP2565) + echo "Total time: ", nanoseconds.float64 / 1e6, " ms for ", execsEIP2565, " iterations" + dos1() echo "\n" dos2() @@ -374,4 +428,6 @@ dos2a() echo "\n" dos2b() echo "\n" -dos2c() \ No newline at end of file +dos2c() +echo "\n" +dos2d() \ No newline at end of file diff --git a/constantine/math_arbitrary_precision/arithmetic/bigints_views.nim b/constantine/math_arbitrary_precision/arithmetic/bigints_views.nim index b95d4405..2c0f9384 100644 --- a/constantine/math_arbitrary_precision/arithmetic/bigints_views.nim +++ b/constantine/math_arbitrary_precision/arithmetic/bigints_views.nim @@ -57,6 +57,12 @@ func powOddMod_vartime*( let aBits = a.getBits_LE_vartime() let mBits = M.getBits_LE_vartime() + let eBits = exponent.getBits_BE_vartime() + + if eBits == 1: + r.view().reduce(a.view(), aBits, M.view(), mBits) + return + let L = wordsRequired(mBits) let m0ninv = M[0].negInvModWord() var rMont = allocStackArray(SecretWord, L) diff --git a/constantine/math_arbitrary_precision/arithmetic/limbs_mod2k.nim b/constantine/math_arbitrary_precision/arithmetic/limbs_mod2k.nim index 2d50379f..ac33f80b 100644 --- a/constantine/math_arbitrary_precision/arithmetic/limbs_mod2k.nim +++ b/constantine/math_arbitrary_precision/arithmetic/limbs_mod2k.nim @@ -115,6 +115,13 @@ func powMod2k_vartime*( r[0] = One # x⁰ = 1, even for 0⁰ return + if msb == 0: # exponent is 1 + for i in 0 ..< min(r.len, a.len): + # range [r.len, a.len) will be truncated (mod 2ᵏ) + r[i] = a[i] + r.mod2k_vartime(k) + return + if a.isEven().bool: let aTrailingZeroes = block: var i = 0