Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
40acc92
add constantine
advaita-saha Aug 26, 2025
9164364
ecRecover shift to constantine
advaita-saha Aug 26, 2025
714333f
add ecAdd
advaita-saha Aug 27, 2025
76e11d7
add ecMul
advaita-saha Aug 27, 2025
b398cf9
add ripemd160
advaita-saha Aug 27, 2025
2a3b64a
add sha256
advaita-saha Aug 28, 2025
ca5d607
add blsG1Add
advaita-saha Aug 28, 2025
a123bbe
restore test vectors
advaita-saha Sep 1, 2025
3ecf377
update constantine
advaita-saha Sep 2, 2025
037b0fd
add bls12381 g1msm
advaita-saha Sep 2, 2025
953f27c
bls12381 g2add
advaita-saha Sep 2, 2025
f973b85
bls12381 g2msm
advaita-saha Sep 2, 2025
5368d4d
remove file level lto
advaita-saha Sep 2, 2025
698417b
Merge branch 'master' into constantine
advaita-saha Sep 2, 2025
5c7fa34
remove pairing check
advaita-saha Sep 2, 2025
a40c4c0
add bls
advaita-saha Sep 3, 2025
03a79e3
Merge branch 'master' into constantine
advaita-saha Sep 3, 2025
2b27d11
Merge branch 'master' into constantine
advaita-saha Sep 6, 2025
515fa01
disable lto and update constantine
advaita-saha Sep 6, 2025
b5b1c78
Merge branch 'master' into constantine
advaita-saha Sep 8, 2025
3048b46
add bn254 ec pairing check
advaita-saha Sep 8, 2025
d52d5e4
remove ec pairing
advaita-saha Sep 10, 2025
ec332f7
Merge branch 'master' into constantine
advaita-saha Sep 10, 2025
84d30a7
Merge branch 'master' into constantine
advaita-saha Sep 10, 2025
dd56c8b
enable -fomit-frame-pointer for windows
advaita-saha Sep 11, 2025
1743557
Merge branch 'master' into constantine
advaita-saha Sep 15, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -226,3 +226,6 @@
path = vendor/nim-minilru
url = https://github.com/status-im/nim-minilru.git
branch = master
[submodule "vendor/constantine"]
path = vendor/constantine
url = https://github.com/mratsim/constantine
27 changes: 27 additions & 0 deletions config.nims
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ if defined(release) and not defined(disableLTO):
switch("passC", "-fvisibility=hidden")

if defined(windows):
# Constantine
switch("passC", "-fomit-frame-pointer")
switch("passL", "-fomit-frame-pointer")
Comment on lines 59 to +62
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Constantine windows issue

# disable timestamps in Windows PE headers - https://wiki.debian.org/ReproducibleBuilds/TimestampsInPEBinaries
switch("passL", "-Wl,--no-insert-timestamp")
# increase stack size, unless something else is setting the stack size
Expand Down Expand Up @@ -171,6 +174,9 @@ switch("warning", "Deprecated:off")
# disable nim-kzg's blst
switch("define", "kzgExternalBlst")

# Constantine missing operand zero assumed error suppression
switch("warning", "User:off")

# We lock down rocksdb to a particular version
# TODO self-build rocksdb dll on windows
when not defined(use_system_rocksdb) and not defined(windows):
Expand Down Expand Up @@ -200,6 +206,27 @@ put("secp256k1.always", "-fno-lto -fomit-frame-pointer")
# Unfortunately this is filename based instead of path-based
# Assumes GCC

# Constantine
put("limbs_asm_bigint_arm64.always", "-fno-lto")
put("limbs_asm_bigint_x86.always", "-fno-lto")
put("limbs_asm_crandall_x86.always", "-fno-lto")
put("limbs_asm_crandall_x86_adx_bmi2.always", "-fno-lto")
put("limbs_asm_modular_arm64.always", "-fno-lto")
put("limbs_asm_modular_dbl_prec_x86.always", "-fno-lto")
put("limbs_asm_modular_x86.always", "-fno-lto")
put("limbs_asm_mul_arm64.always", "-fno-lto")
put("limbs_asm_mul_mont_arm64.always", "-fno-lto")
put("limbs_asm_mul_mont_x86.always", "-fno-lto")
put("limbs_asm_mul_mont_x86_adx_bmi2.always", "-fno-lto")
put("limbs_asm_mul_x86.always", "-fno-lto")
put("limbs_asm_mul_x86_adx_bmi2.always", "-fno-lto")
put("limbs_asm_redc_mont_arm64.always", "-fno-lto")
put("limbs_asm_redc_mont_x86.always", "-fno-lto")
put("limbs_asm_redc_mont_x86_adx_bmi2.always", "-fno-lto")

put("bls12_381_pairings.always", "-fno-lto")
put("ec_multi_scalar_mul_scheduler.always", "-fno-lto")

# BLST
put("server.always", "-fno-lto")
put("assembly.always", "-fno-lto")
Expand Down
202 changes: 64 additions & 138 deletions execution_chain/evm/precompiles.nim
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import
std/[macros],
results,
constantine/ethereum_evm_precompiles,
"."/[types, blake2b_f, blscurve],
./interpreter/[gas_meter, gas_costs, utils/utils_numeric],
eth/common/keys,
Expand Down Expand Up @@ -233,7 +234,11 @@ func sha256(c: Computation): EvmResultVoid =
gasFee = GasSHA256 + wordCount.GasInt * GasSHA256Word

? c.gasMeter.consumeGas(gasFee, reason="SHA256 Precompile")
assign(c.output, sha2.sha256.digest(c.msg.data).data)
c.output.setLen(32)
let res = c.output.eth_evm_sha256(c.msg.data)

if res != cttEVM_Success:
return err(prcErr(PrcInvalidParam))
ok()

func ripemd160(c: Computation): EvmResultVoid =
Expand All @@ -243,7 +248,10 @@ func ripemd160(c: Computation): EvmResultVoid =

? c.gasMeter.consumeGas(gasFee, reason="RIPEMD160 Precompile")
c.output.setLen(32)
assign(c.output.toOpenArray(12, 31), ripemd.ripemd160.digest(c.msg.data).data)
let res =c.output.eth_evm_ripemd160(c.msg.data)

if res != cttEVM_Success:
return err(prcErr(PrcInvalidParam))
ok()

func identity(c: Computation): EvmResultVoid =
Expand Down Expand Up @@ -385,40 +393,29 @@ func bn256ecAdd(c: Computation, fork: EVMFork = FkByzantium): EvmResultVoid =
let gasFee = if fork < FkIstanbul: GasECAdd else: GasECAddIstanbul
? c.gasMeter.consumeGas(gasFee, reason = "ecAdd Precompile")

var
input: array[128, byte]
# Padding data
let len = min(c.msg.data.len, 128) - 1
input[0..len] = c.msg.data[0..len]
var p1 = ? G1.getPoint(input.toOpenArray(0, 63))
var p2 = ? G1.getPoint(input.toOpenArray(64, 127))
var apo = (p1 + p2).toAffine()
var output: array[64, byte]
let res = output.eth_evm_bn254_g1add(c.msg.data)

if res != cttEVM_Success:
return err(prcErr(PrcInvalidParam))

c.output.setLen(64)
if isSome(apo):
# we can discard here because we supply proper buffer
discard apo.get().toBytes(c.output)
assign(c.output, output)

ok()

func bn256ecMul(c: Computation, fork: EVMFork = FkByzantium): EvmResultVoid =
let gasFee = if fork < FkIstanbul: GasECMul else: GasECMulIstanbul
? c.gasMeter.consumeGas(gasFee, reason="ecMul Precompile")

var
input: array[96, byte]
var output: array[64, byte]
let res = output.eth_evm_bn254_g1mul(c.msg.data)

# Padding data
let len = min(c.msg.data.len, 96) - 1
assign(input.toOpenArray(0, len), c.msg.data.toOpenArray(0, len))
var p1 = ? G1.getPoint(input.toOpenArray(0, 63))
var fr = ? getFR(input.toOpenArray(64, 95))
var apo = (p1 * fr).toAffine()
if res != cttEVM_Success:
return err(prcErr(PrcInvalidParam))

c.output.setLen(64)
if isSome(apo):
# we can discard here because we supply buffer of proper size
discard apo.get().toBytes(c.output)
assign(c.output, output)

ok()

Expand Down Expand Up @@ -457,7 +454,7 @@ func bn256ecPairing(c: Computation, fork: EVMFork = FkByzantium): EvmResultVoid
if acc == FQ12.one():
# we can discard here because we supply buffer of proper size
discard BNU256.one().toBytesBE(c.output)

ok()

func blake2bf(c: Computation): EvmResultVoid =
Expand Down Expand Up @@ -485,18 +482,15 @@ func blsG1Add(c: Computation): EvmResultVoid =

? c.gasMeter.consumeGas(Bls12381G1AddGas, reason="blsG1Add Precompile")

var a, b: BLS_G1
if not a.decodePoint(input.toOpenArray(0, 127)):
return err(prcErr(PrcInvalidPoint))

if not b.decodePoint(input.toOpenArray(128, 255)):
return err(prcErr(PrcInvalidPoint))
var output: array[128, byte]
let res = output.eth_evm_bls12381_g1add(c.msg.data)

a.add b
if res != cttEVM_Success:
return err(prcErr(PrcInvalidParam))

c.output.setLen(128)
if not encodePoint(a, c.output):
return err(prcErr(PrcInvalidPoint))
assign(c.output, output)

ok()

const
Expand Down Expand Up @@ -560,35 +554,15 @@ func blsG1MultiExp(c: Computation): EvmResultVoid =

? c.gasMeter.consumeGas(gas, reason="blsG1MultiExp Precompile")

var
p: BLS_G1
s: BLS_SCALAR
acc: BLS_G1
var output: array[128, byte]
let res = output.eth_evm_bls12381_g1msm(input)

# Decode point scalar pairs
for i in 0..<K:
let off = L * i

# Decode G1 point
if not p.decodePoint(input.toOpenArray(off, off+127)):
return err(prcErr(PrcInvalidPoint))

if not p.subgroupCheck:
return err(prcErr(PrcInvalidPoint))

# Decode scalar value
if not s.fromBytes(input.toOpenArray(off+128, off+159)):
return err(prcErr(PrcInvalidParam))

p.mul(s)
if i == 0:
acc = p
else:
acc.add(p)
if res != cttEVM_Success:
return err(prcErr(PrcInvalidParam))

c.output.setLen(128)
if not encodePoint(acc, c.output):
return err(prcErr(PrcInvalidPoint))
assign(c.output, output)

ok()

func blsG2Add(c: Computation): EvmResultVoid =
Expand All @@ -600,18 +574,15 @@ func blsG2Add(c: Computation): EvmResultVoid =

? c.gasMeter.consumeGas(Bls12381G2AddGas, reason="blsG2Add Precompile")

var a, b: BLS_G2
if not a.decodePoint(input.toOpenArray(0, 255)):
return err(prcErr(PrcInvalidPoint))

if not b.decodePoint(input.toOpenArray(256, 511)):
return err(prcErr(PrcInvalidPoint))
var output: array[256, byte]
let res = output.eth_evm_bls12381_g2add(c.msg.data)

a.add b
if res != cttEVM_Success:
return err(prcErr(PrcInvalidParam))

c.output.setLen(256)
if not encodePoint(a, c.output):
return err(prcErr(PrcInvalidPoint))
assign(c.output, output)

ok()

func blsG2MultiExp(c: Computation): EvmResultVoid =
Expand All @@ -628,35 +599,15 @@ func blsG2MultiExp(c: Computation): EvmResultVoid =

? c.gasMeter.consumeGas(gas, reason="blsG2MultiExp Precompile")

var
p: BLS_G2
s: BLS_SCALAR
acc: BLS_G2

# Decode point scalar pairs
for i in 0..<K:
let off = L * i

# Decode G1 point
if not p.decodePoint(input.toOpenArray(off, off+255)):
return err(prcErr(PrcInvalidPoint))

if not p.subgroupCheck:
return err(prcErr(PrcInvalidPoint))

# Decode scalar value
if not s.fromBytes(input.toOpenArray(off+256, off+287)):
return err(prcErr(PrcInvalidParam))
var output: array[256, byte]
let res = output.eth_evm_bls12381_g2msm(input)

p.mul(s)
if i == 0:
acc = p
else:
acc.add(p)
if res != cttEVM_Success:
return err(prcErr(PrcInvalidParam))

c.output.setLen(256)
if not encodePoint(acc, c.output):
return err(prcErr(PrcInvalidPoint))
assign(c.output, output)

ok()

func blsPairing(c: Computation): EvmResultVoid =
Expand All @@ -673,40 +624,15 @@ func blsPairing(c: Computation): EvmResultVoid =

? c.gasMeter.consumeGas(gas, reason="blsG2Pairing Precompile")

var
g1: BLS_G1P
g2: BLS_G2P
acc: BLS_ACC

# Decode pairs
for i in 0..<K:
let off = L * i

# Decode G1 point
if not g1.decodePoint(input.toOpenArray(off, off+127)):
return err(prcErr(PrcInvalidPoint))

# Decode G2 point
if not g2.decodePoint(input.toOpenArray(off+128, off+383)):
return err(prcErr(PrcInvalidPoint))
var output: array[32, byte]
let res = output.eth_evm_bls12381_pairingcheck(input)

# 'point is on curve' check already done,
# Here we need to apply subgroup checks.
if not g1.subgroupCheck:
return err(prcErr(PrcInvalidPoint))

if not g2.subgroupCheck:
return err(prcErr(PrcInvalidPoint))

# Update pairing engine with G1 and G2 points
if i == 0:
acc = millerLoop(g1, g2)
else:
acc.mul(millerLoop(g1, g2))
if res != cttEVM_Success:
return err(prcErr(PrcInvalidParam))

c.output.setLen(32)
if acc.check():
c.output[^1] = 1.byte
assign(c.output, output)

ok()

func blsMapG1(c: Computation): EvmResultVoid =
Expand All @@ -718,15 +644,15 @@ func blsMapG1(c: Computation): EvmResultVoid =

? c.gasMeter.consumeGas(Bls12381MapG1Gas, reason="blsMapG1 Precompile")

var fe: BLS_FE
if not fe.decodeFE(input):
return err(prcErr(PrcInvalidPoint))
var output: array[128, byte]
let res = output.eth_evm_bls12381_map_fp_to_g1(input)

let p = fe.mapFPToG1()
if res != cttEVM_Success:
return err(prcErr(PrcInvalidParam))

c.output.setLen(128)
if not encodePoint(p, c.output):
return err(prcErr(PrcInvalidPoint))
assign(c.output, output)

ok()

func blsMapG2(c: Computation): EvmResultVoid =
Expand All @@ -738,15 +664,15 @@ func blsMapG2(c: Computation): EvmResultVoid =

? c.gasMeter.consumeGas(Bls12381MapG2Gas, reason="blsMapG2 Precompile")

var fe: BLS_FE2
if not fe.decodeFE(input):
return err(prcErr(PrcInvalidPoint))
var output: array[256, byte]
let res = output.eth_evm_bls12381_map_fp2_to_g2(input)

let p = fe.mapFPToG2()
if res != cttEVM_Success:
return err(prcErr(PrcInvalidParam))

c.output.setLen(256)
if not encodePoint(p, c.output):
return err(prcErr(PrcInvalidPoint))
assign(c.output, output)

ok()

proc pointEvaluation(c: Computation): EvmResultVoid =
Expand Down
1 change: 1 addition & 0 deletions vendor/constantine
Submodule constantine added at b3f4eb
Loading