The modular exponentiation is a function that calculates the math expression a^b % n
. For example, let a=5, b=3, and c=4, the expression evaluates 5^3 % 4 = 125 % 4 = 1
.
We explore the case that given the exponent b
and the modulus n
are fixed known numbers, how good we can perform in Solidity language. This is useful when we need to perform the hash to curve operation to validate the aggregated signature on chain.
We use the parameters of BN254 curve throughout the examples. In its hash to curve operation, we check if an input x
has a square root on the G1 subgroup. A modexp is calculated with exponent (n+1)/4
and modulus n
known before the contract is deployed.
n = 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47
def modexp(x):
return pow(x, (n + 1) // 4, n)
> npm run test
Ts implementation
✓ works at some inputs (50ms)
ModExp
Deployment gas 628448
Avg cost 13750
✓ baseline: Calling EIP-198 precompile (426ms)
Avg cost 38673
✓ modexp 1: Naive Solidity (1203ms)
Avg cost 30470
✓ modexp 2: Naive inline assembly (551ms)
Avg cost 23981
✓ modexp 3: Loop unroll (489ms)
Avg cost 22847
✓ modexp 4: Minor optimize (373ms)
Avg cost 21179
✓ modexp 5: Unroll more (358ms)
Avg cost 21021
✓ modexp 6: Remove if statement (355ms)
Avg cost 26489
✓ modexp 7: Reproduce historical result (342ms)
ModExp Monster code
Deployment gas 504279
Avg cost 7133
✓ modexp 8: monster code (257ms)
ModExp AddChainLong
Deployment gas 499965
Avg cost 6744
✓ modexp 9: add chain long (233ms)
Test magic_codegen
pytest magic_codegen.py -s
Proto's magic codegen optimized the Monster code at bytecode level and has a gas cost 5075.