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)
368 lines • 11.6 kB
JavaScript
"use strict";
// import { Field, MerkleList, Mina, PrivateKey, PublicKey, UInt32 } from 'o1js';
// import {
// NumberPacked,
// PLotteryType,
// PStateManager,
// Ticket,
// generateNumbersSeed,
// } from '../../src';
// import { randomInt } from 'crypto';
// import { LotteryAction } from '../../src/Proofs/TicketReduceProof.js';
// import { RandomManagerType } from '../../src/Random/RandomManager.js';
// import { RandomManagerManager } from '../../src/StateManager/RandomManagerManager.js';
// const PLAYERS_AMOUNT = 10;
// const generatePlayers = () => {
// return [...Array(PLAYERS_AMOUNT)].map(() => PrivateKey.randomKeypair());
// };
// const players = generatePlayers();
// interface TicketInfo {
// ticket: Ticket;
// round: Field;
// }
// class Context {
// lottery: PLotteryType;
// randomManager: RandomManagerType;
// lotterySM: PStateManager;
// randomManagerSM: RandomManagerManager;
// boughtTickets: TicketInfo[];
// usedTickets: TicketInfo[];
// }
// class Deviation {
// name: string;
// field: string;
// probability: number;
// expectedError: string | undefined;
// apply: () => Promise<void>;
// }
// type Account = {
// publicKey: PublicKey;
// privateKey: PrivateKey;
// };
// abstract class TestEvent {
// activeDeviations: Deviation[];
// sender: Account;
// context: Context;
// constructor(context: Context, sender: Account) {
// this.context = context;
// this.sender = sender;
// }
// static async randomValid(context: Context): Promise<TestEvent> {
// throw Error('unimplemented');
// }
// abstract getDeviations(): Deviation[];
// addDeviation(deviation: Deviation) {
// this.activeDeviations.push(deviation);
// deviation.apply();
// }
// async safeInvoke() {
// try {
// await this.invoke();
// } catch (e) {
// if (e != this.activeDeviations[0].expectedError) {
// throw Error('Unhandled error');
// }
// }
// }
// abstract invoke(): Promise<void>;
// async checkedInoke() {
// let shouldFail = this.activeDeviations.length > 0;
// try {
// await this.invoke();
// } catch (e) {
// if (shouldFail) {
// console.log(`Expected error ${e} occured`);
// return;
// }
// throw Error(`Unexpected error ${e} occured`);
// }
// if (shouldFail) {
// throw Error(`Expected error, but nothing heppen`);
// return;
// }
// }
// }
// class BuyTicketEvent extends TestEvent {
// ownerIndex: number;
// ticket: Ticket;
// round: Field;
// constructor(context: Context, ownerIndex: number, ticket: Ticket) {
// super(context, players[ownerIndex]);
// this.ownerIndex = ownerIndex;
// this.ticket = ticket;
// }
// static override async randomValid(context: Context): Promise<BuyTicketEvent> {
// const ownerIndex = randomInt(PLAYERS_AMOUNT);
// const owner = players[ownerIndex];
// const ticket = Ticket.random(owner.publicKey);
// return new BuyTicketEvent(context, ownerIndex, ticket);
// }
// getDeviations(): Deviation[] {
// return [
// {
// name: 'wrong numbers',
// field: 'ticket',
// probability: 0.1,
// apply: async () => {
// this.ticket.numbers[randomInt(6)] = UInt32.from(
// randomInt(10, +UInt32.MAXINT)
// );
// },
// expectedError: '????',
// },
// {
// name: 'wrong owner',
// field: 'sender',
// probability: 0.1,
// apply: async () => {
// this.sender = players[(this.ownerIndex + randomInt(1, 10)) % 10];
// },
// expectedError: '????',
// },
// {
// name: 'wrong round',
// field: 'round',
// probability: 0.1,
// apply: async () => {
// // 50/50 less or greater
// if (Math.random() > 0.5) {
// this.round = Field(randomInt(+this.round + 1, +this.round + 1000));
// } else {
// this.round = Field(randomInt(+this.round));
// }
// },
// expectedError: '????',
// },
// ];
// }
// async invoke() {
// let tx = Mina.transaction(this.sender.publicKey, async () => {
// await this.context.lottery.buyTicket(this.ticket, this.round);
// });
// await tx.prove();
// await tx.sign([this.sender.privateKey]).send();
// }
// }
// // class RefundTicketEvent extends TestEvent {}
// class RedeemTicketEvent extends TestEvent {
// round: Field;
// ticket: Ticket;
// constructor(context: Context, round: Field, ticket: Ticket) {
// super(context, players[randomInt(players.length)]);
// this.round = round;
// this.ticket = ticket;
// }
// static override async randomValid(
// context: Context
// ): Promise<RedeemTicketEvent> {
// const { ticket, round } =
// context.boughtTickets[randomInt(context.boughtTickets.length)];
// return new RedeemTicketEvent(context, round, ticket);
// }
// getDeviations(): Deviation[] {
// return [
// {
// name: 'used ticket',
// field: 'ticket',
// probability: 0.1,
// apply: async () => {
// const { ticket, round } =
// this.context.boughtTickets[
// randomInt(this.context.boughtTickets.length)
// ];
// this.round = round;
// this.ticket = ticket;
// },
// expectedError: '????',
// },
// ];
// }
// async invoke() {
// const rp = await this.context.lotterySM.getReward(+this.round, this.ticket);
// let tx = await Mina.transaction(this.sender.publicKey, async () => {
// await this.context.lottery.getReward(
// this.ticket,
// rp.roundWitness,
// rp.roundTicketWitness,
// rp.dp,
// rp.winningNumbers,
// rp.resultWitness,
// rp.bankValue,
// rp.bankWitness,
// rp.nullifierWitness
// );
// });
// await tx.prove();
// await tx.sign([this.sender.privateKey]).send();
// // Change bought ticket to used one
// }
// }
// // class RandomValueGenerationEvent extends TestEvent {}
// class ProduceResultEvent extends TestEvent {
// round: Field;
// randomRound: Field;
// constructor(context: Context, round: Field) {
// super(context, players[randomInt(players.length)]);
// this.round = round;
// this.randomRound = round;
// }
// getDeviations(): Deviation[] {
// return [
// {
// name: 'round-have-not-started',
// field: 'round',
// probability: 0.1,
// expectedError: '???',
// apply: async () => {
// this.activeDeviations = this.activeDeviations.filter(
// (v) => v.field != 'round'
// );
// this.round = Field(randomInt(+this.round + 1, +this.round + 1000));
// },
// },
// {
// name: 'round-has-result',
// field: 'round',
// probability: 0.1,
// expectedError: '???',
// apply: async () => {
// this.activeDeviations = this.activeDeviations.filter(
// (v) => v.field != 'round'
// );
// this.round = Field(randomInt(+this.round));
// },
// },
// {
// name: 'wrong-random-round',
// field: 'randomRound',
// probability: 0.1,
// expectedError: '???',
// apply: async () => {
// let deviantRound = randomInt(+this.round * 2);
// while (deviantRound == +this.round) {
// deviantRound = randomInt(+this.round * 2);
// }
// this.randomRound = Field(deviantRound);
// },
// },
// ];
// }
// async invoke() {
// const resultWV = this.context.randomManagerSM.getResultWitness(
// this.randomRound
// );
// const { resultWitness, bankValue, bankWitness } =
// this.context.lotterySM.updateResult(
// this.round,
// NumberPacked.pack(generateNumbersSeed(resultWV.value))
// );
// let tx = Mina.transaction(this.sender.publicKey, async () => {
// await this.context.lottery.produceResult(
// resultWitness,
// bankValue,
// bankWitness,
// resultWV.witness,
// resultWV.value
// );
// });
// await tx.prove();
// await tx.sign([this.sender.privateKey]).send();
// }
// }
// class ReduceTicketsEvent extends TestEvent {
// fromState: Field;
// toState: Field;
// actions: LotteryAction[][];
// constructor(
// context: Context,
// sender: Account,
// fromState: Field,
// toState: Field,
// actions: LotteryAction[][]
// ) {
// super(context, sender);
// this.fromState = fromState;
// this.toState = toState;
// this.actions = actions;
// }
// static override async randomValid(
// context: Context
// ): Promise<ReduceTicketsEvent> {
// const randomSender = players[randomInt(players.length)];
// const fromState = context.lottery.lastProcessedState.get();
// const toState = context.lottery.account.actionState.get();
// const actions = await context.lottery.reducer.fetchActions({
// fromActionState: fromState,
// endActionState: toState,
// });
// return new ReduceTicketsEvent(
// context,
// randomSender,
// fromState,
// toState,
// actions
// );
// }
// getDeviations(): Deviation[] {
// return [
// {
// name: 'wrong fromState',
// field: 'fromState',
// probability: 0.1,
// expectedError: '???',
// apply: async () => {
// this.fromState = this.toState; // Chenge to one step jump
// this.actions = await this.context.lottery.reducer.fetchActions({
// fromActionState: this.fromState,
// endActionState: this.toState,
// });
// },
// },
// {
// name: 'wrong actions',
// field: 'actions',
// probability: 0.1,
// expectedError: '???',
// apply: async () => {
// let firstIndex = randomInt(this.actions.length);
// let secondIndex = randomInt(
// this.actions[randomInt(firstIndex)].length
// );
// this.actions[firstIndex][secondIndex].ticket.numbers[0] =
// this.actions[firstIndex][secondIndex].ticket.numbers[0]
// .add(1)
// .mod(10)
// .add(1);
// },
// },
// ];
// }
// async invoke() {
// const shouldFail = this.activeDeviations.length > 0;
// let reduceProof = await this.context.lotterySM.reduceTickets(
// this.fromState,
// this.actions,
// !shouldFail
// );
// let tx = Mina.transaction(this.sender.publicKey, async () => {
// await this.context.lottery.reduceTickets(reduceProof);
// });
// await tx.prove();
// await tx.sign([this.sender.privateKey]).send();
// }
// }
// const events = [BuyTicketEvent, ReduceTicketsEvent];
// export class TestOperator {
// async invokeNextEvent(context: Context) {
// const eventType = events[randomInt(events.length)];
// const event = await eventType.randomValid(context);
// const deviations = event.getDeviations();
// deviations.forEach((deviation) => {
// if (deviation.probability > Math.random()) {
// event.addDeviation(deviation);
// }
// });
// await event.invoke();
// }
// }
//# sourceMappingURL=events.js.map