pulsar-contracts
Version:
95 lines • 3.86 kB
JavaScript
import { Bool, Field, Poseidon, Provable, PublicKey, Struct } from 'o1js';
import { LIST_LENGTH, TOTAL_GENERATORS } from '../utils/constants.js';
export { ProofGenerators };
class ProofGenerators extends Struct({
list: Provable.Array(Field, LIST_LENGTH),
}) {
static empty() {
const list = Array(LIST_LENGTH).fill(Field.from(0));
return new ProofGenerators({ list });
}
isEmpty() {
let empty = Bool(true);
for (let i = 0; i < LIST_LENGTH; i++) {
empty = empty.and(this.list[i].equals(Field(0)));
}
return empty;
}
/**
* Creates a ProofGenerators instance from an array of PublicKey. This method meant to be used outside of the provable code.
* @param arr - An array of PublicKeys. The length of the array must be equal to TOTAL_GENERATORS.
* @returns A ProofGenerators instance.
*/
static fromPubkeyArray(arr) {
if (arr.length !== TOTAL_GENERATORS) {
throw new Error(`Array length must be ${TOTAL_GENERATORS}, but got ${arr.length}`);
}
const list = this.empty().list;
for (let i = 0; i < TOTAL_GENERATORS; i++) {
list[i] = arr[i].x;
list[TOTAL_GENERATORS] = list[TOTAL_GENERATORS].add(Number(arr[i].isOdd.toField().toBigInt()) * 2 ** i);
}
return new ProofGenerators({ list });
}
insertAt(index, publicKey) {
let power = Field(1);
let previousValue = this.list[0];
for (let i = 0; i < TOTAL_GENERATORS; i++) {
previousValue = Provable.if(index.equals(Field(i)), this.list[i], previousValue);
this.list[i] = Provable.if(index.equals(Field(i)), publicKey.x, this.list[i]);
power = Provable.if(Field(i).lessThan(index), power.add(power), power);
}
previousValue.assertEquals(Field(0), `ProofGenerators: index already occupied`);
this.list[TOTAL_GENERATORS] = this.list[TOTAL_GENERATORS].add(power.mul(publicKey.isOdd.toField()));
return this;
}
getXAt(index) {
let x = Field(0);
for (let i = 0; i < TOTAL_GENERATORS; i++) {
x = Provable.if(index.equals(Field(i)), this.list[i], x);
}
return x;
}
getIsOddAt(index) {
let isOdd = Bool(false);
let isOddFields = this.list[TOTAL_GENERATORS].toBits(TOTAL_GENERATORS);
for (let i = 0; i < TOTAL_GENERATORS; i++) {
isOdd = Provable.if(index.equals(Field(i)), isOddFields[i], isOdd);
}
return isOdd;
}
getPublicKeyAt(index) {
const x = this.getXAt(index);
const isOdd = this.getIsOddAt(index);
return PublicKey.fromValue({ x, isOdd });
}
assertEquals(other) {
let equal = Bool(true);
for (let i = 0; i < LIST_LENGTH; i++) {
equal = equal.and(this.list[i].equals(other.list[i]));
}
equal.assertTrue('Proof generators list mismatch');
}
toFields() {
return this.list.map((field) => field.toFields()).flat();
}
hash() {
return Poseidon.hash(this.toFields());
}
appendList(length, other) {
let newList = ProofGenerators.empty();
let power = Field(1);
for (let i = 0; i < TOTAL_GENERATORS; i++) {
newList.list[i] = Provable.if(Field(i).lessThan(length), this.list[i], Provable.if(Field(i).greaterThanOrEqual(length), other.getXAt(Field(i).sub(length)), Field(0)));
power = Provable.if(Field(i).lessThan(length), power.add(power), power);
}
newList.list[TOTAL_GENERATORS] = this.list[TOTAL_GENERATORS].add(power.mul(other.list[TOTAL_GENERATORS]));
return newList;
}
toJSON() {
return {
list: this.list.map((field) => field.toString()),
};
}
}
//# sourceMappingURL=proofGenerators.js.map