Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ultrahonk finally #100

Merged
merged 12 commits into from
Dec 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/vite_hardhat.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,4 @@ jobs:
run: bunx hardhat compile

- name: Run tests
run: bun test
run: bun run test
5 changes: 1 addition & 4 deletions .github/workflows/vite_hardhat_nightly.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@ on:
schedule:
# Run a nightly release at 2 AM UTC
- cron: '0 2 * * *'
pull_request:
paths:
- 'vite-hardhat/**'

jobs:
vite-hardhat-setup:
Expand Down Expand Up @@ -86,7 +83,7 @@ jobs:
run: bunx hardhat compile

- name: Run tests
run: bun test
run: bun run test

- name: Send GitHub Action trigger data to Slack workflow - Stable
uses: slackapi/[email protected]
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ package-lock.json

# To use with nektos/act
.github/event.json
bun.lockb
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "noir-starter",
"version": "0.1.1",
"name": "create-noir",
"version": "0.1.3",
"type": "module",
"description": "This is a reference repo to help you get started with writing zero-knowledge circuits with [Noir](https://noir-lang.org/).",
"bin": "npx.js",
Expand Down
4 changes: 3 additions & 1 deletion vite-hardhat/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ crs
artifacts
.yarn/

circuit/target/
noir/target/
contracts
dist
deployment.json
bun.lockb
12 changes: 9 additions & 3 deletions vite-hardhat/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Want to get started in a pinch? Start your project in a free Github Codespace!
2. Install dependencies:

```bash
bun i # "npm i" or "yarn"
bun i
```

3. Run a node
Expand All @@ -32,7 +32,7 @@ Want to get started in a pinch? Start your project in a free Github Codespace!
bunx hardhat node
```

4. Deploy the verifier contract
4. Deploy the verifier contract (UltraPlonk)

```bash
bun run deploy
Expand All @@ -49,11 +49,17 @@ Want to get started in a pinch? Start your project in a free Github Codespace!
You can run the [example test file](./test/index.test.ts) with

```bash
bun test
bun run test
```

This test shows the basic usage of Noir in a TypeScript Node.js environment. It also starts its own network and deploys the verifier contract.

If you want to test only `UltraHonk`, you can run:

```bash
bun run test:uh
```

### Deploying on other networks

The default scripting targets a local environment. For convenience, we added some configurations for
Expand Down
Binary file removed vite-hardhat/bun.lockb
Binary file not shown.
63 changes: 38 additions & 25 deletions vite-hardhat/hardhat.config.cts
Original file line number Diff line number Diff line change
@@ -1,34 +1,18 @@
import '@nomicfoundation/hardhat-toolbox-viem';
import '@nomicfoundation/hardhat-viem';
import '@nomicfoundation/hardhat-chai-matchers';
import 'hardhat-plugin-noir';
import 'hardhat-noirenberg';

import hre, { vars, HardhatUserConfig, task } from 'hardhat/config';
import { writeFileSync } from 'fs';
import { Chain } from 'viem';

task('deploy', 'Deploys the verifier contract').setAction(async ({ attach }, hre) => {
const verifier = await hre.viem.deployContract('UltraVerifier');

const networkConfig = (await import(`viem/chains`))[hre.network.name] as Chain;
const config = {
name: hre.network.name,
address: verifier.address,
networkConfig: {
...networkConfig,
id: hre.network.config.chainId,
},
};

console.log(
`Attached to address ${verifier.address} at network ${hre.network.name} with chainId ${networkConfig.id}...`,
);
writeFileSync('deployment.json', JSON.stringify(config), { flag: 'w' });
});
import { task, vars } from 'hardhat/config';
import { HardhatUserConfig } from 'hardhat/types/config';
import fs from 'fs';
import { resolve } from 'path';

const config: HardhatUserConfig = {
solidity: {
version: '0.8.21',
version: '0.8.28',
settings: {
optimizer: { enabled: true, runs: 5000 },
},
Expand All @@ -51,13 +35,42 @@ const config: HardhatUserConfig = {
accounts: vars.has('holesky') ? [vars.get('holesky')] : [],
},
},
noir: {
version: '0.36.0',
},
paths: {
root: 'packages',
tests: 'tests',
},
};

task('deploy', 'Deploys a verifier contract')
.addOptionalPositionalParam('provingSystem')
.setAction(async (taskArgs, hre) => {
const contractsDir = resolve('packages', 'contracts');
if (fs.existsSync(contractsDir)) fs.rmdirSync(contractsDir, { recursive: true });

hre.config.noirenberg = { provingSystem: taskArgs.provingSystem || 'UltraPlonk' };
await hre.run('compile');

let verifier;
if (taskArgs.provingSystem === 'UltraHonk') {
verifier = await hre.viem.deployContract('HonkVerifier');
} else {
verifier = await hre.viem.deployContract('UltraVerifier');
}

const networkConfig = (await import(`viem/chains`))[hre.network.name] as Chain;
const config = {
name: hre.network.name,
address: verifier.address,
networkConfig: {
...networkConfig,
id: hre.network.config.chainId,
},
};

console.log(
`Attached to address ${verifier.address} at network ${hre.network.name} with chainId ${networkConfig.id}...`,
);
writeFileSync('deployment.json', JSON.stringify(config), { flag: 'w' });
});

export default config;
22 changes: 11 additions & 11 deletions vite-hardhat/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,23 @@
"packages/*"
],
"scripts": {
"deploy": "bunx hardhat compile && bunx hardhat deploy",
"deploy": "bunx hardhat deploy",
"dev": "bun --filter vite dev",
"test:hardhat": "bunx hardhat test",
"test:up": "bun test ./tests/up.test.ts",
"test:uh": "bun test ./tests/uh.test.ts",
"test": "bun test:up && bun test:uh",
"node": "bunx hardhat node"
},
"type": "module",
"devDependencies": {
"hardhat-plugin-noir": "0.1.3",
"@types/bun": "^1.1.12",
"hardhat": "^2.19.2"
},
"dependencies": {
"@aztec/bb.js": "^0.62.0",
"@noir-lang/noir_js": "0.36.0",
"@noir-lang/noir_wasm": "0.36.0",
"@noir-lang/types": "0.36.0",
"@noir-lang/noir_js": "1.0.0-beta.0",
"@noir-lang/noir_wasm": "1.0.0-beta.0",
"@noir-lang/types": "1.0.0-beta.0",
"@aztec/bb.js": "0.63.1",
"@nomicfoundation/hardhat-ignition": "^0.15.5",
"@nomicfoundation/hardhat-ignition-viem": "^0.15.5",
"commander": "^12.1.0",
Expand All @@ -35,9 +36,8 @@
"@types/mocha": "^10.0.1",
"@types/shelljs": "^0.8.7",
"hardhat-gas-reporter": "^1.0.9",
"solidity-coverage": "^0.8.5"
},
"peerDependencies": {
"typescript": "^5.0.0"
"solidity-coverage": "^0.8.5",
"hardhat-noirenberg": "0.2.0",
"typescript": "^5.6.3"
}
}
6 changes: 5 additions & 1 deletion vite-hardhat/packages/vite/hooks/useProofGeneration.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,11 @@ export function useProofGeneration(inputs?: { [key: string]: string }) {
error: 'Error initializing Noir',
});

const { witness } = await noir.execute(inputs);
const { witness } = await toast.promise(noir.execute(inputs), {
pending: 'Generating witness...',
success: 'Witness generated!',
error: 'Error generating witness',
});

const data = await toast.promise(backend.generateProof(witness), {
pending: 'Generating proof',
Expand Down
34 changes: 11 additions & 23 deletions vite-hardhat/packages/vite/index.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
// @ts-ignore
import acvm from '@noir-lang/acvm_js/web/acvm_js_bg.wasm?url';
// @ts-ignore
import noirc from '@noir-lang/noirc_abi/web/noirc_abi_wasm_bg.wasm?url';
import initNoirC from '@noir-lang/noirc_abi';
import initACVM from '@noir-lang/acvm_js';
// @ts-ignore
await Promise.all([initACVM(fetch(acvm)), initNoirC(fetch(noirc))]);

import React, { ReactNode, useEffect } from 'react';
import ReactDOM from 'react-dom/client';
import './App.css';
import 'react-toastify/dist/ReactToastify.css';
import { ToastContainer } from 'react-toastify';
import Component from './components/index.jsx';
import initNoirC from '@noir-lang/noirc_abi';
import initACVM from '@noir-lang/acvm_js';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { WagmiProvider, createConfig, http } from 'wagmi';
import { defineChain, createClient } from 'viem';
Expand All @@ -30,23 +37,6 @@ const config = createConfig({
},
});

const InitWasm = ({ children }: any) => {
const [init, setInit] = React.useState(false);
useEffect(() => {
(async () => {
await Promise.all([
initACVM(new URL('@noir-lang/acvm_js/web/acvm_js_bg.wasm', import.meta.url).toString()),
initNoirC(
new URL('@noir-lang/noirc_abi/web/noirc_abi_wasm_bg.wasm', import.meta.url).toString(),
),
]);
setInit(true);
})();
});

return <div>{init && children}</div>;
};

export function Providers({ children }: { children: React.ReactNode }) {
const [mounted, setMounted] = React.useState(false);
React.useEffect(() => setMounted(true), []);
Expand All @@ -59,9 +49,7 @@ export function Providers({ children }: { children: React.ReactNode }) {

ReactDOM.createRoot(document.getElementById('root')!).render(
<Providers>
<InitWasm>
<Component />
<ToastContainer />
</InitWasm>
<Component />
<ToastContainer />
</Providers>,
);
8 changes: 0 additions & 8 deletions vite-hardhat/packages/vite/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,6 @@
"wagmi": "wagmi generate"
},
"dependencies": {
"@noir-lang/backend_barretenberg": "0.36.0",
"@noir-lang/noir_js": "0.36.0",
"@noir-lang/noir_wasm": "0.36.0",
"@noir-lang/types": "0.36.0",
"@aztec/bb.js": "^0.62.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-toastify": "^9.1.1",
Expand All @@ -34,8 +29,5 @@
"typechain": "^8.1.0",
"typescript": "^4.9.3",
"vite": "^5.0.6"
},
"engines": {
"node": ">=18.19.0"
}
}
11 changes: 2 additions & 9 deletions vite-hardhat/packages/vite/vite.config.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,10 @@
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react-swc';

export default defineConfig({
export default {
optimizeDeps: {
esbuildOptions: {
target: 'esnext',
},
},
build: {
target: 'esnext',
},
plugins: [react()],
server: {
port: 1337,
},
});
};
50 changes: 50 additions & 0 deletions vite-hardhat/tests/uh.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { expect, beforeAll, describe, test } from 'bun:test';
import { Noir } from '@noir-lang/noir_js';
import { ProofData } from '@noir-lang/types';
import { UltraHonkBackend } from '@aztec/bb.js';
import fs from 'fs';
import { resolve } from 'path';

describe('UltraHonk', () => {
let correctProof: ProofData;
let noir: Noir;
let backend: UltraHonkBackend;

beforeAll(async () => {
const contractsDir = resolve('packages', 'contracts');
if (fs.existsSync(contractsDir)) fs.rmdirSync(contractsDir, { recursive: true });

const hre = require('hardhat');

hre.run('node');
hre.config.noirenberg = { provingSystem: 'UltraHonk' };

console.log(hre);
({ noir, backend } = await hre.noirenberg.compile());
await hre.noirenberg.getSolidityVerifier();
});

test('Should generate valid proof for correct input', async () => {
const input = { x: 1, y: 2 };
const { witness } = await noir.execute(input);
correctProof = await backend.generateProof(witness);
expect(correctProof.proof instanceof Uint8Array).toBeTrue;
});

test('Should verify valid proof for correct input', async () => {
const verification = await backend.verifyProof(correctProof);
expect(verification).toBeTrue;
});

test('Should fail to generate valid proof for incorrect input', async () => {
try {
const input = { x: 1, y: 1 };
const { witness } = await noir.execute(input);
const incorrectProof = await backend.generateProof(witness);
} catch (err) {
expect(err instanceof Error).toBeTrue;
const error = err as Error;
expect(error.message).toContain('Cannot satisfy constraint');
}
});
});
Loading
Loading