Skip to main content
Version: 2.4.0

Provable

Provable: {
Array: <A>(elementType: A, length: number) => InferredProvable<ToProvable<A>[]>;
asProver: (f: () => void) => void;
assertEqual: <T>(type: FlexibleProvableType<T>, x: T, y: T) => void<T>(x: T, y: T) => void;
assertEqualIf: <A, T>(enabled: Bool, type: A, x: T, y: T) => void;
constraintSystem: (f: () => Promise<void> | () => void) => Promise<ConstraintSystemSummary>;
equal: <T>(type: FlexibleProvableType<T>, x: T, y: T) => Bool;
if: <T>(condition: Bool, type: FlexibleProvableType<T>, x: T, y: T) => T<T>(condition: Bool, x: T, y: T) => T;
inCheckedComputation: () => boolean;
inProver: () => boolean;
log: (...args: any) => void;
switch: <T, A>(mask: Bool[], type: A, values: T[], __namedParameters: {
allowNonExclusive: boolean;
}) => T;
witness: <A, T>(type: A, compute: () => T) => InferProvable<ToProvable<A>>;
witnessAsync: <A, T>(type: A, compute: () => Promise<T>) => Promise<T>;
witnessFields: <N, C>(size: N, compute: C) => TupleN<Field, N>;
runAndCheck: Promise<void>;
runUnchecked: Promise<void>;
toCanonical: T;
toConstant: T;
};

Defined in: lib/provable/provable.ts:46

Type declaration

Array()

Array: <A>(elementType: A, length: number) => InferredProvable<ToProvable<A>[]> = provableArray;

Creates a Provable for a generic array.

Type Parameters

A extends FlexibleProvableType<any>

Parameters

elementType

A

length

number

Returns

InferredProvable<ToProvable<A>[]>

Example

const ProvableArray = Provable.Array(Field, 5);

asProver()

asProver: (f: () => void) => void;

Runs code as a prover.

Parameters

f

() => void

Returns

void

Example

Provable.asProver(() => {
// Your prover code here
});

assertEqual()

assertEqual: <T>(type: FlexibleProvableType<T>, x: T, y: T) => void<T>(x: T, y: T) => void;

Asserts that two values are equal.

Type Parameters

T

Parameters

type

FlexibleProvableType<T>

x

T

y

T

Returns

void

Type Parameters

T extends ToFieldable

Parameters

x

T

y

T

Returns

void

Example

class MyStruct extends Struct({ a: Field, b: Bool }) {};
const a: MyStruct = { a: Field(0), b: Bool(false) };
const b: MyStruct = { a: Field(1), b: Bool(true) };
Provable.assertEqual(MyStruct, a, b);

assertEqualIf()

assertEqualIf: <A, T>(enabled: Bool, type: A, x: T, y: T) => void;

Asserts that two values are equal, if an enabling condition is true.

If the condition is false, the assertion is skipped.

Type Parameters

A extends ProvableType<any>

T extends any = InferProvableType<A>

Parameters

enabled

Bool

type

A

x

T

y

T

Returns

void

constraintSystem()

constraintSystem: (f: () => Promise<void> | () => void) => Promise<ConstraintSystemSummary>;

Returns information about the constraints created by the callback function.

Parameters

f

() => Promise<void> | () => void

Returns

Promise<ConstraintSystemSummary>

Example

const result = await Provable.constraintSystem(circuit);
console.log(result);

equal()

equal: <T>(type: FlexibleProvableType<T>, x: T, y: T) => Bool;

Checks if two elements are equal.

Type Parameters

T

Parameters

type

FlexibleProvableType<T>

x

T

y

T

Returns

Bool

Example

class MyStruct extends Struct({ a: Field, b: Bool }) {};
const a: MyStruct = { a: Field(0), b: Bool(false) };
const b: MyStruct = { a: Field(1), b: Bool(true) };
const isEqual = Provable.equal(MyStruct, a, b);

if()

if: <T>(condition: Bool, type: FlexibleProvableType<T>, x: T, y: T) => T<T>(condition: Bool, x: T, y: T) => T = if_;

Proof-compatible if-statement. This behaves like a ternary conditional statement in JS.

Warning: Since Provable.if() is a normal JS function call, both the if and the else branch are evaluated before calling it. Therefore, you can't use this function to guard against execution of one of the branches. It only allows you to pick one of two values.

Type Parameters

T

Parameters

condition

Bool

type

FlexibleProvableType<T>

x

T

y

T

Returns

T

Type Parameters

T extends ToFieldable

Parameters

condition

Bool

x

T

y

T

Returns

T

Example

const condition = Bool(true);
const result = Provable.if(condition, Field(1), Field(2)); // returns Field(1)

inCheckedComputation()

inCheckedComputation: () => boolean;

Checks if the code is run in checked computation mode.

Returns

boolean

Example

if (Provable.inCheckedComputation()) {
// Checked computation-specific code
}

inProver()

inProver: () => boolean;

Checks if the code is run in prover mode.

Returns

boolean

Example

if (Provable.inProver()) {
// Prover-specific code
}

log()

log: (...args: any) => void;

Interface to log elements within a circuit. Similar to console.log().

Parameters

args

...any

Returns

void

Example

const element = Field(42);
Provable.log(element);

switch()

switch: <T, A>(mask: Bool[], type: A, values: T[], __namedParameters: {
allowNonExclusive: boolean;
}) => T = switch_;

Generalization of Provable.if for choosing between more than two different cases. It takes a "mask", which is an array of Bools that contains only one true element, a type/constructor, and an array of values of that type. The result is that value which corresponds to the true element of the mask.

Type Parameters

T

A extends FlexibleProvableType<T>

Parameters

mask

Bool[]

type

A

values

T[]

__namedParameters
allowNonExclusive

boolean = false

Returns

T

Example

let x = Provable.switch([Bool(false), Bool(true)], Field, [Field(1), Field(2)]);
x.assertEquals(2);

witness()

witness: <A, T>(type: A, compute: () => T) => InferProvable<ToProvable<A>>;

Create a new witness. A witness, or variable, is a value that is provided as input by the prover. This provides a flexible way to introduce values from outside into the circuit. However, note that nothing about how the value was created is part of the proof - Provable.witness behaves exactly like user input. So, make sure that after receiving the witness you make any assertions that you want to associate with it.

The only constraints enforced on the witnessed value come from its type. This means the witnessed value may be anything which satisfies the constraints defined in Type.check(). Note that for composite types like (Structs, the default Type.check() method calls check() on each Struct field.

Warning: Be extremely wary of any custom check() methods, which may have forgotten to call check() on sub-components of the Struct.

Type Parameters

A extends ProvableType<any, any>

T extends any = From<ToProvable<A>>

Parameters

type

A

compute

() => T

Returns

InferProvable<ToProvable<A>>

Example

Example for re-implementing Field.inv with the help of witness:

let invX = Provable.witness(Field, () => {
// compute the inverse of `x` outside the circuit, however you like!
return Field.inv(x);
}
// prove that `invX` is really the inverse of `x`:
invX.mul(x).assertEquals(1);

Example for decomposing a 64-bit integer into two 32-bit limbs. Provable.witness will prove that the two limbs are actually 32-bits, ensuring the decomposition is unique.

function decompose(value: UInt64) {
// get two arbitrary 32-bit values from the prover
let lowerLimb = Provable.witness(UInt32, () => {
return value.and(new UInt64(0xffffffffn)).toUInt32();
});
let upperLimb = Provable.witness(UInt32, () => {
return value
.and(new UInt64(0xffffffff00000000n))
.div(2 ** 32)
.toUInt32();
});
// prove the 32-bit lower and upper limbs match the 64-bit value
value.assertEquals(
lowerLimb
.toUInt64()
.add(upperLimb.toUInt64().mul(UInt64.from(2n ** 32n)))
);
}

Modified example for decomposing a 64-bit integer into two 32-bit limbs. This time we use a Struct to get both 32-bit values from the prover at once, while still proving each limb is actually 32 bits.

class Decomposition extends Struct({
lower: UInt32,
upper: UInt32,
}) {}

function decompose(value: UInt64) {
// get two arbitrary 32-bit values from the prover
let limbs = Provable.witness(Decomposition, () => {
return new Decomposition({
lower: value.and(new UInt64(0xffffffffn)).toUInt32(),
upper: value
.and(new UInt64(0xffffffff00000000n))
.div(2 ** 32)
.toUInt32(),
});
});
// prove the 32-bit lower and upper limbs match the 64-bit value
value.assertEquals(
limbs.lower
.toUInt64()
.add(limbs.upper.toUInt64().mul(UInt64.from(2n ** 32n)))
);
}

witnessAsync()

witnessAsync: <A, T>(type: A, compute: () => Promise<T>) => Promise<T>;

Create a new witness from an async callback.

See Provable.witness for more information.

Type Parameters

A extends ProvableType<any, any>

T extends any = From<ToProvable<A>>

Parameters

type

A

compute

() => Promise<T>

Returns

Promise<T>

witnessFields()

witnessFields: <N, C>(size: N, compute: C) => TupleN<Field, N>;

Witness a tuple of field elements. This works just like Provable.witness, but optimized for witnessing plain field elements, which is especially common in low-level provable code.

Type Parameters

N extends number

C extends () => TupleN<bigint | Field, N>

Parameters

size

N

compute

C

Returns

TupleN<Field, N>

runAndCheck()

Runs provable code quickly, without creating a proof, but still checking whether constraints are satisfied.

Parameters

f

() => Promise<void> | () => void

Returns

Promise<void>

Example

await Provable.runAndCheck(() => {
// Your code to check here
});

runUnchecked()

Runs provable code quickly, without creating a proof, and not checking whether constraints are satisfied.

Parameters

f

() => Promise<void> | () => void

Returns

Promise<void>

Example

await Provable.runUnchecked(() => {
// Your code to run here
});

toCanonical()

Return a canonical version of a value, where canonical is defined by the type.

Type Parameters

T

Parameters

type

Provable<T, any>

value

T

Returns

T

toConstant()

Returns a constant version of a provable type.

Type Parameters

T

Parameters

type

ProvableType<T>

value

T

Returns

T