o1js
Version:
TypeScript framework for zk-SNARKs and zkApps
309 lines (308 loc) • 13.1 kB
TypeScript
import { Bool } from './bool.js';
import { Field } from './field.js';
import { Provable } from './provable.js';
import { type InferProvable } from './types/provable-derivers.js';
import { Option } from './option.js';
import { ProvableHashable, ProvableType } from './types/provable-intf.js';
import { type From, type InferValue } from '../../bindings/lib/provable-generic.js';
export { DynamicArray };
type DynamicArray<T = any, V = any> = DynamicArrayBase<T, V>;
/**
* Dynamic-length array type that has a
* - constant maximum capacity, but
* - dynamic actual length
*
* ```ts
* const Bytes = DynamicArray(UInt8, { capacity: 32 });
* ```
*
* `capacity` can be any number from 0 to 2^16-1.
*
* **Details**: Internally, this is represented as a static-sized array, plus a
* Field element that represents the length.
* The _only_ requirement on these is that the length is less or equal capacity.
* In particular, there are no provable guarantees maintained on the content of
* the static-sized array beyond the actual length. Instead, our methods ensure
* integrity of array operations _within_ the actual length.
*/
declare function DynamicArray<ElementType extends ProvableType, ProvableValue extends InferProvable<ElementType> = InferProvable<ElementType>, Value extends InferValue<ElementType> = InferValue<ElementType>>(type: ElementType, { capacity, }: {
capacity: number;
}): typeof DynamicArrayBase<ProvableValue, Value> & {
provable: ProvableHashable<DynamicArrayBase<ProvableValue, Value>, Value[]>;
/**
* Create a new DynamicArray from an array of values.
*
* Note: Both the actual length and the values beyond the original ones will
* be constant.
*/
from(v: (ProvableValue | Value)[] | DynamicArrayBase<ProvableValue, Value>): DynamicArrayBase<ProvableValue, Value>;
};
declare namespace DynamicArray {
var Base: typeof DynamicArrayBase;
}
declare class DynamicArrayBase<ProvableValue = any, Value = any> {
#private;
/**
* The internal array, which includes the actual values, padded up to
* `capacity` with unconstrained values.
*/
array: ProvableValue[];
/**
* Length of the array. Guaranteed to be in [0, capacity].
*/
length: Field;
get innerType(): Provable<ProvableValue, Value>;
static get capacity(): number;
get capacity(): number;
get Constructor(): typeof DynamicArrayBase;
/**
* Create a new {@link DynamicArrayBase} instance from an optional list of
* {@link ProvableValue} elements, and optional length.
*
* - If no parameters are passed, it creates an empty array of length 0.
* - If only `array` is passed, it creates a new array with the elements
* of the array.
* - If only `length` is passed, it creates a dummy array of the given length
* filled with NULL values.
* - If both `array` and `length` are passed, it creates a new array with the
* elements of the array, and the length of the dynamic array is set to the
* `length` passed, which should be less or equal than the length of the
* `array` passed (this is to allow for arrays with dummy values at the end).
* - In any case, if `length` is larger than the capacity, it throws.
*
* @example
* ```ts
* let arr = new DynamicArray([new Field(1), new Field(2), new Field(3)]);
* let empty = new DynamicArray();
* ```
*
* Note: this is different from `ProvableValue[]` because it is a provable type.
*/
constructor(array?: ProvableValue[], length?: Field);
/**
* In-circuit assertion that the given index is within the bounds of the
* dynamic array.
* Asserts 0 <= i < this.length, using a cached check that's not
* duplicated when doing it on the same variable multiple times, failing
* with an error message otherwise.
*
* @param i - the index to check
* @param message - optional error message to use in case the assertion fails
*/
assertIndexInRange(i: Field, message?: string): void;
/**
* Gets value at index i, and proves that the index is in the array.
* It uses an internal cache to avoid duplication of constraints when the
* same index is used multiple times.
*/
get(i: Field): ProvableValue;
/**
* Gets a value at index i, as an option that is None if the index is not in
* the array.
*
* Note: The correct type for `i` is actually UInt16 which doesn't exist. The
* method is not complete (but sound) for i >= 2^16. This means that if the
* index is larger than 2^16, the constraints could be satisfiable but the
* result is not correct (because the capacity can at most be 2^16).
*/
getOption(i: Field): Option<ProvableValue>;
/**
* Gets a value at index i, ASSUMING that the index is in the array.
*
* If the index is in fact not in the array, the return value is completely
* unconstrained.
*
* **Warning**: Only use this if you already know/proved by other means that
* the index is within bounds.
*/
getOrUnconstrained(i: Field): ProvableValue;
/**
* Sets a value at index i and proves that the index is in the array.
*/
set(i: Field, value: ProvableValue, message?: string): void;
/**
* Sets a value at index i, or does nothing if the index is not in the array
*/
setOrDoNothing(i: Field, value: ProvableValue): void;
/**
* Map every element of the array to a new value.
*
* **Warning**: The callback will be passed unconstrained dummy values.
*/
map<MapType extends ProvableType>(type: MapType, f: (t: ProvableValue) => From<MapType>): DynamicArray<InferProvable<MapType>, InferValue<MapType>>;
/**
* Iterate over all elements of the array.
*
* The callback will be passed an element and a boolean `isDummy` indicating
* whether the value is part of the actual array. Optionally, an index can be
* passed as a third argument (used in `forEachReversed`)
*/
forEach(f: (t: ProvableValue, isDummy: Bool, i?: number) => void): void;
/**
* Iterate over all elements of the array, in reverse order.
*
* The callback will be passed an element and a boolean `isDummy` indicating whether the value is part of the actual array.
*
* Note: the indices are also passed in reverse order, i.e. we always have `t = this.array[i]`.
*/
forEachReverse(f: (t: ProvableValue, isDummy: Bool, i: number) => void): void;
/**
* Return a version of the same array with a larger capacity.
*
* **Warning**: Does not modify the array, but returns a new one.
*
* **Note**: this doesn't cost constraints, but currently doesn't preserve any
* cached constraints.
*
* @param capacity - the new capacity of the array
*/
growCapacityTo(capacity: number, message?: string): DynamicArray<ProvableValue, Value>;
/**
* Return a version of the same array with a larger capacity.
*
* **Warning**: Does not modify the array, but returns a new one.
*
* **Note**: this doesn't cost constraints, but currently doesn't preserve any
* cached constraints.
*
* @param increment - the amount to increase the capacity by
*/
growCapacityBy(increment: number): DynamicArray<ProvableValue>;
/**
* Increments the length of the current array by n elements, checking that the
* new length is within the capacity, failing with the error message otherwise.
*
* @param n - the number of elements to increase the length by
* @param message - optional error message to use in case the assertion fails
*/
increaseLengthBy(n: Field, message?: string): void;
/**
* Decrements the length of the current array by `n` elements, checking that
* the `n` is less or equal than the current length, failing with the error
* message otherwise.
*
* @param n - the number of elements to decrease the length by
* @param message - optional error message to use in case the assertion fails
*/
decreaseLengthBy(n: Field, message?: string): void;
/**
* Sets the length of the current array to a new value, checking that the
* new length is less or equal than the capacity.
*
* An optional error message can be provided to be used in case the inner
* assertion fails.
*
* @param newLength - the new length to set the array to
* @param message - optional error message
*
* **Warning**: This does not change (add nor remove) the values of the array.
*/
setLengthTo(n: Field, message?: string): void;
/**
* Push a value, without changing the capacity.
*
* Proves that the new length is still within the capacity, fails otherwise.
*
* To grow the capacity along with the actual length, you can use:
*
* ```ts
* array = array.growCapacityhBy(1);
* array.push(value);
* ```
*
* @param value - the value to push into the array
* @param message - optional error message to use in case the assertion fails
*/
push(value: ProvableValue, message?: string): void;
/**
* Removes the last `n` elements from the dynamic array, decreasing the length
* by n. If no amount is provided, only one element is popped. The popped
* positions are set to NULL values.
*
* @param n - the number of elements to pop (one if not provided)
* @param message - optional error message to use in case the assertion fails
*/
pop(n?: Field, message?: string): void;
/**
* In-circuit check whether the array is empty.
*
* @returns true or false depending on whether the dynamic array is empty
*/
isEmpty(): Bool;
/**
* Shifts all elements of the array to the left by `n` positions, reducing
* the length by `n`, which must be less than or equal to the current length
* (failing with an error message otherwise).
*
* @param n - the number of positions to shift left
* @param message - optional error message to use in case the assertion fails
*/
shiftLeft(n: Field, message?: string): void;
/**
* Shifts all elements of the array to the right by `n` positions, increasing
* the length by `n`, which must result in less than or equal to the capacity
* (failing with an error message otherwise). The new elements on the left are
* set to NULL values.
*
* @param n - the number of positions to shift right
* @param message - optional error message to use in case the assertion fails
*/
shiftRight(n: Field, message?: string): void;
/**
* Copies the current dynamic array, returning a new instance with the same
* values and length.
*
* @returns a new DynamicArray instance with the same values as the current.
*
*/
copy(): this;
/**
* Creates a new dynamic array with the values of the current array from
* index `start` (included) to index `end` (excluded). If `start` is not
* provided, it defaults to 0. If `end` is not provided, it defaults to the
* length of the array.
*
* @param start - the starting index of the slice (inclusive)
* @param end - the ending index of the slice (exclusive)
*
* @returns a new DynamicArray instance with the sliced values
*/
slice(start?: Field, end?: Field): DynamicArray<ProvableValue, Value>;
/**
* Returns a new array with the elements reversed.
*/
reverse(): DynamicArray<ProvableValue, Value>;
/**
* Concatenates the current array with another dynamic array, returning a new
* dynamic array with the values of both arrays. The capacity of the new array
* is the sum of the capacities of the two arrays.
*
* @param other - the dynamic array to concatenate
*
* @returns a new DynamicArray instance with the concatenated values
*/
concat(other: DynamicArray<ProvableValue, Value>): DynamicArray<ProvableValue, Value>;
/**
* Inserts a value at index i, shifting all elements after that position to
* the right by one. The length of the array is increased by one, which must
* result in less than or equal to the capacity.
*
* @param i - the index at which to insert the value
* @param value - the value to insert
* @param message - optional error message to use in case the assertion fails
*/
insert(index: Field, value: ProvableValue, message?: string): void;
/**
* Checks whether the dynamic array includes a value.
*
* @param value - the value to check for inclusion in the array
* @returns
*/
includes(value: ProvableValue): Bool;
/**
* Converts the current instance of the dynamic array to a plain array of values.
*
* @returns An array of values representing the elements in the dynamic array.
*/
toValue(): Value[];
}