Skip to content

Commit

Permalink
Merge pull request #15 from bobanetwork/souradeep/demo_script
Browse files Browse the repository at this point in the history
feat: enhance demo scripts
  • Loading branch information
kitounliu committed Apr 15, 2024
2 parents 172d167 + b0e302e commit adf451d
Show file tree
Hide file tree
Showing 9 changed files with 185 additions and 59 deletions.
91 changes: 90 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -219,4 +219,93 @@ $ yarn deploy
Run contract tests using-
```
$ yarn test
```
```

## Running the Demo

The Demo offers a quick, interactive overview of the system's end-to-end flow, including memeber interactions, the different phases and their functionality.

### Step-1: Build

1. Build by running

```
$ cargo build --release
```

2. Download KZG parameters using

```
sh download_params.sh
```

3. Setup proving key and verifying key. This might take a few minutes. This command also generates SNARK verifier contract.

```
RUST_LOG=info ./target/release/client setup -s
```

4. The demo will require a test blockchain, for a quickstart - download [Ganache](https://archive.trufflesuite.com/ganache/) and start a local network

```
ganache --wallet.seed "my insecure seeds"
```

5. Set up your .env file (use .env.example for reference)

```
RPC_URL=HTTP://127.0.0.1:8545
PRIVATE_KEY=<private-key-from-a-ganache-account>
THRESHOLD=3
NUMBER_OF_MEMBERS=5
DEGREE=18
```

### Step-2: Deploy Contracts

1. To deploy the zkdvrf contracts, run-

```
yarn deploy
```

2. Populate your demo-config.json file using-

a) your zkdvrf deployed address
b) five sample addresses, and their private keys from ganache pre-generated accounts

### Step-3: NIDKG

1. Start the demo by running your admin script-

```
yarn admin
```

After adding members on the contract, the admin script needs to be kept running as you move on to the subsequent steps

2. On a separate window, register the members and start the NIDKG process by running-

```
yarn member
```

### Step-4: Generating Random

1. After the NIDKG process is complete, the admin script will automatically initiate a round for random generation. Follow the instructions on the admin window and run the following for the members to submit partial evaluations-

```
yarn random
```

After the members have done submitting partial evaluations - verify that a pseudorandom number is generated on the admin window!

### Re-running
Respond 'yes' on the admin window to continue generating pseudorandom numbers.

If you have exited the admin script, but have already been through the NIDKG process, you can continue with random number generation through running-

```
yarn admin:restart
```

9 changes: 2 additions & 7 deletions contracts/zkdvrf.sol
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ contract zkdvrf is Ownable {
mapping (address => dvrfNode) public addrToNode;
mapping (uint256 => string) public roundInput;
mapping (address => uint256) public lastSubmittedRound;
mapping (uint256 => IPseudoRand.PartialEval[]) public roundToEval;
mapping (uint256 => mapping (uint32 => IPseudoRand.PartialEval)) public roundToEval;
mapping (uint256 => uint32) public roundSubmissionCount;
mapping (uint256 => IPseudoRand.PseudoRandom) public roundToRandom;

Expand Down Expand Up @@ -100,7 +100,6 @@ contract zkdvrf is Ownable {

// each node registers with deposit and confirms
function registerNode(Grumpkin.Point memory pubKey) public payable {
require(registeredCount < currentIndex, "All the permitted nodes have registered so far. Please try again later");
require(contractPhase == Status.Unregistered, "Registration has already been completed");
require(msg.sender == addrToNode[msg.sender].nodeAddress, "Unauthorized call");
require(!addrToNode[msg.sender].status, "Node Already registered");
Expand Down Expand Up @@ -196,7 +195,7 @@ contract zkdvrf is Ownable {
Pairing.G1Point memory vkStored = vkList[pkIndex];
require(IPseudoRand(pseudoRand).verifyPartialEval(currentX, pEval.value, pEval.proof, vkStored), "Verification of partial eval failed");
lastSubmittedRound[msg.sender] = currentRoundNum;
roundToEval[currentRoundNum].push(pEval);
roundToEval[currentRoundNum][pkIndex] = pEval;
roundSubmissionCount[currentRoundNum]++;

if (roundSubmissionCount[currentRoundNum] == threshold) {
Expand Down Expand Up @@ -280,8 +279,4 @@ contract zkdvrf is Ownable {
function getVkList() public view returns (Pairing.G1Point[] memory) {
return vkList;
}

function getEvalList(uint roundNum) public view returns (IPseudoRand.PartialEval[] memory) {
return roundToEval[roundNum];
}
}
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,10 @@
"test": "npx hardhat test",
"deploy": "npx hardhat run scripts/deploy.ts",
"admin": "npx hardhat run scripts/admin.ts",
"admin:restart": "RESTART=true npx hardhat run scripts/admin.ts",
"register": "npx hardhat run scripts/register.ts",
"nidkg": "npx hardhat run scripts/nidkg.ts",
"member": "yarn register && yarn nidkg",
"random": "npx hardhat run scripts/random.ts"
},
"repository": {
Expand Down
93 changes: 65 additions & 28 deletions scripts/admin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,16 @@ import {
waitForWriteJsonToFile,
writeJsonToFile
} from "./utils";
import { createInterface } from "readline";

const config = readJsonFromFile("demo-config.json")
const zkdvrfAddress = config.zkdvrfAddress
const memberAdresses = config.memberAddresses

interface Eval {
indexPlus: number
}

async function main() {
const netprovider = new providers.JsonRpcProvider(process.env.RPC_URL)
const accPrivateKey = process.env.PRIVATE_KEY ?? ''
Expand All @@ -24,10 +29,19 @@ async function main() {
const contractABI = Zkdvrf.interface.format();
const contract = new ethers.Contract(zkdvrfAddress, contractABI, netprovider).connect(adminWallet)

for (let i = 0; i < memberAdresses.length; i++) {
const res = await contract.addPermissionedNodes(memberAdresses[i])
// console.log(res)
console.log("added member", memberAdresses[i])
const restart = process.env.RESTART === 'true'

const rl = createInterface({
input: process.stdin,
output: process.stdout
});

if (!restart) {
for (let i = 0; i < memberAdresses.length; i++) {
const res = await contract.addPermissionedNodes(memberAdresses[i])
// console.log(res)
console.log("added member", memberAdresses[i])
}
}

async function listenRegister() {
Expand All @@ -48,7 +62,9 @@ async function main() {
});
}

listenRegister()
if (!restart) {
listenRegister()
}

async function listenNidkg() {
// This will run when the event is emitted
Expand All @@ -63,8 +79,7 @@ async function main() {
subList.map(num => num.toHexString())
);
const obj = JSON.stringify(ppListHex)
writeJsonToFile(obj, instancesPath)
//await waitForWriteJsonToFile(obj, instancesPath)
await waitForWriteJsonToFile(obj, instancesPath)
//console.log("retrieved all instances from contract")


Expand Down Expand Up @@ -113,28 +128,33 @@ async function main() {
});
}

listenNidkg()
if (!restart) {
listenNidkg()
}

async function listenGpp() {
// This will run when the event is emitted
async function initiateRand(eventReceived) {
console.log("\nevent received ", eventReceived)
// Proceed to the next step here
const res = await contract.initiateRandom()
const receipt = await netprovider.getTransactionReceipt(res.hash);
// Check if the transaction was successful
if (receipt.status === 1) {
console.log("Transaction initiateRandom() successful!");
} else {
console.log("Transaction initiateRandom() failed!");
}

console.log('\n 🔔 Please continue by running \'yarn random\' on a new terminal to submit partial evals...')
}

// start listening for the event
if (!restart) {
const eventGpp = `GlobalPublicParamsCreated`
contract.on(eventGpp, async (event) => {
console.log("\nevent", eventGpp)
// Proceed to the next step here
const res = await contract.initiateRandom()
const receipt = await netprovider.getTransactionReceipt(res.hash);
// Check if the transaction was successful
if (receipt.status === 1) {
console.log("Transaction initiateRandom() successful!");
} else {
console.log("Transaction initiateRandom() failed!");
}

await initiateRand(eventGpp);
});
}

listenGpp()

async function listenRandThreshold() {
const eventRandThreshold = `RandomThresholdReached`
contract.on(eventRandThreshold, async (roundNum, input, event) => {
Expand All @@ -144,7 +164,13 @@ async function main() {
await sleep(2000)
console.log("end sleep")

const evals = await contract.getEvalList(roundNum)
const evals: Eval[] = []
for (let i = 0; i < memberAdresses.length; i++) {
const evalFromContract = await contract.roundToEval(roundNum, i)
if (evalFromContract.indexPlus != 0) {
evals.push(evalFromContract)
}
}

const pEvals = []
for (let i = 0; i < evals.length; i++) {
Expand All @@ -163,7 +189,7 @@ async function main() {

const obj = JSON.stringify(pEvals)
const evalsPath = randDir + `evals.json`
writeJsonToFile(obj, evalsPath)
await waitForWriteJsonToFile(obj, evalsPath)

console.log("begin sleep...")
await sleep(2000)
Expand Down Expand Up @@ -193,13 +219,24 @@ async function main() {
}

const rand = await contract.getLatestRandom()
console.log("pseudorandom from contract", rand.value)


console.log("✅ pseudorandom from contract", rand.value)
});
}

listenRandThreshold()

// start listening for event
const eventRandReady = `RandomReady`
contract.on(eventRandReady, async (roundNum, roundInput, event) => {
rl.question("\n 🔔 Do you want to initiate random again? (yes/no): ", async (answer) => {
if (answer.toLowerCase() === "yes") {
await initiateRand(eventRandReady);
} else {
console.log("Exiting the process...");
process.exit(0);
}
});
});
}


Expand Down
5 changes: 4 additions & 1 deletion scripts/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,10 @@ async function main() {
console.log("Zkdvrf deployed at", zkdvrf.address)
}

main().catch((error) => {
main().then(() => {
process.exit(0);
})
.catch((error) => {
console.error(error);
process.exitCode = 1;
});
8 changes: 5 additions & 3 deletions scripts/nidkg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import {
dkgDir,
readBytesFromFile,
execPromise,
instancesPath
instancesPath,
waitForWriteJsonToFile
} from "./utils";


Expand Down Expand Up @@ -45,7 +46,7 @@ async function main() {
subList.map(num => num.toHexString())
);
const obj = JSON.stringify(ppListHex)
writeJsonToFile(obj, instancesPath)
await waitForWriteJsonToFile(obj, instancesPath)

// each member derives its own secret share and global public parameters
const cmd = `RUST_LOG=info ./target/release/client dkg derive`
Expand All @@ -57,6 +58,7 @@ async function main() {
console.log(res[`stderr`])
}

process.exit(0);
// todo: compare the local global public parameters with the one from the contract
});
}
Expand All @@ -76,7 +78,7 @@ async function main() {
// generate snark proof and instance
console.log("running command <", cmdProve, ">...")
let result = await execPromise(cmdProve)
console.log(result[`stderr`])
console.log(result[`stdout`])

// verify snark proof and instance
console.log("running command <", cmdVerify, ">...")
Expand Down
7 changes: 5 additions & 2 deletions scripts/random.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,10 @@ async function main() {

}

main().catch((error) => {
main().then(() => {
process.exit(0);
})
.catch((error) => {
console.error(error);
process.exitCode = 1;
});
});
8 changes: 5 additions & 3 deletions scripts/register.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import hre, {artifacts, ethers} from "hardhat";
import {Contract, ContractFactory, providers, utils, Wallet} from "ethers";
import { promisify } from 'util';
import { exec } from "child_process";
import {readJsonFromFile, writeJsonToFile, memberDir, mpksPath, execPromise} from "./utils";
import {readJsonFromFile, writeJsonToFile, waitForWriteJsonToFile, memberDir, mpksPath, execPromise} from "./utils";

const config = readJsonFromFile("demo-config.json")
const zkdvrfAddress = config.zkdvrfAddress
Expand All @@ -25,7 +25,9 @@ async function main() {

const pks = res.map(pk => ({x: pk[0].toHexString(), y: pk[1].toHexString()}))
const obj = JSON.stringify(pks);
writeJsonToFile(obj, mpksPath)
await waitForWriteJsonToFile(obj, mpksPath);

process.exit(0);
});


Expand Down Expand Up @@ -62,4 +64,4 @@ async function main() {
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});
});
Loading

0 comments on commit adf451d

Please sign in to comment.