Skip to main content
G1/G2 operations and pairing checks for zero-knowledge proofs. Maps to EVM precompiles 0x06, 0x07, 0x08.
import { Bn254Service, Bn254Live } from 'voltaire-effect/crypto'
import { Effect } from 'effect'

const result = await Effect.runPromise(
  Effect.gen(function* () {
    const bn254 = yield* Bn254Service
    const g1 = yield* bn254.g1Generator()
    const doubled = yield* bn254.g1Mul(g1, 2n)
    const sum = yield* bn254.g1Add(g1, doubled)
    const valid = yield* bn254.pairingCheck([[a, b], [c, vk]])
    return { sum, valid }
  }).pipe(Effect.provide(Bn254Live))
)

EVM Precompiles

AddressOperationMethod
0x06ecAddg1Add
0x07ecMulg1Mul
0x08ecPairingpairingCheck

Testing

import { Bn254Test } from 'voltaire-effect/crypto'
myProgram.pipe(Effect.provide(Bn254Test))
// Pairing always true, fixed mock points

Interface

interface Bn254ServiceShape {
  readonly g1Add: (a: BN254G1PointType, b: BN254G1PointType) => Effect.Effect<BN254G1PointType>
  readonly g1Mul: (point: BN254G1PointType, scalar: bigint) => Effect.Effect<BN254G1PointType>
  readonly g1Generator: () => Effect.Effect<BN254G1PointType>
  readonly g2Add: (a: BN254G2PointType, b: BN254G2PointType) => Effect.Effect<BN254G2PointType>
  readonly g2Mul: (point: BN254G2PointType, scalar: bigint) => Effect.Effect<BN254G2PointType>
  readonly g2Generator: () => Effect.Effect<BN254G2PointType>
  readonly pairingCheck: (pairs: ReadonlyArray<readonly [BN254G1PointType, BN254G2PointType]>) => Effect.Effect<boolean>
}