UNPKG

o1js

Version:

TypeScript framework for zk-SNARKs and zkApps

163 lines (146 loc) 5.19 kB
import { createProvableBigInt } from '../bigint.js'; import { Fq } from '../../../bindings/crypto/finite-field.js'; import { bls12_381 } from '@noble/curves/bls12-381'; import { secp521r1 } from '@noble/curves/p521'; import { equivalentProvable as equivalent, spec, throwError, unit, } from '../../testing/equivalent.js'; import { Random } from '../../testing/property.js'; import { ProvablePure } from '../types/provable-intf.js'; class SmallField extends createProvableBigInt(17n) {} let x = SmallField.fromBigInt(16n); let y = SmallField.fromBigInt(-1n); let z = SmallField.fromBigInt(1n); x.assertEquals(y); // 16 = -1 (mod 17) x.mul(x).assertEquals(z); // 16 * 16 = 15 * 17 + 1 = 1 (mod 17) class BigInt255 extends createProvableBigInt(Fq.modulus) {} BigInt255.provable satisfies ProvablePure<BigInt255>; let fq = spec({ rng: Random.scalar, there: BigInt255.fromBigInt, back: (x: BigInt255) => x.toBigInt(), provable: BigInt255.provable, }); let u255 = spec({ rng: Random.bignat(1n << 255n), there: BigInt255.fromBigInt, back: (x: BigInt255) => x.toBigInt(), provable: BigInt255.provable, }); // arithmetic equivalent({ from: [fq, fq], to: u255 })(Fq.add, (x, y) => x.add(y)); equivalent({ from: [fq], to: u255 })( (x) => Fq.add(x, x), (x) => x.double() ); equivalent({ from: [fq, fq], to: u255 })(Fq.sub, (x, y) => x.sub(y)); equivalent({ from: [fq, fq], to: u255 })(Fq.mul, (x, y) => x.mul(y)); equivalent({ from: [fq], to: u255 })(Fq.square, (x) => x.square()); equivalent({ from: [fq, fq], to: fq })( (x, y) => Fq.div(x, y) ?? throwError('division by 0'), (x, y) => x.div(y) ); equivalent({ from: [fq], to: fq })( (x) => Fq.inverse(x) ?? throwError('division by 0'), (x) => x.inverse() ); equivalent({ from: [fq], to: u255 })(Fq.negate, (x) => x.negate()); equivalent({ from: [fq, fq], to: u255 })(Fq.power, (x, y) => x.pow(y)); equivalent({ from: [fq], to: u255 })( (x) => Fq.sqrt(x) ?? throwError(), (x) => x.sqrt() ); // comparison equivalent({ from: [fq, fq], to: unit })( (x, y) => x === y || throwError('not equal'), (x, y) => x.assertEquals(y) ); const bls_Fp = bls12_381.fields.Fp; class BigInt381 extends createProvableBigInt(bls_Fp.ORDER) {} BigInt381.provable satisfies ProvablePure<BigInt381>; let blsp = spec({ rng: Random.scalar, there: BigInt381.fromBigInt, back: (x: BigInt381) => x.toBigInt(), provable: BigInt381.provable, }); let u381 = spec({ rng: Random.bignat(1n << 381n), there: BigInt381.fromBigInt, back: (x: BigInt381) => x.toBigInt(), provable: BigInt381.provable, }); // arithmetic equivalent({ from: [blsp, blsp], to: u381 })(bls_Fp.add, (x, y) => x.add(y)); equivalent({ from: [blsp], to: u381 })( (x) => bls_Fp.add(x, x), (x) => x.double() ); equivalent({ from: [blsp, blsp], to: u381 })(bls_Fp.sub, (x, y) => x.sub(y)); equivalent({ from: [blsp, blsp], to: u381 })(bls_Fp.mul, (x, y) => x.mul(y)); equivalent({ from: [blsp], to: u381 })(bls_Fp.sqr, (x) => x.square()); equivalent({ from: [blsp, blsp], to: blsp })( (x, y) => bls_Fp.div(x, y) ?? throwError('division by 0'), (x, y) => x.div(y) ); equivalent({ from: [blsp], to: blsp })( (x) => bls_Fp.inv(x) ?? throwError('division by 0'), (x) => x.inverse() ); equivalent({ from: [blsp], to: u381 })(bls_Fp.neg, (x) => x.negate()); equivalent({ from: [blsp, blsp], to: u381 })(bls_Fp.pow, (x, y) => x.pow(y)); equivalent({ from: [blsp], to: u381 })( (x) => bls_Fp.sqrt(x) ?? throwError(), (x) => x.sqrt() ); // comparison equivalent({ from: [blsp, blsp], to: unit })( (x, y) => x === y || throwError('not equal'), (x, y) => x.assertEquals(y) ); const secp521r1_Fp = secp521r1.CURVE.Fp; class BigInt521 extends createProvableBigInt(secp521r1_Fp.ORDER) {} BigInt521.provable satisfies ProvablePure<BigInt521>; let sfp = spec({ rng: Random.scalar, there: BigInt521.fromBigInt, back: (x: BigInt521) => x.toBigInt(), provable: BigInt521.provable, }); let u521 = spec({ rng: Random.bignat(1n << 521n), there: BigInt521.fromBigInt, back: (x: BigInt521) => x.toBigInt(), provable: BigInt521.provable, }); // arithmetic equivalent({ from: [sfp, sfp], to: u521 })(secp521r1_Fp.add, (x, y) => x.add(y)); equivalent({ from: [sfp], to: u521 })( (x) => secp521r1_Fp.add(x, x), (x) => x.double() ); equivalent({ from: [sfp, sfp], to: u521 })(secp521r1_Fp.sub, (x, y) => x.sub(y)); equivalent({ from: [sfp, sfp], to: u521 })(secp521r1_Fp.mul, (x, y) => x.mul(y)); equivalent({ from: [sfp], to: u521 })(secp521r1_Fp.sqr, (x) => x.square()); equivalent({ from: [sfp, sfp], to: sfp })( (x, y) => secp521r1_Fp.div(x, y) ?? throwError('division by 0'), (x, y) => x.div(y) ); equivalent({ from: [sfp], to: sfp })( (x) => secp521r1_Fp.inv(x) ?? throwError('division by 0'), (x) => x.inverse() ); equivalent({ from: [sfp], to: u521 })(secp521r1_Fp.neg, (x) => x.negate()); equivalent({ from: [sfp, sfp], to: u521 })(secp521r1_Fp.pow, (x, y) => x.pow(y)); equivalent({ from: [sfp], to: u521 })( (x) => secp521r1_Fp.sqrt(x) ?? throwError(), (x) => x.sqrt() ); // comparison equivalent({ from: [sfp, sfp], to: unit })( (x, y) => x === y || throwError('not equal'), (x, y) => x.assertEquals(y) );