Skip to content

Commit

Permalink
Merge pull request #94 from AztecProtocol/zpedro/noir_bb_honk
Browse files Browse the repository at this point in the history
updating to 0.36.0 with oleh's Hardhat Plugin
  • Loading branch information
signorecello authored Nov 12, 2024
2 parents ae3919d + 8060297 commit d1b9b8d
Show file tree
Hide file tree
Showing 29 changed files with 204 additions and 7,652 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/vite_hardhat.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,8 @@ jobs:
- name: Install dependencies
run: bun install

- name: Compile
run: bunx hardhat compile

- name: Run tests
run: bun test
3 changes: 3 additions & 0 deletions .github/workflows/vite_hardhat_nightly.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ jobs:
@noir-lang/noir_wasm@${{ matrix.version }} \
@noir-lang/types@${{ matrix.version }}
- name: Compile
run: bunx hardhat compile

- name: Run tests
run: bun test

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "create-noir",
"name": "noir-starter",
"version": "0.1.1",
"type": "module",
"description": "This is a reference repo to help you get started with writing zero-knowledge circuits with [Noir](https://noir-lang.org/).",
Expand Down
1 change: 1 addition & 0 deletions vite-hardhat/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,4 @@ artifacts

circuit/target/
dist
deployment.json
41 changes: 15 additions & 26 deletions vite-hardhat/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,23 @@ Want to get started in a pinch? Start your project in a free Github Codespace!
bun i # "npm i" or "yarn"
```

3. Run the app
3. Run a node

You can run a separate Ethereum node from the dev environment:
```bash
bunx hardhat node
```

```bash
bunx hardhat node
```
4. Deploy the verifier contract

and run the dev environment separately:
```bash
bun run deploy
```

```bash
bunx hardhat dev
```
5. Run the dev environment

```bash
bun dev
```

### Testing

Expand All @@ -48,10 +52,7 @@ You can run the [example test file](./test/index.test.ts) with
bun test
```

This test shows the basic usage of Noir in a TypeScript Node.js environment.

> [!NOTE] The test is a script, not an executable (we're running `bun test` or `yarn test` instead
> of `bunx` or `npx`). This is because the test runs its own network and executables.
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.

### Deploying on other networks

Expand All @@ -69,12 +70,10 @@ network:
bunx hardhat vars set holesky <your_testnet_private_key>
```

You can then run all the commands using that network by passing the `--network` flag. For example:
You can then deploy on that network by passing the `--network` flag. For example:

```bash
bunx hardhat dev --network holesky # deploys and runs a development server on holesky
bunx hardhat deploy --network holesky # deploys on holesky
bunx hardhat build --network holesky # builds the frontend with the holesky target
```

Feel free to add more networks, as long as they're supported by `wagmi`
Expand All @@ -83,13 +82,3 @@ Feel free to add more networks, as long as they're supported by `wagmi`
- Have funds in these accounts
- Add their configuration in the `networks` property in `hardhat.config.cts`
- Use the name that wagmi expects (for example `ethereum` won't work, as `wagmi` calls it `mainnet`)

#### Attaching to an existing contract

You probably don't want to redeploy everytime you build your project. To attach the build to an
already deployed contract, pass the `--attach` flag:

```bash
bunx hardhat deploy --network mainnet # deploys on ethereum mainnet $$$$$!
bunx hardhat dev --network mainnet --attach 0x<yourethereumcontract> # you're now developing using an existing verifier contract
```
Binary file modified vite-hardhat/bun.lockb
Binary file not shown.
151 changes: 23 additions & 128 deletions vite-hardhat/hardhat.config.cts
Original file line number Diff line number Diff line change
@@ -1,141 +1,34 @@
import '@nomicfoundation/hardhat-toolbox-viem';
import '@nomicfoundation/hardhat-viem';
import '@nomicfoundation/hardhat-chai-matchers';
import 'hardhat-plugin-noir';

import { HardhatUserConfig, scope, task, types } from 'hardhat/config';

import { subtask, vars } from 'hardhat/config';
import { TASK_COMPILE_SOLIDITY } from 'hardhat/builtin-tasks/task-names';
import { join, resolve } from 'path';
import { writeFile } from 'fs/promises';
import { mkdirSync, writeFileSync } from 'fs';
import { gunzipSync } from 'zlib';
import { Barretenberg, RawBuffer, Crs } from '@aztec/bb.js';
import { createFileManager, compile } from '@noir-lang/noir_wasm';
import { CompiledCircuit } from '@noir-lang/types';
import { exec } from 'shelljs';
import hre, { vars, HardhatUserConfig, task } from 'hardhat/config';
import { writeFileSync } from 'fs';
import { Chain } from 'viem';

subtask(TASK_COMPILE_SOLIDITY).setAction(async (_, { config }, runSuper) => {
const superRes = await runSuper();

try {
await writeFile(join(config.paths.root, 'artifacts', 'package.json'), '{ "type": "commonjs" }');
} catch (error) {
console.error('Error writing package.json: ', error);
}

return superRes;
});

export async function compileCircuit(path = './circuit') {
const basePath = resolve(join(path));
const fm = createFileManager(basePath);
const result = await compile(fm);
if (!('program' in result)) {
throw new Error('Compilation failed');
}
return result.program as CompiledCircuit;
}
task('deploy', 'Deploys the verifier contract').setAction(async ({ attach }, hre) => {
const verifier = await hre.viem.deployContract('UltraVerifier');

export async function generateArtifacts(path = './circuit', crsPath = './crs') {
const circuit = await compileCircuit(path);
const decompressed = gunzipSync(Buffer.from(circuit.bytecode, 'base64'));
const api = await Barretenberg.new({ threads: 8 });
const [exact, total, subgroup] = await api.acirGetCircuitSizes(decompressed, false);
const subgroupSize = Math.pow(2, Math.ceil(Math.log2(total)));
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,
},
};

const crs = await Crs.new(subgroupSize + 1, crsPath);
await api.commonInitSlabAllocator(subgroupSize);
await api.srsInitSrs(
new RawBuffer(crs.getG1Data()),
crs.numPoints,
new RawBuffer(crs.getG2Data()),
console.log(
`Attached to address ${verifier.address} at network ${hre.network.name} with chainId ${networkConfig.id}...`,
);

const acirComposer = await api.acirNewAcirComposer(subgroupSize);
await api.acirInitProvingKey(acirComposer, decompressed);
await api.acirInitVerificationKey(acirComposer);

const contract = await api.acirGetSolidityVerifier(acirComposer);
return { circuit, contract };
}

task('compile', 'Compile and generate circuits and contracts').setAction(
async (_, __, runSuper) => {
const { circuit, contract } = await generateArtifacts();
mkdirSync('artifacts', { recursive: true });
writeFileSync('artifacts/circuit.json', JSON.stringify(circuit), { flag: 'w' });
writeFileSync('artifacts/contract.sol', contract, { flag: 'w' });
await runSuper();
},
);

task('deploy', 'Deploys the verifier contract')
.addOptionalParam('attach', 'Attach to an existing address', '', types.string)
.setAction(async ({ attach }, hre) => {
let verifier;
if (attach) {
verifier = await hre.viem.getContractAt('UltraVerifier', attach);
} else {
verifier = await hre.viem.deployContract('UltraVerifier');
}

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

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

subtask('generateHooks', 'Generates hooks for the verifier contract').setAction(async (_, hre) => {
exec('wagmi generate');
});

subtask('prep', 'Compiles and deploys the verifier contract')
.addParam('attach', 'Attach to an already deployed contract', '', types.string)
.setAction(async ({ attach }, hre) => {
console.log('Preparing...');
console.log('Compiling circuits and generating contracts...');

await hre.run('compile');
await hre.run('deploy', { attach });

console.log('Generating hooks...');
await hre.run('generateHooks');
});

task('dev', 'Deploys and starts in a development environment')
.addOptionalParam('attach', 'Attach to an existing address', '', types.string)
.setAction(async ({ attach }, hre) => {
await hre.run('prep', { attach });
exec('vite dev');
});

task('build', 'Builds the frontend project')
.addOptionalParam('attach', 'Attach to an existing address', '', types.string)
.setAction(async ({ attach }, hre) => {
await hre.run('prep', { attach });
exec('vite build');
});

task('serve', 'Serves the frontend project').setAction(async (_, hre) => {
exec('vite preview');
writeFileSync('deployment.json', JSON.stringify(config), { flag: 'w' });
});

const config: HardhatUserConfig = {
solidity: {
version: '0.8.18',
version: '0.8.21',
settings: {
optimizer: { enabled: true, runs: 5000 },
},
Expand All @@ -158,10 +51,12 @@ const config: HardhatUserConfig = {
accounts: vars.has('holesky') ? [vars.get('holesky')] : [],
},
},
noir: {
version: '0.36.0',
},
paths: {
root: './',
sources: './artifacts',
artifacts: './artifacts/hardhat',
root: 'packages',
tests: 'tests',
},
};

Expand Down
49 changes: 18 additions & 31 deletions vite-hardhat/package.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,21 @@
{
"name": "noir-starter",
"version": "1.0.0",
"type": "module",
"name": "vite-hardhat",
"description": "A template repository to get started with writing zero knowledge programs with Noir.",
"private": true,
"workspaces": [
"packages/*"
],
"scripts": {
"test": "test/test.sh"
"deploy": "bunx hardhat compile && bunx hardhat deploy",
"dev": "bun --filter vite dev",
"test:hardhat": "bunx hardhat test",
"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",
Expand All @@ -13,44 +24,20 @@
"@noir-lang/types": "0.36.0",
"@nomicfoundation/hardhat-ignition": "^0.15.5",
"@nomicfoundation/hardhat-ignition-viem": "^0.15.5",
"@tanstack/query-sync-storage-persister": "5.0.5",
"@tanstack/react-query": "5.44.0",
"@tanstack/react-query-persist-client": "5.0.5",
"commander": "^12.1.0",
"dotenv": "^16.0.3",
"hardhat": "^2.19.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-toastify": "^9.1.1",
"shelljs": "^0.8.5",
"tsx": "^4.15.4",
"viem": "2.x",
"wagmi": "2.10.0"
},
"devDependencies": {
"@nomicfoundation/hardhat-chai-matchers": "^2.0.7",
"@nomicfoundation/hardhat-ethers": "^3.0.6",
"@nomicfoundation/hardhat-network-helpers": "^1.0.11",
"@nomicfoundation/hardhat-toolbox-viem": "3.0.0",
"@nomicfoundation/hardhat-verify": "^2.0.8",
"@nomicfoundation/hardhat-viem": "2.0.2",
"@tanstack/react-query-devtools": "5.0.5",
"@types/bun": "^1.1.4",
"@types/mocha": "^10.0.1",
"@types/node": "^18.15.5",
"@types/react": "^18.0.26",
"@types/shelljs": "^0.8.7",
"@vitejs/plugin-react-swc": "^3.5.0",
"@wagmi/cli": "^2.1.10",
"chai": "^4.2.0",
"hardhat-gas-reporter": "^1.0.9",
"solidity-coverage": "^0.8.5",
"ts-node": "^10.9.1",
"typechain": "^8.1.0",
"typescript": "^4.9.3",
"vite": "^5.0.6"
"solidity-coverage": "^0.8.5"
},
"engines": {
"node": "^20.10.0"
"peerDependencies": {
"typescript": "^5.0.0"
}
}
1 change: 1 addition & 0 deletions vite-hardhat/packages/noir/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
target
File renamed without changes.
2 changes: 2 additions & 0 deletions vite-hardhat/packages/noir/Prover.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
x = 1
y = 2
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { useState } from 'react';
import React from 'react';

import { useOnChainVerification } from '../hooks/useOnChainVerification.jsx';
import { useProofGeneration } from '../hooks/useProofGeneration.jsx';
import { useOffChainVerification } from '../hooks/useOffChainVerification.jsx';
import { useOnChainVerification } from '../hooks/useOnChainVerification.js';
import { useProofGeneration } from '../hooks/useProofGeneration.js';
import { useOffChainVerification } from '../hooks/useOffChainVerification.js';

function Component() {
const [input, setInput] = useState<{ x: string; y: string } | undefined>();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import React from 'react';
import { ProofData } from '@noir-lang/types';
import { useAccount, useConnect, useDisconnect, useSwitchChain } from 'wagmi';
import { bytesToHex } from 'viem';
import { useEffect, useState } from 'react';
import { Id, toast } from 'react-toastify';
import { ultraVerifierAddress, useReadUltraVerifierVerify } from '../artifacts/generated.js';
import deployment from '../artifacts/deployment.json';
import { useReadUltraVerifierVerify } from '../artifacts/generated.js';
import deployment from '../../../deployment.json';

export function useOnChainVerification(proofData?: ProofData) {
const { connect, connectors } = useConnect();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { toast } from 'react-toastify';
import { useEffect, useState } from 'react';
import { getCircuit } from '../circuit/compile.js';
import { UltraPlonkBackend, ProofData } from '@aztec/bb.js';
import { getCircuit } from '../../noir/compile.js';
import { UltraPlonkBackend } from '@aztec/bb.js';
import { Noir } from '@noir-lang/noir_js';
import { ProofData } from '@noir-lang/types';

export function useProofGeneration(inputs?: { [key: string]: string }) {
const [proofData, setProofData] = useState<ProofData | undefined>();
Expand Down
File renamed without changes.
Loading

0 comments on commit d1b9b8d

Please sign in to comment.