o1js
Version:
TypeScript framework for zk-SNARKs and zkApps
97 lines (86 loc) • 2.33 kB
text/typescript
import { ZkProgram } from '../../proof-system/zkprogram.js';
import {
equivalentProvable as equivalent,
equivalentAsync,
field,
fieldWithRng,
record,
} from '../../testing/equivalent.js';
import { Field } from '../wrapped.js';
import { Gadgets } from '../gadgets/gadgets.js';
import { provable } from '../types/provable-derivers.js';
import { assert } from '../gadgets/common.js';
import { Random } from '../../testing/random.js';
let uint = (length: number) => fieldWithRng(Random.biguint(length));
let Arithmetic = ZkProgram({
name: 'arithmetic',
publicOutput: provable({ remainder: Field, quotient: Field }),
methods: {
divMod32: {
privateInputs: [Field],
async method(a: Field) {
return { publicOutput: Gadgets.divMod32(a) };
},
},
divMod64: {
privateInputs: [Field],
async method(a: Field) {
return { publicOutput: Gadgets.divMod64(a) };
},
},
},
});
await Arithmetic.compile();
const divMod32Helper = (x: bigint) => {
let quotient = x >> 32n;
let remainder = x - (quotient << 32n);
return { remainder, quotient };
};
const divMod64Helper = (x: bigint) => {
let quotient = x >> 64n;
let remainder = x - (quotient << 64n);
return { remainder, quotient };
};
const divModOutput = record({ remainder: field, quotient: field });
equivalent({
from: [field],
to: divModOutput,
})(
(x) => {
assert(x < 1n << 64n, `x needs to fit in 64bit, but got ${x}`);
return divMod32Helper(x);
},
(x) => {
return Gadgets.divMod32(x);
}
);
equivalent({
from: [uint(64)],
to: divModOutput,
})(
(x) => {
assert(x < 1n << 128n, `x needs to fit in 128bit, but got ${x}`);
return divMod64Helper(x);
},
(x) => {
return Gadgets.divMod64(x);
}
);
await equivalentAsync({ from: [field], to: divModOutput }, { runs: 3 })(
(x) => {
assert(x < 1n << 64n, `x needs to fit in 64bit, but got ${x}`);
return divMod32Helper(x);
},
async (x) => {
return (await Arithmetic.divMod32(x)).proof.publicOutput;
}
);
await equivalentAsync({ from: [field], to: divModOutput }, { runs: 3 })(
(x) => {
assert(x < 1n << 128n, `x needs to fit in 128bit, but got ${x}`);
return divMod64Helper(x);
},
async (x) => {
return (await Arithmetic.divMod64(x)).proof.publicOutput;
}
);