l1-lottery-contracts
Version:
This repo contains smart contracts and related scripts for ZkNoid L1 Lottery proposed [here](https://forums.minaprotocol.com/t/zknoid-l1-lottery/6269)
147 lines • 5.2 kB
JavaScript
// import * as fs from 'fs';
import { Field, Provable, provable, Struct, UInt32, UInt64, } from 'o1js';
// import { PackedUInt32Factory } from 'o1js-pack';
const MAX_BITS_PER_FIELD = 254n;
const L = 7; // 7 32-bit uints fit in one Field
const SIZE_IN_BITS = 32n;
export function PackingPlant(elementType, l, bitSize) {
if (bitSize * BigInt(l) > MAX_BITS_PER_FIELD) {
throw new Error(`The Packing Plant is only accepting orders that can fit into one Field, try using MultiPackingPlant`);
}
class Packed_ extends Struct({
packed: Field,
}) {
constructor(packed) {
super({ packed });
}
// Must implement these in type-specific implementation
static extractField(input) {
throw new Error('Must implement extractField');
}
static sizeInBits() {
throw new Error('Must implement sizeInBits');
}
static unpack(f) {
throw new Error('Must implement unpack');
}
// End
/**
*
* @param unpacked Array of the implemented packed type
* @throws if the length of the array is longer than the length of the implementing factory config
*/
static checkPack(unpacked) {
if (unpacked.length > l) {
throw new Error(`Input of size ${unpacked.length} is larger than expected size of ${l}`);
}
}
/**
*
* @param unpacked Array of the implemented packed type, must be shorter than the max allowed, which varies by type, will throw if the input is too long
* @returns Field, packed with the information from the unpacked input
*/
static pack(unpacked) {
this.checkPack(unpacked);
let f = this.extractField(unpacked[0]);
const n = Math.min(unpacked.length, l);
for (let i = 1; i < n; i++) {
const c = Field((2n ** this.sizeInBits()) ** BigInt(i));
f = f.add(this.extractField(unpacked[i]).mul(c));
}
return f;
}
/**
*
* @param f Field, packed with the information, as returned by #pack
* @returns Array of bigints, which can be decoded by the implementing class into the final type
*/
static unpackToBigints(f) {
let unpacked = new Array(l);
unpacked.fill(0n);
let packedN;
if (f) {
packedN = f.toBigInt();
}
else {
throw new Error('No Packed Value Provided');
}
for (let i = 0; i < l; i++) {
unpacked[i] = packedN & ((1n << this.sizeInBits()) - 1n);
packedN >>= this.sizeInBits();
}
return unpacked;
}
// NOTE: adding to fields here breaks the proof generation. Probably not overriding it correctly
/**
* @returns array of single Field element which constitute the packed object
*/
toFields() {
return [this.packed];
}
assertEquals(other) {
this.packed.assertEquals(other.packed);
}
}
Packed_.type = provable({ packed: Field }, {});
Packed_.l = l;
Packed_.bitSize = bitSize;
return Packed_;
}
export function PackedUInt32Factory(l = L) {
class PackedUInt32_ extends PackingPlant(UInt32, l, SIZE_IN_BITS) {
static extractField(input) {
return input.value;
}
static sizeInBits() {
return SIZE_IN_BITS;
}
/**
*
* @param f Field, packed with the information, as returned by #pack
* @returns Array of UInt32
*/
static unpack(f) {
const unpacked = Provable.witness(Provable.Array(UInt32, l), () => {
const unpacked = this.unpackToBigints(f);
return unpacked.map((x) => UInt32.from(x));
});
f.assertEquals(PackedUInt32_.pack(unpacked));
return unpacked;
}
/**
*
* @param uint32s Array of UInt32s to be packed
* @returns Instance of the implementing class
*/
static fromUInt32s(uint32s) {
const packed = PackedUInt32_.pack(uint32s);
return new PackedUInt32_(packed);
}
/**
*
* @param bigints Array of bigints to be packed
* @returns Instance of the implementing class
*/
static fromBigInts(bigints) {
const uint32s = bigints.map((x) => UInt32.from(x));
return PackedUInt32_.fromUInt32s(uint32s);
}
toBigInts() {
return PackedUInt32_.unpack(this.packed).map((x) => x.toBigint());
}
}
return PackedUInt32_;
}
export class NumberPacked extends PackedUInt32Factory() {
}
export function convertToUInt64(value) {
let val = UInt64.Unsafe.fromField(value);
UInt64.check(val);
return val;
}
export function convertToUInt32(value) {
let val = UInt32.Unsafe.fromField(value);
UInt32.check(val);
return val;
}
//# sourceMappingURL=util.js.map