Skip to content

Commit

Permalink
add example with script
Browse files Browse the repository at this point in the history
  • Loading branch information
45930 committed Nov 8, 2023
1 parent d3cc921 commit 5be3506
Show file tree
Hide file tree
Showing 7 changed files with 266 additions and 5 deletions.
44 changes: 44 additions & 0 deletions SampleZkIgniteElection.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,47 @@ Below is a list of proposals for Zk Ignite (the list is real, but the election i
- Proposer: blahblahblah
- Funding Requested: $xxx
- Link to proposal: [Proposal 579](https://zkignite.minaprotocol.com/zkignite/dev4dev/funded/suggestion/579)

#### Index 7: Educational Video Series And Podcast For Community

- Proposer: blahblahblah
- Funding Requested: $xxx
- Link to proposal: [Proposal 482](https://zkignite.minaprotocol.com/zkignite/dev4dev/funded/suggestion/482)

#### Index 8: zkApp Umstad: AI Agent for zkApp Builders

- Proposer: blahblahblah
- Funding Requested: $xxx
- Link to proposal: [Proposal 531](https://zkignite.minaprotocol.com/zkignite/dev4dev/funded/suggestion/531)

#### Index 9: Mina Playground Improvements / New Features

- Proposer: blahblahblah
- Funding Requested: $xxx
- Link to proposal: [Proposal 549](https://zkignite.minaprotocol.com/zkignite/dev4dev/funded/suggestion/549)

#### Index 10: zkNotary: a zkOracle for Mina powered by TLSNotary

- Proposer: blahblahblah
- Funding Requested: $xxx
- Link to proposal: [Proposal 550](https://zkignite.minaprotocol.com/zkignite/dev4dev/funded/suggestion/550)

#### Index 11: zkApps / Ecosystem Hub and zkApp Testing Groups.

- Proposer: blahblahblah
- Funding Requested: $xxx
- Link to proposal: [Proposal 477](https://zkignite.minaprotocol.com/zkignite/dev4dev/funded/suggestion/477)

#### Index 12: zkApp.store - A zkApp marketplace for Mina Protocol

- Proposer: blahblahblah
- Funding Requested: $xxx
- Link to proposal: [Proposal 485](https://zkignite.minaprotocol.com/zkignite/dev4dev/funded/suggestion/485)

#### Index 13: Privacy token on mina

- Proposer: blahblahblah
- Funding Requested: $xxx
- Link to proposal: [Proposal 507](https://zkignite.minaprotocol.com/zkignite/dev4dev/funded/suggestion/507)


2 changes: 1 addition & 1 deletion config.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@
"smartContract": "TokenElection"
}
}
}
}
32 changes: 32 additions & 0 deletions src/examples/ZkIgnite/getElectionDetails.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { Mina, PublicKey, fetchAccount } from 'o1js';
import { TokenElection, IpfsHash } from './../../TokenElection.js';

import * as readline from 'node:readline/promises'; // This uses the promise-based APIs
import { stdin as input, stdout as output } from 'node:process';

const rl = readline.createInterface({ input, output });

const zkAppAddressInput = await rl.question(`At what address is the ZK App Deployed?\n`);

rl.close();

// set up Mina instance and contract we interact with
const Network = Mina.Network('https://proxy.berkeley.minaexplorer.com/graphql');
Mina.setActiveInstance(Network);
let zkAppAddress = PublicKey.fromBase58(zkAppAddressInput);
let zkApp = new TokenElection(zkAppAddress);
await fetchAccount({ publicKey: zkAppAddress });
const onChainIpfsHash = zkApp.electionDetailsIpfs.get();
const ipfsHash = IpfsHash.unpack(onChainIpfsHash.packed).map(x => x.toString()).join('')
console.log(`
Review the details of this election at: https://ipfs.io/ipfs/${ipfsHash}
`)

const ballot = zkApp.ballot.get();
const partial1 = ballot.partial1.toBigInts()
const partial2 = ballot.partial2.toBigInts()
const totalVotes = (partial1.concat(partial2)).map(x => String(x)).join(",")

console.log(`
Current Vote Tallies: ${totalVotes}
`)
76 changes: 76 additions & 0 deletions src/examples/ZkIgnite/joinElection.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { AccountUpdate, Mina, PrivateKey, PublicKey, fetchAccount } from 'o1js';
import { TokenElection, IpfsHash } from './../../TokenElection.js';
import fs from 'fs/promises';

import * as readline from 'node:readline/promises'; // This uses the promise-based APIs
import { stdin as input, stdout as output } from 'node:process';


const rl = readline.createInterface({ input, output });

const zkAppAddressInput = await rl.question(`At what address is the ZK App Deployed?\n`);

rl.close();

let deployAlias = 'berkeley'
Error.stackTraceLimit = 1000;

// parse config and private key from file
type Config = {
deployAliases: Record<
string,
{
url: string;
keyPath: string;
fee: string;
feepayerKeyPath: string;
feepayerAlias: string;
}
>;
};
let configJson: Config = JSON.parse(await fs.readFile('config.json', 'utf8'));
let config = configJson.deployAliases[deployAlias];
let feepayerKeysBase58: { privateKey: string; publicKey: string } = JSON.parse(
await fs.readFile(config.feepayerKeyPath, 'utf8')
);

let zkAppKeysBase58: { privateKey: string; publicKey: string } = JSON.parse(
await fs.readFile(config.keyPath, 'utf8')
);
let feepayerKey = PrivateKey.fromBase58(feepayerKeysBase58.privateKey);
let feepayerAddress = feepayerKey.toPublicKey();

// set up Mina instance and contract we interact with
const Network = Mina.Network(config.url);
const fee = Number(config.fee) * 1e9; // in nanomina (1 billion = 1.0 mina)
Mina.setActiveInstance(Network);
let zkAppAddress = PublicKey.fromBase58(zkAppAddressInput)
let zkApp = new TokenElection(zkAppAddress);
await fetchAccount({ publicKey: zkAppAddress });

let sentTx;
// compile the contract to create prover keys
console.log('compile the contract...');
await TokenElection.compile();
try {
// Join the election by minting tokens to yourself
console.log('build transaction and create proof...');
let tx = await Mina.transaction({ sender: feepayerAddress, fee }, () => {
let senderUpdate = AccountUpdate.fundNewAccount(feepayerAddress);
zkApp.faucet(feepayerAddress);
});
await tx.prove();
console.log('send transaction...');
sentTx = await tx.sign([feepayerKey]).send();
} catch (err) {
console.log(err);
}
if (sentTx?.hash() !== undefined) {
console.log(`
Success! Update transaction sent.
Your smart contract state will be updated
as soon as the transaction is included in a block:
https://berkeley.minaexplorer.com/transaction/${sentTx.hash()}
`);
}
105 changes: 105 additions & 0 deletions src/examples/ZkIgnite/submitVotes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import { AccountUpdate, Mina, PrivateKey, PublicKey, UInt32, fetchAccount, setArchiveGraphqlEndpoint } from 'o1js';
import { TokenElection, IpfsHash, PartialBallot, Ballot } from './../../TokenElection.js';
import fs from 'fs/promises';

import * as readline from 'node:readline/promises'; // This uses the promise-based APIs
import { stdin as input, stdout as output } from 'node:process';


const rl = readline.createInterface({ input, output });

const zkAppAddressInput = await rl.question(`At what address is the ZK App Deployed?\n`);

const confirm = await rl.question(`Votes in votes.json are correct? Y/n\n`);

rl.close();

if (confirm.toLowerCase() != 'y') {
throw new Error("Update votes.json, then continue")
}

let deployAlias = 'berkeley'
Error.stackTraceLimit = 1000;

// parse config and private key from file
type Config = {
deployAliases: Record<
string,
{
url: string;
keyPath: string;
fee: string;
feepayerKeyPath: string;
feepayerAlias: string;
}
>;
};
let configJson: Config = JSON.parse(await fs.readFile('config.json', 'utf8'));
let config = configJson.deployAliases[deployAlias];
let feepayerKeysBase58: { privateKey: string; publicKey: string } = JSON.parse(
await fs.readFile(config.feepayerKeyPath, 'utf8')
);

let zkAppKeysBase58: { privateKey: string; publicKey: string } = JSON.parse(
await fs.readFile(config.keyPath, 'utf8')
);
let feepayerKey = PrivateKey.fromBase58(feepayerKeysBase58.privateKey);
let feepayerAddress = feepayerKey.toPublicKey();

// set up Mina instance and contract we interact with
const Network = Mina.Network(config.url);
setArchiveGraphqlEndpoint('https://api.minascan.io/archive/berkeley/v1/graphql')
const fee = Number(config.fee) * 1e9; // in nanomina (1 billion = 1.0 mina)
Mina.setActiveInstance(Network);
let zkAppAddress = PublicKey.fromBase58(zkAppAddressInput)
let zkApp = new TokenElection(zkAppAddress);
await fetchAccount({ publicKey: zkAppAddress });

const votes = JSON.parse(await fs.readFile('./src/examples/ZkIgnite/votes.json', 'utf8'));
console.log(votes)
const partialBallot1 = new Array(7).fill(0n);
const partialBallot2 = new Array(7).fill(0n);
let sum = 0;
for (let key in votes) {
const keyNum = Number(key)
if (keyNum < 7) {
partialBallot1[keyNum] = BigInt(votes[key])
sum += Number(votes[key])
} else if (keyNum < 14) {
partialBallot2[keyNum - 7] = BigInt(votes[key])
sum += Number(votes[key])
} else {
throw new Error("KeyError: Vote keys must be numeric between 0-13")
}
}
const ballot = new Ballot({
partial1: PartialBallot.fromBigInts(partialBallot1),
partial2: PartialBallot.fromBigInts(partialBallot2),
});
console.log(`Submitting Votes: ${(partialBallot1.concat(partialBallot2)).map(x => String(x)).join(",")}`)
let sentTx;
// compile the contract to create prover keys
console.log('compile the contract...');
await TokenElection.compile();
try {
// Join the election by minting tokens to yourself
console.log('build transaction and create proof...');
let tx = await Mina.transaction({ sender: feepayerAddress, fee }, () => {
zkApp.reduceVotes();
zkApp.castVote(ballot, UInt32.from(sum))
});
await tx.prove();
console.log('send transaction...');
sentTx = await tx.sign([feepayerKey]).send();
} catch (err) {
console.log(err);
}
if (sentTx?.hash() !== undefined) {
console.log(`
Success! Update transaction sent.
Your smart contract state will be updated
as soon as the transaction is included in a block:
https://berkeley.minaexplorer.com/transaction/${sentTx.hash()}
`);
}
4 changes: 4 additions & 0 deletions src/examples/ZkIgnite/votes.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"4": 3200,
"12": 2500
}
8 changes: 4 additions & 4 deletions src/set_election_details.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
const ELECTION_DETAILS_KEY = 'QmaNtrsFkKzF4KxEbdSoSdWr8XoVSdGRYri1U4b8beqwgX';
const ELECTION_DETAILS_KEY = 'QmPKD74Pfc6aH5Suh1EXqjbfKBYDs5QVARxmpqsNKMKxe3';

import { Mina, PrivateKey } from 'o1js';
import fs from 'fs/promises';
import { Election, IpfsHash } from './Election.js';
import { TokenElection, IpfsHash } from './TokenElection.js';

// check command line arg
let deployAlias = process.argv[2];
Expand Down Expand Up @@ -46,12 +46,12 @@ const fee = Number(config.fee) * 1e9; // in nanomina (1 billion = 1.0 mina)
Mina.setActiveInstance(Network);
let feepayerAddress = feepayerKey.toPublicKey();
let zkAppAddress = zkAppKey.toPublicKey();
let zkApp = new Election(zkAppAddress);
let zkApp = new TokenElection(zkAppAddress);

let sentTx;
// compile the contract to create prover keys
console.log('compile the contract...');
await Election.compile();
await TokenElection.compile();
try {
// call update() and send transaction
console.log('build transaction and create proof...');
Expand Down

0 comments on commit 5be3506

Please sign in to comment.