o1js
Version:
TypeScript framework for zk-SNARKs and zkApps
82 lines (71 loc) • 2.6 kB
text/typescript
import type { FiniteField } from '../../../bindings/crypto/finite-field.js';
import { ProvableSpec, map, spec } from '../../testing/equivalent.js';
import { Random } from '../../testing/random.js';
import { Field3 } from '../gadgets/gadgets.js';
import { assert } from '../gadgets/common.js';
import { Bytes } from '../wrapped-classes.js';
import { CurveAffine } from '../../../bindings/crypto/elliptic-curve.js';
import { simpleMapToCurve } from '../gadgets/elliptic-curve.js';
import { provable } from '../types/provable-derivers.js';
export { foreignField, unreducedForeignField, uniformForeignField, bytes, pointSpec, throwError };
// test input specs
function foreignField(F: FiniteField): ProvableSpec<bigint, Field3> {
return {
rng: Random.otherField(F),
there: Field3.from,
back: Field3.toBigint,
provable: Field3.provable,
};
}
// for testing with inputs > f
function unreducedForeignField(maxBits: number, F: FiniteField): ProvableSpec<bigint, Field3> {
return {
rng: Random.bignat(1n << BigInt(maxBits)),
there: Field3.from,
back: Field3.toBigint,
provable: Field3.provable,
assertEqual(x, y, message) {
// need weak equality here because, while ffadd works on bigints larger than the modulus,
// it can't fully reduce them
assert(F.equal(x, y), message);
},
};
}
// for fields that must follow an unbiased distribution, like private keys
function uniformForeignField(F: FiniteField): ProvableSpec<bigint, Field3> {
return {
rng: Random(F.random),
there: Field3.from,
back: Field3.toBigint,
provable: Field3.provable,
};
}
function bytes(length: number) {
const Bytes_ = Bytes(length);
return spec<Uint8Array, Bytes>({
rng: Random.map(Random.bytes(length), (x) => Uint8Array.from(x)),
there: Bytes_.from,
back: (x) => x.toBytes(),
provable: Bytes_.provable,
});
}
function pointSpec<T>(field: ProvableSpec<bigint, T>, Curve: CurveAffine) {
// point but with independently random components, which will never form a valid point
let pointShape = spec({
rng: Random.record({ x: field.rng, y: field.rng }),
there({ x, y }) {
return { x: field.there(x), y: field.there(y) };
},
back({ x, y }) {
return { x: field.back(x), y: field.back(y), infinity: false };
},
provable: provable({ x: field.provable, y: field.provable }),
});
// valid random point
let point = map({ from: field, to: pointShape }, (x) => simpleMapToCurve(x, Curve));
return point;
}
// helper
function throwError<T>(message: string): T {
throw Error(message);
}