Modular exponentiation (arbitrary output) and EIP-198 (#242)
* implement arbitrary precision modular exponentiation (prerequisite EIP-198) * [modexp] implement exponentiation modulo 2ᵏ * add inversion (mod 2ᵏ) * [modexp] High-level wrapper for powmod with odd modulus * [modexp] faster exponentiation (mod 2ᵏ) for even case and Euler's totient function odd case * [modexp] implement general fast modular exponentiation * Fix modular reduction with 64-bit modulus + fuzz powmod vs GMP * add benchmark * add EIP-198 support * fixups following self review * fix test paths
This commit is contained in:
parent
d996ccd5d8
commit
b1ef2682d6
|
@ -211,4 +211,4 @@ proc powUnsafeBench*(T: typedesc, iters: int) =
|
|||
let exponent = rng.random_unsafe(BigInt[T.C.getCurveOrderBitwidth()])
|
||||
bench("Exp curve order (Leak exponent bits) - " & $exponent.bits & "-bit", T, iters):
|
||||
var r = x
|
||||
r.powUnsafeExponent(exponent)
|
||||
r.pow_vartime(exponent)
|
||||
|
|
|
@ -0,0 +1,205 @@
|
|||
import
|
||||
../constantine/math/arithmetic,
|
||||
../constantine/math/io/[io_bigints, io_fields],
|
||||
../constantine/math/config/curves,
|
||||
../constantine/platforms/[abstractions, codecs],
|
||||
../constantine/math_arbitrary_precision/arithmetic/bigints_views,
|
||||
../helpers/prng_unsafe,
|
||||
./platforms, ./bench_blueprint
|
||||
|
||||
import stint, gmp
|
||||
from bigints import nil # force qualified import to avoid conflicts on BigInt
|
||||
|
||||
# Benchmarks for modular exponentiation implementations:
|
||||
#
|
||||
# - Constantine has 2 backends
|
||||
# - The cryptographic backend uses fixed-sized integer.
|
||||
# Often the modulus is known at compile-time (specific elliptic curves),
|
||||
# except for RSA.
|
||||
#
|
||||
# This allows reducing precomputation time,
|
||||
# and unrolling all loops.
|
||||
# This is significant as incrementing a loop counter messes up carry propagation.
|
||||
#
|
||||
# That backend requires the modulus to be prime.
|
||||
#
|
||||
# As cryptography only uses primes (which are odd), this is not a limitation.
|
||||
# However it is not suitable for general-purpose
|
||||
#
|
||||
# - The arbitrary-sized integer backend.
|
||||
# Some protocol like Ethereum modexp (EIP-198) require
|
||||
# modular exponentiation on arbitrary inputs.
|
||||
#
|
||||
# - Stint, GMP, nim-bigints are also benchmarked
|
||||
# for reference. GMP and nim-bigints require dynamic allocation.
|
||||
# - For GMP, we reuse buffers to limit allocation to the first benchmark
|
||||
# - nim-bigints doesn't allow reusing buffers
|
||||
#
|
||||
# Stint requires all inputs to be the same size
|
||||
# so we use 256-bits for all.
|
||||
#
|
||||
# To benchmark the cryptographic backend, we use Secp256k1 (the Bitcoin curve).
|
||||
# Note that Constantine implements it generically,
|
||||
# due to the special form of the prime (2²⁵⁶ - 2³² - 977),
|
||||
# even faster algorithms can be used.
|
||||
# This gives an upper-bound
|
||||
|
||||
proc report(op: string, elapsedNs: int64, elapsedCycles: int64, iters: int) =
|
||||
let ns = elapsedNs div iters
|
||||
let cycles = elapsedCycles div iters
|
||||
let throughput = 1e9 / float64(elapsedNs)
|
||||
when SupportsGetTicks:
|
||||
echo &"{op:<45} {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"
|
||||
|
||||
const # https://gmplib.org/manual/Integer-Import-and-Export.html
|
||||
GMP_WordLittleEndian = -1'i32
|
||||
GMP_WordNativeEndian = 0'i32
|
||||
GMP_WordBigEndian = 1'i32
|
||||
|
||||
GMP_MostSignificantWordFirst = 1'i32
|
||||
GMP_LeastSignificantWordFirst = -1'i32
|
||||
|
||||
const bits = 256
|
||||
|
||||
type BenchDesc = object
|
||||
# Hex strings
|
||||
a: string
|
||||
e: string
|
||||
M: string
|
||||
|
||||
proc genBench(iters: int): seq[BenchDesc] =
|
||||
for _ in 0 ..< iters:
|
||||
let a = rng.random_long01Seq(BigInt[bits])
|
||||
let e = rng.random_long01Seq(BigInt[bits])
|
||||
let M = rng.random_long01Seq(BigInt[bits])
|
||||
result.add BenchDesc(
|
||||
a: a.toHex(),
|
||||
e: e.toHex(),
|
||||
M: M.toHex())
|
||||
|
||||
template bench(fnCall: untyped, ticks, ns: var int64): untyped =
|
||||
block:
|
||||
let startTime = getMonotime()
|
||||
let startClock = getTicks()
|
||||
fnCall
|
||||
let stopClock = getTicks()
|
||||
let stopTime = getMonotime()
|
||||
|
||||
ticks += stopClock - startClock
|
||||
ns += inNanoseconds(stopTime-startTime)
|
||||
|
||||
proc benchAll(desc: seq[BenchDesc]) =
|
||||
|
||||
var perfCttArb, perfCttCrypto, perfGmp, perfStint, perfNimBigInt: int64
|
||||
|
||||
block: # Constantine Arbitrary-precision
|
||||
var ticks, nanoseconds: int64
|
||||
|
||||
for i in 0 ..< desc.len:
|
||||
# The implementation is view based and uses unowned-buffers (seq or arrays)
|
||||
# but for hex parsing simplicity we reuse BigInt buffers
|
||||
# and we directly access the array behind with .limbs
|
||||
var r: BigInt[bits]
|
||||
let a = BigInt[bits].fromHex(desc[i].a)
|
||||
let M = BigInt[bits].fromHex(desc[i].M)
|
||||
let e = array[bits div 8, byte].fromHex(desc[i].e)
|
||||
|
||||
bench(
|
||||
r.limbs.powMod_varTime(a.limbs, e, M.limbs, window = 4),
|
||||
ticks, nanoseconds)
|
||||
|
||||
report("Constantine (generic arbitrary-precision)", nanoseconds, ticks, desc.len)
|
||||
perfCttArb = nanoseconds
|
||||
|
||||
block: # Constantine Cryptographic backend
|
||||
var ticks, nanoseconds: int64
|
||||
var e = newSeq[byte](bits div 8)
|
||||
|
||||
for i in 0 ..< desc.len:
|
||||
var r: Fp[Secp256k1]
|
||||
let a = Fp[Secp256k1].fromHex(desc[i].a)
|
||||
e.paddedFromHex(desc[i].e, bigEndian)
|
||||
|
||||
bench(
|
||||
(r = a; r.pow_varTime(e)),
|
||||
ticks, nanoseconds)
|
||||
|
||||
report("Constantine (crypto fixed 256-bit precision)", nanoseconds, ticks, desc.len)
|
||||
perfCttCrypto = nanoseconds
|
||||
|
||||
block: # GMP
|
||||
var ticks, nanoseconds: int64
|
||||
var a, e, M, r: mpz_t
|
||||
mpz_init(a)
|
||||
mpz_init(e)
|
||||
mpz_init(M)
|
||||
mpz_init(r)
|
||||
|
||||
for i in 0 ..< desc.len:
|
||||
let aCtt = BigInt[bits].fromHex(desc[i].a)
|
||||
a.mpz_import(aCtt.limbs.len, GMP_LeastSignificantWordFirst, sizeof(SecretWord), GMP_WordNativeEndian, 0, aCtt.limbs[0].unsafeAddr)
|
||||
let eCtt = BigInt[bits].fromHex(desc[i].e)
|
||||
e.mpz_import(eCtt.limbs.len, GMP_LeastSignificantWordFirst, sizeof(SecretWord), GMP_WordNativeEndian, 0, eCtt.limbs[0].unsafeAddr)
|
||||
let mCtt = BigInt[bits].fromHex(desc[i].M)
|
||||
M.mpz_import(mCtt.limbs.len, GMP_LeastSignificantWordFirst, sizeof(SecretWord), GMP_WordNativeEndian, 0, mCtt.limbs[0].unsafeAddr)
|
||||
|
||||
bench(
|
||||
r.mpz_powm(a, e, M),
|
||||
ticks, nanoseconds)
|
||||
|
||||
report("GMP", nanoseconds, ticks, desc.len)
|
||||
perfGMP = nanoseconds
|
||||
|
||||
mpz_clear(r)
|
||||
mpz_clear(M)
|
||||
mpz_clear(e)
|
||||
mpz_clear(a)
|
||||
|
||||
block: # Stint
|
||||
var ticks, nanoseconds: int64
|
||||
|
||||
for i in 0 ..< desc.len:
|
||||
let a = Stuint[bits].fromHex(desc[i].a)
|
||||
let e = Stuint[bits].fromHex(desc[i].e)
|
||||
let M = Stuint[bits].fromHex(desc[i].M)
|
||||
|
||||
bench(
|
||||
(let r = powmod(a, e, M)),
|
||||
ticks, nanoseconds)
|
||||
|
||||
report("Stint", nanoseconds, ticks, desc.len)
|
||||
perfStint = nanoseconds
|
||||
|
||||
block: # Nim bigints
|
||||
var ticks, nanoseconds: int64
|
||||
|
||||
for i in 0 ..< desc.len:
|
||||
# Drop the 0x prefix
|
||||
let a = bigints.initBigInt(desc[i].a[2..^1], base = 16)
|
||||
let e = bigints.initBigInt(desc[i].e[2..^1], base = 16)
|
||||
let M = bigints.initBigInt(desc[i].M[2..^1], base = 16)
|
||||
|
||||
bench(
|
||||
(let r = bigints.powmod(a, e, M)),
|
||||
ticks, nanoseconds)
|
||||
|
||||
report("nim-bigints", nanoseconds, ticks, desc.len)
|
||||
perfNimBigInt = nanoseconds
|
||||
|
||||
let ratioCrypto = float64(perfCttCrypto) / float64(perfCttArb)
|
||||
let ratioGMP = float64(perfGMP) / float64(perfCttArb)
|
||||
let ratioStint = float64(perfStint) / float64(perfCttArb)
|
||||
let ratioNimBigInt = float64(perfNimBigInt) / float64(perfCttArb)
|
||||
|
||||
echo ""
|
||||
echo &"Perf ratio Constantine generic vs crypto fixed precision: {ratioCrypto:>8.3f}x"
|
||||
echo &"Perf ratio Constantine generic vs GMP: {ratioGMP:>8.3f}x"
|
||||
echo &"Perf ratio Constantine generic vs Stint: {ratioStint:>8.3f}x"
|
||||
echo &"Perf ratio Constantine generic vs nim-bigints: {ratioNimBigInt:>8.3f}x"
|
||||
|
||||
|
||||
when isMainModule:
|
||||
let benchDesc = genBench(100)
|
||||
benchDesc.benchAll()
|
|
@ -263,10 +263,15 @@ const testDesc: seq[tuple[path: string, useGMP: bool]] = @[
|
|||
("tests/math_bigints/t_io_bigints.nim", false),
|
||||
# ("tests/math_bigints/t_bigints.nim", false),
|
||||
# ("tests/math_bigints/t_bigints_multimod.nim", false),
|
||||
# ("tests/math_bigints/t_bigints_mod_vs_gmp.nim", true),
|
||||
# ("tests/math_bigints/t_bigints_mul_vs_gmp.nim", true),
|
||||
# ("tests/math_bigints/t_bigints_mul_high_words_vs_gmp.nim", true),
|
||||
|
||||
# Big ints - arbitrary precision
|
||||
# ----------------------------------------------------------
|
||||
("tests/math_arbitrary_precision/t_bigints_mod.nim", false),
|
||||
("tests/math_arbitrary_precision/t_bigints_mod_vs_gmp.nim", true),
|
||||
("tests/math_arbitrary_precision/t_bigints_powmod_vs_gmp.nim", true),
|
||||
|
||||
# Field
|
||||
# ----------------------------------------------------------
|
||||
("tests/math_fields/t_io_fields", false),
|
||||
|
@ -824,6 +829,12 @@ task test_nvidia, "Run all tests for Nvidia GPUs":
|
|||
if cmd != "": # Windows doesn't like empty commands
|
||||
exec cmd
|
||||
|
||||
# BigInt benchmark
|
||||
# ------------------------------------------
|
||||
|
||||
task bench_powmod, "Run modular exponentiation benchmark with your CC compiler":
|
||||
runBench("bench_powmod")
|
||||
|
||||
# Finite field 𝔽p
|
||||
# ------------------------------------------
|
||||
|
||||
|
|
|
@ -8,13 +8,14 @@
|
|||
|
||||
import
|
||||
./platforms/abstractions,
|
||||
./math/config/curves,
|
||||
./math/config/[curves, precompute],
|
||||
./math/[arithmetic, extension_fields],
|
||||
./math/arithmetic/limbs_montgomery,
|
||||
./math/ec_shortweierstrass,
|
||||
./math/pairings/[pairings_generic, miller_accumulators],
|
||||
./math/constants/zoo_subgroups,
|
||||
./math/io/[io_bigints, io_fields]
|
||||
./math/io/[io_bigints, io_fields],
|
||||
./math_arbitrary_precision/arithmetic/bigints_views
|
||||
|
||||
# ############################################################
|
||||
#
|
||||
|
@ -28,10 +29,11 @@ import
|
|||
type
|
||||
CttEVMStatus* = enum
|
||||
cttEVM_Success
|
||||
cttEVM_InvalidInputSize
|
||||
cttEVM_InvalidOutputSize
|
||||
cttEVM_IntLargerThanModulus
|
||||
cttEVM_PointNotOnCurve
|
||||
cttEVM_PointNotInSubgroup
|
||||
cttEVM_InvalidInputLength
|
||||
|
||||
func parseRawUint(
|
||||
dst: var Fp[BN254_Snarks],
|
||||
|
@ -86,7 +88,7 @@ func fromRawCoords(
|
|||
|
||||
return cttEVM_Success
|
||||
|
||||
func eth_evm_ecadd*(r: var array[64, byte], inputs: openarray[byte]): CttEVMStatus =
|
||||
func eth_evm_ecadd*(r: var openArray[byte], inputs: openarray[byte]): CttEVMStatus =
|
||||
## Elliptic Curve addition on BN254_Snarks
|
||||
## (also called alt_bn128 in Ethereum specs
|
||||
## and bn256 in Ethereum tests)
|
||||
|
@ -103,6 +105,7 @@ func eth_evm_ecadd*(r: var array[64, byte], inputs: openarray[byte]): CttEVMStat
|
|||
## If the length is greater than 128 bytes, input is truncated to 128 bytes.
|
||||
##
|
||||
## Output
|
||||
## - Output buffer MUST be of length 64 bytes
|
||||
## - A G1 point R with coordinates (Px + Qx, Py + Qy)
|
||||
## - Status code:
|
||||
## cttEVM_Success
|
||||
|
@ -111,6 +114,9 @@ func eth_evm_ecadd*(r: var array[64, byte], inputs: openarray[byte]): CttEVMStat
|
|||
##
|
||||
## Spec https://eips.ethereum.org/EIPS/eip-196
|
||||
|
||||
if r.len != 64:
|
||||
return cttEVM_InvalidOutputSize
|
||||
|
||||
# Auto-pad with zero
|
||||
var padded: array[128, byte]
|
||||
padded.rawCopy(0, inputs, 0, min(inputs.len, 128))
|
||||
|
@ -119,14 +125,12 @@ func eth_evm_ecadd*(r: var array[64, byte], inputs: openarray[byte]): CttEVMStat
|
|||
|
||||
let statusP = P.fromRawCoords(
|
||||
x = padded.toOpenArray(0, 31),
|
||||
y = padded.toOpenArray(32, 63)
|
||||
)
|
||||
y = padded.toOpenArray(32, 63))
|
||||
if statusP != cttEVM_Success:
|
||||
return statusP
|
||||
let statusQ = Q.fromRawCoords(
|
||||
x = padded.toOpenArray(64, 95),
|
||||
y = padded.toOpenArray(96, 127)
|
||||
)
|
||||
y = padded.toOpenArray(96, 127))
|
||||
if statusQ != cttEVM_Success:
|
||||
return statusQ
|
||||
|
||||
|
@ -135,13 +139,13 @@ func eth_evm_ecadd*(r: var array[64, byte], inputs: openarray[byte]): CttEVMStat
|
|||
aff.affine(R)
|
||||
|
||||
r.toOpenArray(0, 31).marshal(
|
||||
aff.x, bigEndian
|
||||
)
|
||||
aff.x, bigEndian)
|
||||
r.toOpenArray(32, 63).marshal(
|
||||
aff.y, bigEndian
|
||||
)
|
||||
aff.y, bigEndian)
|
||||
|
||||
func eth_evm_ecmul*(r: var array[64, byte], inputs: openarray[byte]): CttEVMStatus =
|
||||
return cttEVM_Success
|
||||
|
||||
func eth_evm_ecmul*(r: var openArray[byte], inputs: openarray[byte]): CttEVMStatus =
|
||||
## Elliptic Curve multiplication on BN254_Snarks
|
||||
## (also called alt_bn128 in Ethereum specs
|
||||
## and bn256 in Ethereum tests)
|
||||
|
@ -158,6 +162,7 @@ func eth_evm_ecmul*(r: var array[64, byte], inputs: openarray[byte]): CttEVMStat
|
|||
## If the length is greater than 96 bytes, input is truncated to 96 bytes.
|
||||
##
|
||||
## Output
|
||||
## - Output buffer MUST be of length 64 bytes
|
||||
## - A G1 point R = [s]P
|
||||
## - Status code:
|
||||
## cttEVM_Success
|
||||
|
@ -166,6 +171,9 @@ func eth_evm_ecmul*(r: var array[64, byte], inputs: openarray[byte]): CttEVMStat
|
|||
##
|
||||
## Spec https://eips.ethereum.org/EIPS/eip-196
|
||||
|
||||
if r.len != 64:
|
||||
return cttEVM_InvalidOutputSize
|
||||
|
||||
# Auto-pad with zero
|
||||
var padded: array[128, byte]
|
||||
padded.rawCopy(0, inputs, 0, min(inputs.len, 128))
|
||||
|
@ -174,8 +182,7 @@ func eth_evm_ecmul*(r: var array[64, byte], inputs: openarray[byte]): CttEVMStat
|
|||
|
||||
let statusP = P.fromRawCoords(
|
||||
x = padded.toOpenArray(0, 31),
|
||||
y = padded.toOpenArray(32, 63)
|
||||
)
|
||||
y = padded.toOpenArray(32, 63))
|
||||
if statusP != cttEVM_Success:
|
||||
return statusP
|
||||
|
||||
|
@ -205,11 +212,11 @@ func eth_evm_ecmul*(r: var array[64, byte], inputs: openarray[byte]): CttEVMStat
|
|||
aff.affine(P)
|
||||
|
||||
r.toOpenArray(0, 31).marshal(
|
||||
aff.x, bigEndian
|
||||
)
|
||||
aff.x, bigEndian)
|
||||
r.toOpenArray(32, 63).marshal(
|
||||
aff.y, bigEndian
|
||||
)
|
||||
aff.y, bigEndian)
|
||||
|
||||
return cttEVM_Success
|
||||
|
||||
func subgroupCheck(P: ECP_ShortW_Aff[Fp2[BN254_Snarks], G2]): bool =
|
||||
## A point may be on a curve but in case the curve has a cofactor != 1
|
||||
|
@ -289,7 +296,7 @@ func fromRawCoords(
|
|||
return cttEVM_Success
|
||||
|
||||
func eth_evm_ecpairing*(
|
||||
r: var array[32, byte], inputs: openarray[byte]): CttEVMStatus =
|
||||
r: var openArray[byte], inputs: openarray[byte]): CttEVMStatus =
|
||||
## Elliptic Curve pairing on BN254_Snarks
|
||||
## (also called alt_bn128 in Ethereum specs
|
||||
## and bn256 in Ethereum tests)
|
||||
|
@ -300,24 +307,27 @@ func eth_evm_ecpairing*(
|
|||
## - An array of [(P0, Q0), (P1, Q1), ... (Pk, Qk)] points in (G1, G2)
|
||||
##
|
||||
## Output
|
||||
## - Output buffer MUST be of length 32 bytes
|
||||
## - 0 or 1 in uint256 BigEndian representation
|
||||
## - Status code:
|
||||
## cttEVM_Success
|
||||
## cttEVM_IntLargerThanModulus
|
||||
## cttEVM_PointNotOnCurve
|
||||
## cttEVM_InvalidInputLength
|
||||
## cttEVM_InvalidInputSize
|
||||
##
|
||||
## Spec https://eips.ethereum.org/EIPS/eip-197
|
||||
if r.len != 32:
|
||||
return cttEVM_InvalidOutputSize
|
||||
|
||||
let N = inputs.len div 192
|
||||
if inputs.len mod 192 != 0:
|
||||
return cttEVM_InvalidInputLength
|
||||
return cttEVM_InvalidInputSize
|
||||
|
||||
if N == 0:
|
||||
# Spec: "Empty input is valid and results in returning one."
|
||||
zeroMem(r.addr, r.sizeof())
|
||||
zeroMem(r[0].addr, r.len-1)
|
||||
r[r.len-1] = byte 1
|
||||
return
|
||||
return cttEVM_Success
|
||||
|
||||
var P{.noInit.}: ECP_ShortW_Aff[Fp[BN254_Snarks], G1]
|
||||
var Q{.noInit.}: ECP_ShortW_Aff[Fp2[BN254_Snarks], G2]
|
||||
|
@ -331,8 +341,8 @@ func eth_evm_ecpairing*(
|
|||
|
||||
let statusP = P.fromRawCoords(
|
||||
x = inputs.toOpenArray(pos, pos+31),
|
||||
y = inputs.toOpenArray(pos+32, pos+63)
|
||||
)
|
||||
y = inputs.toOpenArray(pos+32, pos+63))
|
||||
|
||||
if statusP != cttEVM_Success:
|
||||
return statusP
|
||||
|
||||
|
@ -342,8 +352,8 @@ func eth_evm_ecpairing*(
|
|||
x1 = inputs.toOpenArray(pos+64, pos+95),
|
||||
x0 = inputs.toOpenArray(pos+96, pos+127),
|
||||
y1 = inputs.toOpenArray(pos+128, pos+159),
|
||||
y0 = inputs.toOpenArray(pos+160, pos+191)
|
||||
)
|
||||
y0 = inputs.toOpenArray(pos+160, pos+191))
|
||||
|
||||
if statusQ != cttEVM_Success:
|
||||
return statusQ
|
||||
|
||||
|
@ -352,13 +362,118 @@ func eth_evm_ecpairing*(
|
|||
foundInfinity = true
|
||||
|
||||
if foundInfinity: # pairing with infinity returns 1, hence no need to compute the following
|
||||
zeroMem(r[0].addr, r.len-1)
|
||||
r[r.len-1] = byte 1
|
||||
return
|
||||
return cttEVM_Success
|
||||
|
||||
var gt {.noinit.}: Fp12[BN254_Snarks]
|
||||
acc.finish(gt)
|
||||
gt.finalExp()
|
||||
|
||||
zeroMem(r.addr, r.sizeof())
|
||||
zeroMem(r[0].addr, r.len)
|
||||
if gt.isOne().bool:
|
||||
r[r.len-1] = byte 1
|
||||
return cttEVM_Success
|
||||
|
||||
func eth_evm_modexp*(r: var openArray[byte], inputs: openArray[byte]): CttEVMStatus {.noInline, tags:[Alloca, Vartime].} =
|
||||
## Modular exponentiation
|
||||
##
|
||||
## Name: MODEXP
|
||||
##
|
||||
## Inputs:
|
||||
## - `baseLen`: 32 bytes base integer length (in bytes)
|
||||
## - `exponentLen`: 32 bytes exponent length (in bytes)
|
||||
## - `modulusLen`: 32 bytes modulus length (in bytes)
|
||||
## - `base`: base integer (`baseLen` bytes)
|
||||
## - `exponent`: exponent (`exponentLen` bytes)
|
||||
## - `modulus`: modulus (`modulusLen` bytes)
|
||||
##
|
||||
## Output:
|
||||
## - baseᵉˣᵖᵒⁿᵉⁿᵗ (mod modulus)
|
||||
## The result buffer size `r` MUST match the modulusLen
|
||||
## - status code:
|
||||
## cttEVM_Success
|
||||
## cttEVM_InvalidInputSize if the lengths require more than 32-bit or 64-bit addressing (depending on hardware)
|
||||
## cttEVM_InvalidOutputSize
|
||||
##
|
||||
## Spec
|
||||
## Yellow Paper Appendix E
|
||||
## EIP-198 - https://github.com/ethereum/EIPs/blob/master/EIPS/eip-198.md
|
||||
##
|
||||
## Hardware considerations:
|
||||
## This procedure stack allocates a table of (16+1)*modulusLen and many stack temporaries.
|
||||
## Make sure to validate gas costs and reject large inputs to bound stack usage.
|
||||
|
||||
# Input parse sizes
|
||||
# -----------------
|
||||
let
|
||||
bL = BigInt[256].unmarshal(inputs.toOpenArray(0, 31), bigEndian)
|
||||
eL = BigInt[256].unmarshal(inputs.toOpenArray(32, 63), bigEndian)
|
||||
mL = BigInt[256].unmarshal(inputs.toOpenArray(64, 95), bigEndian)
|
||||
|
||||
maxSize = BigInt[256].fromUint(high(uint)) # A CPU can only address up to high(uint)
|
||||
|
||||
# Input validation
|
||||
# -----------------
|
||||
if bool(bL > maxSize):
|
||||
return cttEVM_InvalidInputSize
|
||||
if bool(eL > maxSize):
|
||||
return cttEVM_InvalidInputSize
|
||||
if bool(mL > maxSize):
|
||||
return cttEVM_InvalidInputSize
|
||||
|
||||
let
|
||||
baseLen = cast[int](bL.limbs[0])
|
||||
exponentLen = cast[int](eL.limbs[0])
|
||||
modulusLen = cast[int](mL.limbs[0])
|
||||
|
||||
if r.len != modulusLen:
|
||||
return cttEVM_InvalidOutputSize
|
||||
|
||||
if baseLen.ceilDiv_vartime(WordBitWidth div 8) > modulusLen.ceilDiv_vartime(WordBitWidth div 8):
|
||||
return cttEVM_InvalidInputSize
|
||||
|
||||
# Special cases
|
||||
# ----------------------
|
||||
if modulusLen == 0:
|
||||
r.setZero()
|
||||
return cttEVM_Success
|
||||
if exponentLen == 0:
|
||||
r.setZero()
|
||||
r[r.len-1] = byte 1 # 0^0 = 1 and x^0 = 1
|
||||
return cttEVM_Success
|
||||
if baseLen == 0:
|
||||
r.setZero()
|
||||
return cttEVM_Success
|
||||
|
||||
# Input deserialization
|
||||
# ---------------------
|
||||
var baseBuf = allocStackArray(SecretWord, baseLen)
|
||||
var modulusBuf = allocStackArray(SecretWord, modulusLen)
|
||||
var outputBuf = allocStackArray(SecretWord, modulusLen)
|
||||
|
||||
template base(): untyped = baseBuf.toOpenArray(0, baseLen-1)
|
||||
template modulus(): untyped = modulusBuf.toOpenArray(0, modulusLen-1)
|
||||
template output(): untyped = outputBuf.toOpenArray(0, modulusLen-1)
|
||||
|
||||
# Inclusive stops
|
||||
let baseStart = 96
|
||||
let baseStop = baseStart+baseLen-1
|
||||
let expStart = baseStop+1
|
||||
let expStop = expStart+exponentLen-1
|
||||
let modStart = expStop+1
|
||||
let modStop = modStart+modulusLen-1
|
||||
|
||||
base.toOpenArray(0, baseLen-1).unmarshal(inputs.toOpenArray(baseStart, baseStop), WordBitWidth, bigEndian)
|
||||
modulus.toOpenArray(0, modulusLen-1).unmarshal(inputs.toOpenArray(modStart, modStop), WordBitWidth, bigEndian)
|
||||
template exponent(): untyped =
|
||||
inputs.toOpenArray(expStart, expStop)
|
||||
|
||||
# Computation
|
||||
# ---------------------
|
||||
output.powMod_vartime(base, exponent, modulus, window = 4)
|
||||
|
||||
# Output serialization
|
||||
# ---------------------
|
||||
r.marshal(output, WordBitWidth, bigEndian)
|
||||
return cttEVM_Success
|
|
@ -21,7 +21,7 @@ import
|
|||
|
||||
# A FpDbl is a partially-reduced double-precision element of Fp
|
||||
# The allowed range is [0, 2ⁿp)
|
||||
# with n = w*WordBitSize
|
||||
# with n = w*WordBitWidth
|
||||
# and w the number of words necessary to represent p on the machine.
|
||||
# Concretely a 381-bit p needs 6*64 bits limbs (hence 384 bits total)
|
||||
# and so FpDbl would 768 bits.
|
||||
|
|
|
@ -12,7 +12,7 @@ import
|
|||
./limbs,
|
||||
./limbs_extmul,
|
||||
./limbs_exgcd,
|
||||
./limbs_division
|
||||
../../math_arbitrary_precision/arithmetic/limbs_division
|
||||
|
||||
export BigInt
|
||||
|
||||
|
|
|
@ -104,7 +104,7 @@ func powMont*[mBits: static int](
|
|||
var scratchSpace {.noInit.}: array[scratchLen, Limbs[mBits.wordsRequired]]
|
||||
powMont(a.limbs, exponent, M.limbs, one.limbs, negInvModWord, scratchSpace, spareBits)
|
||||
|
||||
func powMontUnsafeExponent*[mBits: static int](
|
||||
func powMont_vartime*[mBits: static int](
|
||||
a: var BigInt[mBits], exponent: openarray[byte],
|
||||
M, one: BigInt[mBits], negInvModWord: BaseType, windowSize: static int,
|
||||
spareBits: static int
|
||||
|
@ -126,7 +126,7 @@ func powMontUnsafeExponent*[mBits: static int](
|
|||
const scratchLen = if windowSize == 1: 2
|
||||
else: (1 shl windowSize) + 1
|
||||
var scratchSpace {.noInit.}: array[scratchLen, Limbs[mBits.wordsRequired]]
|
||||
powMontUnsafeExponent(a.limbs, exponent, M.limbs, one.limbs, negInvModWord, scratchSpace, spareBits)
|
||||
powMont_vartime(a.limbs, exponent, M.limbs, one.limbs, negInvModWord, scratchSpace, spareBits)
|
||||
|
||||
func powMont*[mBits, eBits: static int](
|
||||
a: var BigInt[mBits], exponent: BigInt[eBits],
|
||||
|
@ -147,7 +147,7 @@ func powMont*[mBits, eBits: static int](
|
|||
|
||||
powMont(a, expBE, M, one, negInvModWord, windowSize, spareBits)
|
||||
|
||||
func powMontUnsafeExponent*[mBits, eBits: static int](
|
||||
func powMont_vartime*[mBits, eBits: static int](
|
||||
a: var BigInt[mBits], exponent: BigInt[eBits],
|
||||
M, one: BigInt[mBits], negInvModWord: BaseType, windowSize: static int,
|
||||
spareBits: static int
|
||||
|
@ -168,7 +168,7 @@ func powMontUnsafeExponent*[mBits, eBits: static int](
|
|||
var expBE {.noInit.}: array[ebits.ceilDiv_vartime(8), byte]
|
||||
expBE.marshal(exponent, bigEndian)
|
||||
|
||||
powMontUnsafeExponent(a, expBE, M, one, negInvModWord, windowSize, spareBits)
|
||||
powMont_vartime(a, expBE, M, one, negInvModWord, windowSize, spareBits)
|
||||
|
||||
{.pop.} # inline
|
||||
{.pop.} # raises no exceptions
|
||||
|
|
|
@ -372,7 +372,7 @@ func pow*(a: var FF, exponent: openarray[byte]) =
|
|||
FF.getSpareBits()
|
||||
)
|
||||
|
||||
func powUnsafeExponent*(a: var FF, exponent: BigInt) =
|
||||
func pow_vartime*(a: var FF, exponent: BigInt) =
|
||||
## Exponentiation modulo p
|
||||
## ``a``: a field element to be exponentiated
|
||||
## ``exponent``: a big integer
|
||||
|
@ -384,14 +384,14 @@ func powUnsafeExponent*(a: var FF, exponent: BigInt) =
|
|||
## - power analysis
|
||||
## - timing analysis
|
||||
const windowSize = 5 # TODO: find best window size for each curves
|
||||
a.mres.powMontUnsafeExponent(
|
||||
a.mres.powMont_vartime(
|
||||
exponent,
|
||||
FF.fieldMod(), FF.getMontyOne(),
|
||||
FF.getNegInvModWord(), windowSize,
|
||||
FF.getSpareBits()
|
||||
)
|
||||
|
||||
func powUnsafeExponent*(a: var FF, exponent: openarray[byte]) =
|
||||
func pow_vartime*(a: var FF, exponent: openarray[byte]) =
|
||||
## Exponentiation modulo p
|
||||
## ``a``: a field element to be exponentiated
|
||||
## ``exponent``: a big integer a big integer in canonical big endian representation
|
||||
|
@ -403,7 +403,7 @@ func powUnsafeExponent*(a: var FF, exponent: openarray[byte]) =
|
|||
## - power analysis
|
||||
## - timing analysis
|
||||
const windowSize = 5 # TODO: find best window size for each curves
|
||||
a.mres.powMontUnsafeExponent(
|
||||
a.mres.powMont_vartime(
|
||||
exponent,
|
||||
FF.fieldMod(), FF.getMontyOne(),
|
||||
FF.getNegInvModWord(), windowSize,
|
||||
|
|
|
@ -22,7 +22,7 @@ type FpDbl*[C: static Curve] = object
|
|||
## Double-precision Fp element
|
||||
## A FpDbl is a partially-reduced double-precision element of Fp
|
||||
## The allowed range is [0, 2ⁿp)
|
||||
## with n = w*WordBitSize
|
||||
## with n = w*WordBitWidth
|
||||
## and w the number of words necessary to represent p on the machine.
|
||||
## Concretely a 381-bit p needs 6*64 bits limbs (hence 384 bits total)
|
||||
## and so FpDbl would 768 bits.
|
||||
|
|
|
@ -39,7 +39,7 @@ func invsqrt_p3mod4(r: var Fp, a: Fp) =
|
|||
# Algorithm
|
||||
#
|
||||
#
|
||||
# From Euler's criterion:
|
||||
# From Euler's criterion:
|
||||
# 𝛘(a) = a^((p-1)/2)) ≡ 1 (mod p) if square
|
||||
# a^((p-1)/2)) * a^-1 ≡ 1/a (mod p)
|
||||
# a^((p-3)/2)) ≡ 1/a (mod p)
|
||||
|
@ -49,7 +49,7 @@ func invsqrt_p3mod4(r: var Fp, a: Fp) =
|
|||
r.invsqrt_addchain(a)
|
||||
else:
|
||||
r = a
|
||||
r.powUnsafeExponent(Fp.getPrimeMinus3div4_BE())
|
||||
r.pow_vartime(Fp.getPrimeMinus3div4_BE())
|
||||
|
||||
# Specialized routine for p ≡ 5 (mod 8)
|
||||
# ------------------------------------------------------------
|
||||
|
@ -106,26 +106,26 @@ func invsqrt_p5mod8(r: var Fp, a: Fp) =
|
|||
# and α = (β/2a)⁽¹⸍²⁾= (2a)^(((p-1)/4 - 1)/2) = (2a)^((p-5)/8)
|
||||
static: doAssert Fp.C.has_P_5mod8_primeModulus()
|
||||
var alpha{.noInit.}, beta{.noInit.}: Fp
|
||||
|
||||
|
||||
# α = (2a)^((p-5)/8)
|
||||
alpha.double(a)
|
||||
beta = alpha
|
||||
when Fp.C.hasSqrtAddchain():
|
||||
alpha.invsqrt_addchain_pminus5over8(alpha)
|
||||
else:
|
||||
alpha.powUnsafeExponent(Fp.getPrimeMinus5div8_BE())
|
||||
alpha.pow_vartime(Fp.getPrimeMinus5div8_BE())
|
||||
|
||||
# Note: if r aliases a, for inverse square root we don't use `a` again
|
||||
|
||||
# β = 2aα²
|
||||
r.square(alpha)
|
||||
beta *= r
|
||||
|
||||
|
||||
# √a = αa(β − 1), so 1/√a = α(β − 1)
|
||||
r.setOne()
|
||||
beta -= r
|
||||
r.prod(alpha, beta)
|
||||
|
||||
|
||||
|
||||
# Specialized routines for addchain-based square roots
|
||||
# ------------------------------------------------------------
|
||||
|
@ -140,7 +140,7 @@ func precompute_tonelli_shanks(a_pre_exp: var Fp, a: Fp) =
|
|||
a_pre_exp.precompute_tonelli_shanks_addchain(a)
|
||||
else:
|
||||
a_pre_exp = a
|
||||
a_pre_exp.powUnsafeExponent(Fp.C.tonelliShanks(exponent))
|
||||
a_pre_exp.pow_vartime(Fp.C.tonelliShanks(exponent))
|
||||
|
||||
func invsqrt_tonelli_shanks_pre(
|
||||
invsqrt: var Fp,
|
||||
|
@ -299,9 +299,9 @@ func isSquare*(a: Fp): SecretBool =
|
|||
func sqrt_ratio_if_square*(r: var Fp, u, v: Fp): SecretBool {.inline.} =
|
||||
## If u/v is a square, compute √(u/v)
|
||||
## if not, the result is undefined
|
||||
##
|
||||
##
|
||||
## r must not alias u or v
|
||||
##
|
||||
##
|
||||
## The square root, if it exist is multivalued,
|
||||
## i.e. both (u/v)² == (-u/v)²
|
||||
## This procedure returns a deterministic result
|
||||
|
|
|
@ -160,14 +160,6 @@ func isOne*(a: Limbs): SecretBool =
|
|||
## Returns true if ``a`` is equal to one
|
||||
a.eq(One)
|
||||
|
||||
func isOdd*(a: Limbs): SecretBool =
|
||||
## Returns true if a is odd
|
||||
SecretBool(a[0] and One)
|
||||
|
||||
func isEven*(a: Limbs): SecretBool =
|
||||
## Returns true if a is even
|
||||
not SecretBool(a[0] and One)
|
||||
|
||||
# Bit manipulation
|
||||
# ------------------------------------------------------------
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ import
|
|||
#
|
||||
# ############################################################
|
||||
|
||||
func invModBitwidth(a: BaseType): BaseType =
|
||||
func invModBitwidth*(a: BaseType): BaseType =
|
||||
# Modular inverse algorithm:
|
||||
# Explanation p11 "Dumas iterations" based on Newton-Raphson:
|
||||
# - Cetin Kaya Koc (2017), https://eprint.iacr.org/2017/411
|
||||
|
@ -67,7 +67,7 @@ func invModBitwidth(a: BaseType): BaseType =
|
|||
for _ in 0 ..< k: # at each iteration we get the inverse mod(2^2k)
|
||||
result *= 2 - a * result # x' = x(2 - ax)
|
||||
|
||||
func invMod2powK(M0: BaseType, k: static BaseType): BaseType =
|
||||
func invMod2k(M0: BaseType, k: static BaseType): BaseType =
|
||||
## Compute 1/M mod 2ᵏ
|
||||
## from M[0]
|
||||
# Algorithm: Cetin Kaya Koc (2017) p11, https://eprint.iacr.org/2017/411
|
||||
|
@ -278,7 +278,7 @@ func matVecMul_shr_k_mod_M[N, E: static int](
|
|||
d, e: var LimbsUnsaturated[N, E],
|
||||
k: static int,
|
||||
M: LimbsUnsaturated[N, E],
|
||||
invMod2powK: SecretWord
|
||||
invMod2k: SecretWord
|
||||
) =
|
||||
## Compute
|
||||
##
|
||||
|
@ -318,8 +318,8 @@ func matVecMul_shr_k_mod_M[N, E: static int](
|
|||
me.cadd(q, sign_d)
|
||||
me.cadd(r, sign_e)
|
||||
|
||||
md = md - (SignedSecretWord(invMod2powK * SecretWord(cd.lo) + SecretWord(md)) and Max)
|
||||
me = me - (SignedSecretWord(invMod2powK * SecretWord(ce.lo) + SecretWord(me)) and Max)
|
||||
md = md - (SignedSecretWord(invMod2k * SecretWord(cd.lo) + SecretWord(md)) and Max)
|
||||
me = me - (SignedSecretWord(invMod2k * SecretWord(ce.lo) + SecretWord(me)) and Max)
|
||||
|
||||
# First iteration of [u v] [d] [md]
|
||||
# [q r].[e] + [me].M[0]
|
||||
|
@ -399,7 +399,7 @@ func matVecMul_shr_k[N, E: static int](t: TransitionMatrix, f, g: var LimbsUnsat
|
|||
func invmodImpl[N, E](
|
||||
a: var LimbsUnsaturated[N, E],
|
||||
F, M: LimbsUnsaturated[N, E],
|
||||
invMod2powK: SecretWord,
|
||||
invMod2k: SecretWord,
|
||||
k, bits: static int) =
|
||||
## Modular inversion using Bernstein-Yang algorithm
|
||||
## r ≡ F.a⁻¹ (mod M)
|
||||
|
@ -425,7 +425,7 @@ func invmodImpl[N, E](
|
|||
# Apply the transition matrix
|
||||
# [u v] [d]
|
||||
# [q r]/2ᵏ.[e] mod M
|
||||
t.matVecMul_shr_k_mod_M(d, e, k, M, invMod2powK)
|
||||
t.matVecMul_shr_k_mod_M(d, e, k, M, invMod2k)
|
||||
# [u v] [f]
|
||||
# [q r]/2ᵏ.[g]
|
||||
t.matVecMul_shr_k(f, g, k)
|
||||
|
@ -450,7 +450,7 @@ func invmod*(
|
|||
var factor {.noInit.}: LimbsUnsaturated[NumUnsatWords, Excess]
|
||||
m2.fromPackedRepr(M)
|
||||
factor.fromPackedRepr(F)
|
||||
let m0invK = SecretWord invMod2powK(BaseType M[0], k)
|
||||
let m0invK = SecretWord invMod2k(BaseType M[0], k)
|
||||
|
||||
var a2 {.noInit.}: LimbsUnsaturated[NumUnsatWords, Excess]
|
||||
a2.fromPackedRepr(a)
|
||||
|
@ -475,7 +475,7 @@ func invmod*(
|
|||
# Convert values to unsaturated repr
|
||||
const m2 = LimbsUnsaturated[NumUnsatWords, Excess].fromPackedRepr(M)
|
||||
const factor = LimbsUnsaturated[NumUnsatWords, Excess].fromPackedRepr(F)
|
||||
const m0invK = SecretWord invMod2powK(BaseType M[0], k)
|
||||
const m0invK = SecretWord invMod2k(BaseType M[0], k)
|
||||
|
||||
var a2 {.noInit.}: LimbsUnsaturated[NumUnsatWords, Excess]
|
||||
a2.fromPackedRepr(a)
|
||||
|
@ -805,7 +805,7 @@ func discardUnusedLimb_vartime[N, E: static int](limbsLeft: var int, f, g: var L
|
|||
func invmodImpl_vartime[N, E: static int](
|
||||
a: var LimbsUnsaturated[N, E],
|
||||
F, M: LimbsUnsaturated[N, E],
|
||||
invMod2powK: SecretWord,
|
||||
invMod2k: SecretWord,
|
||||
k, bits: static int) {.tags:[VarTime].} =
|
||||
## **Variable-time** Modular inversion using Bernstein-Yang algorithm
|
||||
## r ≡ F.a⁻¹ (mod M)
|
||||
|
@ -830,7 +830,7 @@ func invmodImpl_vartime[N, E: static int](
|
|||
# Apply the transition matrix
|
||||
# [u v] [d]
|
||||
# [q r]/2ᵏ.[e] mod M
|
||||
t.matVecMul_shr_k_mod_M(d, e, k, M, invMod2powK)
|
||||
t.matVecMul_shr_k_mod_M(d, e, k, M, invMod2k)
|
||||
# [u v] [f]
|
||||
# [q r]/2ᵏ.[g]
|
||||
t.matVecMul_shr_k_partial(f, g, limbsLeft, k)
|
||||
|
@ -858,7 +858,7 @@ func invmod_vartime*(
|
|||
var factor {.noInit.}: LimbsUnsaturated[NumUnsatWords, Excess]
|
||||
m2.fromPackedRepr(M)
|
||||
factor.fromPackedRepr(F)
|
||||
let m0invK = SecretWord invMod2powK(BaseType M[0], k)
|
||||
let m0invK = SecretWord invMod2k(BaseType M[0], k)
|
||||
|
||||
var a2 {.noInit.}: LimbsUnsaturated[NumUnsatWords, Excess]
|
||||
a2.fromPackedRepr(a)
|
||||
|
@ -883,7 +883,7 @@ func invmod_vartime*(
|
|||
# Convert values to unsaturated repr
|
||||
const m2 = LimbsUnsaturated[NumUnsatWords, Excess].fromPackedRepr(M)
|
||||
const factor = LimbsUnsaturated[NumUnsatWords, Excess].fromPackedRepr(F)
|
||||
const m0invK = SecretWord invMod2powK(BaseType M[0], k)
|
||||
const m0invK = SecretWord invMod2k(BaseType M[0], k)
|
||||
|
||||
var a2 {.noInit.}: LimbsUnsaturated[NumUnsatWords, Excess]
|
||||
a2.fromPackedRepr(a)
|
||||
|
|
|
@ -36,6 +36,7 @@ when UseASM_X86_64:
|
|||
|
||||
func prod_comba[rLen, aLen, bLen: static int](r: var Limbs[rLen], a: Limbs[aLen], b: Limbs[bLen]) =
|
||||
## Extended precision multiplication
|
||||
## `r` must not alias ``a`` or ``b``
|
||||
# We use Product Scanning / Comba multiplication
|
||||
var t, u, v = Zero
|
||||
const stopEx = min(a.len+b.len, r.len)
|
||||
|
@ -59,7 +60,7 @@ func prod_comba[rLen, aLen, bLen: static int](r: var Limbs[rLen], a: Limbs[aLen]
|
|||
for i in aLen+bLen ..< rLen:
|
||||
r[i] = Zero
|
||||
|
||||
func prod*[rLen, aLen, bLen: static int](r: var Limbs[rLen], a: Limbs[aLen], b: Limbs[bLen]) {.inline.} =
|
||||
func prod*[rLen, aLen, bLen: static int](r{.noalias.}: var Limbs[rLen], a: Limbs[aLen], b: Limbs[bLen]) {.inline.} =
|
||||
## Multi-precision multiplication
|
||||
## r <- a*b
|
||||
##
|
||||
|
|
|
@ -46,7 +46,7 @@ when UseASM_X86_64:
|
|||
# to save on code size.
|
||||
|
||||
# No exceptions allowed
|
||||
{.push raises: [].}
|
||||
{.push raises: [], checks: off.}
|
||||
|
||||
# Montgomery Reduction
|
||||
# ------------------------------------------------------------
|
||||
|
@ -570,7 +570,7 @@ func fromMont*(r: var Limbs, a, M: Limbs,
|
|||
## with W = M.len
|
||||
## and R = (2^WordBitWidth)^W
|
||||
##
|
||||
## Does "a * R^-1 (mod M)"
|
||||
## Does "a * R^-1 (mod M)" = montMul(a, 1)
|
||||
##
|
||||
## This is called a Montgomery Reduction
|
||||
## The Montgomery Magic Constant is µ = -1/N mod M
|
||||
|
@ -730,9 +730,8 @@ func powMont*(
|
|||
M, one: Limbs,
|
||||
m0ninv: BaseType,
|
||||
scratchspace: var openarray[Limbs],
|
||||
spareBits: static int
|
||||
) =
|
||||
## Modular exponentiation r = a^exponent mod M
|
||||
spareBits: static int) =
|
||||
## Modular exponentiation a <- a^exponent (mod M)
|
||||
## in the Montgomery domain
|
||||
##
|
||||
## This uses fixed-window optimization if possible
|
||||
|
@ -773,8 +772,7 @@ func powMont*(
|
|||
a, exponent, M, m0ninv,
|
||||
scratchspace[0], window,
|
||||
acc, acc_len, e,
|
||||
spareBits
|
||||
)
|
||||
spareBits)
|
||||
|
||||
# Window lookup: we set scratchspace[1] to the lookup value.
|
||||
# If the window length is 1, then it's already set.
|
||||
|
@ -791,7 +789,7 @@ func powMont*(
|
|||
scratchspace[0].mulMont(a, scratchspace[1], M, m0ninv, spareBits)
|
||||
a.ccopy(scratchspace[0], SecretWord(bits).isNonZero())
|
||||
|
||||
func powMontUnsafeExponent*(
|
||||
func powMont_vartime*(
|
||||
a: var Limbs,
|
||||
exponent: openarray[byte],
|
||||
M, one: Limbs,
|
||||
|
@ -799,7 +797,7 @@ func powMontUnsafeExponent*(
|
|||
scratchspace: var openarray[Limbs],
|
||||
spareBits: static int
|
||||
) =
|
||||
## Modular exponentiation r = a^exponent mod M
|
||||
## Modular exponentiation a <- a^exponent (mod M)
|
||||
## in the Montgomery domain
|
||||
##
|
||||
## Warning ⚠️ :
|
||||
|
@ -821,8 +819,7 @@ func powMontUnsafeExponent*(
|
|||
a, exponent, M, m0ninv,
|
||||
scratchspace[0], window,
|
||||
acc, acc_len, e,
|
||||
spareBits
|
||||
)
|
||||
spareBits)
|
||||
|
||||
## Warning ⚠️: Exposes the exponent bits
|
||||
if bits != 0:
|
||||
|
|
|
@ -238,6 +238,8 @@ func checkValidModulus(M: BigInt) =
|
|||
const expectedMsb = M.bits-1 - WordBitWidth * (M.limbs.len - 1)
|
||||
let msb = log2_vartime(BaseType(M.limbs[M.limbs.len-1]))
|
||||
|
||||
# This is important for the constant-time explicit modulo operation
|
||||
# "reduce" and bigint division.
|
||||
doAssert msb == expectedMsb, "Internal Error: the modulus must use all declared bits and only those:\n" &
|
||||
" Modulus '" & M.toHex() & "' is declared with " & $M.bits &
|
||||
" bits but uses " & $(msb + WordBitWidth * (M.limbs.len - 1)) & " bits."
|
||||
|
@ -287,6 +289,12 @@ func invModBitwidth*[T: SomeUnsignedInt](a: T): T =
|
|||
for _ in 0 ..< k: # at each iteration we get the inverse mod(2^2k)
|
||||
result *= 2 - a * result # x' = x(2 - ax)
|
||||
|
||||
func negInvModWord*[T: SomeUnsignedInt or SecretWord](a: T): T =
|
||||
let t = invModBitwidth(BaseType a)
|
||||
{.push hint[ConvFromXtoItselfNotNeeded]: off.}
|
||||
return T(-SecretWord(t))
|
||||
{.pop.}
|
||||
|
||||
func negInvModWord*(M: BigInt): BaseType =
|
||||
## Returns the Montgomery domain magic constant for the input modulus:
|
||||
##
|
||||
|
@ -299,10 +307,7 @@ func negInvModWord*(M: BigInt): BaseType =
|
|||
##
|
||||
## µ ≡ -1/M[0] (mod 2^64)
|
||||
checkValidModulus(M)
|
||||
|
||||
result = invModBitwidth(BaseType M.limbs[0])
|
||||
# negate to obtain the negative inverse
|
||||
result = not(result) + 1
|
||||
return BaseType M.limbs[0].negInvModWord()
|
||||
|
||||
func r_powmod(n: static int, M: BigInt): BigInt =
|
||||
## Returns the Montgomery domain magic constant for the input modulus:
|
||||
|
|
|
@ -8,11 +8,6 @@
|
|||
|
||||
import ../../platforms/abstractions
|
||||
|
||||
func wordsRequired*(bits: int): int {.compileTime.} =
|
||||
## Compute the number of limbs required
|
||||
# from the **announced** bit length
|
||||
bits.ceilDiv_vartime(WordBitWidth)
|
||||
|
||||
type
|
||||
BigInt*[bits: static int] = object
|
||||
## Fixed-precision big integer
|
||||
|
@ -29,24 +24,6 @@ type
|
|||
|
||||
|
||||
debug:
|
||||
func toHex*(a: SecretWord): string =
|
||||
const hexChars = "0123456789abcdef"
|
||||
const L = 2*sizeof(SecretWord)
|
||||
result = newString(2 + L)
|
||||
result[0] = '0'
|
||||
result[1] = 'x'
|
||||
var a = a
|
||||
for j in countdown(result.len-1, 0):
|
||||
result[j] = hexChars.secretLookup(a and SecretWord 0xF)
|
||||
a = a shr 4
|
||||
|
||||
func toString*(a: Limbs): string =
|
||||
result = "["
|
||||
result.add " " & toHex(a[0])
|
||||
for i in 1 ..< a.len:
|
||||
result.add ", " & toHex(a[i])
|
||||
result.add "]"
|
||||
|
||||
func `$`*(a: BigInt): string =
|
||||
result = "BigInt["
|
||||
result.add $BigInt.bits
|
||||
|
|
|
@ -19,15 +19,9 @@ import
|
|||
# Support files for testing Elliptic Curve arithmetic
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
iterator unpack(scalarByte: byte): bool =
|
||||
yield bool((scalarByte and 0b10000000) shr 7)
|
||||
yield bool((scalarByte and 0b01000000) shr 6)
|
||||
yield bool((scalarByte and 0b00100000) shr 5)
|
||||
yield bool((scalarByte and 0b00010000) shr 4)
|
||||
yield bool((scalarByte and 0b00001000) shr 3)
|
||||
yield bool((scalarByte and 0b00000100) shr 2)
|
||||
yield bool((scalarByte and 0b00000010) shr 1)
|
||||
yield bool( scalarByte and 0b00000001)
|
||||
iterator unpackBE(scalarByte: byte): bool =
|
||||
for i in countdown(7, 0):
|
||||
yield bool((scalarByte shr i) and 1)
|
||||
|
||||
func scalarMul_doubleAdd_vartime*[EC](P: var EC, scalar: BigInt) {.tags:[VarTime].} =
|
||||
## **Variable-time** Elliptic Curve Scalar Multiplication
|
||||
|
@ -46,7 +40,7 @@ func scalarMul_doubleAdd_vartime*[EC](P: var EC, scalar: BigInt) {.tags:[VarTime
|
|||
|
||||
P.setInf()
|
||||
for scalarByte in scalarCanonical:
|
||||
for bit in unpack(scalarByte):
|
||||
for bit in unpackBE(scalarByte):
|
||||
P.double()
|
||||
if bit:
|
||||
P += Paff
|
||||
|
|
|
@ -101,7 +101,7 @@ func powSquarings[F](
|
|||
|
||||
return (k, bits)
|
||||
|
||||
func powUnsafeExponent[F](
|
||||
func pow_vartime[F](
|
||||
a: var F,
|
||||
exponent: openArray[byte],
|
||||
scratchspace: var openArray[F]) =
|
||||
|
@ -136,7 +136,7 @@ func powUnsafeExponent[F](
|
|||
scratchspace[0].prod(a, scratchspace[1])
|
||||
a = scratchspace[0]
|
||||
|
||||
func powUnsafeExponent*[F](
|
||||
func pow_vartime*[F](
|
||||
a: var F,
|
||||
exponent: openArray[byte],
|
||||
window: static int
|
||||
|
@ -159,9 +159,9 @@ func powUnsafeExponent*[F](
|
|||
const scratchLen = if window == 1: 2
|
||||
else: (1 shl window) + 1
|
||||
var scratchSpace {.noInit.}: array[scratchLen, typeof(a)]
|
||||
a.powUnsafeExponent(exponent, scratchspace)
|
||||
a.pow_vartime(exponent, scratchspace)
|
||||
|
||||
func powUnsafeExponent*[F; bits: static int](
|
||||
func pow_vartime*[F; bits: static int](
|
||||
a: var F,
|
||||
exponent: BigInt[bits],
|
||||
window: static int
|
||||
|
@ -183,4 +183,4 @@ func powUnsafeExponent*[F; bits: static int](
|
|||
## - timing analysis
|
||||
var expBE {.noInit.}: array[bits.ceilDiv_vartime(8), byte]
|
||||
expBE.marshal(exponent, bigEndian)
|
||||
a.powUnsafeExponent(expBE, window)
|
||||
a.pow_vartime(expBE, window)
|
||||
|
|
|
@ -80,7 +80,7 @@ func millerLoopGenericBLS12*[C](
|
|||
func finalExpGeneric[C: static Curve](f: var Fp12[C]) =
|
||||
## A generic and slow implementation of final exponentiation
|
||||
## for sanity checks purposes.
|
||||
f.powUnsafeExponent(C.pairing(finalexponent), window = 3)
|
||||
f.pow_vartime(C.pairing(finalexponent), window = 3)
|
||||
|
||||
func pairing_bls12_reference*[C](
|
||||
gt: var Fp12[C],
|
||||
|
|
|
@ -92,7 +92,7 @@ func millerLoopGenericBN*[C](
|
|||
func finalExpGeneric[C: static Curve](f: var Fp12[C]) =
|
||||
## A generic and slow implementation of final exponentiation
|
||||
## for sanity checks purposes.
|
||||
f.powUnsafeExponent(C.pairing(finalexponent), window = 3)
|
||||
f.pow_vartime(C.pairing(finalexponent), window = 3)
|
||||
|
||||
func pairing_bn_reference*[C](
|
||||
gt: var Fp12[C],
|
||||
|
|
|
@ -63,12 +63,12 @@ func millerLoopBW6_761_naive[C](
|
|||
func finalExpGeneric[C: static Curve](f: var Fp6[C]) =
|
||||
## A generic and slow implementation of final exponentiation
|
||||
## for sanity checks purposes.
|
||||
f.powUnsafeExponent(C.pairing(finalexponent), window = 3)
|
||||
f.pow_vartime(C.pairing(finalexponent), window = 3)
|
||||
|
||||
func finalExpHard_BW6_761*[C: static Curve](f: var Fp6[C]) =
|
||||
## A generic and slow implementation of final exponentiation
|
||||
## for sanity checks purposes.
|
||||
f.powUnsafeExponent(C.pairing(finalexponent_hard), window = 3)
|
||||
f.pow_vartime(C.pairing(finalexponent_hard), window = 3)
|
||||
|
||||
# Optimized pairing implementation
|
||||
# ----------------------------------------------------------------
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
# Arbitrary-precision math backend
|
||||
|
||||
While cryptographic protocols allow Constantine to focus on named elliptic curves
|
||||
and so fixed precision arithmetic, some protocols might need arbitrary-precision.
|
||||
|
||||
For example, this can cover can cover:
|
||||
- Modular exponentiation https://eips.ethereum.org/EIPS/eip-198
|
||||
- RSA (though in practice RSA2048, RSA3072 and RSA 4096 are likely the only sizes needed)
|
||||
- primality testing
|
||||
|
||||
And arbitrary precision elliptic curves would allow implementing the Lenstra elliptic curve factorization method
|
|
@ -0,0 +1,202 @@
|
|||
# Constantine
|
||||
# Copyright (c) 2018-2019 Status Research & Development GmbH
|
||||
# Copyright (c) 2020-Present Mamy André-Ratsimbazafy
|
||||
# Licensed and distributed under either of
|
||||
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
|
||||
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
|
||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||
|
||||
import
|
||||
# Internal
|
||||
../../platforms/[abstractions, allocs],
|
||||
../../math/config/precompute,
|
||||
./limbs_views,
|
||||
./limbs_montgomery,
|
||||
./limbs_mod2k,
|
||||
./limbs_multiprec,
|
||||
./limbs_extmul,
|
||||
./limbs_division
|
||||
|
||||
# No exceptions allowed
|
||||
{.push raises: [], checks: off.}
|
||||
|
||||
# ############################################################
|
||||
#
|
||||
# Arbitrary-precision integers
|
||||
#
|
||||
# ############################################################
|
||||
#
|
||||
# We only implement algorithms that work on views allocated by the caller
|
||||
# as providing a full-blown arbitrary-precision library is not the goal.
|
||||
# As the bigint sizes are relatively constrained
|
||||
# in protocols we implement (4096 bits for RSA, 8192 bit s for the Ethereum EVM),
|
||||
# this allows us to avoid heap allocations, which simplifies reentrancy and thread-safety.
|
||||
|
||||
# TODO: choose between:
|
||||
# - openArray + countLeadingZeros
|
||||
# - bits + wordsRequired
|
||||
# for parameter passing
|
||||
# This also impacts ergonomics of allocStackArray
|
||||
#
|
||||
# Also need to take into account constant-time for RSA
|
||||
# i.e. countLeadingZeros can only be done on public moduli.
|
||||
|
||||
func powOddMod_vartime*(
|
||||
r: var openArray[SecretWord],
|
||||
a: openArray[SecretWord],
|
||||
exponent: openArray[byte],
|
||||
M: openArray[SecretWord],
|
||||
window: int) {.noInline, tags:[Alloca, VarTime].} =
|
||||
## r <- a^exponent (mod M) with M odd
|
||||
## assumes a < M
|
||||
##
|
||||
## At least (2^window + 4) * sizeof(M) stack space will be allocated.
|
||||
|
||||
debug:
|
||||
doAssert bool(M.isOdd())
|
||||
|
||||
let aBits = a.getBits_vartime()
|
||||
let mBits = M.getBits_vartime()
|
||||
let L = wordsRequired(mBits)
|
||||
let m0ninv = M[0].negInvModWord()
|
||||
var rMont = allocStackArray(SecretWord, L)
|
||||
|
||||
block:
|
||||
var r2Buf = allocStackArray(SecretWord, L)
|
||||
template r2: untyped = r2Buf.toOpenArray(0, L-1)
|
||||
r2.r2_vartime(M.toOpenArray(0, L-1))
|
||||
|
||||
# Conversion to Montgomery can auto-reduced by up to M*R
|
||||
# if we use redc2xMont (a/R) and montgomery multiplication by R³
|
||||
# For now, we call explicit reduction as it can handle all sizes.
|
||||
# TODO: explicit reduction uses constant-time division which is **very** expensive
|
||||
# TODO: fix https://github.com/mratsim/constantine/issues/241
|
||||
if a.len != M.len:
|
||||
let t = allocStackArray(SecretWord, L)
|
||||
t.LimbsViewMut.reduce(a.view(), aBits, M.view(), mBits)
|
||||
rMont.LimbsViewMut.getMont(LimbsViewConst t, M.view(), LimbsViewConst r2.view(), m0ninv, mBits)
|
||||
else:
|
||||
rMont.LimbsViewMut.getMont(a.view(), M.view(), LimbsViewConst r2.view(), m0ninv, mBits)
|
||||
|
||||
block:
|
||||
var oneMontBuf = allocStackArray(SecretWord, L)
|
||||
template oneMont: untyped = oneMontBuf.toOpenArray(0, L-1)
|
||||
oneMont.oneMont_vartime(M.toOpenArray(0, L-1))
|
||||
|
||||
let scratchLen = L * ((1 shl window) + 1)
|
||||
var scratchSpace = allocStackArray(SecretWord, scratchLen)
|
||||
|
||||
rMont.LimbsViewMut.powMont_vartime(
|
||||
exponent, M.view(), LimbsViewConst oneMontBuf,
|
||||
m0ninv, LimbsViewMut scratchSpace, scratchLen, mBits)
|
||||
|
||||
r.view().fromMont(LimbsViewConst rMont, M.view(), m0ninv, mBits)
|
||||
|
||||
|
||||
func powMod_vartime*(
|
||||
r: var openArray[SecretWord],
|
||||
a: openArray[SecretWord],
|
||||
exponent: openArray[byte],
|
||||
M: openArray[SecretWord],
|
||||
window: int) {.noInline, tags:[Alloca, VarTime].} =
|
||||
## r <- a^exponent (mod M) with M odd
|
||||
## assumes a < exponent
|
||||
##
|
||||
## At least (2^window + 4) * sizeof(M) stack space will be allocated.
|
||||
|
||||
# Special cases: early returns
|
||||
# -------------------------------------------------------------------
|
||||
let mBits = M.getBits_vartime()
|
||||
if mBits < 2: # Check if modulus = 0 or 1
|
||||
r.setZero()
|
||||
return
|
||||
|
||||
let eBits = exponent.getBits_vartime()
|
||||
if eBits == 0: # Check if exponent == 0
|
||||
r.setOne() # a⁰ = 1 and 0⁰ = 1
|
||||
return
|
||||
|
||||
let aBits = a.getBits_vartime()
|
||||
if aBits < 2: # Check if a == 0 or a == 1
|
||||
r[0] = a[0]
|
||||
for i in 1 ..< r.len:
|
||||
r[i] = Zero
|
||||
return
|
||||
|
||||
# Odd modulus
|
||||
# -------------------------------------------------------------------
|
||||
if M.isOdd().bool:
|
||||
r.powOddMod_vartime(a, exponent, M, window)
|
||||
return
|
||||
|
||||
# Even modulus
|
||||
# -------------------------------------------------------------------
|
||||
|
||||
var i = 0
|
||||
|
||||
# Find the first non-zero word from right-to-left. (a != 0)
|
||||
while i < M.len-1:
|
||||
if bool(M[i] != Zero):
|
||||
break
|
||||
i += 1
|
||||
|
||||
let ctz = int(countTrailingZeroBits_vartime(BaseType M[i])) +
|
||||
WordBitWidth*i
|
||||
|
||||
# Even modulus: power of two (mod 2ᵏ)
|
||||
# -------------------------------------------------------------------
|
||||
|
||||
if mBits-ctz == 1: # The modulus is a power of 2
|
||||
r.powMod2k_vartime(a, exponent, k = uint mBits)
|
||||
return
|
||||
|
||||
# Even modulus: general case
|
||||
# -------------------------------------------------------------------
|
||||
#
|
||||
# We split exponentiation aᵉ (mod M)
|
||||
# into a₁ = aᵉ (mod q)
|
||||
# and a₂ = aᵉ (mod 2ᵏ)
|
||||
# with M = q.2ᵏ
|
||||
# and we recombine the results using the Chinese Remainder Theorem.
|
||||
# following
|
||||
# Montgomery reduction with even modulus
|
||||
# Çetin Kaya Koç, 1994
|
||||
# https://cetinkayakoc.net/docs/j34.pdf
|
||||
|
||||
let qBits = mBits-ctz
|
||||
let pBits = 1+ctz
|
||||
# let qWords = qBits.wordsRequired() # TODO: use minimum size for q
|
||||
let pWords = pBits.wordsRequired()
|
||||
|
||||
var qBuf = allocStackArray(SecretWord, M.len)
|
||||
var a1Buf = allocStackArray(SecretWord, M.len)
|
||||
var a2Buf = allocStackArray(SecretWord, pWords)
|
||||
var yBuf = allocStackArray(SecretWord, pWords)
|
||||
var qInv2kBuf = allocStackArray(SecretWord, pWords)
|
||||
|
||||
template q: untyped = qBuf.toOpenArray(0, M.len-1)
|
||||
template a1: untyped = a1Buf.toOpenArray(0, M.len-1)
|
||||
template a2: untyped = a2Buf.toOpenArray(0, pWords-1)
|
||||
template y: untyped = yBuf.toOpenArray(0, pWords-1)
|
||||
template qInv2k: untyped = qInv2kBuf.toOpenArray(0, pWords-1)
|
||||
|
||||
q.shiftRight_vartime(M, ctz)
|
||||
|
||||
a1.powOddMod_vartime(a, exponent, q, window)
|
||||
a2.powMod2k_vartime(a, exponent, k = uint ctz)
|
||||
|
||||
block:
|
||||
let min = min(pWords, M.len)
|
||||
for i in 0 ..< min:
|
||||
qInv2k[i] = q[i]
|
||||
for i in min ..< pWords:
|
||||
qInv2k[i] = Zero
|
||||
|
||||
qInv2k.invMod2k_vartime(uint ctz)
|
||||
y.submod2k_vartime(a2, a1, uint ctz)
|
||||
y.mulmod2k_vartime(y, qInv2k, uint ctz)
|
||||
|
||||
var qyBuf = allocStackArray(SecretWord, M.len)
|
||||
template qy: untyped = qyBuf.toOpenArray(0, M.len-1)
|
||||
qy.prod(q, y)
|
||||
discard r.addMP(qy, a1)
|
|
@ -6,7 +6,10 @@
|
|||
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
|
||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||
|
||||
import ../../platforms/abstractions
|
||||
import
|
||||
../../platforms/abstractions,
|
||||
./limbs_views,
|
||||
./limbs_fixedprec
|
||||
|
||||
# No exceptions allowed
|
||||
{.push raises: [].}
|
||||
|
@ -22,107 +25,6 @@ import ../../platforms/abstractions
|
|||
# we use type-erased procedures, instead of instantiating
|
||||
# one per number of limbs combination
|
||||
|
||||
# Type-erasure
|
||||
# ------------------------------------------------------------
|
||||
|
||||
type
|
||||
LimbsView = ptr UncheckedArray[SecretWord]
|
||||
## Type-erased fixed-precision limbs
|
||||
##
|
||||
## This type mirrors the Limb type and is used
|
||||
## for some low-level computation API
|
||||
## This design
|
||||
## - avoids code bloat due to generic monomorphization
|
||||
## otherwise limbs routines would have an instantiation for
|
||||
## each number of words.
|
||||
##
|
||||
## Accesses should be done via BigIntViewConst / BigIntViewConst
|
||||
## to have the compiler check for mutability
|
||||
|
||||
# "Indirection" to enforce pointer types deep immutability
|
||||
LimbsViewConst = distinct LimbsView
|
||||
## Immutable view into the limbs of a BigInt
|
||||
LimbsViewMut = distinct LimbsView
|
||||
## Mutable view into a BigInt
|
||||
LimbsViewAny = LimbsViewConst or LimbsViewMut
|
||||
|
||||
# Deep Mutability safety
|
||||
# ------------------------------------------------------------
|
||||
|
||||
template view(a: Limbs): LimbsViewConst =
|
||||
## Returns a borrowed type-erased immutable view to a bigint
|
||||
LimbsViewConst(cast[LimbsView](a.unsafeAddr))
|
||||
|
||||
template view(a: var Limbs): LimbsViewMut =
|
||||
## Returns a borrowed type-erased mutable view to a mutable bigint
|
||||
LimbsViewMut(cast[LimbsView](a.addr))
|
||||
|
||||
template `[]`*(v: LimbsViewConst, limbIdx: int): SecretWord =
|
||||
LimbsView(v)[limbIdx]
|
||||
|
||||
template `[]`*(v: LimbsViewMut, limbIdx: int): var SecretWord =
|
||||
LimbsView(v)[limbIdx]
|
||||
|
||||
template `[]=`*(v: LimbsViewMut, limbIdx: int, val: SecretWord) =
|
||||
LimbsView(v)[limbIdx] = val
|
||||
|
||||
# Copy
|
||||
# ------------------------------------------------------------
|
||||
|
||||
func copyWords(
|
||||
a: LimbsViewMut, startA: int,
|
||||
b: LimbsViewAny, startB: int,
|
||||
numWords: int
|
||||
) =
|
||||
## Copy a slice of B into A. This properly deals
|
||||
## with overlaps when A and B are slices of the same buffer
|
||||
if startA > startB:
|
||||
for i in countdown(numWords-1, 0):
|
||||
a[startA+i] = b[startB+i]
|
||||
else:
|
||||
for i in 0 ..< numWords:
|
||||
a[startA+i] = b[startB+i]
|
||||
|
||||
# Type-erased add-sub
|
||||
# ------------------------------------------------------------
|
||||
|
||||
func cadd(a: LimbsViewMut, b: LimbsViewAny, ctl: SecretBool, len: int): Carry =
|
||||
## Type-erased conditional addition
|
||||
## Returns the carry
|
||||
##
|
||||
## if ctl is true: a <- a + b
|
||||
## if ctl is false: a <- a
|
||||
## The carry is always computed whether ctl is true or false
|
||||
##
|
||||
## Time and memory accesses are the same whether a copy occurs or not
|
||||
result = Carry(0)
|
||||
var sum: SecretWord
|
||||
for i in 0 ..< len:
|
||||
addC(result, sum, a[i], b[i], result)
|
||||
ctl.ccopy(a[i], sum)
|
||||
|
||||
func csub(a: LimbsViewMut, b: LimbsViewAny, ctl: SecretBool, len: int): Borrow =
|
||||
## Type-erased conditional addition
|
||||
## Returns the borrow
|
||||
##
|
||||
## if ctl is true: a <- a - b
|
||||
## if ctl is false: a <- a
|
||||
## The borrow is always computed whether ctl is true or false
|
||||
##
|
||||
## Time and memory accesses are the same whether a copy occurs or not
|
||||
result = Borrow(0)
|
||||
var diff: SecretWord
|
||||
for i in 0 ..< len:
|
||||
subB(result, diff, a[i], b[i], result)
|
||||
ctl.ccopy(a[i], diff)
|
||||
|
||||
# Modular reduction
|
||||
# ------------------------------------------------------------
|
||||
|
||||
func numWordsFromBits(bits: int): int {.inline.} =
|
||||
const divShiftor = log2_vartime(uint32(WordBitWidth))
|
||||
result = (bits + WordBitWidth - 1) shr divShiftor
|
||||
|
||||
func shlAddMod_estimate(a: LimbsViewMut, aLen: int,
|
||||
c: SecretWord, M: LimbsViewConst, mBits: int
|
||||
): tuple[neg, tooBig: SecretBool] =
|
||||
|
@ -136,7 +38,7 @@ func shlAddMod_estimate(a: LimbsViewMut, aLen: int,
|
|||
|
||||
# Aliases
|
||||
# ----------------------------------------------------------------------
|
||||
let MLen = numWordsFromBits(mBits)
|
||||
let MLen = wordsRequired(mBits)
|
||||
|
||||
# Captures aLen and MLen
|
||||
template `[]`(v: untyped, limbIdxFromEnd: BackwardsIndex): SecretWord {.dirty.}=
|
||||
|
@ -190,10 +92,7 @@ func shlAddMod_estimate(a: LimbsViewMut, aLen: int,
|
|||
subB(borrow, a[i], a[i], qp_lo, Borrow(0))
|
||||
carry += SecretWord(borrow) # Adjust if borrow
|
||||
|
||||
over_p = mux(
|
||||
a[i] == M[i], over_p,
|
||||
a[i] > M[i]
|
||||
)
|
||||
over_p = mux(a[i] == M[i], over_p, a[i] > M[i])
|
||||
|
||||
# Fix quotient, the true quotient is either q-1, q or q+1
|
||||
#
|
||||
|
@ -221,14 +120,19 @@ func shlAddMod(a: LimbsViewMut, aLen: int,
|
|||
let R = mBits and (WordBitWidth - 1)
|
||||
|
||||
# (hi, lo) = a * 2^64 + c
|
||||
let hi = (a[0] shl (WordBitWidth-R)) or (c shr R)
|
||||
let lo = c shl (WordBitWidth-R)
|
||||
let m0 = M[0] shl (WordBitWidth-R)
|
||||
if R == 0:
|
||||
var q, r: SecretWord
|
||||
div2n1n(q, r, a[0], c, M[0]) # (hi, lo) mod M
|
||||
a[0] = r
|
||||
else:
|
||||
let hi = (a[0] shl (WordBitWidth-R)) or (c shr R)
|
||||
let lo = c shl (WordBitWidth-R)
|
||||
let m0 = M[0] shl (WordBitWidth-R)
|
||||
|
||||
var q, r: SecretWord
|
||||
div2n1n(q, r, hi, lo, m0) # (hi, lo) mod M
|
||||
var q, r: SecretWord
|
||||
div2n1n(q, r, hi, lo, m0) # (hi, lo) mod M
|
||||
|
||||
a[0] = r shr (WordBitWidth-R)
|
||||
a[0] = r shr (WordBitWidth-R)
|
||||
|
||||
else:
|
||||
## Multiple limbs
|
||||
|
@ -236,12 +140,14 @@ func shlAddMod(a: LimbsViewMut, aLen: int,
|
|||
discard a.cadd(M, ctl = neg, aLen)
|
||||
discard a.csub(M, ctl = tooBig, aLen)
|
||||
|
||||
func reduce(r: LimbsViewMut,
|
||||
func reduce*(r: LimbsViewMut,
|
||||
a: LimbsViewAny, aBits: int,
|
||||
M: LimbsViewConst, mBits: int) =
|
||||
## Reduce `a` modulo `M` and store the result in `r`
|
||||
let aLen = numWordsFromBits(aBits)
|
||||
let mLen = numWordsFromBits(mBits)
|
||||
##
|
||||
## The modulus `M` most-significant bit at `mBits` MUST be set.
|
||||
let aLen = wordsRequired(aBits)
|
||||
let mLen = wordsRequired(mBits)
|
||||
let rLen = mLen
|
||||
|
||||
if aBits < mBits:
|
||||
|
@ -269,6 +175,8 @@ func reduce*[aLen, mLen](r: var Limbs[mLen],
|
|||
## Reduce `a` modulo `M` and store the result in `r`
|
||||
##
|
||||
## This uses constant-time division
|
||||
##
|
||||
## The modulus `M` most-significant bit at `mBits` MUST be set.
|
||||
# This is implemented via type-erased indirection to avoid
|
||||
# a significant amount of code duplication if instantiated for
|
||||
# varying bitwidth.
|
|
@ -0,0 +1,44 @@
|
|||
# Constantine
|
||||
# Copyright (c) 2018-2019 Status Research & Development GmbH
|
||||
# Copyright (c) 2020-Present Mamy André-Ratsimbazafy
|
||||
# Licensed and distributed under either of
|
||||
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
|
||||
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
|
||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||
|
||||
import
|
||||
# Internal
|
||||
../../platforms/[abstractions, allocs]
|
||||
|
||||
func prod_comba(r: var openArray[SecretWord], a, b: openArray[SecretWord]) {.noInline, tags: [Alloca].} =
|
||||
## Extended precision multiplication
|
||||
# We use Product Scanning / Comba multiplication
|
||||
var t, u, v = Zero
|
||||
let stopEx = min(a.len+b.len, r.len)
|
||||
|
||||
let tmp = allocStackArray(SecretWord, stopEx)
|
||||
|
||||
for i in 0 ..< stopEx:
|
||||
# Invariant for product scanning:
|
||||
# if we multiply accumulate by a[k1] * b[k2]
|
||||
# we have k1+k2 == i
|
||||
let ib = min(b.len-1, i)
|
||||
let ia = i - ib
|
||||
for j in 0 ..< min(a.len - ia, ib+1):
|
||||
mulAcc(t, u, v, a[ia+j], b[ib-j])
|
||||
|
||||
tmp[i] = v
|
||||
if i < stopEx-1:
|
||||
v = u
|
||||
u = t
|
||||
t = Zero
|
||||
|
||||
for i in 0 ..< stopEx:
|
||||
r[i] = tmp[i]
|
||||
|
||||
for i in stopEx ..< r.len:
|
||||
r[i] = Zero
|
||||
|
||||
func prod*(r: var openArray[SecretWord], a, b: openArray[SecretWord]) {.inline.}=
|
||||
## Extended precision multiplication
|
||||
r.prod_comba(a, b)
|
|
@ -0,0 +1,74 @@
|
|||
# Constantine
|
||||
# Copyright (c) 2018-2019 Status Research & Development GmbH
|
||||
# Copyright (c) 2020-Present Mamy André-Ratsimbazafy
|
||||
# Licensed and distributed under either of
|
||||
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
|
||||
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
|
||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||
|
||||
import
|
||||
../../platforms/abstractions,
|
||||
./limbs_views
|
||||
|
||||
# No exceptions allowed
|
||||
{.push raises: [].}
|
||||
|
||||
# ############################################################
|
||||
#
|
||||
# Fixed-precision type-erased arithmetic
|
||||
#
|
||||
# ############################################################
|
||||
#
|
||||
# This file implements non-performance critical type-erased
|
||||
# fixed-precision primitives, i.e. it assumes that
|
||||
# inputs use the same number of limbs.
|
||||
#
|
||||
# The goal is to avoid code-size explosion for procedures
|
||||
# that are not in a hot path and don't benefits from staticFor loops
|
||||
# like division or modular reduction.
|
||||
|
||||
# Comparison
|
||||
# ------------------------------------------------------------
|
||||
|
||||
func lt*(a, b: distinct LimbsViewAny, len: int): SecretBool =
|
||||
## Returns true if a < b
|
||||
## Comparison is constant-time
|
||||
var diff: SecretWord
|
||||
var borrow: Borrow
|
||||
for i in 0 ..< len:
|
||||
subB(borrow, diff, a[i], b[i], borrow)
|
||||
|
||||
result = (SecretBool)(borrow)
|
||||
|
||||
# Type-erased add-sub
|
||||
# ------------------------------------------------------------
|
||||
|
||||
func cadd*(a: LimbsViewMut, b: LimbsViewAny, ctl: SecretBool, len: int): Carry =
|
||||
## Type-erased conditional addition
|
||||
## Returns the carry
|
||||
##
|
||||
## if ctl is true: a <- a + b
|
||||
## if ctl is false: a <- a
|
||||
## The carry is always computed whether ctl is true or false
|
||||
##
|
||||
## Time and memory accesses are the same whether a copy occurs or not
|
||||
result = Carry(0)
|
||||
var sum: SecretWord
|
||||
for i in 0 ..< len:
|
||||
addC(result, sum, a[i], b[i], result)
|
||||
ctl.ccopy(a[i], sum)
|
||||
|
||||
func csub*(a: LimbsViewMut, b: LimbsViewAny, ctl: SecretBool, len: int): Borrow =
|
||||
## Type-erased conditional addition
|
||||
## Returns the borrow
|
||||
##
|
||||
## if ctl is true: a <- a - b
|
||||
## if ctl is false: a <- a
|
||||
## The borrow is always computed whether ctl is true or false
|
||||
##
|
||||
## Time and memory accesses are the same whether a copy occurs or not
|
||||
result = Borrow(0)
|
||||
var diff: SecretWord
|
||||
for i in 0 ..< len:
|
||||
subB(result, diff, a[i], b[i], result)
|
||||
ctl.ccopy(a[i], diff)
|
|
@ -0,0 +1,48 @@
|
|||
# Constantine
|
||||
# Copyright (c) 2018-2019 Status Research & Development GmbH
|
||||
# Copyright (c) 2020-Present Mamy André-Ratsimbazafy
|
||||
# Licensed and distributed under either of
|
||||
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
|
||||
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
|
||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||
|
||||
import
|
||||
# Internal
|
||||
../../platforms/abstractions,
|
||||
./limbs_multiprec
|
||||
|
||||
# ############################################################
|
||||
#
|
||||
# Multi-precision modular arithmetic
|
||||
#
|
||||
# ############################################################
|
||||
|
||||
func addmod_vartime*(r: var openArray[SecretWord], a, b, M: openArray[SecretWord]) =
|
||||
## r <- a+b (mod M)
|
||||
## assumes a and b are in the range [0, M)
|
||||
|
||||
debug:
|
||||
doAssert r.len == M.len
|
||||
|
||||
var tBuf = allocStackArray(SecretWord, r.len)
|
||||
template t: untyped = tBuf.toOpenArray(0, r.len-1)
|
||||
|
||||
let overflow = t.addMP(a, b)
|
||||
|
||||
if overflow:
|
||||
# t <- a+b overflowed so it is greater than M.
|
||||
discard r.subMP(t, M)
|
||||
return
|
||||
|
||||
# Operation didn't overflow in an extra limb but r can still be greater than M
|
||||
let underflow = r.subMP(t, M)
|
||||
# r <- t-M
|
||||
# If there is an underflow t < M, t has the correct result
|
||||
# if there isn't an underflow, t >= M, r has the correct result
|
||||
if underflow:
|
||||
for i in 0 ..< r.len:
|
||||
r[i] = t[i]
|
||||
|
||||
func doublemod_vartime*(r: var openArray[SecretWord], a, M: openArray[SecretWord]) {.inline.} =
|
||||
## r <- 2a (mod M)
|
||||
r.addmod_vartime(a, a, M)
|
|
@ -0,0 +1,194 @@
|
|||
# Constantine
|
||||
# Copyright (c) 2018-2019 Status Research & Development GmbH
|
||||
# Copyright (c) 2020-Present Mamy André-Ratsimbazafy
|
||||
# Licensed and distributed under either of
|
||||
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
|
||||
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
|
||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||
|
||||
import
|
||||
# Internal
|
||||
../../platforms/abstractions,
|
||||
../../math/arithmetic/limbs_exgcd,
|
||||
./limbs_views,
|
||||
./limbs_extmul,
|
||||
./limbs_multiprec
|
||||
|
||||
# No exceptions allowed
|
||||
{.push raises: [], checks: off.}
|
||||
|
||||
func mod2k_vartime*(a: var openArray[SecretWord], k: uint) =
|
||||
## a <- a (mod 2ᵏ)
|
||||
const SlotShift = log2_vartime(WordBitWidth.uint32)
|
||||
const SelectMask = WordBitWidth - 1
|
||||
|
||||
let hiIndex = k.int shr SlotShift
|
||||
|
||||
if a.len <= hiIndex:
|
||||
return
|
||||
|
||||
let bitPos = k and SelectMask
|
||||
|
||||
if bitPos != 0:
|
||||
let mask = (One shl bitPos) - One
|
||||
a[hiIndex] = a[hiIndex] and mask
|
||||
else:
|
||||
a[hiIndex] = Zero
|
||||
|
||||
for i in hiIndex+1 ..< a.len:
|
||||
a[i] = Zero
|
||||
|
||||
func submod2k_vartime*(r{.noAlias.}: var openArray[SecretWord], a, b: openArray[SecretWord], k: uint) =
|
||||
## r <- a - b (mod 2ᵏ)
|
||||
debug:
|
||||
const SlotShift = log2_vartime(WordBitWidth.uint32)
|
||||
doAssert r.len >= k.int shr SlotShift, block:
|
||||
"r.len: " & $r.len & "\n" &
|
||||
"k: " & $k & "\n" &
|
||||
"k/WordBitWidth: " & $(k.int shr SlotShift)
|
||||
|
||||
# We can compute (mod 2ʷ) with w >= k
|
||||
# Hence we truncate the substraction to the next multiple of the word size
|
||||
template trunc(x: openArray[SecretWord]): openArray[SecretWord] =
|
||||
x.toOpenArray(0, k.int.wordsRequired()-1)
|
||||
|
||||
if a.len >= b.len:
|
||||
let underflow {.used.} = r.subMP(a.trunc(), b.trunc())
|
||||
else:
|
||||
let underflow {.used.} = r.subMP(b.trunc(), a.trunc())
|
||||
r.neg()
|
||||
|
||||
r.mod2k_vartime(k)
|
||||
|
||||
func mulmod2k_vartime*(r: var openArray[SecretWord], a, b: openArray[SecretWord], k: uint) {.inline.} =
|
||||
## r <- a*b (mod 2ᵏ)
|
||||
r.prod(a, b)
|
||||
r.mod2k_vartime(k)
|
||||
|
||||
iterator unpackLE(scalarByte: byte): bool =
|
||||
for i in 0 ..< 8:
|
||||
yield bool((scalarByte shr i) and 1)
|
||||
|
||||
func powMod2k_vartime*(
|
||||
r{.noAlias.}: var openArray[SecretWord],
|
||||
a{.noAlias.}: openArray[SecretWord],
|
||||
exponent: openArray[byte], k: uint) {.noInline, tags: [Alloca].} =
|
||||
## r <- a^exponent (mod 2ᵏ)
|
||||
##
|
||||
## Requires:
|
||||
## - r.len > 0
|
||||
## - r.len <= a.len
|
||||
## - r.len >= ceilDiv(k, WordBitWidth) = (k+63)/64
|
||||
## - r and a don't alias
|
||||
|
||||
# Fast special cases:
|
||||
# 1. if a is even, it can be represented as a = 2b
|
||||
# if exponent e is greater than k, e = k+n
|
||||
# we have r ≡ aᵉ (mod 2ᵏ) ≡ (2b)ᵏ⁺ⁿ (mod 2ᵏ)
|
||||
# ≡ 2ᵏ.2ⁿ.bᵏ⁺ⁿ (mod 2ᵏ)
|
||||
# ≡ 0 (mod 2ᵏ)
|
||||
# 2. if a is odd, a and 2ᵏ are coprime
|
||||
# we can apply the Euler's totient theorem (https://en.wikipedia.org/wiki/Euler%27s_theorem
|
||||
# i.e. aᵠ⁽²^ᵏ⁾ ≡ 1 (mod 2ᵏ)
|
||||
# with
|
||||
# - ψ(n), the Euler's totient function, the count of coprimes in [0, n)
|
||||
# ψ(2ᵏ) = 2ᵏ⁻¹ as half the number (i.e. the odd numbers) are coprimes
|
||||
# with a power of 2.
|
||||
# - e' = e (mod ψ(2ᵏ))
|
||||
# aᵉ (mod 2ᵏ) ≡ aᵉ' (mod 2ᵏ)
|
||||
#
|
||||
# The remaining case is when a is even
|
||||
# and exponent < 2ᵏ⁻¹
|
||||
#
|
||||
# We use LSB to MSB square-and-multiply algorithm
|
||||
# with early stopping when we reach ψ(2ᵏ) if a is odd
|
||||
|
||||
for i in 0 ..< r.len:
|
||||
r[i] = Zero
|
||||
|
||||
let msb = getMSB_vartime(exponent)
|
||||
|
||||
if msb == -1: # exponent is 0
|
||||
r[0] = One # x⁰ = 1, even for 0⁰
|
||||
return
|
||||
|
||||
if a.isEven().bool and # if a is even
|
||||
1+msb >= k.int: # The msb of a n-bit integer is at n-1
|
||||
return # r ≡ aᵉ (mod 2ᵏ) ≡ (2b)ᵏ⁺ⁿ (mod 2ᵏ) ≡ 2ᵏ.2ⁿ.bᵏ⁺ⁿ (mod 2ᵏ) ≡ 0 (mod 2ᵏ)
|
||||
|
||||
var bitsLeft = msb+1
|
||||
if a.isOdd().bool and # if a is odd
|
||||
int(k-1) < bitsLeft:
|
||||
bitsLeft = int(k-1) # Euler's totient acceleration
|
||||
|
||||
r[0] = One
|
||||
|
||||
var sBuf = allocStackArray(SecretWord, r.len)
|
||||
template s: untyped = sBuf.toOpenArray(0, r.len-1)
|
||||
|
||||
for i in 0 ..< r.len:
|
||||
# range [r.len, a.len) will be truncated (mod 2ᵏ)
|
||||
sBuf[i] = a[i]
|
||||
|
||||
# TODO: sliding window
|
||||
for i in countdown(exponent.len-1, 0):
|
||||
for bit in unpackLE(exponent[i]):
|
||||
if bit:
|
||||
r.mulmod2k_vartime(r, s, k)
|
||||
s.mulmod2k_vartime(s, s, k)
|
||||
bitsLeft -= 1
|
||||
if bitsLeft == 0:
|
||||
return
|
||||
|
||||
func invModBitwidth(a: SecretWord): SecretWord {.borrow.}
|
||||
## Inversion a⁻¹ (mod 2³²) or a⁻¹ (mod 2⁶⁴)
|
||||
|
||||
func invMod2k_vartime*(a: var openArray[SecretWord], k: uint) {.noInline, tags: [Alloca].} =
|
||||
## Inversion a⁻¹ (mod 2ᵏ)
|
||||
## with 2ᵏ a multi-precision integer.
|
||||
#
|
||||
# Algorithm:
|
||||
# - Dumas iteration based on Newton-Raphson (see litterature in invModBitwidth)
|
||||
# ax ≡ 1 (mod 2ᵏ) <=> ax(2 - ax) ≡ 1 (mod 2²ᵏ)
|
||||
# which grows in O(log(log(a)))
|
||||
# - start with a seed inverse a'⁻¹ (mod 2ⁿ)
|
||||
# we can start with 2³² or 2⁶⁴
|
||||
# - Double the number of correct bits at each Dumas iteration
|
||||
# - once n >= k, reduce mod 2ᵏ
|
||||
|
||||
var x = allocStackArray(SecretWord, a.len)
|
||||
var t = allocStackArray(SecretWord, a.len)
|
||||
var u = allocStackArray(SecretWord, a.len)
|
||||
|
||||
x[0] = a[0].invModBitwidth()
|
||||
for i in 1 ..< a.len:
|
||||
x[i] = Zero
|
||||
|
||||
var correctWords = 1
|
||||
|
||||
while correctWords.uint*WordBitWidth < k:
|
||||
# x *= 2-ax
|
||||
let words = 2*correctWords
|
||||
t.toOpenArray(0, words-1)
|
||||
.mulmod2k_vartime(
|
||||
x.toOpenArray(0, correctWords-1),
|
||||
a.toOpenArray(0, words-1),
|
||||
words.uint*WordBitWidth)
|
||||
|
||||
u.toOpenArray(0, words-1)
|
||||
.submod2k_vartime(
|
||||
[SecretWord 2],
|
||||
t.toOpenArray(0, words-1),
|
||||
words.uint*WordBitWidth)
|
||||
|
||||
x.toOpenArray(0, words-1)
|
||||
.mulmod2k_vartime(
|
||||
x.toOpenArray(0, correctWords-1),
|
||||
u.toOpenArray(0, words-1),
|
||||
words.uint*WordBitWidth)
|
||||
|
||||
correctWords = words
|
||||
|
||||
x.toOpenArray(0, a.len-1).mod2k_vartime(k)
|
||||
for i in 0 ..< a.len:
|
||||
a[i] = x[i]
|
|
@ -0,0 +1,420 @@
|
|||
# Constantine
|
||||
# Copyright (c) 2018-2019 Status Research & Development GmbH
|
||||
# Copyright (c) 2020-Present Mamy André-Ratsimbazafy
|
||||
# Licensed and distributed under either of
|
||||
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
|
||||
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
|
||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||
|
||||
import
|
||||
# Internal
|
||||
../../platforms/[abstractions, allocs, bithacks],
|
||||
./limbs_views,
|
||||
./limbs_mod,
|
||||
./limbs_fixedprec
|
||||
|
||||
# No exceptions allowed
|
||||
{.push raises: [], checks: off.}
|
||||
|
||||
# ############################################################
|
||||
#
|
||||
# Arbitrary-precision Montgomery Arithmetic
|
||||
#
|
||||
# ############################################################
|
||||
|
||||
# Montgomery magic constants
|
||||
# ------------------------------------------
|
||||
|
||||
func r_powmod_vartime(r: var openArray[SecretWord], M: openArray[SecretWord], n: static int) =
|
||||
## Returns the Montgomery domain magic constant for the input modulus:
|
||||
##
|
||||
## R ≡ R (mod M) with R = (2^WordBitWidth)^numWords
|
||||
## or
|
||||
## R² ≡ R² (mod M) with R = (2^WordBitWidth)^numWords
|
||||
##
|
||||
## Assuming a field modulus of size 256-bit with 63-bit words, we require 5 words
|
||||
## R² ≡ ((2^63)^5)^2 (mod M) = 2^630 (mod M)
|
||||
|
||||
# Algorithm
|
||||
# Bos and Montgomery, Montgomery Arithmetic from a Software Perspective
|
||||
# https://eprint.iacr.org/2017/1057.pdf
|
||||
#
|
||||
# For R = r^n = 2^wn and 2^(wn − 1) ≤ N < 2^wn
|
||||
# r^n = 2^63 in on 64-bit and w the number of words
|
||||
#
|
||||
# 1. C0 = 2^(wn - 1), the power of two immediately less than N
|
||||
# 2. for i in 1 ... wn+1
|
||||
# Ci = C(i-1) + C(i-1) (mod M)
|
||||
#
|
||||
# Thus: C(wn+1) ≡ 2^(wn+1) C0 ≡ 2^(wn + 1) 2^(wn - 1) ≡ 2^(2wn) ≡ (2^wn)^2 ≡ R² (mod M)
|
||||
|
||||
debug:
|
||||
doAssert bool(M[0] and One)
|
||||
doAssert BaseType(M[M.len-1]) != 0
|
||||
doAssert r.len == M.len
|
||||
|
||||
let
|
||||
w = M.len
|
||||
msb = int log2_vartime(BaseType M[M.len-1])
|
||||
start = (w-1)*WordBitWidth + msb
|
||||
stop = n*WordBitWidth*w
|
||||
|
||||
for i in 0 ..< r.len-1:
|
||||
r[i] = Zero
|
||||
r[r.len-1] = SecretWord(BaseType(1) shl msb) # C0 = 2^(wn-1), the power of 2 immediatly less than the modulus
|
||||
|
||||
for i in start ..< stop:
|
||||
r.doublemod_vartime(r, M)
|
||||
|
||||
func oneMont_vartime*(r: var openArray[SecretWord], M: openArray[SecretWord]) =
|
||||
## Returns 1 in Montgomery domain:
|
||||
r.r_powmod_vartime(M, 1)
|
||||
|
||||
func r2_vartime*(r: var openArray[SecretWord], M: openArray[SecretWord]) =
|
||||
## Returns the Montgomery domain magic constant for the input modulus:
|
||||
##
|
||||
## R² ≡ R² (mod M) with R = (2^WordBitWidth)^numWords
|
||||
##
|
||||
## Assuming a field modulus of size 256-bit with 63-bit words, we require 5 words
|
||||
## R² ≡ ((2^63)^5)^2 (mod M) = 2^630 (mod M)
|
||||
r.r_powmod_vartime(M, 2)
|
||||
|
||||
# Montgomery multiplication
|
||||
# ------------------------------------------
|
||||
|
||||
func mulMont_FIPS*(
|
||||
r: LimbsViewMut,
|
||||
a, b: distinct LimbsViewAny,
|
||||
M: LimbsViewConst,
|
||||
m0ninv: SecretWord,
|
||||
mBits: int,
|
||||
skipFinalSub: static bool = false) {.noInline, tags:[Alloca].} =
|
||||
## Montgomery Multiplication using Finely Integrated Product Scanning (FIPS)
|
||||
##
|
||||
## This maps
|
||||
## - [0, 2p) -> [0, 2p) with skipFinalSub
|
||||
## - [0, 2p) -> [0, p) without
|
||||
##
|
||||
## skipFinalSub skips the final substraction step.
|
||||
# - Architectural Enhancements for Montgomery
|
||||
# Multiplication on Embedded RISC Processors
|
||||
# Johann Großschädl and Guy-Armand Kamendje, 2003
|
||||
# https://pure.tugraz.at/ws/portalfiles/portal/2887154/ACNS2003_AEM.pdf
|
||||
#
|
||||
# - New Speed Records for Montgomery Modular
|
||||
# Multiplication on 8-bit AVR Microcontrollers
|
||||
# Zhe Liu and Johann Großschädl, 2013
|
||||
# https://eprint.iacr.org/2013/882.pdf
|
||||
let L = wordsRequired(mBits)
|
||||
var z = LimbsViewMut allocStackArray(SecretWord, L)
|
||||
z.setZero(L)
|
||||
|
||||
var t, u, v = Zero
|
||||
|
||||
for i in 0 ..< L:
|
||||
for j in 0 ..< i:
|
||||
mulAcc(t, u, v, a[j], b[i-j])
|
||||
mulAcc(t, u, v, z[j], M[i-j])
|
||||
mulAcc(t, u, v, a[i], b[0])
|
||||
z[i] = v * m0ninv
|
||||
mulAcc(t, u, v, z[i], M[0])
|
||||
v = u
|
||||
u = t
|
||||
t = Zero
|
||||
for i in L ..< 2*L:
|
||||
for j in i-L+1 ..< L:
|
||||
mulAcc(t, u, v, a[j], b[i-j])
|
||||
mulAcc(t, u, v, z[j], M[i-j])
|
||||
z[i-L] = v
|
||||
v = u
|
||||
u = t
|
||||
t = Zero
|
||||
|
||||
when not skipFinalSub:
|
||||
discard z.csub(M, v.isNonZero() or not(z.lt(M, L)), L)
|
||||
r.copyWords(0, z, 0, L)
|
||||
|
||||
# Montgomery conversions
|
||||
# ------------------------------------------
|
||||
|
||||
func fromMont*(r: LimbsViewMut, a: LimbsViewAny, M: LimbsViewConst,
|
||||
m0ninv: SecretWord, mBits: int) {.noInline, tags:[Alloca].} =
|
||||
## Transform a bigint ``a`` from it's Montgomery N-residue representation (mod N)
|
||||
## to the regular natural representation (mod N)
|
||||
##
|
||||
## with W = M.len
|
||||
## and R = (2^WordBitWidth)^W
|
||||
##
|
||||
## Does "a * R^-1 (mod M)" = montMul(a, 1)
|
||||
##
|
||||
## This is called a Montgomery Reduction
|
||||
## The Montgomery Magic Constant is µ = -1/N mod M
|
||||
## is used internally and can be precomputed with m0ninv(Curve)
|
||||
let N = wordsRequired(mBits)
|
||||
var t = LimbsViewMut allocStackArray(SecretWord, N)
|
||||
t.copyWords(0, a, 0, N)
|
||||
|
||||
for i in 0 ..< N:
|
||||
let m = t[0] * m0ninv
|
||||
var C, lo: SecretWord
|
||||
muladd1(C, lo, m, M[0], t[0])
|
||||
for j in 1 ..< N:
|
||||
muladd2(C, t[j-1], m, M[j], C, t[j])
|
||||
t[N-1] = C
|
||||
|
||||
discard t.csub(M, not(t.lt(M, N)), N)
|
||||
r.copyWords(0, t, 0, N)
|
||||
|
||||
func getMont*(r: LimbsViewMut, a: LimbsViewAny, M, r2modM: LimbsViewConst,
|
||||
m0ninv: SecretWord, mBits: int) {.inline.} =
|
||||
## Transform a bigint ``a`` from it's natural representation (mod N)
|
||||
## to a the Montgomery n-residue representation
|
||||
##
|
||||
## Montgomery-Multiplication - based
|
||||
##
|
||||
## with W = M.len
|
||||
## and R = (2^WordBitWidth)^W
|
||||
##
|
||||
## Does "a * R (mod M)"
|
||||
##
|
||||
## `a`: The source BigInt in the natural representation. `a` in [0, N) range
|
||||
## `M`: The field modulus. M must be odd.
|
||||
## `r2modM`: 2^WordBitWidth mod `M`. Can be precomputed with `r2mod` function
|
||||
##
|
||||
## Important: `r` is overwritten
|
||||
## The result `r` buffer size MUST be at least the size of `M` buffer
|
||||
# Reference: https://eprint.iacr.org/2017/1057.pdf
|
||||
mulMont_FIPS(r, a, r2ModM, M, m0ninv, mBits)
|
||||
|
||||
|
||||
# Montgomery Modular Exponentiation
|
||||
# ------------------------------------------
|
||||
# We use fixed-window based exponentiation
|
||||
# that is constant-time: i.e. the number of multiplications
|
||||
# does not depend on the number of set bits in the exponents
|
||||
# those are always done and conditionally copied.
|
||||
#
|
||||
# The exponent MUST NOT be private data (until audited otherwise)
|
||||
# - Power attack on RSA, https://www.di.ens.fr/~fouque/pub/ches06.pdf
|
||||
# - Flush-and-reload on Sliding window exponentiation: https://tutcris.tut.fi/portal/files/8966761/p1639_pereida_garcia.pdf
|
||||
# - Sliding right into disaster, https://eprint.iacr.org/2017/627.pdf
|
||||
# - Fixed window leak: https://www.scirp.org/pdf/JCC_2019102810331929.pdf
|
||||
# - Constructing sliding-windows leak, https://easychair.org/publications/open/fBNC
|
||||
#
|
||||
# For pairing curves, this is the case since exponentiation is only
|
||||
# used for inversion via the Little Fermat theorem.
|
||||
# For RSA, some exponentiations uses private exponents.
|
||||
#
|
||||
# Note:
|
||||
# - Implementation closely follows Thomas Pornin's BearSSL
|
||||
# - Apache Milagro Crypto has an alternative implementation
|
||||
# that is more straightforward however:
|
||||
# - the exponent hamming weight is used as loop bounds
|
||||
# - the baseᵏ is stored at each index of a temp table of size k
|
||||
# - the baseᵏ to use is indexed by the hamming weight
|
||||
# of the exponent, leaking this to cache attacks
|
||||
# - in contrast BearSSL touches the whole table to
|
||||
# hide the actual selection
|
||||
|
||||
template checkPowScratchSpaceLen(bufLen, wordLen: int) =
|
||||
## Checks that there is a minimum of scratchspace to hold the temporaries
|
||||
debug:
|
||||
assert bufLen >= 2*wordLen, "Internal Error: the scratchspace for powmod should be equal or greater than 2"
|
||||
|
||||
func getWindowLen(bufLen, wordLen: int): uint =
|
||||
## Compute the maximum window size that fits in the scratchspace buffer
|
||||
checkPowScratchSpaceLen(bufLen, wordLen)
|
||||
result = 5
|
||||
while ((1 shl result) + 1)*wordLen > bufLen:
|
||||
dec result
|
||||
|
||||
func powMontPrologue(
|
||||
a: LimbsViewMut, M, one: LimbsViewConst,
|
||||
m0ninv: SecretWord,
|
||||
scratchspace: LimbsViewMut,
|
||||
scratchLen: int,
|
||||
mBits: int): uint {.tags:[Alloca].} =
|
||||
## Setup the scratchspace
|
||||
## Returns the fixed-window size for exponentiation with window optimization.
|
||||
# Precompute window content, special case for window = 1
|
||||
# (i.e scratchspace has only space for 2 temporaries)
|
||||
# The content scratchspace[2+k] is set at aᵏ
|
||||
# with scratchspace[0] untouched
|
||||
let wordLen = wordsRequired(mBits)
|
||||
result = scratchLen.getWindowLen(wordLen)
|
||||
if result == 1:
|
||||
scratchspace.copyWords(1*wordLen, a, 0, wordLen)
|
||||
else:
|
||||
scratchspace.copyWords(2*wordLen, a, 0, wordLen)
|
||||
for k in 2 ..< 1 shl result:
|
||||
let sk1 = cast[LimbsViewMut](scratchspace[(k+1)*wordLen].addr)
|
||||
let sk = cast[LimbsViewConst](scratchspace[k*wordLen].addr)
|
||||
sk1.mulMont_FIPS(sk, a, M, m0ninv, mBits)
|
||||
|
||||
# Set a to one
|
||||
a.copyWords(0, one, 0, wordLen)
|
||||
|
||||
func powMontSquarings(
|
||||
a: LimbsViewMut,
|
||||
exponent: openarray[byte],
|
||||
M: LimbsViewConst,
|
||||
m0ninv: SecretWord,
|
||||
mBits: int,
|
||||
tmp: LimbsViewMut,
|
||||
window: uint,
|
||||
acc, acc_len: var uint,
|
||||
e: var int): tuple[k, bits: uint] {.inline.}=
|
||||
## Squaring step of exponentiation by squaring
|
||||
## Get the next k bits in range [1, window)
|
||||
## Square k times
|
||||
## Returns the number of squarings done and the corresponding bits
|
||||
##
|
||||
## Updates iteration variables and accumulators
|
||||
# Due to the high number of parameters,
|
||||
# forcing this inline actually reduces the code size
|
||||
#
|
||||
# ⚠️: Extreme care should be used to not leak
|
||||
# the exponent bits nor its real bitlength
|
||||
# i.e. if the exponent is zero but encoded in a
|
||||
# 256-bit integer, only "256" should leak
|
||||
# as for some application like RSA
|
||||
# the exponent might be the user secret key.
|
||||
|
||||
# Get the next bits
|
||||
# acc/acc_len must be uint to avoid Nim runtime checks leaking bits
|
||||
# acc/acc_len must be uint to avoid Nim runtime checks leaking bits
|
||||
# e is public
|
||||
var k = window
|
||||
if acc_len < window:
|
||||
if e < exponent.len:
|
||||
acc = (acc shl 8) or exponent[e].uint
|
||||
inc e
|
||||
acc_len += 8
|
||||
else: # Drained all exponent bits
|
||||
k = acc_len
|
||||
|
||||
let bits = (acc shr (acc_len - k)) and ((1'u32 shl k) - 1)
|
||||
acc_len -= k
|
||||
|
||||
# We have k bits and can do k squaring
|
||||
for i in 0 ..< k:
|
||||
a.mulMont_FIPS(a, a, M, m0ninv, mBits)
|
||||
|
||||
return (k, bits)
|
||||
|
||||
func powMont*(
|
||||
a: LimbsViewMut,
|
||||
exponent: openarray[byte],
|
||||
M, one: LimbsViewConst,
|
||||
m0ninv: SecretWord,
|
||||
scratchspace: LimbsViewMut,
|
||||
scratchLen: int,
|
||||
mBits: int) =
|
||||
## Modular exponentiation r = a^exponent mod M
|
||||
## in the Montgomery domain
|
||||
##
|
||||
## This uses fixed-window optimization if possible
|
||||
##
|
||||
## - On input ``a`` is the base, on ``output`` a = a^exponent (mod M)
|
||||
## ``a`` is in the Montgomery domain
|
||||
## - ``exponent`` is the exponent in big-endian canonical format (octet-string)
|
||||
## Use ``marshal`` for conversion
|
||||
## - ``M`` is the modulus
|
||||
## - ``one`` is 1 (mod M) in montgomery representation
|
||||
## - ``m0ninv`` is the montgomery magic constant "-1/M[0] mod 2^WordBitWidth"
|
||||
## - ``scratchspace`` with k the window bitsize of size up to 5
|
||||
## This is a buffer that can hold between 2 and up to 2ᵏ + 1 big-ints
|
||||
## A window of 1-bit (no window optimization) requires only 2 big-ints
|
||||
##
|
||||
## Note that the best window size require benchmarking and is a tradeoff between
|
||||
## - performance
|
||||
## - stack usage
|
||||
## - precomputation
|
||||
##
|
||||
## For example BLS12-381 window size of 5 is 30% faster than no window,
|
||||
## but windows of size 2, 3, 4 bring no performance benefit, only increased stack space.
|
||||
## A window of size 5 requires (2^5 + 1)*(381 + 7)/8 = 33 * 48 bytes = 1584 bytes
|
||||
## of scratchspace (on the stack).
|
||||
|
||||
let N = wordsRequired(mBits)
|
||||
let window = powMontPrologue(a, M, one, m0ninv, scratchspace, scratchLen, mBits)
|
||||
|
||||
# We process bits with from most to least significant.
|
||||
# At each loop iteration with have acc_len bits in acc.
|
||||
# To maintain constant-time the number of iterations
|
||||
# or the number of operations or memory accesses should be the same
|
||||
# regardless of acc & acc_len
|
||||
var
|
||||
acc, acc_len: uint
|
||||
e = 0
|
||||
|
||||
let s0 = cast[LimbsViewMut](scratchspace[0].addr)
|
||||
let s1 = cast[LimbsViewConst](scratchspace[1*N].addr)
|
||||
|
||||
while acc_len > 0 or e < exponent.len:
|
||||
let (k, bits) = powMontSquarings(
|
||||
a, exponent, M, m0ninv, mBits,
|
||||
s0, window,
|
||||
acc, acc_len, e)
|
||||
|
||||
# Window lookup: we set scratchspace[1] to the lookup value.
|
||||
# If the window length is 1, then it's already set.
|
||||
if window > 1:
|
||||
# otherwise we need a constant-time lookup
|
||||
# in particular we need the same memory accesses, we can't
|
||||
# just index the openarray with the bits to avoid cache attacks.
|
||||
for i in 1 ..< 1 shl k:
|
||||
let ctl = SecretWord(i) == SecretWord(bits)
|
||||
scratchspace.ccopyWords(1*N, scratchspace, (1+i)*N, ctl, N)
|
||||
|
||||
# Multiply with the looked-up value
|
||||
# we keep the product only if the exponent bits are not all zeroes
|
||||
s0.mulMont_FIPS(a, s1, M, m0ninv, mBits)
|
||||
a.ccopyWords(0, s0, 0, SecretWord(bits).isNonZero(), N)
|
||||
|
||||
func powMont_vartime*(
|
||||
a: LimbsViewMut,
|
||||
exponent: openArray[byte],
|
||||
M, one: LimbsViewConst,
|
||||
m0ninv: SecretWord,
|
||||
scratchspace: LimbsViewMut,
|
||||
scratchLen: int,
|
||||
mBits: int) {.tags:[VarTime, Alloca].} =
|
||||
## Modular exponentiation a <- a^exponent (mod M)
|
||||
## in the Montgomery domain
|
||||
##
|
||||
## Warning ⚠️ :
|
||||
## This is an optimization for public exponent
|
||||
## Otherwise bits of the exponent can be retrieved with:
|
||||
## - memory access analysis
|
||||
## - power analysis
|
||||
## - timing analysis
|
||||
|
||||
# TODO: scratchspace[1] is unused when window > 1
|
||||
let N = wordsRequired(mBits)
|
||||
let window = powMontPrologue(a, M, one, m0ninv, scratchspace, scratchLen, mBits)
|
||||
|
||||
var
|
||||
acc, acc_len: uint
|
||||
e = 0
|
||||
|
||||
let s0 = cast[LimbsViewMut](scratchspace[0].addr)
|
||||
let s1 = cast[LimbsViewConst](scratchspace[1*N].addr)
|
||||
|
||||
while acc_len > 0 or e < exponent.len:
|
||||
let (_, bits) = powMontSquarings(
|
||||
a, exponent, M, m0ninv, mBits,
|
||||
s0, window,
|
||||
acc, acc_len, e)
|
||||
|
||||
## Warning ⚠️: Exposes the exponent bits
|
||||
if bits != 0:
|
||||
if window > 1:
|
||||
let sBits = cast[LimbsViewConst](scratchspace[int(1+bits)*N].addr)
|
||||
s0.mulMont_FIPS(a, sBits, M, m0ninv, mBits)
|
||||
else:
|
||||
# scratchspace[1] holds the original `a`
|
||||
s0.mulMont_FIPS(a, s1, M, m0ninv, mBits)
|
||||
a.copyWords(0, s0, 0, N)
|
||||
|
||||
{.pop.}
|
|
@ -0,0 +1,163 @@
|
|||
# Constantine
|
||||
# Copyright (c) 2018-2019 Status Research & Development GmbH
|
||||
# Copyright (c) 2020-Present Mamy André-Ratsimbazafy
|
||||
# Licensed and distributed under either of
|
||||
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
|
||||
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
|
||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||
|
||||
import
|
||||
# Internal
|
||||
../../platforms/abstractions
|
||||
|
||||
# ############################################################
|
||||
#
|
||||
# Multi-precision arithmetic
|
||||
#
|
||||
# ############################################################
|
||||
#
|
||||
# This file implements multi-precision primitives
|
||||
# with unbalanced number of limbs.
|
||||
|
||||
# Logical Shift Right
|
||||
# --------------------------------------------------------
|
||||
|
||||
func shrSmall(r {.noalias.}: var openArray[SecretWord], a: openArray[SecretWord], k: SomeInteger) =
|
||||
## Shift right by k.
|
||||
##
|
||||
## k MUST be less than the base word size (2^32 or 2^64)
|
||||
# Note: for speed, loading a[i] and a[i+1]
|
||||
# instead of a[i-1] and a[i]
|
||||
# is probably easier to parallelize for the compiler
|
||||
# (antidependence WAR vs loop-carried dependence RAW)
|
||||
for i in 0 ..< a.len-1:
|
||||
r[i] = (a[i] shr k) or (a[i+1] shl (WordBitWidth - k))
|
||||
if a.len-1 < r.len:
|
||||
r[a.len-1] = a[a.len-1] shr k
|
||||
|
||||
for i in a.len ..< r.len:
|
||||
r[i] = Zero
|
||||
|
||||
func shrLarge(r {.noalias.}: var openArray[SecretWord], a: openArray[SecretWord], w, shift: SomeInteger) =
|
||||
## Shift right by `w` words + `shift` bits
|
||||
if w >= a.len:
|
||||
r.setZero()
|
||||
return
|
||||
|
||||
for i in w ..< a.len-1:
|
||||
r[i-w] = (a[i] shr shift) or (a[i+1] shl (WordBitWidth - shift))
|
||||
if a.len-1-w < r.len:
|
||||
r[a.len-1-w] = a[a.len-1] shr shift
|
||||
|
||||
for i in a.len-w ..< r.len:
|
||||
r[i] = Zero
|
||||
|
||||
func shrWords(r {.noalias.}: var openArray[SecretWord], a: openArray[SecretWord], w: SomeInteger) =
|
||||
## Shift right by w word
|
||||
|
||||
for i in 0 ..< a.len-w:
|
||||
r[i] = a[i+w]
|
||||
|
||||
for i in a.len-w ..< r.len:
|
||||
r[i] = Zero
|
||||
|
||||
func shiftRight_vartime*(r {.noalias.}: var openArray[SecretWord], a: openArray[SecretWord], k: SomeInteger) =
|
||||
## Shift `a` right by k bits and store in `r`
|
||||
if k == 0:
|
||||
let min = min(a.len, r.len)
|
||||
for i in 0 ..< min:
|
||||
r[i] = a[i]
|
||||
for i in min ..< r.len:
|
||||
r[i] = Zero
|
||||
return
|
||||
|
||||
if k < WordBitWidth:
|
||||
r.shrSmall(a, k)
|
||||
return
|
||||
|
||||
# w = k div WordBitWidth, shift = k mod WordBitWidth
|
||||
let w = k shr static(log2_vartime(uint32(WordBitWidth)))
|
||||
let shift = k and (WordBitWidth - 1)
|
||||
|
||||
if shift == 0:
|
||||
r.shrWords(a, w)
|
||||
else:
|
||||
r.shrLarge(a, w, shift)
|
||||
|
||||
# Arithmetic
|
||||
# --------------------------------------------------------
|
||||
|
||||
func neg*(a: var openArray[SecretWord]) =
|
||||
## Computes the additive inverse -a
|
||||
## in 2-complement representation
|
||||
|
||||
# Algorithm: -a = not(a) + 1
|
||||
var carry = Carry(0)
|
||||
addC(carry, a[0], not(a[0]), One, carry)
|
||||
for i in 1 ..< a.len:
|
||||
addC(carry, a[i], not(a[i]), Zero, carry)
|
||||
|
||||
func addMP*(r {.noAlias.}: var openArray[SecretWord], a, b: openArray[SecretWord]): bool =
|
||||
## r <- a + b
|
||||
## and
|
||||
## returns the carry
|
||||
##
|
||||
## Requirements:
|
||||
## - r.len >= a.len
|
||||
## - r.len >= b.len
|
||||
|
||||
debug:
|
||||
doAssert r.len >= a.len
|
||||
doAssert r.len >= b.len
|
||||
|
||||
if a.len < b.len:
|
||||
return r.addMP(b, a)
|
||||
|
||||
let minLen = b.len
|
||||
let maxLen = a.len
|
||||
|
||||
var carry = Carry(0)
|
||||
for i in 0 ..< minLen:
|
||||
addC(carry, r[i], a[i], b[i], carry)
|
||||
for i in minLen ..< maxLen:
|
||||
addC(carry, r[i], a[i], Zero, carry)
|
||||
|
||||
if maxLen < r.len:
|
||||
r[maxLen] = SecretWord(carry)
|
||||
for i in maxLen+1 ..< r.len:
|
||||
r[i] = Zero
|
||||
return false # the rest cannot carry
|
||||
else:
|
||||
return bool carry
|
||||
|
||||
func subMP*(r {.noAlias.}: var openArray[SecretWord], a, b: openArray[SecretWord]): bool =
|
||||
## r <- a - b
|
||||
## and
|
||||
## returns false if a >= b
|
||||
## returns true if a < b
|
||||
## (in that case the 2-complement is stored)
|
||||
##
|
||||
## Requirements:
|
||||
## - r.len >= a.len
|
||||
## - a.len >= b.len
|
||||
|
||||
debug:
|
||||
doAssert r.len >= a.len
|
||||
doAssert a.len >= b.len
|
||||
|
||||
let minLen = b.len
|
||||
let maxLen = a.len
|
||||
|
||||
var borrow = Borrow(0)
|
||||
for i in 0 ..< minLen:
|
||||
subB(borrow, r[i], a[i], b[i], borrow)
|
||||
for i in minLen ..< maxLen:
|
||||
subB(borrow, r[i], a[i], Zero, borrow)
|
||||
|
||||
result = bool borrow
|
||||
|
||||
# if a >= b, no borrow, mask = 0
|
||||
# if a < b, borrow, we store the 2-complement, mask = -1
|
||||
let mask = Zero - SecretWord(borrow)
|
||||
for i in maxLen ..< r.len:
|
||||
r[i] = mask
|
|
@ -0,0 +1,122 @@
|
|||
# Constantine
|
||||
# Copyright (c) 2018-2019 Status Research & Development GmbH
|
||||
# Copyright (c) 2020-Present Mamy André-Ratsimbazafy
|
||||
# Licensed and distributed under either of
|
||||
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
|
||||
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
|
||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||
|
||||
import ../../platforms/abstractions
|
||||
|
||||
# No exceptions allowed
|
||||
{.push raises: [].}
|
||||
|
||||
# Datatype
|
||||
# ------------------------------------------------------------
|
||||
|
||||
# TODO: cleanup openArray vs LimbsView
|
||||
|
||||
type
|
||||
LimbsView* = ptr UncheckedArray[SecretWord]
|
||||
## Type-erased fixed-precision limbs
|
||||
##
|
||||
## This type mirrors the Limb type and is used
|
||||
## for some low-level computation API
|
||||
## This design
|
||||
## - avoids code bloat due to generic monomorphization
|
||||
## otherwise limbs routines would have an instantiation for
|
||||
## each number of words.
|
||||
##
|
||||
## Accesses should be done via BigIntViewConst / BigIntViewConst
|
||||
## to have the compiler check for mutability
|
||||
|
||||
# "Indirection" to enforce pointer types deep immutability
|
||||
LimbsViewConst* = distinct LimbsView
|
||||
## Immutable view into the limbs of a BigInt
|
||||
LimbsViewMut* = distinct LimbsView
|
||||
## Mutable view into a BigInt
|
||||
LimbsViewAny* = LimbsViewConst or LimbsViewMut
|
||||
|
||||
# Deep Mutability safety
|
||||
# ------------------------------------------------------------
|
||||
|
||||
template view*(a: Limbs): LimbsViewConst =
|
||||
## Returns a borrowed type-erased immutable view to a bigint
|
||||
LimbsViewConst(cast[LimbsView](a.unsafeAddr))
|
||||
|
||||
template view*(a: var Limbs): LimbsViewMut =
|
||||
## Returns a borrowed type-erased mutable view to a mutable bigint
|
||||
LimbsViewMut(cast[LimbsView](a.addr))
|
||||
|
||||
template view*(a: openArray[SecretWord]): LimbsViewConst =
|
||||
## Returns a borrowed type-erased immutable view to a bigint
|
||||
LimbsViewConst(cast[LimbsView](a[0].unsafeAddr))
|
||||
|
||||
template view*(a: var openArray[SecretWord]): LimbsViewMut =
|
||||
## Returns a borrowed type-erased mutable view to a mutable bigint
|
||||
LimbsViewMut(cast[LimbsView](a[0].addr))
|
||||
|
||||
template `[]`*(v: LimbsViewConst, limbIdx: int): SecretWord =
|
||||
LimbsView(v)[limbIdx]
|
||||
|
||||
template `[]`*(v: LimbsViewMut, limbIdx: int): var SecretWord =
|
||||
LimbsView(v)[limbIdx]
|
||||
|
||||
template `[]=`*(v: LimbsViewMut, limbIdx: int, val: SecretWord) =
|
||||
LimbsView(v)[limbIdx] = val
|
||||
|
||||
# Init
|
||||
# ------------------------------------------------------------
|
||||
|
||||
func setZero*(p: LimbsViewMut, len: int) {.inline.} =
|
||||
for i in 0 ..< len:
|
||||
p[i] = Zero
|
||||
|
||||
# Copy
|
||||
# ------------------------------------------------------------
|
||||
|
||||
func copyWords*(
|
||||
a: LimbsViewMut, startA: int,
|
||||
b: LimbsViewAny, startB: int,
|
||||
numWords: int) {.inline.} =
|
||||
## Copy a slice of B into A. This properly deals
|
||||
## with overlaps when A and B are slices of the same buffer
|
||||
if startA > startB:
|
||||
for i in countdown(numWords-1, 0):
|
||||
a[startA+i] = b[startB+i]
|
||||
else:
|
||||
for i in 0 ..< numWords:
|
||||
a[startA+i] = b[startB+i]
|
||||
|
||||
func ccopyWords*(
|
||||
a: LimbsViewMut, startA: int,
|
||||
b: LimbsViewAny, startB: int,
|
||||
ctl: SecretBool,
|
||||
numWords: int) {.inline.} =
|
||||
## Copy a slice of B into A. This properly deals
|
||||
## with overlaps when A and B are slices of the same buffer
|
||||
if startA > startB:
|
||||
for i in countdown(numWords-1, 0):
|
||||
ctl.ccopy(a[startA+i], b[startB+i])
|
||||
else:
|
||||
for i in 0 ..< numWords:
|
||||
ctl.ccopy(a[startA+i], b[startB+i])
|
||||
|
||||
# Bit operations
|
||||
# ------------------------------------------------------------
|
||||
|
||||
func getMSB_vartime*[T](a: openArray[T]): int =
|
||||
## Returns the position of the most significant bit
|
||||
## of `a`.
|
||||
## Returns -1 if a == 0
|
||||
result = -1
|
||||
for i in countdown(a.len-1, 0):
|
||||
if bool a[i] != T(0):
|
||||
return int(log2_vartime(uint64 a[i])) + 8*sizeof(T)*i
|
||||
|
||||
func getBits_vartime*[T](a: openArray[T]): int {.inline.} =
|
||||
## Returns the number of bits used by `a`
|
||||
## Returns 0 for 0
|
||||
1 + getMSB_vartime(a)
|
||||
|
||||
{.pop.} # raises no exceptions
|
|
@ -17,6 +17,21 @@ import ../../metering/tracer
|
|||
|
||||
export primitives, tracer
|
||||
|
||||
# ------------------------------------------------------------
|
||||
|
||||
const CttASM {.booldefine.} = true
|
||||
const UseASM_X86_32* = CttASM and X86 and GCC_Compatible
|
||||
const UseASM_X86_64* = sizeof(pointer)*8 == 64 and UseASM_X86_32
|
||||
|
||||
# We use Nim effect system to track vartime subroutines
|
||||
type VarTime* = object
|
||||
|
||||
# ############################################################
|
||||
#
|
||||
# Secret Words
|
||||
#
|
||||
# ############################################################
|
||||
|
||||
when sizeof(int) == 8 and not defined(Ctt32):
|
||||
type
|
||||
BaseType* = uint64
|
||||
|
@ -52,12 +67,51 @@ const
|
|||
One* = SecretWord(1)
|
||||
MaxWord* = SecretWord(high(BaseType))
|
||||
|
||||
const CttASM {.booldefine.} = true
|
||||
const UseASM_X86_32* = CttASM and X86 and GCC_Compatible
|
||||
const UseASM_X86_64* = WordBitWidth == 64 and UseASM_X86_32
|
||||
func wordsRequired*(bits: int): int {.inline.} =
|
||||
## Compute the number of limbs required
|
||||
## from the **announced** bit length
|
||||
|
||||
# We use Nim effect system to track vartime subroutines
|
||||
type VarTime* = object
|
||||
# bits.ceilDiv_vartime(WordBitWidth)
|
||||
# with guarantee to avoid division (especially at compile-time)
|
||||
const divShiftor = log2_vartime(uint32(WordBitWidth))
|
||||
result = (bits + WordBitWidth - 1) shr divShiftor
|
||||
|
||||
func isOdd*(a: SecretWord): SecretBool {.inline.} =
|
||||
SecretBool(a and One)
|
||||
|
||||
func isOdd*(a: openArray[SecretWord]): SecretBool {.inline.} =
|
||||
SecretBool(a[0] and One)
|
||||
|
||||
func isEven*(a: openArray[SecretWord]): SecretBool {.inline.} =
|
||||
not a.isOdd
|
||||
|
||||
func setZero*(a: var openArray[SecretWord]){.inline.} =
|
||||
for i in 0 ..< a.len:
|
||||
a[i] = Zero
|
||||
|
||||
func setOne*(a: var openArray[SecretWord]){.inline.} =
|
||||
a[0] = One
|
||||
for i in 1 ..< a.len:
|
||||
a[i] = Zero
|
||||
|
||||
debug: # Don't allow printing secret words by default
|
||||
func toHex*(a: SecretWord): string =
|
||||
const hexChars = "0123456789abcdef"
|
||||
const L = 2*sizeof(SecretWord)
|
||||
result = newString(2 + L)
|
||||
result[0] = '0'
|
||||
result[1] = 'x'
|
||||
var a = a
|
||||
for j in countdown(result.len-1, 2):
|
||||
result[j] = hexChars.secretLookup(a and SecretWord 0xF)
|
||||
a = a shr 4
|
||||
|
||||
func toString*(a: openArray[SecretWord]): string =
|
||||
result = "["
|
||||
result.add " " & toHex(a[0])
|
||||
for i in 1 ..< a.len:
|
||||
result.add ", " & toHex(a[i])
|
||||
result.add "]"
|
||||
|
||||
# ############################################################
|
||||
#
|
||||
|
|
|
@ -100,7 +100,7 @@ func byteLen(bits: SomeInteger): SomeInteger {.inline.} =
|
|||
## Length in bytes to serialize BigNum
|
||||
(bits + 7) shr 3 # (bits + 8 - 1) div 8
|
||||
|
||||
func wordsRequiredForBits(bits, wordBitwidth: SomeInteger): SomeInteger {.inline.} =
|
||||
func wordsRequired(bits, wordBitwidth: SomeInteger): SomeInteger {.inline.} =
|
||||
## Compute the number of limbs required
|
||||
## from the announced bit length
|
||||
|
||||
|
@ -117,7 +117,7 @@ func fromHex[T](a: var BigNum[T], s: string) =
|
|||
|
||||
func fromHex[T](BN: type BigNum[T], bits: uint32, s: string): BN =
|
||||
const wordBitwidth = sizeof(T) * 8
|
||||
let numWords = wordsRequiredForBits(bits, wordBitwidth)
|
||||
let numWords = wordsRequired(bits, wordBitwidth)
|
||||
|
||||
result.bits = bits
|
||||
result.limbs.setLen(numWords)
|
||||
|
@ -161,10 +161,7 @@ func negInvModWord[T](M: BigNum[T]): T =
|
|||
##
|
||||
## µ ≡ -1/M[0] (mod 2^64)
|
||||
checkValidModulus(M)
|
||||
|
||||
result = invModBitwidth(M.limbs[0])
|
||||
# negate to obtain the negative inverse
|
||||
result = not(result) + 1
|
||||
return M.limbs[0].negInvModWord()
|
||||
|
||||
# ############################################################
|
||||
#
|
||||
|
@ -209,7 +206,7 @@ proc setFieldConst(fc: var FieldConst, ctx: ContextRef, wordSize: WordSize, modB
|
|||
of size32: 32'u32
|
||||
of size64: 64'u32
|
||||
|
||||
let numWords = wordsRequiredForBits(modBits, wordBitwidth)
|
||||
let numWords = wordsRequired(modBits, wordBitwidth)
|
||||
|
||||
fc.wordTy = wordTy
|
||||
fc.fieldTy = array_t(wordTy, numWords)
|
||||
|
|
|
@ -82,10 +82,15 @@ func ceilDiv_vartime*(a, b: auto): auto {.inline.} =
|
|||
#
|
||||
# ############################################################
|
||||
|
||||
func setZero*[N](a: var array[N, SomeNumber]){.inline.} =
|
||||
func setZero*(a: var openArray[SomeNumber]){.inline.} =
|
||||
for i in 0 ..< a.len:
|
||||
a[i] = 0
|
||||
|
||||
func setOne*(a: var openArray[SomeNumber]){.inline.} =
|
||||
a[0] = 1
|
||||
for i in 1 ..< a.len:
|
||||
a[i] = 0
|
||||
|
||||
func rawCopy*(
|
||||
dst: var openArray[byte],
|
||||
dStart: SomeInteger,
|
||||
|
|
|
@ -30,7 +30,7 @@ func buildRootLUT(F: type Fr): array[32, F] =
|
|||
var i = result.len - 1
|
||||
exponent.shiftRight(i)
|
||||
result[i].fromUint(BLS12_381_Fr_primitive_root)
|
||||
result[i].powUnsafeExponent(exponent)
|
||||
result[i].pow_vartime(exponent)
|
||||
|
||||
while i > 0:
|
||||
result[i-1].square(result[i])
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
# From issue #241
|
||||
|
||||
import
|
||||
../../constantine/math/[
|
||||
arithmetic,
|
||||
io/io_bigints]
|
||||
|
||||
let a = BigInt[64].fromUint(0xa0e5cb56a1c08396'u64)
|
||||
let M = BigInt[64].fromUint(0xae57180eceb0206f'u64)
|
||||
|
||||
var r: BigInt[64]
|
||||
|
||||
r.reduce(a, M)
|
||||
|
||||
let rU64 = 0xa0e5cb56a1c08396'u64 mod 0xae57180eceb0206f'u64
|
||||
echo r.toHex()
|
||||
|
||||
doAssert rU64 == a.limbs[0].uint64
|
||||
doAssert bool(a == r)
|
|
@ -12,9 +12,8 @@ import
|
|||
# Third-party
|
||||
gmp,
|
||||
# Internal
|
||||
../../constantine/math/io/io_bigints,
|
||||
../../constantine/math/arithmetic,
|
||||
../../constantine/platforms/primitives,
|
||||
../../constantine/math/[arithmetic, io/io_bigints],
|
||||
../../constantine/platforms/[primitives, codecs],
|
||||
# Test utilities
|
||||
../../helpers/prng_unsafe
|
||||
|
||||
|
@ -26,6 +25,9 @@ const CryptoModSizes = [
|
|||
# Modulus sizes occuring in crypto
|
||||
# To be tested more often
|
||||
|
||||
# Special-case
|
||||
64,
|
||||
|
||||
# RSA
|
||||
1024,
|
||||
2048,
|
||||
|
@ -59,7 +61,7 @@ macro testRandomModSizes(numSizes: static int, aBits, mBits, body: untyped): unt
|
|||
result = newStmtList()
|
||||
|
||||
for _ in 0 ..< numSizes:
|
||||
let aBitsVal = bitSizeRNG.rand(126 .. 8192)
|
||||
let aBitsVal = bitSizeRNG.rand(62 .. 8192)
|
||||
let mBitsVal = block:
|
||||
# Pick from curve modulus if odd
|
||||
if bool(bitSizeRNG.rand(high(int)) and 1):
|
||||
|
@ -95,7 +97,7 @@ proc main() =
|
|||
mpz_init(m)
|
||||
mpz_init(r)
|
||||
|
||||
testRandomModSizes(12, aBits, mBits):
|
||||
testRandomModSizes(60, aBits, mBits):
|
||||
# echo "--------------------------------------------------------------------------------"
|
||||
echo "Testing: random dividend (" & align($aBits, 4) & "-bit) -- random modulus (" & align($mBits, 4) & "-bit)"
|
||||
|
||||
|
|
|
@ -0,0 +1,125 @@
|
|||
# Constantine
|
||||
# Copyright (c) 2018-2019 Status Research & Development GmbH
|
||||
# Copyright (c) 2020-Present Mamy André-Ratsimbazafy
|
||||
# Licensed and distributed under either of
|
||||
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
|
||||
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
|
||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||
|
||||
import
|
||||
../../constantine/math_arbitrary_precision/arithmetic/[bigints_views, limbs_views, limbs_division],
|
||||
../../constantine/platforms/abstractions,
|
||||
../../helpers/prng_unsafe,
|
||||
|
||||
std/[times, strformat],
|
||||
gmp
|
||||
|
||||
# debug
|
||||
import
|
||||
../../constantine/platforms/codecs,
|
||||
../../constantine/math/io/io_bigints
|
||||
|
||||
const # https://gmplib.org/manual/Integer-Import-and-Export.html
|
||||
GMP_WordLittleEndian = -1'i32
|
||||
GMP_WordNativeEndian = 0'i32
|
||||
GMP_WordBigEndian = 1'i32
|
||||
|
||||
GMP_MostSignificantWordFirst = 1'i32
|
||||
GMP_LeastSignificantWordFirst = -1'i32
|
||||
|
||||
const
|
||||
moduleName = "t_powmod_vs_gmp"
|
||||
Iters = 100
|
||||
|
||||
var rng: RngState
|
||||
let seed = uint32(getTime().toUnix() and (1'i64 shl 32 - 1)) # unixTime mod 2^32
|
||||
rng.seed(seed)
|
||||
echo "\n------------------------------------------------------\n"
|
||||
echo moduleName, " xoshiro512** seed: ", seed
|
||||
|
||||
proc fromHex(T: typedesc, hex: string): T =
|
||||
result.unmarshal(array[sizeof(T), byte].fromHex(hex), WordBitWidth, bigEndian)
|
||||
|
||||
proc toHex(a: mpz_t): string =
|
||||
let size = mpz_sizeinbase(a, 16)
|
||||
result.setLen(size+2)
|
||||
|
||||
result[0] = '0'
|
||||
result[1] = 'x'
|
||||
discard mpz_get_str(cast[cstring](result[2].addr), 16, a)
|
||||
|
||||
proc test(rng: var RngState) =
|
||||
let
|
||||
aLen = rng.random_unsafe(1..100)
|
||||
eLen = rng.random_unsafe(1..400)
|
||||
mLen = rng.random_unsafe(1..100)
|
||||
|
||||
var
|
||||
a = newSeq[SecretWord](aLen)
|
||||
e = newSeq[byte](eLen)
|
||||
M = newSeq[SecretWord](mLen)
|
||||
|
||||
rGMP = newSeq[SecretWord](mLen)
|
||||
rCtt = newSeq[SecretWord](mLen)
|
||||
|
||||
for word in a.mitems():
|
||||
word = SecretWord rng.next()
|
||||
for octet in e.mitems():
|
||||
octet = byte rng.next()
|
||||
for word in M.mitems():
|
||||
word = SecretWord rng.next()
|
||||
|
||||
var aa, ee, mm, rr: mpz_t
|
||||
mpz_init(aa)
|
||||
mpz_init(ee)
|
||||
mpz_init(mm)
|
||||
mpz_init(rr)
|
||||
|
||||
aa.mpz_import(aLen, GMP_LeastSignificantWordFirst, sizeof(SecretWord), GMP_WordNativeEndian, 0, a[0].addr)
|
||||
ee.mpz_import(eLen, GMP_MostSignificantWordFirst, sizeof(byte), GMP_WordNativeEndian, 0, e[0].addr)
|
||||
mm.mpz_import(mLen, GMP_LeastSignificantWordFirst, sizeof(SecretWord), GMP_WordNativeEndian, 0, M[0].addr)
|
||||
|
||||
debug:
|
||||
echo "----------------------------------------------"
|
||||
echo " a (Ctt): ", a.toString()
|
||||
echo " a (GMP): ", aa.toHex()
|
||||
echo " e (Ctt): ", e.toHex()
|
||||
echo " e (GMP): ", ee.toHex()
|
||||
echo " M (Ctt): ", M.toString()
|
||||
echo " M (GMP): ", mm.toHex()
|
||||
|
||||
rr.mpz_powm(aa, ee, mm)
|
||||
|
||||
var rWritten: csize
|
||||
discard rGMP[0].addr.mpz_export(rWritten.addr, GMP_LeastSignificantWordFirst, sizeof(SecretWord), GMP_WordNativeEndian, 0, rr)
|
||||
|
||||
debug:
|
||||
echo " r (GMP): ", rr.toHex()
|
||||
|
||||
mpz_clear(aa)
|
||||
mpz_clear(ee)
|
||||
mpz_clear(mm)
|
||||
mpz_clear(rr)
|
||||
|
||||
let
|
||||
aBits = a.getBits_vartime()
|
||||
eBits = e.getBits_vartime()
|
||||
mBits = M.getBits_vartime()
|
||||
|
||||
rCtt.powMod_vartime(a, e, M, window = 4)
|
||||
|
||||
debug:
|
||||
echo " r (GMP): " & rGMP.toString()
|
||||
echo " r (Ctt): " & rCtt.toString()
|
||||
|
||||
doAssert (seq[BaseType])(rGMP) == (seq[BaseType])(rCtt), block:
|
||||
"Failure with sizes:\n" &
|
||||
&" a.len (word): {a.len:>3}, a.bits: {aBits:>4}\n" &
|
||||
&" e.len (byte): {e.len:>3}, e.bits: {eBits:>4}\n" &
|
||||
&" M.len (word): {M.len:>3}, M.bits: {mBits:>4}\n"
|
||||
|
||||
|
||||
for _ in 0 ..< Iters:
|
||||
rng.test()
|
||||
stdout.write'.'
|
||||
stdout.write'\n'
|
|
@ -57,15 +57,15 @@ proc test_sameBaseProduct(C: static Curve, gen: RandomGen) =
|
|||
b.div2()
|
||||
|
||||
var xa = x
|
||||
xa.powUnsafeExponent(a, window = 3)
|
||||
xa.pow_vartime(a, window = 3)
|
||||
|
||||
var xb = x
|
||||
xb.powUnsafeExponent(b, window = 3)
|
||||
xb.pow_vartime(b, window = 3)
|
||||
|
||||
var xapb = x
|
||||
var apb: BigInt[128]
|
||||
discard apb.sum(a, b)
|
||||
xapb.powUnsafeExponent(apb, window = 3)
|
||||
xapb.pow_vartime(apb, window = 3)
|
||||
|
||||
xa *= xb
|
||||
doAssert: bool(xa == xapb)
|
||||
|
@ -82,10 +82,10 @@ proc test_powpow(C: static Curve, gen: RandomGen) =
|
|||
|
||||
var y = x
|
||||
|
||||
x.powUnsafeExponent(a, window = 3)
|
||||
x.powUnsafeExponent(b, window = 3)
|
||||
x.pow_vartime(a, window = 3)
|
||||
x.pow_vartime(b, window = 3)
|
||||
|
||||
y.powUnsafeExponent(ab, window = 3)
|
||||
y.pow_vartime(ab, window = 3)
|
||||
doAssert: bool(x == y)
|
||||
|
||||
proc test_powprod(C: static Curve, gen: RandomGen) =
|
||||
|
@ -98,10 +98,10 @@ proc test_powprod(C: static Curve, gen: RandomGen) =
|
|||
var xy{.noInit.}: Fp12[C]
|
||||
xy.prod(x, y)
|
||||
|
||||
xy.powUnsafeExponent(a, window=3)
|
||||
xy.pow_vartime(a, window=3)
|
||||
|
||||
x.powUnsafeExponent(a, window=3)
|
||||
y.powUnsafeExponent(a, window=3)
|
||||
x.pow_vartime(a, window=3)
|
||||
y.pow_vartime(a, window=3)
|
||||
|
||||
x *= y
|
||||
|
||||
|
@ -112,7 +112,7 @@ proc test_pow0(C: static Curve, gen: RandomGen) =
|
|||
var x = rng.random_elem(Fp12[C], gen)
|
||||
var a: BigInt[128] # 0-init
|
||||
|
||||
x.powUnsafeExponent(a, window=3)
|
||||
x.pow_vartime(a, window=3)
|
||||
doAssert: bool x.isOne()
|
||||
|
||||
proc test_0pow0(C: static Curve, gen: RandomGen) =
|
||||
|
@ -120,7 +120,7 @@ proc test_0pow0(C: static Curve, gen: RandomGen) =
|
|||
var x: Fp12[C] # 0-init
|
||||
var a: BigInt[128] # 0-init
|
||||
|
||||
x.powUnsafeExponent(a, window=3)
|
||||
x.pow_vartime(a, window=3)
|
||||
doAssert: bool x.isOne()
|
||||
|
||||
proc test_powinv(C: static Curve, gen: RandomGen) =
|
||||
|
@ -137,10 +137,10 @@ proc test_powinv(C: static Curve, gen: RandomGen) =
|
|||
cswap(a, b, a < b)
|
||||
|
||||
var xa = x
|
||||
xa.powUnsafeExponent(a, window = 3)
|
||||
xa.pow_vartime(a, window = 3)
|
||||
|
||||
var xb = x
|
||||
xb.powUnsafeExponent(b, window = 3)
|
||||
xb.pow_vartime(b, window = 3)
|
||||
|
||||
xb.inv()
|
||||
xa *= xb
|
||||
|
@ -148,7 +148,7 @@ proc test_powinv(C: static Curve, gen: RandomGen) =
|
|||
var xamb = x
|
||||
var amb: BigInt[128]
|
||||
discard amb.diff(a, b)
|
||||
xamb.powUnsafeExponent(amb, window = 3)
|
||||
xamb.pow_vartime(amb, window = 3)
|
||||
|
||||
doAssert: bool(xa == xamb)
|
||||
|
||||
|
@ -160,10 +160,10 @@ proc test_invpow(C: static Curve, gen: RandomGen) =
|
|||
var a = rng.random_elem(BigInt[128], gen)
|
||||
|
||||
var xa = x
|
||||
xa.powUnsafeExponent(a, window = 3)
|
||||
xa.pow_vartime(a, window = 3)
|
||||
|
||||
var ya = y
|
||||
ya.powUnsafeExponent(a, window = 3)
|
||||
ya.pow_vartime(a, window = 3)
|
||||
ya.inv()
|
||||
xa *= ya
|
||||
|
||||
|
@ -171,7 +171,7 @@ proc test_invpow(C: static Curve, gen: RandomGen) =
|
|||
var invy = y
|
||||
invy.inv()
|
||||
xqya *= invy
|
||||
xqya.powUnsafeExponent(a, window = 3)
|
||||
xqya.pow_vartime(a, window = 3)
|
||||
|
||||
doAssert: bool(xa == xqya)
|
||||
|
||||
|
|
|
@ -74,7 +74,7 @@ proc runFrobeniusTowerTests*[N](
|
|||
var a = rng.random_elem(Field, gen)
|
||||
var fa {.noInit.}: typeof(a)
|
||||
fa.frobenius_map(a, k = 1)
|
||||
a.powUnsafeExponent(Field.fieldMod(), window = 3)
|
||||
a.pow_vartime(Field.fieldMod(), window = 3)
|
||||
check: bool(a == fa)
|
||||
|
||||
staticFor(curve, TestCurves):
|
||||
|
@ -90,8 +90,8 @@ proc runFrobeniusTowerTests*[N](
|
|||
var fa {.noInit.}: typeof(a)
|
||||
fa.frobenius_map(a, k = 2)
|
||||
|
||||
a.powUnsafeExponent(Field.fieldMod(), window = 3)
|
||||
a.powUnsafeExponent(Field.fieldMod(), window = 3)
|
||||
a.pow_vartime(Field.fieldMod(), window = 3)
|
||||
a.pow_vartime(Field.fieldMod(), window = 3)
|
||||
|
||||
check:
|
||||
bool(a == fa)
|
||||
|
@ -109,9 +109,9 @@ proc runFrobeniusTowerTests*[N](
|
|||
var fa {.noInit.}: typeof(a)
|
||||
fa.frobenius_map(a, k = 3)
|
||||
|
||||
a.powUnsafeExponent(Field.fieldMod(), window = 3)
|
||||
a.powUnsafeExponent(Field.fieldMod(), window = 3)
|
||||
a.powUnsafeExponent(Field.fieldMod(), window = 3)
|
||||
a.pow_vartime(Field.fieldMod(), window = 3)
|
||||
a.pow_vartime(Field.fieldMod(), window = 3)
|
||||
a.pow_vartime(Field.fieldMod(), window = 3)
|
||||
check: bool(a == fa)
|
||||
|
||||
staticFor(curve, TestCurves):
|
||||
|
|
|
@ -151,7 +151,7 @@ proc main() =
|
|||
|
||||
let expected = "0x0636759a0f3034fa47174b2c0334902f11e9915b7bd89c6a2b3082b109abbc9837da17201f6d8286fe6203caa1b9d4c8"
|
||||
|
||||
x.powUnsafeExponent(exponent)
|
||||
x.pow_vartime(exponent)
|
||||
let computed = x.toHex()
|
||||
|
||||
check:
|
||||
|
@ -338,7 +338,7 @@ proc main_anti_regression =
|
|||
# # square of "0x406e5e74ee09c84fa0c59f2db3ac814a4937e2f57ecd3c0af4265e04598d643c5b772a6549a2d9b825445c34b8ba100fe8d912e61cfda43d"
|
||||
# a.fromHex("0x1e6511b2bfabd7d32d8df7492c66df29ade7fdb21bb0d8f6cacfccb05e45a812a27cd087e1bbb2d202ee29f75a021a6a68d990a2a5e73410")
|
||||
|
||||
# a.powUnsafeExponent(FKM12_447.getPrimeMinus1div2_BE())
|
||||
# a.pow_vartime(FKM12_447.getPrimeMinus1div2_BE())
|
||||
# check: bool a.isOne()
|
||||
|
||||
test "#42 - a^(p-3)/4 (inverse square root)":
|
||||
|
@ -357,7 +357,7 @@ proc main_anti_regression =
|
|||
discard pm3div4.sub SecretWord(3)
|
||||
pm3div4.shiftRight(2)
|
||||
|
||||
a.powUnsafeExponent(pm3div4)
|
||||
a.pow_vartime(pm3div4)
|
||||
|
||||
var expected: Fp[BLS12_381]
|
||||
expected.fromHex"ec6fc6cd4d8a3afe1114d5288759b40a87b6b2f001c8c41693f13132be04de21ca22ea38bded36f3748e06d7b4c348c"
|
||||
|
@ -380,7 +380,7 @@ proc main_anti_regression =
|
|||
discard pm3div4.sub SecretWord(3)
|
||||
pm3div4.shiftRight(2)
|
||||
|
||||
a.powUnsafeExponent(pm3div4)
|
||||
a.pow_vartime(pm3div4)
|
||||
|
||||
var expected: Fp[BLS12_381]
|
||||
expected.fromHex"16bf380e9b6d01aa6961c4fcee02a00cb827b52d0eb2b541ea8b598d32100d0bd7dc9a600852b49f0379e63ba9c5d35e"
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
{
|
||||
"func": "modexp",
|
||||
"fork": "byzantium",
|
||||
"data":
|
||||
[
|
||||
{
|
||||
"Input": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002003fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2efffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f",
|
||||
"Expected": "0000000000000000000000000000000000000000000000000000000000000001",
|
||||
"Name": "eip_example1",
|
||||
"Gas": 13056,
|
||||
"NoBenchmark": false
|
||||
},
|
||||
{
|
||||
"Input": "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2efffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f",
|
||||
"Expected": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"Name": "eip_example2",
|
||||
"Gas": 13056,
|
||||
"NoBenchmark": false
|
||||
},
|
||||
{
|
||||
"Input": "000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040e09ad9675465c53a109fac66a445c91b292d2bb2c5268addb30cd82f80fcb0033ff97c80a5fc6f39193ae969c6ede6710a6b7ac27078a06d90ef1c72e5c85fb502fc9e1f6beb81516545975218075ec2af118cd8798df6e08a147c60fd6095ac2bb02c2908cf4dd7c81f11c289e4bce98f3553768f392a80ce22bf5c4f4a248c6b",
|
||||
"Expected": "60008f1614cc01dcfb6bfb09c625cf90b47d4468db81b5f8b7a39d42f332eab9b2da8f2d95311648a8f243f4bb13cfb3d8f7f2a3c014122ebb3ed41b02783adc",
|
||||
"Name": "nagydani-1-square",
|
||||
"Gas": 204,
|
||||
"NoBenchmark": false
|
||||
},
|
||||
{
|
||||
"Input": "000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040e09ad9675465c53a109fac66a445c91b292d2bb2c5268addb30cd82f80fcb0033ff97c80a5fc6f39193ae969c6ede6710a6b7ac27078a06d90ef1c72e5c85fb503fc9e1f6beb81516545975218075ec2af118cd8798df6e08a147c60fd6095ac2bb02c2908cf4dd7c81f11c289e4bce98f3553768f392a80ce22bf5c4f4a248c6b",
|
||||
"Expected": "4834a46ba565db27903b1c720c9d593e84e4cbd6ad2e64b31885d944f68cd801f92225a8961c952ddf2797fa4701b330c85c4b363798100b921a1a22a46a7fec",
|
||||
"Name": "nagydani-1-qube",
|
||||
"Gas": 204,
|
||||
"NoBenchmark": false
|
||||
},
|
||||
{
|
||||
"Input": "000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000040e09ad9675465c53a109fac66a445c91b292d2bb2c5268addb30cd82f80fcb0033ff97c80a5fc6f39193ae969c6ede6710a6b7ac27078a06d90ef1c72e5c85fb5010001fc9e1f6beb81516545975218075ec2af118cd8798df6e08a147c60fd6095ac2bb02c2908cf4dd7c81f11c289e4bce98f3553768f392a80ce22bf5c4f4a248c6b",
|
||||
"Expected": "c36d804180c35d4426b57b50c5bfcca5c01856d104564cd513b461d3c8b8409128a5573e416d0ebe38f5f736766d9dc27143e4da981dfa4d67f7dc474cbee6d2",
|
||||
"Name": "nagydani-1-pow0x10001",
|
||||
"Gas": 3276,
|
||||
"NoBenchmark": false
|
||||
},
|
||||
{
|
||||
"Input": "000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000080cad7d991a00047dd54d3399b6b0b937c718abddef7917c75b6681f40cc15e2be0003657d8d4c34167b2f0bbbca0ccaa407c2a6a07d50f1517a8f22979ce12a81dcaf707cc0cebfc0ce2ee84ee7f77c38b9281b9822a8d3de62784c089c9b18dcb9a2a5eecbede90ea788a862a9ddd9d609c2c52972d63e289e28f6a590ffbf5102e6d893b80aeed5e6e9ce9afa8a5d5675c93a32ac05554cb20e9951b2c140e3ef4e433068cf0fb73bc9f33af1853f64aa27a0028cbf570d7ac9048eae5dc7b28c87c31e5810f1e7fa2cda6adf9f1076dbc1ec1238560071e7efc4e9565c49be9e7656951985860a558a754594115830bcdb421f741408346dd5997bb01c287087",
|
||||
"Expected": "981dd99c3b113fae3e3eaa9435c0dc96779a23c12a53d1084b4f67b0b053a27560f627b873e3f16ad78f28c94f14b6392def26e4d8896c5e3c984e50fa0b3aa44f1da78b913187c6128baa9340b1e9c9a0fd02cb78885e72576da4a8f7e5a113e173a7a2889fde9d407bd9f06eb05bc8fc7b4229377a32941a02bf4edcc06d70",
|
||||
"Name": "nagydani-2-square",
|
||||
"Gas": 665,
|
||||
"NoBenchmark": false
|
||||
},
|
||||
{
|
||||
"Input": "000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000080cad7d991a00047dd54d3399b6b0b937c718abddef7917c75b6681f40cc15e2be0003657d8d4c34167b2f0bbbca0ccaa407c2a6a07d50f1517a8f22979ce12a81dcaf707cc0cebfc0ce2ee84ee7f77c38b9281b9822a8d3de62784c089c9b18dcb9a2a5eecbede90ea788a862a9ddd9d609c2c52972d63e289e28f6a590ffbf5103e6d893b80aeed5e6e9ce9afa8a5d5675c93a32ac05554cb20e9951b2c140e3ef4e433068cf0fb73bc9f33af1853f64aa27a0028cbf570d7ac9048eae5dc7b28c87c31e5810f1e7fa2cda6adf9f1076dbc1ec1238560071e7efc4e9565c49be9e7656951985860a558a754594115830bcdb421f741408346dd5997bb01c287087",
|
||||
"Expected": "d89ceb68c32da4f6364978d62aaa40d7b09b59ec61eb3c0159c87ec3a91037f7dc6967594e530a69d049b64adfa39c8fa208ea970cfe4b7bcd359d345744405afe1cbf761647e32b3184c7fbe87cee8c6c7ff3b378faba6c68b83b6889cb40f1603ee68c56b4c03d48c595c826c041112dc941878f8c5be828154afd4a16311f",
|
||||
"Name": "nagydani-2-qube",
|
||||
"Gas": 665,
|
||||
"NoBenchmark": false
|
||||
},
|
||||
{
|
||||
"Input": "000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000080cad7d991a00047dd54d3399b6b0b937c718abddef7917c75b6681f40cc15e2be0003657d8d4c34167b2f0bbbca0ccaa407c2a6a07d50f1517a8f22979ce12a81dcaf707cc0cebfc0ce2ee84ee7f77c38b9281b9822a8d3de62784c089c9b18dcb9a2a5eecbede90ea788a862a9ddd9d609c2c52972d63e289e28f6a590ffbf51010001e6d893b80aeed5e6e9ce9afa8a5d5675c93a32ac05554cb20e9951b2c140e3ef4e433068cf0fb73bc9f33af1853f64aa27a0028cbf570d7ac9048eae5dc7b28c87c31e5810f1e7fa2cda6adf9f1076dbc1ec1238560071e7efc4e9565c49be9e7656951985860a558a754594115830bcdb421f741408346dd5997bb01c287087",
|
||||
"Expected": "ad85e8ef13fd1dd46eae44af8b91ad1ccae5b7a1c92944f92a19f21b0b658139e0cabe9c1f679507c2de354bf2c91ebd965d1e633978a830d517d2f6f8dd5fd58065d58559de7e2334a878f8ec6992d9b9e77430d4764e863d77c0f87beede8f2f7f2ab2e7222f85cc9d98b8467f4bb72e87ef2882423ebdb6daf02dddac6db2",
|
||||
"Name": "nagydani-2-pow0x10001",
|
||||
"Gas": 10649,
|
||||
"NoBenchmark": false
|
||||
},
|
||||
{
|
||||
"Input": "000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000100c9130579f243e12451760976261416413742bd7c91d39ae087f46794062b8c239f2a74abf3918605a0e046a7890e049475ba7fbb78f5de6490bd22a710cc04d30088179a919d86c2da62cf37f59d8f258d2310d94c24891be2d7eeafaa32a8cb4b0cfe5f475ed778f45907dc8916a73f03635f233f7a77a00a3ec9ca6761a5bbd558a2318ecd0caa1c5016691523e7e1fa267dd35e70c66e84380bdcf7c0582f540174e572c41f81e93da0b757dff0b0fe23eb03aa19af0bdec3afb474216febaacb8d0381e631802683182b0fe72c28392539850650b70509f54980241dc175191a35d967288b532a7a8223ce2440d010615f70df269501944d4ec16fe4a3cb02d7a85909174757835187cb52e71934e6c07ef43b4c46fc30bbcd0bc72913068267c54a4aabebb493922492820babdeb7dc9b1558fcf7bd82c37c82d3147e455b623ab0efa752fe0b3a67ca6e4d126639e645a0bf417568adbb2a6a4eef62fa1fa29b2a5a43bebea1f82193a7dd98eb483d09bb595af1fa9c97c7f41f5649d976aee3e5e59e2329b43b13bea228d4a93f16ba139ccb511de521ffe747aa2eca664f7c9e33da59075cc335afcd2bf3ae09765f01ab5a7c3e3938ec168b74724b5074247d200d9970382f683d6059b94dbc336603d1dfee714e4b447ac2fa1d99ecb4961da2854e03795ed758220312d101e1e3d87d5313a6d052aebde75110363d",
|
||||
"Expected": "affc7507ea6d84751ec6b3f0d7b99dbcc263f33330e450d1b3ff0bc3d0874320bf4edd57debd587306988157958cb3cfd369cc0c9c198706f635c9e0f15d047df5cb44d03e2727f26b083c4ad8485080e1293f171c1ed52aef5993a5815c35108e848c951cf1e334490b4a539a139e57b68f44fee583306f5b85ffa57206b3ee5660458858534e5386b9584af3c7f67806e84c189d695e5eb96e1272d06ec2df5dc5fabc6e94b793718c60c36be0a4d031fc84cd658aa72294b2e16fc240aef70cb9e591248e38bd49c5a554d1afa01f38dab72733092f7555334bbef6c8c430119840492380aa95fa025dcf699f0a39669d812b0c6946b6091e6e235337b6f8",
|
||||
"Name": "nagydani-3-square",
|
||||
"Gas": 1894,
|
||||
"NoBenchmark": false
|
||||
},
|
||||
{
|
||||
"Input": "000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000100c9130579f243e12451760976261416413742bd7c91d39ae087f46794062b8c239f2a74abf3918605a0e046a7890e049475ba7fbb78f5de6490bd22a710cc04d30088179a919d86c2da62cf37f59d8f258d2310d94c24891be2d7eeafaa32a8cb4b0cfe5f475ed778f45907dc8916a73f03635f233f7a77a00a3ec9ca6761a5bbd558a2318ecd0caa1c5016691523e7e1fa267dd35e70c66e84380bdcf7c0582f540174e572c41f81e93da0b757dff0b0fe23eb03aa19af0bdec3afb474216febaacb8d0381e631802683182b0fe72c28392539850650b70509f54980241dc175191a35d967288b532a7a8223ce2440d010615f70df269501944d4ec16fe4a3cb03d7a85909174757835187cb52e71934e6c07ef43b4c46fc30bbcd0bc72913068267c54a4aabebb493922492820babdeb7dc9b1558fcf7bd82c37c82d3147e455b623ab0efa752fe0b3a67ca6e4d126639e645a0bf417568adbb2a6a4eef62fa1fa29b2a5a43bebea1f82193a7dd98eb483d09bb595af1fa9c97c7f41f5649d976aee3e5e59e2329b43b13bea228d4a93f16ba139ccb511de521ffe747aa2eca664f7c9e33da59075cc335afcd2bf3ae09765f01ab5a7c3e3938ec168b74724b5074247d200d9970382f683d6059b94dbc336603d1dfee714e4b447ac2fa1d99ecb4961da2854e03795ed758220312d101e1e3d87d5313a6d052aebde75110363d",
|
||||
"Expected": "1b280ecd6a6bf906b806d527c2a831e23b238f89da48449003a88ac3ac7150d6a5e9e6b3be4054c7da11dd1e470ec29a606f5115801b5bf53bc1900271d7c3ff3cd5ed790d1c219a9800437a689f2388ba1a11d68f6a8e5b74e9a3b1fac6ee85fc6afbac599f93c391f5dc82a759e3c6c0ab45ce3f5d25d9b0c1bf94cf701ea6466fc9a478dacc5754e593172b5111eeba88557048bceae401337cd4c1182ad9f700852bc8c99933a193f0b94cf1aedbefc48be3bc93ef5cb276d7c2d5462ac8bb0c8fe8923a1db2afe1c6b90d59c534994a6a633f0ead1d638fdc293486bb634ff2c8ec9e7297c04241a61c37e3ae95b11d53343d4ba2b4cc33d2cfa7eb705e",
|
||||
"Name": "nagydani-3-qube",
|
||||
"Gas": 1894,
|
||||
"NoBenchmark": false
|
||||
},
|
||||
{
|
||||
"Input": "000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000100c9130579f243e12451760976261416413742bd7c91d39ae087f46794062b8c239f2a74abf3918605a0e046a7890e049475ba7fbb78f5de6490bd22a710cc04d30088179a919d86c2da62cf37f59d8f258d2310d94c24891be2d7eeafaa32a8cb4b0cfe5f475ed778f45907dc8916a73f03635f233f7a77a00a3ec9ca6761a5bbd558a2318ecd0caa1c5016691523e7e1fa267dd35e70c66e84380bdcf7c0582f540174e572c41f81e93da0b757dff0b0fe23eb03aa19af0bdec3afb474216febaacb8d0381e631802683182b0fe72c28392539850650b70509f54980241dc175191a35d967288b532a7a8223ce2440d010615f70df269501944d4ec16fe4a3cb010001d7a85909174757835187cb52e71934e6c07ef43b4c46fc30bbcd0bc72913068267c54a4aabebb493922492820babdeb7dc9b1558fcf7bd82c37c82d3147e455b623ab0efa752fe0b3a67ca6e4d126639e645a0bf417568adbb2a6a4eef62fa1fa29b2a5a43bebea1f82193a7dd98eb483d09bb595af1fa9c97c7f41f5649d976aee3e5e59e2329b43b13bea228d4a93f16ba139ccb511de521ffe747aa2eca664f7c9e33da59075cc335afcd2bf3ae09765f01ab5a7c3e3938ec168b74724b5074247d200d9970382f683d6059b94dbc336603d1dfee714e4b447ac2fa1d99ecb4961da2854e03795ed758220312d101e1e3d87d5313a6d052aebde75110363d",
|
||||
"Expected": "37843d7c67920b5f177372fa56e2a09117df585f81df8b300fba245b1175f488c99476019857198ed459ed8d9799c377330e49f4180c4bf8e8f66240c64f65ede93d601f957b95b83efdee1e1bfde74169ff77002eaf078c71815a9220c80b2e3b3ff22c2f358111d816ebf83c2999026b6de50bfc711ff68705d2f40b753424aefc9f70f08d908b5a20276ad613b4ab4309a3ea72f0c17ea9df6b3367d44fb3acab11c333909e02e81ea2ed404a712d3ea96bba87461720e2d98723e7acd0520ac1a5212dbedcd8dc0c1abf61d4719e319ff4758a774790b8d463cdfe131d1b2dcfee52d002694e98e720cb6ae7ccea353bc503269ba35f0f63bf8d7b672a76",
|
||||
"Name": "nagydani-3-pow0x10001",
|
||||
"Gas": 30310,
|
||||
"NoBenchmark": false
|
||||
},
|
||||
{
|
||||
"Input": "000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000200db34d0e438249c0ed685c949cc28776a05094e1c48691dc3f2dca5fc3356d2a0663bd376e4712839917eb9a19c670407e2c377a2de385a3ff3b52104f7f1f4e0c7bf7717fb913896693dc5edbb65b760ef1b00e42e9d8f9af17352385e1cd742c9b006c0f669995cb0bb21d28c0aced2892267637b6470d8cee0ab27fc5d42658f6e88240c31d6774aa60a7ebd25cd48b56d0da11209f1928e61005c6eb709f3e8e0aaf8d9b10f7d7e296d772264dc76897ccdddadc91efa91c1903b7232a9e4c3b941917b99a3bc0c26497dedc897c25750af60237aa67934a26a2bc491db3dcc677491944bc1f51d3e5d76b8d846a62db03dedd61ff508f91a56d71028125035c3a44cbb041497c83bf3e4ae2a9613a401cc721c547a2afa3b16a2969933d3626ed6d8a7428648f74122fd3f2a02a20758f7f693892c8fd798b39abac01d18506c45e71432639e9f9505719ee822f62ccbf47f6850f096ff77b5afaf4be7d772025791717dbe5abf9b3f40cff7d7aab6f67e38f62faf510747276e20a42127e7500c444f9ed92baf65ade9e836845e39c4316d9dce5f8e2c8083e2c0acbb95296e05e51aab13b6b8f53f06c9c4276e12b0671133218cc3ea907da3bd9a367096d9202128d14846cc2e20d56fc8473ecb07cecbfb8086919f3971926e7045b853d85a69d026195c70f9f7a823536e2a8f4b3e12e94d9b53a934353451094b8102df3143a0057457d75e8c708b6337a6f5a4fd1a06727acf9fb93e2993c62f3378b37d56c85e7b1e00f0145ebf8e4095bd723166293c60b6ac1252291ef65823c9e040ddad14969b3b340a4ef714db093a587c37766d68b8d6b5016e741587e7e6bf7e763b44f0247e64bae30f994d248bfd20541a333e5b225ef6a61199e301738b1e688f70ec1d7fb892c183c95dc543c3e12adf8a5e8b9ca9d04f9445cced3ab256f29e998e69efaa633a7b60e1db5a867924ccab0a171d9d6e1098dfa15acde9553de599eaa56490c8f411e4985111f3d40bddfc5e301edb01547b01a886550a61158f7e2033c59707789bf7c854181d0c2e2a42a93cf09209747d7082e147eb8544de25c3eb14f2e35559ea0c0f5877f2f3fc92132c0ae9da4e45b2f6c866a224ea6d1f28c05320e287750fbc647368d41116e528014cc1852e5531d53e4af938374daba6cee4baa821ed07117253bb3601ddd00d59a3d7fb2ef1f5a2fbba7c429f0cf9a5b3462410fd833a69118f8be9c559b1000cc608fd877fb43f8e65c2d1302622b944462579056874b387208d90623fcdaf93920ca7a9e4ba64ea208758222ad868501cc2c345e2d3a5ea2a17e5069248138c8a79c0251185d29ee73e5afab5354769142d2bf0cb6712727aa6bf84a6245fcdae66e4938d84d1b9dd09a884818622080ff5f98942fb20acd7e0c916c2d5ea7ce6f7e173315384518f",
|
||||
"Expected": "8a5aea5f50dcc03dc7a7a272b5aeebc040554dbc1ffe36753c4fc75f7ed5f6c2cc0de3a922bf96c78bf0643a73025ad21f45a4a5cadd717612c511ab2bff1190fe5f1ae05ba9f8fe3624de1de2a817da6072ddcdb933b50216811dbe6a9ca79d3a3c6b3a476b079fd0d05f04fb154e2dd3e5cb83b148a006f2bcbf0042efb2ae7b916ea81b27aac25c3bf9a8b6d35440062ad8eae34a83f3ffa2cc7b40346b62174a4422584f72f95316f6b2bee9ff232ba9739301c97c99a9ded26c45d72676eb856ad6ecc81d36a6de36d7f9dafafee11baa43a4b0d5e4ecffa7b9b7dcefd58c397dd373e6db4acd2b2c02717712e6289bed7c813b670c4a0c6735aa7f3b0f1ce556eae9fcc94b501b2c8781ba50a8c6220e8246371c3c7359fe4ef9da786ca7d98256754ca4e496be0a9174bedbecb384bdf470779186d6a833f068d2838a88d90ef3ad48ff963b67c39cc5a3ee123baf7bf3125f64e77af7f30e105d72c4b9b5b237ed251e4c122c6d8c1405e736299c3afd6db16a28c6a9cfa68241e53de4cd388271fe534a6a9b0dbea6171d170db1b89858468885d08fecbd54c8e471c3e25d48e97ba450b96d0d87e00ac732aaa0d3ce4309c1064bd8a4c0808a97e0143e43a24cfa847635125cd41c13e0574487963e9d725c01375db99c31da67b4cf65eff555f0c0ac416c727ff8d438ad7c42030551d68c2e7adda0abb1ca7c10",
|
||||
"Name": "nagydani-4-square",
|
||||
"Gas": 5580,
|
||||
"NoBenchmark": false
|
||||
},
|
||||
{
|
||||
"Input": "000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000200db34d0e438249c0ed685c949cc28776a05094e1c48691dc3f2dca5fc3356d2a0663bd376e4712839917eb9a19c670407e2c377a2de385a3ff3b52104f7f1f4e0c7bf7717fb913896693dc5edbb65b760ef1b00e42e9d8f9af17352385e1cd742c9b006c0f669995cb0bb21d28c0aced2892267637b6470d8cee0ab27fc5d42658f6e88240c31d6774aa60a7ebd25cd48b56d0da11209f1928e61005c6eb709f3e8e0aaf8d9b10f7d7e296d772264dc76897ccdddadc91efa91c1903b7232a9e4c3b941917b99a3bc0c26497dedc897c25750af60237aa67934a26a2bc491db3dcc677491944bc1f51d3e5d76b8d846a62db03dedd61ff508f91a56d71028125035c3a44cbb041497c83bf3e4ae2a9613a401cc721c547a2afa3b16a2969933d3626ed6d8a7428648f74122fd3f2a02a20758f7f693892c8fd798b39abac01d18506c45e71432639e9f9505719ee822f62ccbf47f6850f096ff77b5afaf4be7d772025791717dbe5abf9b3f40cff7d7aab6f67e38f62faf510747276e20a42127e7500c444f9ed92baf65ade9e836845e39c4316d9dce5f8e2c8083e2c0acbb95296e05e51aab13b6b8f53f06c9c4276e12b0671133218cc3ea907da3bd9a367096d9202128d14846cc2e20d56fc8473ecb07cecbfb8086919f3971926e7045b853d85a69d026195c70f9f7a823536e2a8f4b3e12e94d9b53a934353451094b8103df3143a0057457d75e8c708b6337a6f5a4fd1a06727acf9fb93e2993c62f3378b37d56c85e7b1e00f0145ebf8e4095bd723166293c60b6ac1252291ef65823c9e040ddad14969b3b340a4ef714db093a587c37766d68b8d6b5016e741587e7e6bf7e763b44f0247e64bae30f994d248bfd20541a333e5b225ef6a61199e301738b1e688f70ec1d7fb892c183c95dc543c3e12adf8a5e8b9ca9d04f9445cced3ab256f29e998e69efaa633a7b60e1db5a867924ccab0a171d9d6e1098dfa15acde9553de599eaa56490c8f411e4985111f3d40bddfc5e301edb01547b01a886550a61158f7e2033c59707789bf7c854181d0c2e2a42a93cf09209747d7082e147eb8544de25c3eb14f2e35559ea0c0f5877f2f3fc92132c0ae9da4e45b2f6c866a224ea6d1f28c05320e287750fbc647368d41116e528014cc1852e5531d53e4af938374daba6cee4baa821ed07117253bb3601ddd00d59a3d7fb2ef1f5a2fbba7c429f0cf9a5b3462410fd833a69118f8be9c559b1000cc608fd877fb43f8e65c2d1302622b944462579056874b387208d90623fcdaf93920ca7a9e4ba64ea208758222ad868501cc2c345e2d3a5ea2a17e5069248138c8a79c0251185d29ee73e5afab5354769142d2bf0cb6712727aa6bf84a6245fcdae66e4938d84d1b9dd09a884818622080ff5f98942fb20acd7e0c916c2d5ea7ce6f7e173315384518f",
|
||||
"Expected": "5a2664252aba2d6e19d9600da582cdd1f09d7a890ac48e6b8da15ae7c6ff1856fc67a841ac2314d283ffa3ca81a0ecf7c27d89ef91a5a893297928f5da0245c99645676b481b7e20a566ee6a4f2481942bee191deec5544600bb2441fd0fb19e2ee7d801ad8911c6b7750affec367a4b29a22942c0f5f4744a4e77a8b654da2a82571037099e9c6d930794efe5cdca73c7b6c0844e386bdca8ea01b3d7807146bb81365e2cdc6475f8c23e0ff84463126189dc9789f72bbce2e3d2d114d728a272f1345122de23df54c922ec7a16e5c2a8f84da8871482bd258c20a7c09bbcd64c7a96a51029bbfe848736a6ba7bf9d931a9b7de0bcaf3635034d4958b20ae9ab3a95a147b0421dd5f7ebff46c971010ebfc4adbbe0ad94d5498c853e7142c450d8c71de4b2f84edbf8acd2e16d00c8115b150b1c30e553dbb82635e781379fe2a56360420ff7e9f70cc64c00aba7e26ed13c7c19622865ae07248daced36416080f35f8cc157a857ed70ea4f347f17d1bee80fa038abd6e39b1ba06b97264388b21364f7c56e192d4b62d9b161405f32ab1e2594e86243e56fcf2cb30d21adef15b9940f91af681da24328c883d892670c6aa47940867a81830a82b82716895db810df1b834640abefb7db2092dd92912cb9a735175bc447be40a503cf22dfe565b4ed7a3293ca0dfd63a507430b323ee248ec82e843b673c97ad730728cebc",
|
||||
"Name": "nagydani-4-qube",
|
||||
"Gas": 5580,
|
||||
"NoBenchmark": false
|
||||
},
|
||||
{
|
||||
"Input": "000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000200db34d0e438249c0ed685c949cc28776a05094e1c48691dc3f2dca5fc3356d2a0663bd376e4712839917eb9a19c670407e2c377a2de385a3ff3b52104f7f1f4e0c7bf7717fb913896693dc5edbb65b760ef1b00e42e9d8f9af17352385e1cd742c9b006c0f669995cb0bb21d28c0aced2892267637b6470d8cee0ab27fc5d42658f6e88240c31d6774aa60a7ebd25cd48b56d0da11209f1928e61005c6eb709f3e8e0aaf8d9b10f7d7e296d772264dc76897ccdddadc91efa91c1903b7232a9e4c3b941917b99a3bc0c26497dedc897c25750af60237aa67934a26a2bc491db3dcc677491944bc1f51d3e5d76b8d846a62db03dedd61ff508f91a56d71028125035c3a44cbb041497c83bf3e4ae2a9613a401cc721c547a2afa3b16a2969933d3626ed6d8a7428648f74122fd3f2a02a20758f7f693892c8fd798b39abac01d18506c45e71432639e9f9505719ee822f62ccbf47f6850f096ff77b5afaf4be7d772025791717dbe5abf9b3f40cff7d7aab6f67e38f62faf510747276e20a42127e7500c444f9ed92baf65ade9e836845e39c4316d9dce5f8e2c8083e2c0acbb95296e05e51aab13b6b8f53f06c9c4276e12b0671133218cc3ea907da3bd9a367096d9202128d14846cc2e20d56fc8473ecb07cecbfb8086919f3971926e7045b853d85a69d026195c70f9f7a823536e2a8f4b3e12e94d9b53a934353451094b81010001df3143a0057457d75e8c708b6337a6f5a4fd1a06727acf9fb93e2993c62f3378b37d56c85e7b1e00f0145ebf8e4095bd723166293c60b6ac1252291ef65823c9e040ddad14969b3b340a4ef714db093a587c37766d68b8d6b5016e741587e7e6bf7e763b44f0247e64bae30f994d248bfd20541a333e5b225ef6a61199e301738b1e688f70ec1d7fb892c183c95dc543c3e12adf8a5e8b9ca9d04f9445cced3ab256f29e998e69efaa633a7b60e1db5a867924ccab0a171d9d6e1098dfa15acde9553de599eaa56490c8f411e4985111f3d40bddfc5e301edb01547b01a886550a61158f7e2033c59707789bf7c854181d0c2e2a42a93cf09209747d7082e147eb8544de25c3eb14f2e35559ea0c0f5877f2f3fc92132c0ae9da4e45b2f6c866a224ea6d1f28c05320e287750fbc647368d41116e528014cc1852e5531d53e4af938374daba6cee4baa821ed07117253bb3601ddd00d59a3d7fb2ef1f5a2fbba7c429f0cf9a5b3462410fd833a69118f8be9c559b1000cc608fd877fb43f8e65c2d1302622b944462579056874b387208d90623fcdaf93920ca7a9e4ba64ea208758222ad868501cc2c345e2d3a5ea2a17e5069248138c8a79c0251185d29ee73e5afab5354769142d2bf0cb6712727aa6bf84a6245fcdae66e4938d84d1b9dd09a884818622080ff5f98942fb20acd7e0c916c2d5ea7ce6f7e173315384518f",
|
||||
"Expected": "bed8b970c4a34849fc6926b08e40e20b21c15ed68d18f228904878d4370b56322d0da5789da0318768a374758e6375bfe4641fca5285ec7171828922160f48f5ca7efbfee4d5148612c38ad683ae4e3c3a053d2b7c098cf2b34f2cb19146eadd53c86b2d7ccf3d83b2c370bfb840913ee3879b1057a6b4e07e110b6bcd5e958bc71a14798c91d518cc70abee264b0d25a4110962a764b364ac0b0dd1ee8abc8426d775ec0f22b7e47b32576afaf1b5a48f64573ed1c5c29f50ab412188d9685307323d990802b81dacc06c6e05a1e901830ba9fcc67688dc29c5e27bde0a6e845ca925f5454b6fb3747edfaa2a5820838fb759eadf57f7cb5cec57fc213ddd8a4298fa079c3c0f472b07fb15aa6a7f0a3780bd296ff6a62e58ef443870b02260bd4fd2bbc98255674b8e1f1f9f8d33c7170b0ebbea4523b695911abbf26e41885344823bd0587115fdd83b721a4e8457a31c9a84b3d3520a07e0e35df7f48e5a9d534d0ec7feef1ff74de6a11e7f93eab95175b6ce22c68d78a642ad642837897ec11349205d8593ac19300207572c38d29ca5dfa03bc14cdbc32153c80e5cc3e739403d34c75915e49beb43094cc6dcafb3665b305ddec9286934ae66ec6b777ca528728c851318eb0f207b39f1caaf96db6eeead6b55ed08f451939314577d42bcc9f97c0b52d0234f88fd07e4c1d7780fdebc025cfffcb572cb27a8c33963",
|
||||
"Name": "nagydani-4-pow0x10001",
|
||||
"Gas": 89292,
|
||||
"NoBenchmark": false
|
||||
},
|
||||
{
|
||||
"Input": "000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000400c5a1611f8be90071a43db23cc2fe01871cc4c0e8ab5743f6378e4fef77f7f6db0095c0727e20225beb665645403453e325ad5f9aeb9ba99bf3c148f63f9c07cf4fe8847ad5242d6b7d4499f93bd47056ddab8f7dee878fc2314f344dbee2a7c41a5d3db91eff372c730c2fdd3a141a4b61999e36d549b9870cf2f4e632c4d5df5f024f81c028000073a0ed8847cfb0593d36a47142f578f05ccbe28c0c06aeb1b1da027794c48db880278f79ba78ae64eedfea3c07d10e0562668d839749dc95f40467d15cf65b9cfc52c7c4bcef1cda3596dd52631aac942f146c7cebd46065131699ce8385b0db1874336747ee020a5698a3d1a1082665721e769567f579830f9d259cec1a836845109c21cf6b25da572512bf3c42fd4b96e43895589042ab60dd41f497db96aec102087fe784165bb45f942859268fd2ff6c012d9d00c02ba83eace047cc5f7b2c392c2955c58a49f0338d6fc58749c9db2155522ac17914ec216ad87f12e0ee95574613942fa615898c4d9e8a3be68cd6afa4e7a003dedbdf8edfee31162b174f965b20ae752ad89c967b3068b6f722c16b354456ba8e280f987c08e0a52d40a2e8f3a59b94d590aeef01879eb7a90b3ee7d772c839c85519cbeaddc0c193ec4874a463b53fcaea3271d80ebfb39b33489365fc039ae549a17a9ff898eea2f4cb27b8dbee4c17b998438575b2b8d107e4a0d66ba7fca85b41a58a8d51f191a35c856dfbe8aef2b00048a694bbccff832d23c8ca7a7ff0b6c0b3011d00b97c86c0628444d267c951d9e4fb8f83e154b8f74fb51aa16535e498235c5597dac9606ed0be3173a3836baa4e7d756ffe1e2879b415d3846bccd538c05b847785699aefde3e305decb600cd8fb0e7d8de5efc26971a6ad4e6d7a2d91474f1023a0ac4b78dc937da0ce607a45974d2cac1c33a2631ff7fe6144a3b2e5cf98b531a9627dea92c1dc82204d09db0439b6a11dd64b484e1263aa45fd9539b6020b55e3baece3986a8bffc1003406348f5c61265099ed43a766ee4f93f5f9c5abbc32a0fd3ac2b35b87f9ec26037d88275bd7dd0a54474995ee34ed3727f3f97c48db544b1980193a4b76a8a3ddab3591ce527f16d91882e67f0103b5cda53f7da54d489fc4ac08b6ab358a5a04aa9daa16219d50bd672a7cb804ed769d218807544e5993f1c27427104b349906a0b654df0bf69328afd3013fbe430155339c39f236df5557bf92f1ded7ff609a8502f49064ec3d1dbfb6c15d3a4c11a4f8acd12278cbf68acd5709463d12e3338a6eddb8c112f199645e23154a8e60879d2a654e3ed9296aa28f134168619691cd2c6b9e2eba4438381676173fc63c2588a3c5910dc149cf3760f0aa9fa9c3f5faa9162b0bf1aac9dd32b706a60ef53cbdb394b6b40222b5bc80eea82ba8958386672564cae3794f977871ab62337cf02e30049201ec12937e7ce79d0f55d9c810e20acf52212aca1d3888949e0e4830aad88d804161230eb89d4d329cc83570fe257217d2119134048dd2ed167646975fc7d77136919a049ea74cf08ddd2b896890bb24a0ba18094a22baa351bf29ad96c66bbb1a598f2ca391749620e62d61c3561a7d3653ccc8892c7b99baaf76bf836e2991cb06d6bc0514568ff0d1ec8bb4b3d6984f5eaefb17d3ea2893722375d3ddb8e389a8eef7d7d198f8e687d6a513983df906099f9a2d23f4f9dec6f8ef2f11fc0a21fac45353b94e00486f5e17d386af42502d09db33cf0cf28310e049c07e88682aeeb00cb833c5174266e62407a57583f1f88b304b7c6e0c84bbe1c0fd423072d37a5bd0aacf764229e5c7cd02473460ba3645cd8e8ae144065bf02d0dd238593d8e230354f67e0b2f23012c23274f80e3ee31e35e2606a4a3f31d94ab755e6d163cff52cbb36b6d0cc67ffc512aeed1dce4d7a0d70ce82f2baba12e8d514dc92a056f994adfb17b5b9712bd5186f27a2fda1f7039c5df2c8587fdc62f5627580c13234b55be4df3056050e2d1ef3218f0dd66cb05265fe1acfb0989d8213f2c19d1735a7cf3fa65d88dad5af52dc2bba22b7abf46c3bc77b5091baab9e8f0ddc4d5e581037de91a9f8dcbc69309be29cc815cf19a20a7585b8b3073edf51fc9baeb3e509b97fa4ecfd621e0fd57bd61cac1b895c03248ff12bdbc57509250df3517e8a3fe1d776836b34ab352b973d932ef708b14f7418f9eceb1d87667e61e3e758649cb083f01b133d37ab2f5afa96d6c84bcacf4efc3851ad308c1e7d9113624fce29fab460ab9d2a48d92cdb281103a5250ad44cb2ff6e67ac670c02fdafb3e0f1353953d6d7d5646ca1568dea55275a050ec501b7c6250444f7219f1ba7521ba3b93d089727ca5f3bbe0d6c1300b423377004954c5628fdb65770b18ced5c9b23a4a5a6d6ef25fe01b4ce278de0bcc4ed86e28a0a68818ffa40970128cf2c38740e80037984428c1bd5113f40ff47512ee6f4e4d8f9b8e8e1b3040d2928d003bd1c1329dc885302fbce9fa81c23b4dc49c7c82d29b52957847898676c89aa5d32b5b0e1c0d5a2b79a19d67562f407f19425687971a957375879d90c5f57c857136c17106c9ab1b99d80e69c8c954ed386493368884b55c939b8d64d26f643e800c56f90c01079d7c534e3b2b7ae352cefd3016da55f6a85eb803b85e2304915fd2001f77c74e28746293c46e4f5f0fd49cf988aafd0026b8e7a3bab2da5cdce1ea26c2e29ec03f4807fac432662b2d6c060be1c7be0e5489de69d0a6e03a4b9117f9244b34a0f1ecba89884f781c6320412413a00c4980287409a2a78c2cd7e65cecebbe4ec1c28cac4dd95f6998e78fc6f1392384331c9436aa10e10e2bf8ad2c4eafbcf276aa7bae64b74428911b3269c749338b0fc5075ad",
|
||||
"Expected": "d61fe4e3f32ac260915b5b03b78a86d11bfc41d973fce5b0cc59035cf8289a8a2e3878ea15fa46565b0d806e2f85b53873ea20ed653869b688adf83f3ef444535bf91598ff7e80f334fb782539b92f39f55310cc4b35349ab7b278346eda9bc37c0d8acd3557fae38197f412f8d9e57ce6a76b7205c23564cab06e5615be7c6f05c3d05ec690cba91da5e89d55b152ff8dd2157dc5458190025cf94b1ad98f7cbe64e9482faba95e6b33844afc640892872b44a9932096508f4a782a4805323808f23e54b6ff9b841dbfa87db3505ae4f687972c18ea0f0d0af89d36c1c2a5b14560c153c3fee406f5cf15cfd1c0bb45d767426d465f2f14c158495069d0c5955a00150707862ecaae30624ebacdd8ac33e4e6aab3ff90b6ba445a84689386b9e945d01823a65874444316e83767290fcff630d2477f49d5d8ffdd200e08ee1274270f86ed14c687895f6caf5ce528bd970c20d2408a9ba66216324c6a011ac4999098362dbd98a038129a2d40c8da6ab88318aa3046cb660327cc44236d9e5d2163bd0959062195c51ed93d0088b6f92051fc99050ece2538749165976233697ab4b610385366e5ce0b02ad6b61c168ecfbedcdf74278a38de340fd7a5fead8e588e294795f9b011e2e60377a89e25c90e145397cdeabc60fd32444a6b7642a611a83c464d8b8976666351b4865c37b02e6dc21dbcdf5f930341707b618cc0f03c3122646b3385c9df9f2ec730eec9d49e7dfc9153b6e6289da8c4f0ebea9ccc1b751948e3bb7171c9e4d57423b0eeeb79095c030cb52677b3f7e0b45c30f645391f3f9c957afa549c4e0b2465b03c67993cd200b1af01035962edbc4c9e89b31c82ac121987d6529dafdeef67a132dc04b6dc68e77f22862040b75e2ceb9ff16da0fca534e6db7bd12fa7b7f51b6c08c1e23dfcdb7acbd2da0b51c87ffbced065a612e9b1c8bba9b7e2d8d7a2f04fcc4aaf355b60d764879a76b5e16762d5f2f55d585d0c8e82df6940960cddfb72c91dfa71f6b4e1c6ca25dfc39a878e998a663c04fe29d5e83b9586d047b4d7ff70a9f0d44f127e7d741685ca75f11629128d916a0ffef4be586a30c4b70389cc746e84ebf177c01ee8a4511cfbb9d1ecf7f7b33c7dd8177896e10bbc82f838dcd6db7ac67de62bf46b6a640fb580c5d1d2708f3862e3d2b645d0d18e49ef088053e3a220adc0e033c2afcfe61c90e32151152eb3caaf746c5e377d541cafc6cbb0cc0fa48b5caf1728f2e1957f5addfc234f1a9d89e40d49356c9172d0561a695fce6dab1d412321bbf407f63766ffd7b6b3d79bcfa07991c5a9709849c1008689e3b47c50d613980bec239fb64185249d055b30375ccb4354d71fe4d05648fbf6c80634dfc3575f2f24abb714c1e4c95e8896763bf4316e954c7ad19e5780ab7a040ca6fb9271f90a8b22ae738daf6cb",
|
||||
"Name": "nagydani-5-square",
|
||||
"Gas": 17868,
|
||||
"NoBenchmark": false
|
||||
},
|
||||
{
|
||||
"Input": "000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000400c5a1611f8be90071a43db23cc2fe01871cc4c0e8ab5743f6378e4fef77f7f6db0095c0727e20225beb665645403453e325ad5f9aeb9ba99bf3c148f63f9c07cf4fe8847ad5242d6b7d4499f93bd47056ddab8f7dee878fc2314f344dbee2a7c41a5d3db91eff372c730c2fdd3a141a4b61999e36d549b9870cf2f4e632c4d5df5f024f81c028000073a0ed8847cfb0593d36a47142f578f05ccbe28c0c06aeb1b1da027794c48db880278f79ba78ae64eedfea3c07d10e0562668d839749dc95f40467d15cf65b9cfc52c7c4bcef1cda3596dd52631aac942f146c7cebd46065131699ce8385b0db1874336747ee020a5698a3d1a1082665721e769567f579830f9d259cec1a836845109c21cf6b25da572512bf3c42fd4b96e43895589042ab60dd41f497db96aec102087fe784165bb45f942859268fd2ff6c012d9d00c02ba83eace047cc5f7b2c392c2955c58a49f0338d6fc58749c9db2155522ac17914ec216ad87f12e0ee95574613942fa615898c4d9e8a3be68cd6afa4e7a003dedbdf8edfee31162b174f965b20ae752ad89c967b3068b6f722c16b354456ba8e280f987c08e0a52d40a2e8f3a59b94d590aeef01879eb7a90b3ee7d772c839c85519cbeaddc0c193ec4874a463b53fcaea3271d80ebfb39b33489365fc039ae549a17a9ff898eea2f4cb27b8dbee4c17b998438575b2b8d107e4a0d66ba7fca85b41a58a8d51f191a35c856dfbe8aef2b00048a694bbccff832d23c8ca7a7ff0b6c0b3011d00b97c86c0628444d267c951d9e4fb8f83e154b8f74fb51aa16535e498235c5597dac9606ed0be3173a3836baa4e7d756ffe1e2879b415d3846bccd538c05b847785699aefde3e305decb600cd8fb0e7d8de5efc26971a6ad4e6d7a2d91474f1023a0ac4b78dc937da0ce607a45974d2cac1c33a2631ff7fe6144a3b2e5cf98b531a9627dea92c1dc82204d09db0439b6a11dd64b484e1263aa45fd9539b6020b55e3baece3986a8bffc1003406348f5c61265099ed43a766ee4f93f5f9c5abbc32a0fd3ac2b35b87f9ec26037d88275bd7dd0a54474995ee34ed3727f3f97c48db544b1980193a4b76a8a3ddab3591ce527f16d91882e67f0103b5cda53f7da54d489fc4ac08b6ab358a5a04aa9daa16219d50bd672a7cb804ed769d218807544e5993f1c27427104b349906a0b654df0bf69328afd3013fbe430155339c39f236df5557bf92f1ded7ff609a8502f49064ec3d1dbfb6c15d3a4c11a4f8acd12278cbf68acd5709463d12e3338a6eddb8c112f199645e23154a8e60879d2a654e3ed9296aa28f134168619691cd2c6b9e2eba4438381676173fc63c2588a3c5910dc149cf3760f0aa9fa9c3f5faa9162b0bf1aac9dd32b706a60ef53cbdb394b6b40222b5bc80eea82ba8958386672564cae3794f977871ab62337cf03e30049201ec12937e7ce79d0f55d9c810e20acf52212aca1d3888949e0e4830aad88d804161230eb89d4d329cc83570fe257217d2119134048dd2ed167646975fc7d77136919a049ea74cf08ddd2b896890bb24a0ba18094a22baa351bf29ad96c66bbb1a598f2ca391749620e62d61c3561a7d3653ccc8892c7b99baaf76bf836e2991cb06d6bc0514568ff0d1ec8bb4b3d6984f5eaefb17d3ea2893722375d3ddb8e389a8eef7d7d198f8e687d6a513983df906099f9a2d23f4f9dec6f8ef2f11fc0a21fac45353b94e00486f5e17d386af42502d09db33cf0cf28310e049c07e88682aeeb00cb833c5174266e62407a57583f1f88b304b7c6e0c84bbe1c0fd423072d37a5bd0aacf764229e5c7cd02473460ba3645cd8e8ae144065bf02d0dd238593d8e230354f67e0b2f23012c23274f80e3ee31e35e2606a4a3f31d94ab755e6d163cff52cbb36b6d0cc67ffc512aeed1dce4d7a0d70ce82f2baba12e8d514dc92a056f994adfb17b5b9712bd5186f27a2fda1f7039c5df2c8587fdc62f5627580c13234b55be4df3056050e2d1ef3218f0dd66cb05265fe1acfb0989d8213f2c19d1735a7cf3fa65d88dad5af52dc2bba22b7abf46c3bc77b5091baab9e8f0ddc4d5e581037de91a9f8dcbc69309be29cc815cf19a20a7585b8b3073edf51fc9baeb3e509b97fa4ecfd621e0fd57bd61cac1b895c03248ff12bdbc57509250df3517e8a3fe1d776836b34ab352b973d932ef708b14f7418f9eceb1d87667e61e3e758649cb083f01b133d37ab2f5afa96d6c84bcacf4efc3851ad308c1e7d9113624fce29fab460ab9d2a48d92cdb281103a5250ad44cb2ff6e67ac670c02fdafb3e0f1353953d6d7d5646ca1568dea55275a050ec501b7c6250444f7219f1ba7521ba3b93d089727ca5f3bbe0d6c1300b423377004954c5628fdb65770b18ced5c9b23a4a5a6d6ef25fe01b4ce278de0bcc4ed86e28a0a68818ffa40970128cf2c38740e80037984428c1bd5113f40ff47512ee6f4e4d8f9b8e8e1b3040d2928d003bd1c1329dc885302fbce9fa81c23b4dc49c7c82d29b52957847898676c89aa5d32b5b0e1c0d5a2b79a19d67562f407f19425687971a957375879d90c5f57c857136c17106c9ab1b99d80e69c8c954ed386493368884b55c939b8d64d26f643e800c56f90c01079d7c534e3b2b7ae352cefd3016da55f6a85eb803b85e2304915fd2001f77c74e28746293c46e4f5f0fd49cf988aafd0026b8e7a3bab2da5cdce1ea26c2e29ec03f4807fac432662b2d6c060be1c7be0e5489de69d0a6e03a4b9117f9244b34a0f1ecba89884f781c6320412413a00c4980287409a2a78c2cd7e65cecebbe4ec1c28cac4dd95f6998e78fc6f1392384331c9436aa10e10e2bf8ad2c4eafbcf276aa7bae64b74428911b3269c749338b0fc5075ad",
|
||||
"Expected": "5f9c70ec884926a89461056ad20ac4c30155e817f807e4d3f5bb743d789c83386762435c3627773fa77da5144451f2a8aad8adba88e0b669f5377c5e9bad70e45c86fe952b613f015a9953b8a5de5eaee4566acf98d41e327d93a35bd5cef4607d025e58951167957df4ff9b1627649d3943805472e5e293d3efb687cfd1e503faafeb2840a3e3b3f85d016051a58e1c9498aab72e63b748d834b31eb05d85dcde65e27834e266b85c75cc4ec0135135e0601cb93eeeb6e0010c8ceb65c4c319623c5e573a2c8c9fbbf7df68a930beb412d3f4dfd146175484f45d7afaa0d2e60684af9b34730f7c8438465ad3e1d0c3237336722f2aa51095bd5759f4b8ab4dda111b684aa3dac62a761722e7ae43495b7709933512c81c4e3c9133a51f7ce9f2b51fcec064f65779666960b4e45df3900f54311f5613e8012dd1b8efd359eda31a778264c72aa8bb419d862734d769076bce2810011989a45374e5c5d8729fec21427f0bf397eacbb4220f603cf463a4b0c94efd858ffd9768cd60d6ce68d755e0fbad007ce5c2223d70c7018345a102e4ab3c60a13a9e7794303156d4c2063e919f2153c13961fb324c80b240742f47773a7a8e25b3e3fb19b00ce839346c6eb3c732fbc6b888df0b1fe0a3d07b053a2e9402c267b2d62f794d8a2840526e3ade15ce2264496ccd7519571dfde47f7a4bb16292241c20b2be59f3f8fb4f6383f232d838c5a22d8c95b6834d9d2ca493f5a505ebe8899503b0e8f9b19e6e2dd81c1628b80016d02097e0134de51054c4e7674824d4d758760fc52377d2cad145e259aa2ffaf54139e1a66b1e0c1c191e32ac59474c6b526f5b3ba07d3e5ec286eddf531fcd5292869be58c9f22ef91026159f7cf9d05ef66b4299f4da48cc1635bf2243051d342d378a22c83390553e873713c0454ce5f3234397111ac3fe3207b86f0ed9fc025c81903e1748103692074f83824fda6341be4f95ff00b0a9a208c267e12fa01825054cc0513629bf3dbb56dc5b90d4316f87654a8be18227978ea0a8a522760cad620d0d14fd38920fb7321314062914275a5f99f677145a6979b156bd82ecd36f23f8e1273cc2759ecc0b2c69d94dad5211d1bed939dd87ed9e07b91d49713a6e16ade0a98aea789f04994e318e4ff2c8a188cd8d43aeb52c6daa3bc29b4af50ea82a247c5cd67b573b34cbadcc0a376d3bbd530d50367b42705d870f2e27a8197ef46070528bfe408360faa2ebb8bf76e9f388572842bcb119f4d84ee34ae31f5cc594f23705a49197b181fb78ed1ec99499c690f843a4d0cf2e226d118e9372271054fbabdcc5c92ae9fefaef0589cd0e722eaf30c1703ec4289c7fd81beaa8a455ccee5298e31e2080c10c366a6fcf56f7d13582ad0bcad037c612b710fc595b70fbefaaca23623b60c6c39b11beb8e5843b6b3dac60f",
|
||||
"Name": "nagydani-5-qube",
|
||||
"Gas": 17868,
|
||||
"NoBenchmark": false
|
||||
},
|
||||
{
|
||||
"Input": "000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000400c5a1611f8be90071a43db23cc2fe01871cc4c0e8ab5743f6378e4fef77f7f6db0095c0727e20225beb665645403453e325ad5f9aeb9ba99bf3c148f63f9c07cf4fe8847ad5242d6b7d4499f93bd47056ddab8f7dee878fc2314f344dbee2a7c41a5d3db91eff372c730c2fdd3a141a4b61999e36d549b9870cf2f4e632c4d5df5f024f81c028000073a0ed8847cfb0593d36a47142f578f05ccbe28c0c06aeb1b1da027794c48db880278f79ba78ae64eedfea3c07d10e0562668d839749dc95f40467d15cf65b9cfc52c7c4bcef1cda3596dd52631aac942f146c7cebd46065131699ce8385b0db1874336747ee020a5698a3d1a1082665721e769567f579830f9d259cec1a836845109c21cf6b25da572512bf3c42fd4b96e43895589042ab60dd41f497db96aec102087fe784165bb45f942859268fd2ff6c012d9d00c02ba83eace047cc5f7b2c392c2955c58a49f0338d6fc58749c9db2155522ac17914ec216ad87f12e0ee95574613942fa615898c4d9e8a3be68cd6afa4e7a003dedbdf8edfee31162b174f965b20ae752ad89c967b3068b6f722c16b354456ba8e280f987c08e0a52d40a2e8f3a59b94d590aeef01879eb7a90b3ee7d772c839c85519cbeaddc0c193ec4874a463b53fcaea3271d80ebfb39b33489365fc039ae549a17a9ff898eea2f4cb27b8dbee4c17b998438575b2b8d107e4a0d66ba7fca85b41a58a8d51f191a35c856dfbe8aef2b00048a694bbccff832d23c8ca7a7ff0b6c0b3011d00b97c86c0628444d267c951d9e4fb8f83e154b8f74fb51aa16535e498235c5597dac9606ed0be3173a3836baa4e7d756ffe1e2879b415d3846bccd538c05b847785699aefde3e305decb600cd8fb0e7d8de5efc26971a6ad4e6d7a2d91474f1023a0ac4b78dc937da0ce607a45974d2cac1c33a2631ff7fe6144a3b2e5cf98b531a9627dea92c1dc82204d09db0439b6a11dd64b484e1263aa45fd9539b6020b55e3baece3986a8bffc1003406348f5c61265099ed43a766ee4f93f5f9c5abbc32a0fd3ac2b35b87f9ec26037d88275bd7dd0a54474995ee34ed3727f3f97c48db544b1980193a4b76a8a3ddab3591ce527f16d91882e67f0103b5cda53f7da54d489fc4ac08b6ab358a5a04aa9daa16219d50bd672a7cb804ed769d218807544e5993f1c27427104b349906a0b654df0bf69328afd3013fbe430155339c39f236df5557bf92f1ded7ff609a8502f49064ec3d1dbfb6c15d3a4c11a4f8acd12278cbf68acd5709463d12e3338a6eddb8c112f199645e23154a8e60879d2a654e3ed9296aa28f134168619691cd2c6b9e2eba4438381676173fc63c2588a3c5910dc149cf3760f0aa9fa9c3f5faa9162b0bf1aac9dd32b706a60ef53cbdb394b6b40222b5bc80eea82ba8958386672564cae3794f977871ab62337cf010001e30049201ec12937e7ce79d0f55d9c810e20acf52212aca1d3888949e0e4830aad88d804161230eb89d4d329cc83570fe257217d2119134048dd2ed167646975fc7d77136919a049ea74cf08ddd2b896890bb24a0ba18094a22baa351bf29ad96c66bbb1a598f2ca391749620e62d61c3561a7d3653ccc8892c7b99baaf76bf836e2991cb06d6bc0514568ff0d1ec8bb4b3d6984f5eaefb17d3ea2893722375d3ddb8e389a8eef7d7d198f8e687d6a513983df906099f9a2d23f4f9dec6f8ef2f11fc0a21fac45353b94e00486f5e17d386af42502d09db33cf0cf28310e049c07e88682aeeb00cb833c5174266e62407a57583f1f88b304b7c6e0c84bbe1c0fd423072d37a5bd0aacf764229e5c7cd02473460ba3645cd8e8ae144065bf02d0dd238593d8e230354f67e0b2f23012c23274f80e3ee31e35e2606a4a3f31d94ab755e6d163cff52cbb36b6d0cc67ffc512aeed1dce4d7a0d70ce82f2baba12e8d514dc92a056f994adfb17b5b9712bd5186f27a2fda1f7039c5df2c8587fdc62f5627580c13234b55be4df3056050e2d1ef3218f0dd66cb05265fe1acfb0989d8213f2c19d1735a7cf3fa65d88dad5af52dc2bba22b7abf46c3bc77b5091baab9e8f0ddc4d5e581037de91a9f8dcbc69309be29cc815cf19a20a7585b8b3073edf51fc9baeb3e509b97fa4ecfd621e0fd57bd61cac1b895c03248ff12bdbc57509250df3517e8a3fe1d776836b34ab352b973d932ef708b14f7418f9eceb1d87667e61e3e758649cb083f01b133d37ab2f5afa96d6c84bcacf4efc3851ad308c1e7d9113624fce29fab460ab9d2a48d92cdb281103a5250ad44cb2ff6e67ac670c02fdafb3e0f1353953d6d7d5646ca1568dea55275a050ec501b7c6250444f7219f1ba7521ba3b93d089727ca5f3bbe0d6c1300b423377004954c5628fdb65770b18ced5c9b23a4a5a6d6ef25fe01b4ce278de0bcc4ed86e28a0a68818ffa40970128cf2c38740e80037984428c1bd5113f40ff47512ee6f4e4d8f9b8e8e1b3040d2928d003bd1c1329dc885302fbce9fa81c23b4dc49c7c82d29b52957847898676c89aa5d32b5b0e1c0d5a2b79a19d67562f407f19425687971a957375879d90c5f57c857136c17106c9ab1b99d80e69c8c954ed386493368884b55c939b8d64d26f643e800c56f90c01079d7c534e3b2b7ae352cefd3016da55f6a85eb803b85e2304915fd2001f77c74e28746293c46e4f5f0fd49cf988aafd0026b8e7a3bab2da5cdce1ea26c2e29ec03f4807fac432662b2d6c060be1c7be0e5489de69d0a6e03a4b9117f9244b34a0f1ecba89884f781c6320412413a00c4980287409a2a78c2cd7e65cecebbe4ec1c28cac4dd95f6998e78fc6f1392384331c9436aa10e10e2bf8ad2c4eafbcf276aa7bae64b74428911b3269c749338b0fc5075ad",
|
||||
"Expected": "5a0eb2bdf0ac1cae8e586689fa16cd4b07dfdedaec8a110ea1fdb059dd5253231b6132987598dfc6e11f86780428982d50cf68f67ae452622c3b336b537ef3298ca645e8f89ee39a26758206a5a3f6409afc709582f95274b57b71fae5c6b74619ae6f089a5393c5b79235d9caf699d23d88fb873f78379690ad8405e34c19f5257d596580c7a6a7206a3712825afe630c76b31cdb4a23e7f0632e10f14f4e282c81a66451a26f8df2a352b5b9f607a7198449d1b926e27036810368e691a74b91c61afa73d9d3b99453e7c8b50fd4f09c039a2f2feb5c419206694c31b92df1d9586140cb3417b38d0c503c7b508cc2ed12e813a1c795e9829eb39ee78eeaf360a169b491a1d4e419574e712402de9d48d54c1ae5e03739b7156615e8267e1fb0a897f067afd11fb33f6e24182d7aaaaa18fe5bc1982f20d6b871e5a398f0f6f718181d31ec225cfa9a0a70124ed9a70031bdf0c1c7829f708b6e17d50419ef361cf77d99c85f44607186c8d683106b8bd38a49b5d0fb503b397a83388c5678dcfcc737499d84512690701ed621a6f0172aecf037184ddf0f2453e4053024018e5ab2e30d6d5363b56e8b41509317c99042f517247474ab3abc848e00a07f69c254f46f2a05cf6ed84e5cc906a518fdcfdf2c61ce731f24c5264f1a25fc04934dc28aec112134dd523f70115074ca34e3807aa4cb925147f3a0ce152d323bd8c675ace446d0fd1ae30c4b57f0eb2c23884bc18f0964c0114796c5b6d080c3d89175665fbf63a6381a6a9da39ad070b645c8bb1779506da14439a9f5b5d481954764ea114fac688930bc68534d403cff4210673b6a6ff7ae416b7cd41404c3d3f282fcd193b86d0f54d0006c2a503b40d5c3930da980565b8f9630e9493a79d1c03e74e5f93ac8e4dc1a901ec5e3b3e57049124c7b72ea345aa359e782285d9e6a5c144a378111dd02c40855ff9c2be9b48425cb0b2fd62dc8678fd151121cf26a65e917d65d8e0dacfae108eb5508b601fb8ffa370be1f9a8b749a2d12eeab81f41079de87e2d777994fa4d28188c579ad327f9957fb7bdecec5c680844dd43cb57cf87aeb763c003e65011f73f8c63442df39a92b946a6bd968a1c1e4d5fa7d88476a68bd8e20e5b70a99259c7d3f85fb1b65cd2e93972e6264e74ebf289b8b6979b9b68a85cd5b360c1987f87235c3c845d62489e33acf85d53fa3561fe3a3aee18924588d9c6eba4edb7a4d106b31173e42929f6f0c48c80ce6a72d54eca7c0fe870068b7a7c89c63cdda593f5b32d3cb4ea8a32c39f00ab449155757172d66763ed9527019d6de6c9f2416aa6203f4d11c9ebee1e1d3845099e55504446448027212616167eb36035726daa7698b075286f5379cd3e93cb3e0cf4f9cb8d017facbb5550ed32d5ec5400ae57e47e2bf78d1eaeff9480cc765ceff39db500",
|
||||
"Name": "nagydani-5-pow0x10001",
|
||||
"Gas": 285900,
|
||||
"NoBenchmark": false
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,126 @@
|
|||
{
|
||||
"func": "modexp",
|
||||
"fork": "berlin",
|
||||
"data":
|
||||
[
|
||||
{
|
||||
"Input": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002003fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2efffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f",
|
||||
"Expected": "0000000000000000000000000000000000000000000000000000000000000001",
|
||||
"Name": "eip_example1",
|
||||
"Gas": 1360,
|
||||
"NoBenchmark": false
|
||||
},
|
||||
{
|
||||
"Input": "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2efffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f",
|
||||
"Expected": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"Name": "eip_example2",
|
||||
"Gas": 1360,
|
||||
"NoBenchmark": false
|
||||
},
|
||||
{
|
||||
"Input": "000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040e09ad9675465c53a109fac66a445c91b292d2bb2c5268addb30cd82f80fcb0033ff97c80a5fc6f39193ae969c6ede6710a6b7ac27078a06d90ef1c72e5c85fb502fc9e1f6beb81516545975218075ec2af118cd8798df6e08a147c60fd6095ac2bb02c2908cf4dd7c81f11c289e4bce98f3553768f392a80ce22bf5c4f4a248c6b",
|
||||
"Expected": "60008f1614cc01dcfb6bfb09c625cf90b47d4468db81b5f8b7a39d42f332eab9b2da8f2d95311648a8f243f4bb13cfb3d8f7f2a3c014122ebb3ed41b02783adc",
|
||||
"Name": "nagydani-1-square",
|
||||
"Gas": 200,
|
||||
"NoBenchmark": false
|
||||
},
|
||||
{
|
||||
"Input": "000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040e09ad9675465c53a109fac66a445c91b292d2bb2c5268addb30cd82f80fcb0033ff97c80a5fc6f39193ae969c6ede6710a6b7ac27078a06d90ef1c72e5c85fb503fc9e1f6beb81516545975218075ec2af118cd8798df6e08a147c60fd6095ac2bb02c2908cf4dd7c81f11c289e4bce98f3553768f392a80ce22bf5c4f4a248c6b",
|
||||
"Expected": "4834a46ba565db27903b1c720c9d593e84e4cbd6ad2e64b31885d944f68cd801f92225a8961c952ddf2797fa4701b330c85c4b363798100b921a1a22a46a7fec",
|
||||
"Name": "nagydani-1-qube",
|
||||
"Gas": 200,
|
||||
"NoBenchmark": false
|
||||
},
|
||||
{
|
||||
"Input": "000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000040e09ad9675465c53a109fac66a445c91b292d2bb2c5268addb30cd82f80fcb0033ff97c80a5fc6f39193ae969c6ede6710a6b7ac27078a06d90ef1c72e5c85fb5010001fc9e1f6beb81516545975218075ec2af118cd8798df6e08a147c60fd6095ac2bb02c2908cf4dd7c81f11c289e4bce98f3553768f392a80ce22bf5c4f4a248c6b",
|
||||
"Expected": "c36d804180c35d4426b57b50c5bfcca5c01856d104564cd513b461d3c8b8409128a5573e416d0ebe38f5f736766d9dc27143e4da981dfa4d67f7dc474cbee6d2",
|
||||
"Name": "nagydani-1-pow0x10001",
|
||||
"Gas": 341,
|
||||
"NoBenchmark": false
|
||||
},
|
||||
{
|
||||
"Input": "000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000080cad7d991a00047dd54d3399b6b0b937c718abddef7917c75b6681f40cc15e2be0003657d8d4c34167b2f0bbbca0ccaa407c2a6a07d50f1517a8f22979ce12a81dcaf707cc0cebfc0ce2ee84ee7f77c38b9281b9822a8d3de62784c089c9b18dcb9a2a5eecbede90ea788a862a9ddd9d609c2c52972d63e289e28f6a590ffbf5102e6d893b80aeed5e6e9ce9afa8a5d5675c93a32ac05554cb20e9951b2c140e3ef4e433068cf0fb73bc9f33af1853f64aa27a0028cbf570d7ac9048eae5dc7b28c87c31e5810f1e7fa2cda6adf9f1076dbc1ec1238560071e7efc4e9565c49be9e7656951985860a558a754594115830bcdb421f741408346dd5997bb01c287087",
|
||||
"Expected": "981dd99c3b113fae3e3eaa9435c0dc96779a23c12a53d1084b4f67b0b053a27560f627b873e3f16ad78f28c94f14b6392def26e4d8896c5e3c984e50fa0b3aa44f1da78b913187c6128baa9340b1e9c9a0fd02cb78885e72576da4a8f7e5a113e173a7a2889fde9d407bd9f06eb05bc8fc7b4229377a32941a02bf4edcc06d70",
|
||||
"Name": "nagydani-2-square",
|
||||
"Gas": 200,
|
||||
"NoBenchmark": false
|
||||
},
|
||||
{
|
||||
"Input": "000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000080cad7d991a00047dd54d3399b6b0b937c718abddef7917c75b6681f40cc15e2be0003657d8d4c34167b2f0bbbca0ccaa407c2a6a07d50f1517a8f22979ce12a81dcaf707cc0cebfc0ce2ee84ee7f77c38b9281b9822a8d3de62784c089c9b18dcb9a2a5eecbede90ea788a862a9ddd9d609c2c52972d63e289e28f6a590ffbf5103e6d893b80aeed5e6e9ce9afa8a5d5675c93a32ac05554cb20e9951b2c140e3ef4e433068cf0fb73bc9f33af1853f64aa27a0028cbf570d7ac9048eae5dc7b28c87c31e5810f1e7fa2cda6adf9f1076dbc1ec1238560071e7efc4e9565c49be9e7656951985860a558a754594115830bcdb421f741408346dd5997bb01c287087",
|
||||
"Expected": "d89ceb68c32da4f6364978d62aaa40d7b09b59ec61eb3c0159c87ec3a91037f7dc6967594e530a69d049b64adfa39c8fa208ea970cfe4b7bcd359d345744405afe1cbf761647e32b3184c7fbe87cee8c6c7ff3b378faba6c68b83b6889cb40f1603ee68c56b4c03d48c595c826c041112dc941878f8c5be828154afd4a16311f",
|
||||
"Name": "nagydani-2-qube",
|
||||
"Gas": 200,
|
||||
"NoBenchmark": false
|
||||
},
|
||||
{
|
||||
"Input": "000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000080cad7d991a00047dd54d3399b6b0b937c718abddef7917c75b6681f40cc15e2be0003657d8d4c34167b2f0bbbca0ccaa407c2a6a07d50f1517a8f22979ce12a81dcaf707cc0cebfc0ce2ee84ee7f77c38b9281b9822a8d3de62784c089c9b18dcb9a2a5eecbede90ea788a862a9ddd9d609c2c52972d63e289e28f6a590ffbf51010001e6d893b80aeed5e6e9ce9afa8a5d5675c93a32ac05554cb20e9951b2c140e3ef4e433068cf0fb73bc9f33af1853f64aa27a0028cbf570d7ac9048eae5dc7b28c87c31e5810f1e7fa2cda6adf9f1076dbc1ec1238560071e7efc4e9565c49be9e7656951985860a558a754594115830bcdb421f741408346dd5997bb01c287087",
|
||||
"Expected": "ad85e8ef13fd1dd46eae44af8b91ad1ccae5b7a1c92944f92a19f21b0b658139e0cabe9c1f679507c2de354bf2c91ebd965d1e633978a830d517d2f6f8dd5fd58065d58559de7e2334a878f8ec6992d9b9e77430d4764e863d77c0f87beede8f2f7f2ab2e7222f85cc9d98b8467f4bb72e87ef2882423ebdb6daf02dddac6db2",
|
||||
"Name": "nagydani-2-pow0x10001",
|
||||
"Gas": 1365,
|
||||
"NoBenchmark": false
|
||||
},
|
||||
{
|
||||
"Input": "000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000100c9130579f243e12451760976261416413742bd7c91d39ae087f46794062b8c239f2a74abf3918605a0e046a7890e049475ba7fbb78f5de6490bd22a710cc04d30088179a919d86c2da62cf37f59d8f258d2310d94c24891be2d7eeafaa32a8cb4b0cfe5f475ed778f45907dc8916a73f03635f233f7a77a00a3ec9ca6761a5bbd558a2318ecd0caa1c5016691523e7e1fa267dd35e70c66e84380bdcf7c0582f540174e572c41f81e93da0b757dff0b0fe23eb03aa19af0bdec3afb474216febaacb8d0381e631802683182b0fe72c28392539850650b70509f54980241dc175191a35d967288b532a7a8223ce2440d010615f70df269501944d4ec16fe4a3cb02d7a85909174757835187cb52e71934e6c07ef43b4c46fc30bbcd0bc72913068267c54a4aabebb493922492820babdeb7dc9b1558fcf7bd82c37c82d3147e455b623ab0efa752fe0b3a67ca6e4d126639e645a0bf417568adbb2a6a4eef62fa1fa29b2a5a43bebea1f82193a7dd98eb483d09bb595af1fa9c97c7f41f5649d976aee3e5e59e2329b43b13bea228d4a93f16ba139ccb511de521ffe747aa2eca664f7c9e33da59075cc335afcd2bf3ae09765f01ab5a7c3e3938ec168b74724b5074247d200d9970382f683d6059b94dbc336603d1dfee714e4b447ac2fa1d99ecb4961da2854e03795ed758220312d101e1e3d87d5313a6d052aebde75110363d",
|
||||
"Expected": "affc7507ea6d84751ec6b3f0d7b99dbcc263f33330e450d1b3ff0bc3d0874320bf4edd57debd587306988157958cb3cfd369cc0c9c198706f635c9e0f15d047df5cb44d03e2727f26b083c4ad8485080e1293f171c1ed52aef5993a5815c35108e848c951cf1e334490b4a539a139e57b68f44fee583306f5b85ffa57206b3ee5660458858534e5386b9584af3c7f67806e84c189d695e5eb96e1272d06ec2df5dc5fabc6e94b793718c60c36be0a4d031fc84cd658aa72294b2e16fc240aef70cb9e591248e38bd49c5a554d1afa01f38dab72733092f7555334bbef6c8c430119840492380aa95fa025dcf699f0a39669d812b0c6946b6091e6e235337b6f8",
|
||||
"Name": "nagydani-3-square",
|
||||
"Gas": 341,
|
||||
"NoBenchmark": false
|
||||
},
|
||||
{
|
||||
"Input": "000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000100c9130579f243e12451760976261416413742bd7c91d39ae087f46794062b8c239f2a74abf3918605a0e046a7890e049475ba7fbb78f5de6490bd22a710cc04d30088179a919d86c2da62cf37f59d8f258d2310d94c24891be2d7eeafaa32a8cb4b0cfe5f475ed778f45907dc8916a73f03635f233f7a77a00a3ec9ca6761a5bbd558a2318ecd0caa1c5016691523e7e1fa267dd35e70c66e84380bdcf7c0582f540174e572c41f81e93da0b757dff0b0fe23eb03aa19af0bdec3afb474216febaacb8d0381e631802683182b0fe72c28392539850650b70509f54980241dc175191a35d967288b532a7a8223ce2440d010615f70df269501944d4ec16fe4a3cb03d7a85909174757835187cb52e71934e6c07ef43b4c46fc30bbcd0bc72913068267c54a4aabebb493922492820babdeb7dc9b1558fcf7bd82c37c82d3147e455b623ab0efa752fe0b3a67ca6e4d126639e645a0bf417568adbb2a6a4eef62fa1fa29b2a5a43bebea1f82193a7dd98eb483d09bb595af1fa9c97c7f41f5649d976aee3e5e59e2329b43b13bea228d4a93f16ba139ccb511de521ffe747aa2eca664f7c9e33da59075cc335afcd2bf3ae09765f01ab5a7c3e3938ec168b74724b5074247d200d9970382f683d6059b94dbc336603d1dfee714e4b447ac2fa1d99ecb4961da2854e03795ed758220312d101e1e3d87d5313a6d052aebde75110363d",
|
||||
"Expected": "1b280ecd6a6bf906b806d527c2a831e23b238f89da48449003a88ac3ac7150d6a5e9e6b3be4054c7da11dd1e470ec29a606f5115801b5bf53bc1900271d7c3ff3cd5ed790d1c219a9800437a689f2388ba1a11d68f6a8e5b74e9a3b1fac6ee85fc6afbac599f93c391f5dc82a759e3c6c0ab45ce3f5d25d9b0c1bf94cf701ea6466fc9a478dacc5754e593172b5111eeba88557048bceae401337cd4c1182ad9f700852bc8c99933a193f0b94cf1aedbefc48be3bc93ef5cb276d7c2d5462ac8bb0c8fe8923a1db2afe1c6b90d59c534994a6a633f0ead1d638fdc293486bb634ff2c8ec9e7297c04241a61c37e3ae95b11d53343d4ba2b4cc33d2cfa7eb705e",
|
||||
"Name": "nagydani-3-qube",
|
||||
"Gas": 341,
|
||||
"NoBenchmark": false
|
||||
},
|
||||
{
|
||||
"Input": "000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000100c9130579f243e12451760976261416413742bd7c91d39ae087f46794062b8c239f2a74abf3918605a0e046a7890e049475ba7fbb78f5de6490bd22a710cc04d30088179a919d86c2da62cf37f59d8f258d2310d94c24891be2d7eeafaa32a8cb4b0cfe5f475ed778f45907dc8916a73f03635f233f7a77a00a3ec9ca6761a5bbd558a2318ecd0caa1c5016691523e7e1fa267dd35e70c66e84380bdcf7c0582f540174e572c41f81e93da0b757dff0b0fe23eb03aa19af0bdec3afb474216febaacb8d0381e631802683182b0fe72c28392539850650b70509f54980241dc175191a35d967288b532a7a8223ce2440d010615f70df269501944d4ec16fe4a3cb010001d7a85909174757835187cb52e71934e6c07ef43b4c46fc30bbcd0bc72913068267c54a4aabebb493922492820babdeb7dc9b1558fcf7bd82c37c82d3147e455b623ab0efa752fe0b3a67ca6e4d126639e645a0bf417568adbb2a6a4eef62fa1fa29b2a5a43bebea1f82193a7dd98eb483d09bb595af1fa9c97c7f41f5649d976aee3e5e59e2329b43b13bea228d4a93f16ba139ccb511de521ffe747aa2eca664f7c9e33da59075cc335afcd2bf3ae09765f01ab5a7c3e3938ec168b74724b5074247d200d9970382f683d6059b94dbc336603d1dfee714e4b447ac2fa1d99ecb4961da2854e03795ed758220312d101e1e3d87d5313a6d052aebde75110363d",
|
||||
"Expected": "37843d7c67920b5f177372fa56e2a09117df585f81df8b300fba245b1175f488c99476019857198ed459ed8d9799c377330e49f4180c4bf8e8f66240c64f65ede93d601f957b95b83efdee1e1bfde74169ff77002eaf078c71815a9220c80b2e3b3ff22c2f358111d816ebf83c2999026b6de50bfc711ff68705d2f40b753424aefc9f70f08d908b5a20276ad613b4ab4309a3ea72f0c17ea9df6b3367d44fb3acab11c333909e02e81ea2ed404a712d3ea96bba87461720e2d98723e7acd0520ac1a5212dbedcd8dc0c1abf61d4719e319ff4758a774790b8d463cdfe131d1b2dcfee52d002694e98e720cb6ae7ccea353bc503269ba35f0f63bf8d7b672a76",
|
||||
"Name": "nagydani-3-pow0x10001",
|
||||
"Gas": 5461,
|
||||
"NoBenchmark": false
|
||||
},
|
||||
{
|
||||
"Input": "000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000200db34d0e438249c0ed685c949cc28776a05094e1c48691dc3f2dca5fc3356d2a0663bd376e4712839917eb9a19c670407e2c377a2de385a3ff3b52104f7f1f4e0c7bf7717fb913896693dc5edbb65b760ef1b00e42e9d8f9af17352385e1cd742c9b006c0f669995cb0bb21d28c0aced2892267637b6470d8cee0ab27fc5d42658f6e88240c31d6774aa60a7ebd25cd48b56d0da11209f1928e61005c6eb709f3e8e0aaf8d9b10f7d7e296d772264dc76897ccdddadc91efa91c1903b7232a9e4c3b941917b99a3bc0c26497dedc897c25750af60237aa67934a26a2bc491db3dcc677491944bc1f51d3e5d76b8d846a62db03dedd61ff508f91a56d71028125035c3a44cbb041497c83bf3e4ae2a9613a401cc721c547a2afa3b16a2969933d3626ed6d8a7428648f74122fd3f2a02a20758f7f693892c8fd798b39abac01d18506c45e71432639e9f9505719ee822f62ccbf47f6850f096ff77b5afaf4be7d772025791717dbe5abf9b3f40cff7d7aab6f67e38f62faf510747276e20a42127e7500c444f9ed92baf65ade9e836845e39c4316d9dce5f8e2c8083e2c0acbb95296e05e51aab13b6b8f53f06c9c4276e12b0671133218cc3ea907da3bd9a367096d9202128d14846cc2e20d56fc8473ecb07cecbfb8086919f3971926e7045b853d85a69d026195c70f9f7a823536e2a8f4b3e12e94d9b53a934353451094b8102df3143a0057457d75e8c708b6337a6f5a4fd1a06727acf9fb93e2993c62f3378b37d56c85e7b1e00f0145ebf8e4095bd723166293c60b6ac1252291ef65823c9e040ddad14969b3b340a4ef714db093a587c37766d68b8d6b5016e741587e7e6bf7e763b44f0247e64bae30f994d248bfd20541a333e5b225ef6a61199e301738b1e688f70ec1d7fb892c183c95dc543c3e12adf8a5e8b9ca9d04f9445cced3ab256f29e998e69efaa633a7b60e1db5a867924ccab0a171d9d6e1098dfa15acde9553de599eaa56490c8f411e4985111f3d40bddfc5e301edb01547b01a886550a61158f7e2033c59707789bf7c854181d0c2e2a42a93cf09209747d7082e147eb8544de25c3eb14f2e35559ea0c0f5877f2f3fc92132c0ae9da4e45b2f6c866a224ea6d1f28c05320e287750fbc647368d41116e528014cc1852e5531d53e4af938374daba6cee4baa821ed07117253bb3601ddd00d59a3d7fb2ef1f5a2fbba7c429f0cf9a5b3462410fd833a69118f8be9c559b1000cc608fd877fb43f8e65c2d1302622b944462579056874b387208d90623fcdaf93920ca7a9e4ba64ea208758222ad868501cc2c345e2d3a5ea2a17e5069248138c8a79c0251185d29ee73e5afab5354769142d2bf0cb6712727aa6bf84a6245fcdae66e4938d84d1b9dd09a884818622080ff5f98942fb20acd7e0c916c2d5ea7ce6f7e173315384518f",
|
||||
"Expected": "8a5aea5f50dcc03dc7a7a272b5aeebc040554dbc1ffe36753c4fc75f7ed5f6c2cc0de3a922bf96c78bf0643a73025ad21f45a4a5cadd717612c511ab2bff1190fe5f1ae05ba9f8fe3624de1de2a817da6072ddcdb933b50216811dbe6a9ca79d3a3c6b3a476b079fd0d05f04fb154e2dd3e5cb83b148a006f2bcbf0042efb2ae7b916ea81b27aac25c3bf9a8b6d35440062ad8eae34a83f3ffa2cc7b40346b62174a4422584f72f95316f6b2bee9ff232ba9739301c97c99a9ded26c45d72676eb856ad6ecc81d36a6de36d7f9dafafee11baa43a4b0d5e4ecffa7b9b7dcefd58c397dd373e6db4acd2b2c02717712e6289bed7c813b670c4a0c6735aa7f3b0f1ce556eae9fcc94b501b2c8781ba50a8c6220e8246371c3c7359fe4ef9da786ca7d98256754ca4e496be0a9174bedbecb384bdf470779186d6a833f068d2838a88d90ef3ad48ff963b67c39cc5a3ee123baf7bf3125f64e77af7f30e105d72c4b9b5b237ed251e4c122c6d8c1405e736299c3afd6db16a28c6a9cfa68241e53de4cd388271fe534a6a9b0dbea6171d170db1b89858468885d08fecbd54c8e471c3e25d48e97ba450b96d0d87e00ac732aaa0d3ce4309c1064bd8a4c0808a97e0143e43a24cfa847635125cd41c13e0574487963e9d725c01375db99c31da67b4cf65eff555f0c0ac416c727ff8d438ad7c42030551d68c2e7adda0abb1ca7c10",
|
||||
"Name": "nagydani-4-square",
|
||||
"Gas": 1365,
|
||||
"NoBenchmark": false
|
||||
},
|
||||
{
|
||||
"Input": "000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000200db34d0e438249c0ed685c949cc28776a05094e1c48691dc3f2dca5fc3356d2a0663bd376e4712839917eb9a19c670407e2c377a2de385a3ff3b52104f7f1f4e0c7bf7717fb913896693dc5edbb65b760ef1b00e42e9d8f9af17352385e1cd742c9b006c0f669995cb0bb21d28c0aced2892267637b6470d8cee0ab27fc5d42658f6e88240c31d6774aa60a7ebd25cd48b56d0da11209f1928e61005c6eb709f3e8e0aaf8d9b10f7d7e296d772264dc76897ccdddadc91efa91c1903b7232a9e4c3b941917b99a3bc0c26497dedc897c25750af60237aa67934a26a2bc491db3dcc677491944bc1f51d3e5d76b8d846a62db03dedd61ff508f91a56d71028125035c3a44cbb041497c83bf3e4ae2a9613a401cc721c547a2afa3b16a2969933d3626ed6d8a7428648f74122fd3f2a02a20758f7f693892c8fd798b39abac01d18506c45e71432639e9f9505719ee822f62ccbf47f6850f096ff77b5afaf4be7d772025791717dbe5abf9b3f40cff7d7aab6f67e38f62faf510747276e20a42127e7500c444f9ed92baf65ade9e836845e39c4316d9dce5f8e2c8083e2c0acbb95296e05e51aab13b6b8f53f06c9c4276e12b0671133218cc3ea907da3bd9a367096d9202128d14846cc2e20d56fc8473ecb07cecbfb8086919f3971926e7045b853d85a69d026195c70f9f7a823536e2a8f4b3e12e94d9b53a934353451094b8103df3143a0057457d75e8c708b6337a6f5a4fd1a06727acf9fb93e2993c62f3378b37d56c85e7b1e00f0145ebf8e4095bd723166293c60b6ac1252291ef65823c9e040ddad14969b3b340a4ef714db093a587c37766d68b8d6b5016e741587e7e6bf7e763b44f0247e64bae30f994d248bfd20541a333e5b225ef6a61199e301738b1e688f70ec1d7fb892c183c95dc543c3e12adf8a5e8b9ca9d04f9445cced3ab256f29e998e69efaa633a7b60e1db5a867924ccab0a171d9d6e1098dfa15acde9553de599eaa56490c8f411e4985111f3d40bddfc5e301edb01547b01a886550a61158f7e2033c59707789bf7c854181d0c2e2a42a93cf09209747d7082e147eb8544de25c3eb14f2e35559ea0c0f5877f2f3fc92132c0ae9da4e45b2f6c866a224ea6d1f28c05320e287750fbc647368d41116e528014cc1852e5531d53e4af938374daba6cee4baa821ed07117253bb3601ddd00d59a3d7fb2ef1f5a2fbba7c429f0cf9a5b3462410fd833a69118f8be9c559b1000cc608fd877fb43f8e65c2d1302622b944462579056874b387208d90623fcdaf93920ca7a9e4ba64ea208758222ad868501cc2c345e2d3a5ea2a17e5069248138c8a79c0251185d29ee73e5afab5354769142d2bf0cb6712727aa6bf84a6245fcdae66e4938d84d1b9dd09a884818622080ff5f98942fb20acd7e0c916c2d5ea7ce6f7e173315384518f",
|
||||
"Expected": "5a2664252aba2d6e19d9600da582cdd1f09d7a890ac48e6b8da15ae7c6ff1856fc67a841ac2314d283ffa3ca81a0ecf7c27d89ef91a5a893297928f5da0245c99645676b481b7e20a566ee6a4f2481942bee191deec5544600bb2441fd0fb19e2ee7d801ad8911c6b7750affec367a4b29a22942c0f5f4744a4e77a8b654da2a82571037099e9c6d930794efe5cdca73c7b6c0844e386bdca8ea01b3d7807146bb81365e2cdc6475f8c23e0ff84463126189dc9789f72bbce2e3d2d114d728a272f1345122de23df54c922ec7a16e5c2a8f84da8871482bd258c20a7c09bbcd64c7a96a51029bbfe848736a6ba7bf9d931a9b7de0bcaf3635034d4958b20ae9ab3a95a147b0421dd5f7ebff46c971010ebfc4adbbe0ad94d5498c853e7142c450d8c71de4b2f84edbf8acd2e16d00c8115b150b1c30e553dbb82635e781379fe2a56360420ff7e9f70cc64c00aba7e26ed13c7c19622865ae07248daced36416080f35f8cc157a857ed70ea4f347f17d1bee80fa038abd6e39b1ba06b97264388b21364f7c56e192d4b62d9b161405f32ab1e2594e86243e56fcf2cb30d21adef15b9940f91af681da24328c883d892670c6aa47940867a81830a82b82716895db810df1b834640abefb7db2092dd92912cb9a735175bc447be40a503cf22dfe565b4ed7a3293ca0dfd63a507430b323ee248ec82e843b673c97ad730728cebc",
|
||||
"Name": "nagydani-4-qube",
|
||||
"Gas": 1365,
|
||||
"NoBenchmark": false
|
||||
},
|
||||
{
|
||||
"Input": "000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000200db34d0e438249c0ed685c949cc28776a05094e1c48691dc3f2dca5fc3356d2a0663bd376e4712839917eb9a19c670407e2c377a2de385a3ff3b52104f7f1f4e0c7bf7717fb913896693dc5edbb65b760ef1b00e42e9d8f9af17352385e1cd742c9b006c0f669995cb0bb21d28c0aced2892267637b6470d8cee0ab27fc5d42658f6e88240c31d6774aa60a7ebd25cd48b56d0da11209f1928e61005c6eb709f3e8e0aaf8d9b10f7d7e296d772264dc76897ccdddadc91efa91c1903b7232a9e4c3b941917b99a3bc0c26497dedc897c25750af60237aa67934a26a2bc491db3dcc677491944bc1f51d3e5d76b8d846a62db03dedd61ff508f91a56d71028125035c3a44cbb041497c83bf3e4ae2a9613a401cc721c547a2afa3b16a2969933d3626ed6d8a7428648f74122fd3f2a02a20758f7f693892c8fd798b39abac01d18506c45e71432639e9f9505719ee822f62ccbf47f6850f096ff77b5afaf4be7d772025791717dbe5abf9b3f40cff7d7aab6f67e38f62faf510747276e20a42127e7500c444f9ed92baf65ade9e836845e39c4316d9dce5f8e2c8083e2c0acbb95296e05e51aab13b6b8f53f06c9c4276e12b0671133218cc3ea907da3bd9a367096d9202128d14846cc2e20d56fc8473ecb07cecbfb8086919f3971926e7045b853d85a69d026195c70f9f7a823536e2a8f4b3e12e94d9b53a934353451094b81010001df3143a0057457d75e8c708b6337a6f5a4fd1a06727acf9fb93e2993c62f3378b37d56c85e7b1e00f0145ebf8e4095bd723166293c60b6ac1252291ef65823c9e040ddad14969b3b340a4ef714db093a587c37766d68b8d6b5016e741587e7e6bf7e763b44f0247e64bae30f994d248bfd20541a333e5b225ef6a61199e301738b1e688f70ec1d7fb892c183c95dc543c3e12adf8a5e8b9ca9d04f9445cced3ab256f29e998e69efaa633a7b60e1db5a867924ccab0a171d9d6e1098dfa15acde9553de599eaa56490c8f411e4985111f3d40bddfc5e301edb01547b01a886550a61158f7e2033c59707789bf7c854181d0c2e2a42a93cf09209747d7082e147eb8544de25c3eb14f2e35559ea0c0f5877f2f3fc92132c0ae9da4e45b2f6c866a224ea6d1f28c05320e287750fbc647368d41116e528014cc1852e5531d53e4af938374daba6cee4baa821ed07117253bb3601ddd00d59a3d7fb2ef1f5a2fbba7c429f0cf9a5b3462410fd833a69118f8be9c559b1000cc608fd877fb43f8e65c2d1302622b944462579056874b387208d90623fcdaf93920ca7a9e4ba64ea208758222ad868501cc2c345e2d3a5ea2a17e5069248138c8a79c0251185d29ee73e5afab5354769142d2bf0cb6712727aa6bf84a6245fcdae66e4938d84d1b9dd09a884818622080ff5f98942fb20acd7e0c916c2d5ea7ce6f7e173315384518f",
|
||||
"Expected": "bed8b970c4a34849fc6926b08e40e20b21c15ed68d18f228904878d4370b56322d0da5789da0318768a374758e6375bfe4641fca5285ec7171828922160f48f5ca7efbfee4d5148612c38ad683ae4e3c3a053d2b7c098cf2b34f2cb19146eadd53c86b2d7ccf3d83b2c370bfb840913ee3879b1057a6b4e07e110b6bcd5e958bc71a14798c91d518cc70abee264b0d25a4110962a764b364ac0b0dd1ee8abc8426d775ec0f22b7e47b32576afaf1b5a48f64573ed1c5c29f50ab412188d9685307323d990802b81dacc06c6e05a1e901830ba9fcc67688dc29c5e27bde0a6e845ca925f5454b6fb3747edfaa2a5820838fb759eadf57f7cb5cec57fc213ddd8a4298fa079c3c0f472b07fb15aa6a7f0a3780bd296ff6a62e58ef443870b02260bd4fd2bbc98255674b8e1f1f9f8d33c7170b0ebbea4523b695911abbf26e41885344823bd0587115fdd83b721a4e8457a31c9a84b3d3520a07e0e35df7f48e5a9d534d0ec7feef1ff74de6a11e7f93eab95175b6ce22c68d78a642ad642837897ec11349205d8593ac19300207572c38d29ca5dfa03bc14cdbc32153c80e5cc3e739403d34c75915e49beb43094cc6dcafb3665b305ddec9286934ae66ec6b777ca528728c851318eb0f207b39f1caaf96db6eeead6b55ed08f451939314577d42bcc9f97c0b52d0234f88fd07e4c1d7780fdebc025cfffcb572cb27a8c33963",
|
||||
"Name": "nagydani-4-pow0x10001",
|
||||
"Gas": 21845,
|
||||
"NoBenchmark": false
|
||||
},
|
||||
{
|
||||
"Input": "000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000400c5a1611f8be90071a43db23cc2fe01871cc4c0e8ab5743f6378e4fef77f7f6db0095c0727e20225beb665645403453e325ad5f9aeb9ba99bf3c148f63f9c07cf4fe8847ad5242d6b7d4499f93bd47056ddab8f7dee878fc2314f344dbee2a7c41a5d3db91eff372c730c2fdd3a141a4b61999e36d549b9870cf2f4e632c4d5df5f024f81c028000073a0ed8847cfb0593d36a47142f578f05ccbe28c0c06aeb1b1da027794c48db880278f79ba78ae64eedfea3c07d10e0562668d839749dc95f40467d15cf65b9cfc52c7c4bcef1cda3596dd52631aac942f146c7cebd46065131699ce8385b0db1874336747ee020a5698a3d1a1082665721e769567f579830f9d259cec1a836845109c21cf6b25da572512bf3c42fd4b96e43895589042ab60dd41f497db96aec102087fe784165bb45f942859268fd2ff6c012d9d00c02ba83eace047cc5f7b2c392c2955c58a49f0338d6fc58749c9db2155522ac17914ec216ad87f12e0ee95574613942fa615898c4d9e8a3be68cd6afa4e7a003dedbdf8edfee31162b174f965b20ae752ad89c967b3068b6f722c16b354456ba8e280f987c08e0a52d40a2e8f3a59b94d590aeef01879eb7a90b3ee7d772c839c85519cbeaddc0c193ec4874a463b53fcaea3271d80ebfb39b33489365fc039ae549a17a9ff898eea2f4cb27b8dbee4c17b998438575b2b8d107e4a0d66ba7fca85b41a58a8d51f191a35c856dfbe8aef2b00048a694bbccff832d23c8ca7a7ff0b6c0b3011d00b97c86c0628444d267c951d9e4fb8f83e154b8f74fb51aa16535e498235c5597dac9606ed0be3173a3836baa4e7d756ffe1e2879b415d3846bccd538c05b847785699aefde3e305decb600cd8fb0e7d8de5efc26971a6ad4e6d7a2d91474f1023a0ac4b78dc937da0ce607a45974d2cac1c33a2631ff7fe6144a3b2e5cf98b531a9627dea92c1dc82204d09db0439b6a11dd64b484e1263aa45fd9539b6020b55e3baece3986a8bffc1003406348f5c61265099ed43a766ee4f93f5f9c5abbc32a0fd3ac2b35b87f9ec26037d88275bd7dd0a54474995ee34ed3727f3f97c48db544b1980193a4b76a8a3ddab3591ce527f16d91882e67f0103b5cda53f7da54d489fc4ac08b6ab358a5a04aa9daa16219d50bd672a7cb804ed769d218807544e5993f1c27427104b349906a0b654df0bf69328afd3013fbe430155339c39f236df5557bf92f1ded7ff609a8502f49064ec3d1dbfb6c15d3a4c11a4f8acd12278cbf68acd5709463d12e3338a6eddb8c112f199645e23154a8e60879d2a654e3ed9296aa28f134168619691cd2c6b9e2eba4438381676173fc63c2588a3c5910dc149cf3760f0aa9fa9c3f5faa9162b0bf1aac9dd32b706a60ef53cbdb394b6b40222b5bc80eea82ba8958386672564cae3794f977871ab62337cf02e30049201ec12937e7ce79d0f55d9c810e20acf52212aca1d3888949e0e4830aad88d804161230eb89d4d329cc83570fe257217d2119134048dd2ed167646975fc7d77136919a049ea74cf08ddd2b896890bb24a0ba18094a22baa351bf29ad96c66bbb1a598f2ca391749620e62d61c3561a7d3653ccc8892c7b99baaf76bf836e2991cb06d6bc0514568ff0d1ec8bb4b3d6984f5eaefb17d3ea2893722375d3ddb8e389a8eef7d7d198f8e687d6a513983df906099f9a2d23f4f9dec6f8ef2f11fc0a21fac45353b94e00486f5e17d386af42502d09db33cf0cf28310e049c07e88682aeeb00cb833c5174266e62407a57583f1f88b304b7c6e0c84bbe1c0fd423072d37a5bd0aacf764229e5c7cd02473460ba3645cd8e8ae144065bf02d0dd238593d8e230354f67e0b2f23012c23274f80e3ee31e35e2606a4a3f31d94ab755e6d163cff52cbb36b6d0cc67ffc512aeed1dce4d7a0d70ce82f2baba12e8d514dc92a056f994adfb17b5b9712bd5186f27a2fda1f7039c5df2c8587fdc62f5627580c13234b55be4df3056050e2d1ef3218f0dd66cb05265fe1acfb0989d8213f2c19d1735a7cf3fa65d88dad5af52dc2bba22b7abf46c3bc77b5091baab9e8f0ddc4d5e581037de91a9f8dcbc69309be29cc815cf19a20a7585b8b3073edf51fc9baeb3e509b97fa4ecfd621e0fd57bd61cac1b895c03248ff12bdbc57509250df3517e8a3fe1d776836b34ab352b973d932ef708b14f7418f9eceb1d87667e61e3e758649cb083f01b133d37ab2f5afa96d6c84bcacf4efc3851ad308c1e7d9113624fce29fab460ab9d2a48d92cdb281103a5250ad44cb2ff6e67ac670c02fdafb3e0f1353953d6d7d5646ca1568dea55275a050ec501b7c6250444f7219f1ba7521ba3b93d089727ca5f3bbe0d6c1300b423377004954c5628fdb65770b18ced5c9b23a4a5a6d6ef25fe01b4ce278de0bcc4ed86e28a0a68818ffa40970128cf2c38740e80037984428c1bd5113f40ff47512ee6f4e4d8f9b8e8e1b3040d2928d003bd1c1329dc885302fbce9fa81c23b4dc49c7c82d29b52957847898676c89aa5d32b5b0e1c0d5a2b79a19d67562f407f19425687971a957375879d90c5f57c857136c17106c9ab1b99d80e69c8c954ed386493368884b55c939b8d64d26f643e800c56f90c01079d7c534e3b2b7ae352cefd3016da55f6a85eb803b85e2304915fd2001f77c74e28746293c46e4f5f0fd49cf988aafd0026b8e7a3bab2da5cdce1ea26c2e29ec03f4807fac432662b2d6c060be1c7be0e5489de69d0a6e03a4b9117f9244b34a0f1ecba89884f781c6320412413a00c4980287409a2a78c2cd7e65cecebbe4ec1c28cac4dd95f6998e78fc6f1392384331c9436aa10e10e2bf8ad2c4eafbcf276aa7bae64b74428911b3269c749338b0fc5075ad",
|
||||
"Expected": "d61fe4e3f32ac260915b5b03b78a86d11bfc41d973fce5b0cc59035cf8289a8a2e3878ea15fa46565b0d806e2f85b53873ea20ed653869b688adf83f3ef444535bf91598ff7e80f334fb782539b92f39f55310cc4b35349ab7b278346eda9bc37c0d8acd3557fae38197f412f8d9e57ce6a76b7205c23564cab06e5615be7c6f05c3d05ec690cba91da5e89d55b152ff8dd2157dc5458190025cf94b1ad98f7cbe64e9482faba95e6b33844afc640892872b44a9932096508f4a782a4805323808f23e54b6ff9b841dbfa87db3505ae4f687972c18ea0f0d0af89d36c1c2a5b14560c153c3fee406f5cf15cfd1c0bb45d767426d465f2f14c158495069d0c5955a00150707862ecaae30624ebacdd8ac33e4e6aab3ff90b6ba445a84689386b9e945d01823a65874444316e83767290fcff630d2477f49d5d8ffdd200e08ee1274270f86ed14c687895f6caf5ce528bd970c20d2408a9ba66216324c6a011ac4999098362dbd98a038129a2d40c8da6ab88318aa3046cb660327cc44236d9e5d2163bd0959062195c51ed93d0088b6f92051fc99050ece2538749165976233697ab4b610385366e5ce0b02ad6b61c168ecfbedcdf74278a38de340fd7a5fead8e588e294795f9b011e2e60377a89e25c90e145397cdeabc60fd32444a6b7642a611a83c464d8b8976666351b4865c37b02e6dc21dbcdf5f930341707b618cc0f03c3122646b3385c9df9f2ec730eec9d49e7dfc9153b6e6289da8c4f0ebea9ccc1b751948e3bb7171c9e4d57423b0eeeb79095c030cb52677b3f7e0b45c30f645391f3f9c957afa549c4e0b2465b03c67993cd200b1af01035962edbc4c9e89b31c82ac121987d6529dafdeef67a132dc04b6dc68e77f22862040b75e2ceb9ff16da0fca534e6db7bd12fa7b7f51b6c08c1e23dfcdb7acbd2da0b51c87ffbced065a612e9b1c8bba9b7e2d8d7a2f04fcc4aaf355b60d764879a76b5e16762d5f2f55d585d0c8e82df6940960cddfb72c91dfa71f6b4e1c6ca25dfc39a878e998a663c04fe29d5e83b9586d047b4d7ff70a9f0d44f127e7d741685ca75f11629128d916a0ffef4be586a30c4b70389cc746e84ebf177c01ee8a4511cfbb9d1ecf7f7b33c7dd8177896e10bbc82f838dcd6db7ac67de62bf46b6a640fb580c5d1d2708f3862e3d2b645d0d18e49ef088053e3a220adc0e033c2afcfe61c90e32151152eb3caaf746c5e377d541cafc6cbb0cc0fa48b5caf1728f2e1957f5addfc234f1a9d89e40d49356c9172d0561a695fce6dab1d412321bbf407f63766ffd7b6b3d79bcfa07991c5a9709849c1008689e3b47c50d613980bec239fb64185249d055b30375ccb4354d71fe4d05648fbf6c80634dfc3575f2f24abb714c1e4c95e8896763bf4316e954c7ad19e5780ab7a040ca6fb9271f90a8b22ae738daf6cb",
|
||||
"Name": "nagydani-5-square",
|
||||
"Gas": 5461,
|
||||
"NoBenchmark": false
|
||||
},
|
||||
{
|
||||
"Input": "000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000400c5a1611f8be90071a43db23cc2fe01871cc4c0e8ab5743f6378e4fef77f7f6db0095c0727e20225beb665645403453e325ad5f9aeb9ba99bf3c148f63f9c07cf4fe8847ad5242d6b7d4499f93bd47056ddab8f7dee878fc2314f344dbee2a7c41a5d3db91eff372c730c2fdd3a141a4b61999e36d549b9870cf2f4e632c4d5df5f024f81c028000073a0ed8847cfb0593d36a47142f578f05ccbe28c0c06aeb1b1da027794c48db880278f79ba78ae64eedfea3c07d10e0562668d839749dc95f40467d15cf65b9cfc52c7c4bcef1cda3596dd52631aac942f146c7cebd46065131699ce8385b0db1874336747ee020a5698a3d1a1082665721e769567f579830f9d259cec1a836845109c21cf6b25da572512bf3c42fd4b96e43895589042ab60dd41f497db96aec102087fe784165bb45f942859268fd2ff6c012d9d00c02ba83eace047cc5f7b2c392c2955c58a49f0338d6fc58749c9db2155522ac17914ec216ad87f12e0ee95574613942fa615898c4d9e8a3be68cd6afa4e7a003dedbdf8edfee31162b174f965b20ae752ad89c967b3068b6f722c16b354456ba8e280f987c08e0a52d40a2e8f3a59b94d590aeef01879eb7a90b3ee7d772c839c85519cbeaddc0c193ec4874a463b53fcaea3271d80ebfb39b33489365fc039ae549a17a9ff898eea2f4cb27b8dbee4c17b998438575b2b8d107e4a0d66ba7fca85b41a58a8d51f191a35c856dfbe8aef2b00048a694bbccff832d23c8ca7a7ff0b6c0b3011d00b97c86c0628444d267c951d9e4fb8f83e154b8f74fb51aa16535e498235c5597dac9606ed0be3173a3836baa4e7d756ffe1e2879b415d3846bccd538c05b847785699aefde3e305decb600cd8fb0e7d8de5efc26971a6ad4e6d7a2d91474f1023a0ac4b78dc937da0ce607a45974d2cac1c33a2631ff7fe6144a3b2e5cf98b531a9627dea92c1dc82204d09db0439b6a11dd64b484e1263aa45fd9539b6020b55e3baece3986a8bffc1003406348f5c61265099ed43a766ee4f93f5f9c5abbc32a0fd3ac2b35b87f9ec26037d88275bd7dd0a54474995ee34ed3727f3f97c48db544b1980193a4b76a8a3ddab3591ce527f16d91882e67f0103b5cda53f7da54d489fc4ac08b6ab358a5a04aa9daa16219d50bd672a7cb804ed769d218807544e5993f1c27427104b349906a0b654df0bf69328afd3013fbe430155339c39f236df5557bf92f1ded7ff609a8502f49064ec3d1dbfb6c15d3a4c11a4f8acd12278cbf68acd5709463d12e3338a6eddb8c112f199645e23154a8e60879d2a654e3ed9296aa28f134168619691cd2c6b9e2eba4438381676173fc63c2588a3c5910dc149cf3760f0aa9fa9c3f5faa9162b0bf1aac9dd32b706a60ef53cbdb394b6b40222b5bc80eea82ba8958386672564cae3794f977871ab62337cf03e30049201ec12937e7ce79d0f55d9c810e20acf52212aca1d3888949e0e4830aad88d804161230eb89d4d329cc83570fe257217d2119134048dd2ed167646975fc7d77136919a049ea74cf08ddd2b896890bb24a0ba18094a22baa351bf29ad96c66bbb1a598f2ca391749620e62d61c3561a7d3653ccc8892c7b99baaf76bf836e2991cb06d6bc0514568ff0d1ec8bb4b3d6984f5eaefb17d3ea2893722375d3ddb8e389a8eef7d7d198f8e687d6a513983df906099f9a2d23f4f9dec6f8ef2f11fc0a21fac45353b94e00486f5e17d386af42502d09db33cf0cf28310e049c07e88682aeeb00cb833c5174266e62407a57583f1f88b304b7c6e0c84bbe1c0fd423072d37a5bd0aacf764229e5c7cd02473460ba3645cd8e8ae144065bf02d0dd238593d8e230354f67e0b2f23012c23274f80e3ee31e35e2606a4a3f31d94ab755e6d163cff52cbb36b6d0cc67ffc512aeed1dce4d7a0d70ce82f2baba12e8d514dc92a056f994adfb17b5b9712bd5186f27a2fda1f7039c5df2c8587fdc62f5627580c13234b55be4df3056050e2d1ef3218f0dd66cb05265fe1acfb0989d8213f2c19d1735a7cf3fa65d88dad5af52dc2bba22b7abf46c3bc77b5091baab9e8f0ddc4d5e581037de91a9f8dcbc69309be29cc815cf19a20a7585b8b3073edf51fc9baeb3e509b97fa4ecfd621e0fd57bd61cac1b895c03248ff12bdbc57509250df3517e8a3fe1d776836b34ab352b973d932ef708b14f7418f9eceb1d87667e61e3e758649cb083f01b133d37ab2f5afa96d6c84bcacf4efc3851ad308c1e7d9113624fce29fab460ab9d2a48d92cdb281103a5250ad44cb2ff6e67ac670c02fdafb3e0f1353953d6d7d5646ca1568dea55275a050ec501b7c6250444f7219f1ba7521ba3b93d089727ca5f3bbe0d6c1300b423377004954c5628fdb65770b18ced5c9b23a4a5a6d6ef25fe01b4ce278de0bcc4ed86e28a0a68818ffa40970128cf2c38740e80037984428c1bd5113f40ff47512ee6f4e4d8f9b8e8e1b3040d2928d003bd1c1329dc885302fbce9fa81c23b4dc49c7c82d29b52957847898676c89aa5d32b5b0e1c0d5a2b79a19d67562f407f19425687971a957375879d90c5f57c857136c17106c9ab1b99d80e69c8c954ed386493368884b55c939b8d64d26f643e800c56f90c01079d7c534e3b2b7ae352cefd3016da55f6a85eb803b85e2304915fd2001f77c74e28746293c46e4f5f0fd49cf988aafd0026b8e7a3bab2da5cdce1ea26c2e29ec03f4807fac432662b2d6c060be1c7be0e5489de69d0a6e03a4b9117f9244b34a0f1ecba89884f781c6320412413a00c4980287409a2a78c2cd7e65cecebbe4ec1c28cac4dd95f6998e78fc6f1392384331c9436aa10e10e2bf8ad2c4eafbcf276aa7bae64b74428911b3269c749338b0fc5075ad",
|
||||
"Expected": "5f9c70ec884926a89461056ad20ac4c30155e817f807e4d3f5bb743d789c83386762435c3627773fa77da5144451f2a8aad8adba88e0b669f5377c5e9bad70e45c86fe952b613f015a9953b8a5de5eaee4566acf98d41e327d93a35bd5cef4607d025e58951167957df4ff9b1627649d3943805472e5e293d3efb687cfd1e503faafeb2840a3e3b3f85d016051a58e1c9498aab72e63b748d834b31eb05d85dcde65e27834e266b85c75cc4ec0135135e0601cb93eeeb6e0010c8ceb65c4c319623c5e573a2c8c9fbbf7df68a930beb412d3f4dfd146175484f45d7afaa0d2e60684af9b34730f7c8438465ad3e1d0c3237336722f2aa51095bd5759f4b8ab4dda111b684aa3dac62a761722e7ae43495b7709933512c81c4e3c9133a51f7ce9f2b51fcec064f65779666960b4e45df3900f54311f5613e8012dd1b8efd359eda31a778264c72aa8bb419d862734d769076bce2810011989a45374e5c5d8729fec21427f0bf397eacbb4220f603cf463a4b0c94efd858ffd9768cd60d6ce68d755e0fbad007ce5c2223d70c7018345a102e4ab3c60a13a9e7794303156d4c2063e919f2153c13961fb324c80b240742f47773a7a8e25b3e3fb19b00ce839346c6eb3c732fbc6b888df0b1fe0a3d07b053a2e9402c267b2d62f794d8a2840526e3ade15ce2264496ccd7519571dfde47f7a4bb16292241c20b2be59f3f8fb4f6383f232d838c5a22d8c95b6834d9d2ca493f5a505ebe8899503b0e8f9b19e6e2dd81c1628b80016d02097e0134de51054c4e7674824d4d758760fc52377d2cad145e259aa2ffaf54139e1a66b1e0c1c191e32ac59474c6b526f5b3ba07d3e5ec286eddf531fcd5292869be58c9f22ef91026159f7cf9d05ef66b4299f4da48cc1635bf2243051d342d378a22c83390553e873713c0454ce5f3234397111ac3fe3207b86f0ed9fc025c81903e1748103692074f83824fda6341be4f95ff00b0a9a208c267e12fa01825054cc0513629bf3dbb56dc5b90d4316f87654a8be18227978ea0a8a522760cad620d0d14fd38920fb7321314062914275a5f99f677145a6979b156bd82ecd36f23f8e1273cc2759ecc0b2c69d94dad5211d1bed939dd87ed9e07b91d49713a6e16ade0a98aea789f04994e318e4ff2c8a188cd8d43aeb52c6daa3bc29b4af50ea82a247c5cd67b573b34cbadcc0a376d3bbd530d50367b42705d870f2e27a8197ef46070528bfe408360faa2ebb8bf76e9f388572842bcb119f4d84ee34ae31f5cc594f23705a49197b181fb78ed1ec99499c690f843a4d0cf2e226d118e9372271054fbabdcc5c92ae9fefaef0589cd0e722eaf30c1703ec4289c7fd81beaa8a455ccee5298e31e2080c10c366a6fcf56f7d13582ad0bcad037c612b710fc595b70fbefaaca23623b60c6c39b11beb8e5843b6b3dac60f",
|
||||
"Name": "nagydani-5-qube",
|
||||
"Gas": 5461,
|
||||
"NoBenchmark": false
|
||||
},
|
||||
{
|
||||
"Input": "000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000400c5a1611f8be90071a43db23cc2fe01871cc4c0e8ab5743f6378e4fef77f7f6db0095c0727e20225beb665645403453e325ad5f9aeb9ba99bf3c148f63f9c07cf4fe8847ad5242d6b7d4499f93bd47056ddab8f7dee878fc2314f344dbee2a7c41a5d3db91eff372c730c2fdd3a141a4b61999e36d549b9870cf2f4e632c4d5df5f024f81c028000073a0ed8847cfb0593d36a47142f578f05ccbe28c0c06aeb1b1da027794c48db880278f79ba78ae64eedfea3c07d10e0562668d839749dc95f40467d15cf65b9cfc52c7c4bcef1cda3596dd52631aac942f146c7cebd46065131699ce8385b0db1874336747ee020a5698a3d1a1082665721e769567f579830f9d259cec1a836845109c21cf6b25da572512bf3c42fd4b96e43895589042ab60dd41f497db96aec102087fe784165bb45f942859268fd2ff6c012d9d00c02ba83eace047cc5f7b2c392c2955c58a49f0338d6fc58749c9db2155522ac17914ec216ad87f12e0ee95574613942fa615898c4d9e8a3be68cd6afa4e7a003dedbdf8edfee31162b174f965b20ae752ad89c967b3068b6f722c16b354456ba8e280f987c08e0a52d40a2e8f3a59b94d590aeef01879eb7a90b3ee7d772c839c85519cbeaddc0c193ec4874a463b53fcaea3271d80ebfb39b33489365fc039ae549a17a9ff898eea2f4cb27b8dbee4c17b998438575b2b8d107e4a0d66ba7fca85b41a58a8d51f191a35c856dfbe8aef2b00048a694bbccff832d23c8ca7a7ff0b6c0b3011d00b97c86c0628444d267c951d9e4fb8f83e154b8f74fb51aa16535e498235c5597dac9606ed0be3173a3836baa4e7d756ffe1e2879b415d3846bccd538c05b847785699aefde3e305decb600cd8fb0e7d8de5efc26971a6ad4e6d7a2d91474f1023a0ac4b78dc937da0ce607a45974d2cac1c33a2631ff7fe6144a3b2e5cf98b531a9627dea92c1dc82204d09db0439b6a11dd64b484e1263aa45fd9539b6020b55e3baece3986a8bffc1003406348f5c61265099ed43a766ee4f93f5f9c5abbc32a0fd3ac2b35b87f9ec26037d88275bd7dd0a54474995ee34ed3727f3f97c48db544b1980193a4b76a8a3ddab3591ce527f16d91882e67f0103b5cda53f7da54d489fc4ac08b6ab358a5a04aa9daa16219d50bd672a7cb804ed769d218807544e5993f1c27427104b349906a0b654df0bf69328afd3013fbe430155339c39f236df5557bf92f1ded7ff609a8502f49064ec3d1dbfb6c15d3a4c11a4f8acd12278cbf68acd5709463d12e3338a6eddb8c112f199645e23154a8e60879d2a654e3ed9296aa28f134168619691cd2c6b9e2eba4438381676173fc63c2588a3c5910dc149cf3760f0aa9fa9c3f5faa9162b0bf1aac9dd32b706a60ef53cbdb394b6b40222b5bc80eea82ba8958386672564cae3794f977871ab62337cf010001e30049201ec12937e7ce79d0f55d9c810e20acf52212aca1d3888949e0e4830aad88d804161230eb89d4d329cc83570fe257217d2119134048dd2ed167646975fc7d77136919a049ea74cf08ddd2b896890bb24a0ba18094a22baa351bf29ad96c66bbb1a598f2ca391749620e62d61c3561a7d3653ccc8892c7b99baaf76bf836e2991cb06d6bc0514568ff0d1ec8bb4b3d6984f5eaefb17d3ea2893722375d3ddb8e389a8eef7d7d198f8e687d6a513983df906099f9a2d23f4f9dec6f8ef2f11fc0a21fac45353b94e00486f5e17d386af42502d09db33cf0cf28310e049c07e88682aeeb00cb833c5174266e62407a57583f1f88b304b7c6e0c84bbe1c0fd423072d37a5bd0aacf764229e5c7cd02473460ba3645cd8e8ae144065bf02d0dd238593d8e230354f67e0b2f23012c23274f80e3ee31e35e2606a4a3f31d94ab755e6d163cff52cbb36b6d0cc67ffc512aeed1dce4d7a0d70ce82f2baba12e8d514dc92a056f994adfb17b5b9712bd5186f27a2fda1f7039c5df2c8587fdc62f5627580c13234b55be4df3056050e2d1ef3218f0dd66cb05265fe1acfb0989d8213f2c19d1735a7cf3fa65d88dad5af52dc2bba22b7abf46c3bc77b5091baab9e8f0ddc4d5e581037de91a9f8dcbc69309be29cc815cf19a20a7585b8b3073edf51fc9baeb3e509b97fa4ecfd621e0fd57bd61cac1b895c03248ff12bdbc57509250df3517e8a3fe1d776836b34ab352b973d932ef708b14f7418f9eceb1d87667e61e3e758649cb083f01b133d37ab2f5afa96d6c84bcacf4efc3851ad308c1e7d9113624fce29fab460ab9d2a48d92cdb281103a5250ad44cb2ff6e67ac670c02fdafb3e0f1353953d6d7d5646ca1568dea55275a050ec501b7c6250444f7219f1ba7521ba3b93d089727ca5f3bbe0d6c1300b423377004954c5628fdb65770b18ced5c9b23a4a5a6d6ef25fe01b4ce278de0bcc4ed86e28a0a68818ffa40970128cf2c38740e80037984428c1bd5113f40ff47512ee6f4e4d8f9b8e8e1b3040d2928d003bd1c1329dc885302fbce9fa81c23b4dc49c7c82d29b52957847898676c89aa5d32b5b0e1c0d5a2b79a19d67562f407f19425687971a957375879d90c5f57c857136c17106c9ab1b99d80e69c8c954ed386493368884b55c939b8d64d26f643e800c56f90c01079d7c534e3b2b7ae352cefd3016da55f6a85eb803b85e2304915fd2001f77c74e28746293c46e4f5f0fd49cf988aafd0026b8e7a3bab2da5cdce1ea26c2e29ec03f4807fac432662b2d6c060be1c7be0e5489de69d0a6e03a4b9117f9244b34a0f1ecba89884f781c6320412413a00c4980287409a2a78c2cd7e65cecebbe4ec1c28cac4dd95f6998e78fc6f1392384331c9436aa10e10e2bf8ad2c4eafbcf276aa7bae64b74428911b3269c749338b0fc5075ad",
|
||||
"Expected": "5a0eb2bdf0ac1cae8e586689fa16cd4b07dfdedaec8a110ea1fdb059dd5253231b6132987598dfc6e11f86780428982d50cf68f67ae452622c3b336b537ef3298ca645e8f89ee39a26758206a5a3f6409afc709582f95274b57b71fae5c6b74619ae6f089a5393c5b79235d9caf699d23d88fb873f78379690ad8405e34c19f5257d596580c7a6a7206a3712825afe630c76b31cdb4a23e7f0632e10f14f4e282c81a66451a26f8df2a352b5b9f607a7198449d1b926e27036810368e691a74b91c61afa73d9d3b99453e7c8b50fd4f09c039a2f2feb5c419206694c31b92df1d9586140cb3417b38d0c503c7b508cc2ed12e813a1c795e9829eb39ee78eeaf360a169b491a1d4e419574e712402de9d48d54c1ae5e03739b7156615e8267e1fb0a897f067afd11fb33f6e24182d7aaaaa18fe5bc1982f20d6b871e5a398f0f6f718181d31ec225cfa9a0a70124ed9a70031bdf0c1c7829f708b6e17d50419ef361cf77d99c85f44607186c8d683106b8bd38a49b5d0fb503b397a83388c5678dcfcc737499d84512690701ed621a6f0172aecf037184ddf0f2453e4053024018e5ab2e30d6d5363b56e8b41509317c99042f517247474ab3abc848e00a07f69c254f46f2a05cf6ed84e5cc906a518fdcfdf2c61ce731f24c5264f1a25fc04934dc28aec112134dd523f70115074ca34e3807aa4cb925147f3a0ce152d323bd8c675ace446d0fd1ae30c4b57f0eb2c23884bc18f0964c0114796c5b6d080c3d89175665fbf63a6381a6a9da39ad070b645c8bb1779506da14439a9f5b5d481954764ea114fac688930bc68534d403cff4210673b6a6ff7ae416b7cd41404c3d3f282fcd193b86d0f54d0006c2a503b40d5c3930da980565b8f9630e9493a79d1c03e74e5f93ac8e4dc1a901ec5e3b3e57049124c7b72ea345aa359e782285d9e6a5c144a378111dd02c40855ff9c2be9b48425cb0b2fd62dc8678fd151121cf26a65e917d65d8e0dacfae108eb5508b601fb8ffa370be1f9a8b749a2d12eeab81f41079de87e2d777994fa4d28188c579ad327f9957fb7bdecec5c680844dd43cb57cf87aeb763c003e65011f73f8c63442df39a92b946a6bd968a1c1e4d5fa7d88476a68bd8e20e5b70a99259c7d3f85fb1b65cd2e93972e6264e74ebf289b8b6979b9b68a85cd5b360c1987f87235c3c845d62489e33acf85d53fa3561fe3a3aee18924588d9c6eba4edb7a4d106b31173e42929f6f0c48c80ce6a72d54eca7c0fe870068b7a7c89c63cdda593f5b32d3cb4ea8a32c39f00ab449155757172d66763ed9527019d6de6c9f2416aa6203f4d11c9ebee1e1d3845099e55504446448027212616167eb36035726daa7698b075286f5379cd3e93cb3e0cf4f9cb8d017facbb5550ed32d5ec5400ae57e47e2bf78d1eaeff9480cc765ceff39db500",
|
||||
"Name": "nagydani-5-pow0x10001",
|
||||
"Gas": 87381,
|
||||
"NoBenchmark": false
|
||||
}
|
||||
]
|
||||
}
|
|
@ -16,14 +16,14 @@ import
|
|||
../constantine/ethereum_evm_precompiles
|
||||
|
||||
type
|
||||
BN256Tests = object
|
||||
PrecompileTests = object
|
||||
`func`: string
|
||||
fork: string
|
||||
data: seq[BN256Test]
|
||||
data: seq[PrecompileTest]
|
||||
|
||||
HexString = string
|
||||
|
||||
BN256Test = object
|
||||
PrecompileTest = object
|
||||
Input: HexString
|
||||
Expected: HexString
|
||||
Name: string
|
||||
|
@ -38,36 +38,39 @@ proc loadVectors(TestType: typedesc, filename: string): TestType =
|
|||
let content = readFile(TestVectorsDir/filename)
|
||||
result = content.fromJson(TestType)
|
||||
|
||||
template runBN256Tests(filename: string, funcname: untyped, osize: static int) =
|
||||
proc `bn256testrunner _ funcname`() =
|
||||
let vec = loadVectors(BN256Tests, filename)
|
||||
echo "Running ", filename
|
||||
template runPrecompileTests(filename: string, funcname: untyped) =
|
||||
block:
|
||||
proc `PrecompileTestrunner _ funcname`() =
|
||||
let vec = loadVectors(PrecompileTests, filename)
|
||||
echo "Running ", filename
|
||||
|
||||
for test in vec.data:
|
||||
stdout.write " Testing " & test.Name & " ... "
|
||||
for test in vec.data:
|
||||
stdout.write " Testing " & test.Name & " ... "
|
||||
|
||||
# Length: 2 hex characters -> 1 byte
|
||||
var inputbytes = newSeq[byte](test.Input.len div 2)
|
||||
inputbytes.paddedFromHex(test.Input, bigEndian)
|
||||
# Length: 2 hex characters -> 1 byte
|
||||
var inputbytes = newSeq[byte](test.Input.len div 2)
|
||||
inputbytes.paddedFromHex(test.Input, bigEndian)
|
||||
|
||||
var r: array[osize, byte]
|
||||
var expected: array[osize, byte]
|
||||
var expected = newSeq[byte](test.Expected.len div 2)
|
||||
expected.paddedFromHex(test.Expected, bigEndian)
|
||||
|
||||
let status = funcname(r, inputbytes)
|
||||
if status != cttEVM_Success:
|
||||
reset(r)
|
||||
var r = newSeq[byte](test.Expected.len div 2)
|
||||
|
||||
expected.paddedFromHex(test.Expected, bigEndian)
|
||||
let status = funcname(r, inputbytes)
|
||||
if status != cttEVM_Success:
|
||||
reset(r)
|
||||
|
||||
doAssert r == expected, "[Test Failure]\n" &
|
||||
" " & funcname.astToStr & " status: " & $status & "\n" &
|
||||
" " & "result: " & r.toHex() & "\n" &
|
||||
" " & "expected: " & expected.toHex() & '\n'
|
||||
doAssert r == expected, "[Test Failure]\n" &
|
||||
" " & funcname.astToStr & " status: " & $status & "\n" &
|
||||
" " & "result: " & r.toHex() & "\n" &
|
||||
" " & "expected: " & expected.toHex() & '\n'
|
||||
|
||||
stdout.write "Success\n"
|
||||
stdout.write "Success\n"
|
||||
|
||||
`bn256testrunner _ funcname`()
|
||||
`PrecompileTestrunner _ funcname`()
|
||||
|
||||
runBN256Tests("bn256Add.json", eth_evm_ecadd, 64)
|
||||
runBN256Tests("bn256mul.json", eth_evm_ecmul, 64)
|
||||
runBN256Tests("pairing.json", eth_evm_ecpairing, 32)
|
||||
runPrecompileTests("bn256Add.json", eth_evm_ecadd)
|
||||
runPrecompileTests("bn256mul.json", eth_evm_ecmul)
|
||||
runPrecompileTests("pairing.json", eth_evm_ecpairing)
|
||||
runPrecompileTests("modexp.json", eth_evm_modexp)
|
||||
runPrecompileTests("modexp_eip2565.json", eth_evm_modexp)
|
Loading…
Reference in New Issue