UNPKG

o1js

Version:

TypeScript framework for zk-SNARKs and zkApps

144 lines (143 loc) 5.58 kB
import type { Field } from '../field.js'; import { Tuple } from '../../util/types.js'; import type { Bool } from '../bool.js'; export { ForeignField, Field3 }; export { bigint3, Sign, split, combine, weakBound, Sum, assertMul, field3FromBits }; /** * A 3-tuple of Fields, representing a 3-limb bigint. */ type Field3 = [Field, Field, Field]; type bigint3 = [bigint, bigint, bigint]; type Sign = -1n | 1n; declare const ForeignField: { add(x: Field3, y: Field3, f: bigint): Field3; sub(x: Field3, y: Field3, f: bigint): Field3; negate(x: Field3, f: bigint): Field3; sum: typeof sum; Sum(x: Field3): Sum; mul: typeof multiply; inv: typeof inverse; div: typeof divide; assertMul: typeof assertMul; assertAlmostReduced: typeof assertAlmostReduced; assertLessThan: typeof assertLessThan; assertLessThanOrEqual: typeof assertLessThanOrEqual; assertEquals: typeof assertEquals; equals: typeof equals; toCanonical: typeof toCanonical; }; /** * computes x[0] + sign[0] * x[1] + ... + sign[n-1] * x[n] modulo f * * assumes that inputs are range checked, does range check on the result. */ declare function sum(x: Field3[], sign: Sign[], f: bigint): Field3; declare function multiply(a: Field3, b: Field3, f: bigint): Field3; declare function inverse(x: Field3, f: bigint): Field3; declare function divide(x: Field3, y: Field3, f: bigint, { allowZeroOverZero }?: { allowZeroOverZero?: boolean | undefined; }): Field3; declare function weakBound(x: Field, f: bigint): Field; /** * Apply range checks and weak bounds checks to a list of Field3s. * Optimal if the list length is a multiple of 3. */ declare function assertAlmostReduced(xs: Field3[], f: bigint, skipMrc?: boolean): void; /** * check whether x = c mod f * * c is a constant, and we require c in [0, f) * * assumes that x is almost reduced mod f, so we know that x might be c or c + f, but not c + 2f, c + 3f, ... */ declare function equals(x: Field3, c: bigint, f: bigint): Bool; declare function assertEquals(x: Field3, y: Field3): void; /** * Convert x, which may be unreduced, to a canonical representative < f. * * Note: This method is complete, it works for all unreduced field elements. * It can therefore be used to protect against incompleteness of field operations in other places. */ declare function toCanonical(x: Field3, f: bigint): Field3; declare const Field3: { /** * Turn a bigint into a 3-tuple of Fields */ from(x: bigint | Field3): Field3; /** * Turn a 3-tuple of Fields into a bigint */ toBigint(x: Field3): bigint; /** * Turn several 3-tuples of Fields into bigints */ toBigints<T extends Tuple<Field3>>(...xs: T): [...{ [i in keyof T]: bigint; }]; /** * Check whether a 3-tuple of Fields is constant */ isConstant(x: Field3): boolean; /** * `Provable<T>` interface for `Field3 = [Field, Field, Field]`. * * Note: Witnessing this creates a plain tuple of field elements without any implicit * range checks. */ provable: { toValue(x: Field3): bigint; fromValue(x: bigint | Field3): Field3; toFields: (x: [Field, Field, Field]) => Field[]; toAuxiliary: (x?: [Field, Field, Field] | undefined) => any[]; sizeInFields: () => number; check: (x: [Field, Field, Field]) => void; toCanonical?: ((x: [Field, Field, Field]) => [Field, Field, Field]) | undefined; fromFields: (x: Field[]) => [Field, Field, Field]; toInput: (x: [Field, Field, Field]) => { fields?: Field[] | undefined; packed?: [Field, number][] | undefined; }; toJSON: (x: [Field, Field, Field]) => [any, any, any]; fromJSON: (x: [any, any, any]) => [Field, Field, Field]; empty: () => [Field, Field, Field]; }; /** * Splits a bigint into three limbs using bitwise operations. */ split: typeof split; }; declare function combine([x0, x1, x2]: bigint3): bigint; declare function split(x: bigint): bigint3; /** * Optimized multiplication of sums, like (x + y)*z = a + b + c * * We use several optimizations over naive summing and then multiplying: * * - we skip the range check on the remainder sum, because ffmul is sound with r being a sum of range-checked values * - we replace the range check on the input sums with an extra low limb sum using generic gates * - we chain the first input's sum into the ffmul gate * * As usual, all values are assumed to be range checked, and the left and right multiplication inputs * are assumed to be bounded such that `l * r < 2^264 * (native modulus)`. * However, all extra checks that are needed on the _sums_ are handled here. */ declare function assertMul(x: Field3 | Sum, y: Field3 | Sum, xy: Field3 | Sum, f: bigint, message?: string): void; /** * @internal * * Lazy sum of {@link Field3} elements, which can be used as input to `Gadgets.ForeignField.assertMul()`. */ declare class Sum { #private; constructor(x: Field3); get result(): Field3; get length(): number; add(y: Field3): this; sub(y: Field3): this; isConstant(): boolean; finish(f: bigint, isChained?: boolean): Field3; finishForMulInput(f: bigint, isChained?: boolean): Field3; rangeCheck(): void; static fromUnfinished(x: Field3 | Sum): Sum; } declare function assertLessThan(x: Field3, y: bigint | Field3): void; declare function assertLessThanOrEqual(x: Field3, y: bigint | Field3): void; declare function field3FromBits(bits: Bool[]): Field3;