UNPKG

o1js

Version:

TypeScript framework for zk-SNARKs and zkApps

366 lines (365 loc) 15.2 kB
import { CurveParams, CurveAffine } from '../../../bindings/crypto/elliptic-curve.js'; import { ProvablePureExtended } from '../types/struct.js'; import { AlmostForeignField } from '../foreign-field.js'; import { Point } from '../gadgets/elliptic-curve.js'; import { Field3 } from '../gadgets/foreign-field.js'; export { createForeignCurve, ForeignCurve }; export { toPoint, FlexiblePoint, ForeignCurveNotNeeded }; type FlexiblePoint = { x: AlmostForeignField | Field3 | bigint | number; y: AlmostForeignField | Field3 | bigint | number; }; declare function toPoint({ x, y }: ForeignCurve): Point; declare class ForeignCurve { x: AlmostForeignField; y: AlmostForeignField; /** * Create a new {@link ForeignCurve} from an object representing the (affine) x and y coordinates. * * Note: Inputs must be range checked if they originate from a different field with a different modulus or if they are not constants. Please refer to the {@link ForeignField} constructor comments for more details. * * @example * ```ts * let x = new ForeignCurve({ x: 1n, y: 1n }); * ``` * * **Important**: By design, there is no way for a `ForeignCurve` to represent the zero point. * * **Warning**: This fails for a constant input which does not represent an actual point on the curve. */ constructor(g: { x: AlmostForeignField | Field3 | bigint | number; y: AlmostForeignField | Field3 | bigint | number; }); /** * Coerce the input to a {@link ForeignCurve}. */ static from(g: ForeignCurve | FlexiblePoint): ForeignCurve; /** * Parses a hexadecimal string representing an uncompressed elliptic curve point and coerces it into a {@link ForeignCurve} point. * * The method extracts the x and y coordinates from the provided hex string and verifies that the resulting point lies on the curve. * * **Note:** This method only supports uncompressed elliptic curve points, which are 65 bytes in total (1-byte prefix + 32 bytes for x + 32 bytes for y). * * @param hex - The hexadecimal string representing the uncompressed elliptic curve point. * @returns - A point on the foreign curve, parsed from the given hexadecimal string. * * @throws - Throws an error if the input is not a valid public key. * * @example * ```ts * class Secp256k1 extends createForeignCurve(Crypto.CurveParams.Secp256k1) {} * * const publicKeyHex = '04f8b8db25c619d0c66b2dc9e97ecbafafae...'; // Example hex string for uncompressed point * const point = Secp256k1.fromHex(publicKeyHex); * ``` * * **Important:** This method is only designed to handle uncompressed elliptic curve points in hex format. */ static fromHex(hex: string): ForeignCurve; /** * Create a new {@link ForeignCurve} instance from an Ethereum public key in hex format, which may be either compressed or uncompressed. * This method is designed to handle the parsing of public keys as used by the ethers.js library. * * The input should represent the affine x and y coordinates of the point, in hexadecimal format. * Compressed keys are 33 bytes long and begin with 0x02 or 0x03, while uncompressed keys are 65 bytes long and begin with 0x04. * * **Warning:** This method is specifically designed for use with the Secp256k1 curve. Using it with other curves may result in incorrect behavior or errors. * Ensure that the curve setup matches Secp256k1, as shown in the example, to avoid unintended issues. * * @example * ```ts * import { Wallet, Signature, getBytes } from 'ethers'; * * class Secp256k1 extends createForeignCurve(Crypto.CurveParams.Secp256k1) {} * * const wallet = Wallet.createRandom(); * * const publicKey = Secp256k1.fromEthers(wallet.publicKey.slice(2)); * ``` * * @param hex - The public key as a hexadecimal string (without the "0x" prefix). * @returns A new instance of the curve representing the given public key. */ static fromEthers(hex: string): ForeignCurve; /** * The constant generator point. */ static get generator(): ForeignCurve; /** * The size of the curve's base field. */ static get modulus(): bigint; /** * The size of the curve's base field. */ get modulus(): bigint; /** * @internal * Checks whether this curve point is constant. * * See {@link FieldVar} to understand constants vs variables. */ isConstant(): boolean; /** * Convert this curve point to a point with bigint coordinates. */ toBigint(): import("../../../bindings/crypto/elliptic-curve.js").GroupAffine; /** * Elliptic curve addition. * * ```ts * let r = p.add(q); // r = p + q * ``` * * **Important**: this is _incomplete addition_ and does not handle the degenerate cases: * - Inputs are equal, `g = h` (where you would use {@link double}). * In this case, the result of this method is garbage and can be manipulated arbitrarily by a malicious prover. * - Inputs are inverses of each other, `g = -h`, so that the result would be the zero point. * In this case, the proof fails. * * If you want guaranteed soundness regardless of the input, use {@link addSafe} instead. * * @throws if the inputs are inverses of each other. */ add(h: ForeignCurve | FlexiblePoint): ForeignCurve; /** * Safe elliptic curve addition. * * This is the same as {@link add}, but additionally proves that the inputs are not equal. * Therefore, the method is guaranteed to either fail or return a valid addition result. * * **Beware**: this is more expensive than {@link add}, and is still incomplete in that * it does not succeed on equal or inverse inputs. * * @throws if the inputs are equal or inverses of each other. */ addSafe(h: ForeignCurve | FlexiblePoint): ForeignCurve; /** * Elliptic curve doubling. * * @example * ```ts * let r = p.double(); // r = 2 * p * ``` */ double(): ForeignCurve; /** * Elliptic curve negation. * * @example * ```ts * let r = p.negate(); // r = -p * ``` */ negate(): ForeignCurve; /** * Elliptic curve scalar multiplication, where the scalar is represented as a {@link ForeignField} element. * * **Important**: this proves that the result of the scalar multiplication is not the zero point. * * @throws if the scalar multiplication results in the zero point; for example, if the scalar is zero. * * @example * ```ts * let r = p.scale(s); // r = s * p * ``` */ scale(scalar: AlmostForeignField | bigint | number): ForeignCurve; static assertOnCurve(g: ForeignCurve): void; /** * Assert that this point lies on the elliptic curve, which means it satisfies the equation * `y^2 = x^3 + ax + b` */ assertOnCurve(): void; static assertInSubgroup(g: ForeignCurve): void; /** * Assert that this point lies in the subgroup defined by `order*P = 0`. * * Note: this is a no-op if the curve has cofactor equal to 1. Otherwise * it performs the full scalar multiplication `order*P` and is expensive. */ assertInSubgroup(): void; /** * Check that this is a valid element of the target subgroup of the curve: * - Check that the coordinates are valid field elements * - Use {@link assertOnCurve()} to check that the point lies on the curve * - If the curve has cofactor unequal to 1, use {@link assertInSubgroup()}. */ static check(g: ForeignCurveNotNeeded): void; get Constructor(): typeof ForeignCurve; static _Bigint?: CurveAffine; static _Field?: typeof AlmostForeignField; static _Scalar?: typeof AlmostForeignField; static _provable?: ProvablePureExtended<ForeignCurve, { x: bigint; y: bigint; }, { x: string; y: string; }>; /** * Curve arithmetic on JS bigints. */ static get Bigint(): { name: string; Field: { modulus: bigint; sizeInBits: number; t: bigint; M: bigint; twoadicRoot: bigint; mod(x: bigint): bigint; add(x: bigint, y: bigint): bigint; not(x: bigint, bits: number): bigint; negate(x: bigint): bigint; sub(x: bigint, y: bigint): bigint; mul(x: bigint, y: bigint): bigint; inverse: (x: bigint) => bigint | undefined; div(x: bigint, y: bigint): bigint | undefined; square(x: bigint): bigint; isSquare(x: bigint): boolean; sqrt(x: bigint): bigint | undefined; power(x: bigint, n: bigint): bigint; dot(x: bigint[], y: bigint[]): bigint; equal(x: bigint, y: bigint): boolean; isEven(x: bigint): boolean; random(): bigint; fromNumber(x: number): bigint; fromBigint(x: bigint): bigint; rot(x: bigint, bits: bigint, direction?: "left" | "right", maxBits?: bigint): bigint; leftShift(x: bigint, bits: number, maxBitSize?: number): bigint; rightShift(x: bigint, bits: number): bigint; }; Scalar: { modulus: bigint; sizeInBits: number; t: bigint; M: bigint; twoadicRoot: bigint; mod(x: bigint): bigint; add(x: bigint, y: bigint): bigint; not(x: bigint, bits: number): bigint; negate(x: bigint): bigint; sub(x: bigint, y: bigint): bigint; mul(x: bigint, y: bigint): bigint; inverse: (x: bigint) => bigint | undefined; div(x: bigint, y: bigint): bigint | undefined; square(x: bigint): bigint; isSquare(x: bigint): boolean; sqrt(x: bigint): bigint | undefined; power(x: bigint, n: bigint): bigint; dot(x: bigint[], y: bigint[]): bigint; equal(x: bigint, y: bigint): boolean; isEven(x: bigint): boolean; random(): bigint; fromNumber(x: number): bigint; fromBigint(x: bigint): bigint; rot(x: bigint, bits: bigint, direction?: "left" | "right", maxBits?: bigint): bigint; leftShift(x: bigint, bits: number, maxBitSize?: number): bigint; rightShift(x: bigint, bits: number): bigint; }; modulus: bigint; order: bigint; a: bigint; b: bigint; cofactor: bigint | undefined; hasCofactor: boolean; zero: { x: bigint; y: bigint; infinity: true; }; one: { infinity: boolean; x: bigint; y: bigint; }; hasEndomorphism: boolean; readonly Endo: { scalar: bigint; base: bigint; decomposeMaxBits: number; decompose(s: bigint): readonly [{ readonly value: bigint; readonly isNegative: boolean; readonly abs: bigint; }, { readonly value: bigint; readonly isNegative: boolean; readonly abs: bigint; }]; endomorphism(P: import("../../../bindings/crypto/elliptic-curve.js").GroupAffine): { x: bigint; y: bigint; }; scaleProjective(g: import("../../../bindings/crypto/elliptic-curve.js").GroupProjective, s: bigint): { x: bigint; y: bigint; z: bigint; }; scale(g: import("../../../bindings/crypto/elliptic-curve.js").GroupAffine, s: bigint): import("../../../bindings/crypto/elliptic-curve.js").GroupAffine; }; from(g: { x: bigint; y: bigint; }): import("../../../bindings/crypto/elliptic-curve.js").GroupAffine; fromNonzero(g: { x: bigint; y: bigint; }): import("../../../bindings/crypto/elliptic-curve.js").GroupAffine; equal(g: import("../../../bindings/crypto/elliptic-curve.js").GroupAffine, h: import("../../../bindings/crypto/elliptic-curve.js").GroupAffine): boolean; isOnCurve(g: import("../../../bindings/crypto/elliptic-curve.js").GroupAffine): boolean; isInSubgroup(g: import("../../../bindings/crypto/elliptic-curve.js").GroupAffine): boolean; add(g: import("../../../bindings/crypto/elliptic-curve.js").GroupAffine, h: import("../../../bindings/crypto/elliptic-curve.js").GroupAffine): import("../../../bindings/crypto/elliptic-curve.js").GroupAffine; double(g: import("../../../bindings/crypto/elliptic-curve.js").GroupAffine): import("../../../bindings/crypto/elliptic-curve.js").GroupAffine; negate(g: import("../../../bindings/crypto/elliptic-curve.js").GroupAffine): import("../../../bindings/crypto/elliptic-curve.js").GroupAffine; sub(g: import("../../../bindings/crypto/elliptic-curve.js").GroupAffine, h: import("../../../bindings/crypto/elliptic-curve.js").GroupAffine): import("../../../bindings/crypto/elliptic-curve.js").GroupAffine; scale(g: import("../../../bindings/crypto/elliptic-curve.js").GroupAffine, s: bigint | boolean[]): import("../../../bindings/crypto/elliptic-curve.js").GroupAffine; }; /** * The base field of this curve as a {@link ForeignField}. */ static get Field(): typeof AlmostForeignField; /** * The scalar field of this curve as a {@link ForeignField}. */ static get Scalar(): typeof AlmostForeignField; /** * `Provable<ForeignCurve>` */ static get provable(): ProvablePureExtended<ForeignCurve, { x: bigint; y: bigint; }, { x: string; y: string; }>; } /** * @see: {@link ForeignCurve} */ declare class ForeignCurveNotNeeded extends ForeignCurve { constructor(g: { x: AlmostForeignField | Field3 | bigint | number; y: AlmostForeignField | Field3 | bigint | number; }); static check(g: ForeignCurveNotNeeded): void; } /** * Create a class representing an elliptic curve group, which is different from the native {@link Group}. * * ```ts * const Curve = createForeignCurve(Crypto.CurveParams.Secp256k1); * ``` * * `createForeignCurve(params)` takes curve parameters `CurveParams` as input. * We support `modulus` and `order` to be prime numbers up to 259 bits. * * The returned {@link ForeignCurveNotNeeded} class represents a _non-zero curve point_ and supports standard * elliptic curve operations like point addition and scalar multiplication. * * {@link ForeignCurveNotNeeded} also includes to associated foreign fields: `ForeignCurve.Field` and `ForeignCurve.Scalar`, see {@link createForeignField}. */ declare function createForeignCurve(params: CurveParams): typeof ForeignCurve;