Skip to content
Closed
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
85 changes: 68 additions & 17 deletions .github/workflows/benchmark.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,34 @@ name: Benchmarks

on:
push:
branches:
- master
branches:
- master
pull_request:

env:
MINIMUM_NOIR_VERSION: 1.0.0-beta.17

jobs:
test:
name: Benchmark library
runs-on: ubuntu-latest
permissions:
deployments: write
contents: write

steps:
- name: Checkout sources
uses: actions/checkout@v4

- name: Install Nargo
uses: noir-lang/[email protected].3
uses: noir-lang/[email protected].4
with:
toolchain: 1.0.0-beta.3
toolchain: ${{env.MINIMUM_NOIR_VERSION}}

- name: Install bb
run: |
npm install -g bbup
bbup -nv 1.0.0-beta.3
curl -L https://raw.githubusercontent.com/AztecProtocol/aztec-packages/refs/heads/next/barretenberg/bbup/install | bash
~/.bb/bbup -nv ${{env.MINIMUM_NOIR_VERSION}}
sudo apt install libc++-dev

- name: Build Noir benchmark programs
Expand All @@ -33,17 +40,61 @@ jobs:
env:
BACKEND: /home/runner/.bb/bb

- name: Compare gates reports
id: gates_diff
uses: noir-lang/noir-gates-diff@dbe920a8dcc3370af4be4f702ca9cef29317bec1
- name: Store ACIR opcode benchmark result
uses: benchmark-action/github-action-benchmark@v1
with:
name: "ACIR Opcodes"
tool: "customSmallerIsBetter"
output-file-path: "benchmark-opcodes.json"
gh-pages-branch: "gh-pages"
benchmark-data-dir-path: "dev/bench"
github-token: ${{ secrets.GITHUB_TOKEN }}
auto-push: ${{ github.ref == 'refs/heads/master' }}
comment-always: ${{ contains( github.event.pull_request.labels.*.name, 'bench-show') }}
comment-on-alert: true
alert-threshold: "101%"
fail-on-alert: false
max-items-in-chart: 50

- name: Store gates benchmark result
uses: benchmark-action/github-action-benchmark@v1
with:
report: gates_report.json
summaryQuantile: 0.9 # only display the 10% most significant circuit size diffs in the summary (defaults to 20%)
name: "Circuit Size"
tool: "customSmallerIsBetter"
output-file-path: "benchmark-circuit.json"
gh-pages-branch: "gh-pages"
benchmark-data-dir-path: "dev/bench"
github-token: ${{ secrets.GITHUB_TOKEN }}
auto-push: ${{ github.ref == 'refs/heads/master' }}
comment-always: ${{ contains( github.event.pull_request.labels.*.name, 'bench-show') }}
comment-on-alert: true
alert-threshold: "101%"
fail-on-alert: false
max-items-in-chart: 50
skip-fetch-gh-pages: true

- name: Delete export files
run: rm -rf export

- name: Build Brillig benchmark programs
run: nargo export --force-brillig

- name: Generate brillig report
run: ./scripts/build-brillig-report.sh

- name: Add gates diff to sticky comment
if: github.event_name == 'pull_request' || github.event_name == 'pull_request_target'
uses: marocchino/sticky-pull-request-comment@v2
- name: Store brillig benchmark result
uses: benchmark-action/github-action-benchmark@v1
with:
# delete the comment in case changes no longer impact circuit sizes
delete: ${{ !steps.gates_diff.outputs.markdown }}
message: ${{ steps.gates_diff.outputs.markdown }}
name: "Brillig Bytecode Size"
tool: "customSmallerIsBetter"
output-file-path: "benchmark-brillig.json"
gh-pages-branch: "gh-pages"
benchmark-data-dir-path: "dev/bench"
github-token: ${{ secrets.GITHUB_TOKEN }}
auto-push: ${{ github.ref == 'refs/heads/master' }}
comment-always: ${{ contains( github.event.pull_request.labels.*.name, 'bench-show') }}
comment-on-alert: true
alert-threshold: "101%"
fail-on-alert: false
max-items-in-chart: 50
skip-fetch-gh-pages: true
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ dist
node_modules
target
export
gates_report.json
package-lock.json
8 changes: 8 additions & 0 deletions gates_report.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{"programs": [
{"package_name": "poseidon2_length_10.json", "functions": [{
"acir_opcodes": 26,
"circuit_size": 584,
"name": "main"
}]
}
]}
89 changes: 72 additions & 17 deletions oracle_server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { BarretenbergSync, Fr } from "@aztec/bb.js";
import express, { Request, Response } from "express";
import bodyParser from "body-parser";
import cors from "cors";
import { poseidon1, poseidon2, poseidon3, poseidon4, poseidon5, poseidon6, poseidon7, poseidon8, poseidon9, poseidon10, poseidon11, poseidon12, poseidon13, poseidon14, poseidon15, poseidon16 } from "poseidon-lite";

// Type definitions
interface JsonRpcRequest {
Expand Down Expand Up @@ -98,10 +99,12 @@ app.post("/", async (req: Request<{}, JsonRpcResponse, JsonRpcRequest>, res: Res
async function handleForeignCall(params: any[]): Promise<ForeignCallResult> {
const [callInfo] = params as [ForeignCallInfo];
const { function: functionName, inputs } = callInfo;


if (functionName === "getPoseidon2Hash") {
return await handlePoseidon2Hash(inputs);
} else if (functionName === "getPoseidonHash") {
return await handlePoseidonHash(inputs);
} else {
throw new Error(`Unknown oracle function: ${functionName}`);
}
Expand All @@ -121,25 +124,77 @@ function hexToBigInt(hex: string): bigint {

async function handlePoseidon2Hash(inputs: string[][]): Promise<ForeignCallResult> {
try {
// Extract the input array from the first parameter
const inputArray = inputs[0] || [];

const fieldInputs: Fr[] = inputArray.map((input: string) => new Fr(hexToBigInt(input)))

// Perform Poseidon2 hash using bb.js
let result: Fr;
if (fieldInputs.length === 0) {
// Empty input case
result = await bb.poseidon2Hash([]);
} else {
result = await bb.poseidon2Hash(fieldInputs);
// For dynamic slices [Field], Noir sends:
// inputs[0] = array length (metadata)
// inputs[1] = array contents
// inputs[2] = message_size

const inputArray = inputs[1] || [];

// For u32, Noir sends as strings, not arrays
const messageSizeHex = inputs[2] as unknown as string;
if (!messageSizeHex) {
throw new Error("message_size parameter is missing");
}


const messageSize = Number(hexToBigInt(messageSizeHex));

// Convert input array to Field elements
const fieldInputs: Fr[] = inputArray.map((input: string) => new Fr(hexToBigInt(input)));

// Slice to only use the first message_size elements
const slicedInputs = fieldInputs.slice(0, messageSize);

// Get Poseidon2 hash using bb.js
const result = bb.poseidon2Hash(slicedInputs);

return {
values: [result.toString()]
};


} catch (error) {
throw error;
}
}

async function handlePoseidonHash(inputs: string[][]): Promise<ForeignCallResult> {
try {

// Extract the input array from the second parameter (inputs[1])
const inputArray = inputs[1] || [];

// Extract message_size from the third parameter (inputs[2])
const messageSizeHex = inputs[2] as unknown as string;
if (!messageSizeHex) {
throw new Error("message_size parameter is missing");
}
const messageSize = Number(hexToBigInt(messageSizeHex));

if (messageSize < 1 || messageSize > 16) {
throw new Error(`message_size must be between 1 and 16, got ${messageSize}`);
}

// Convert input array to BigInt array, slicing to message_size
const bigIntInputs: bigint[] = inputArray
.slice(0, messageSize)
.map((input: string) => hexToBigInt(input));

// Map to appropriate poseidon function
const poseidonFunctions = [
poseidon1, poseidon2, poseidon3, poseidon4, poseidon5, poseidon6,
poseidon7, poseidon8, poseidon9, poseidon10, poseidon11, poseidon12,
poseidon13, poseidon14, poseidon15, poseidon16
];

const poseidonFunc = poseidonFunctions[messageSize - 1];
if (!poseidonFunc) {
throw new Error(`No poseidon function available for message_size ${messageSize}`);
}
const result = poseidonFunc(bigIntInputs);

return {
values: ["0x" + result.toString(16)]
};

} catch (error) {
throw error;
}
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
"@aztec/bb.js": "^1.2.1",
"body-parser": "^1.20.2",
"cors": "^2.8.5",
"express": "^4.18.2"
"express": "^4.18.2",
"poseidon-lite": "^0.3.0"
},
"devDependencies": {
"@types/body-parser": "^1.19.2",
Expand Down
29 changes: 29 additions & 0 deletions scripts/build-brillig-report.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/usr/bin/env bash
set -e

INSPECTOR=${INSPECTOR:-noir-inspector}
cd $(dirname "$0")/../

artifacts_path="./export"
artifacts=$(ls $artifacts_path)

# Start the JSON array
REPORTS=$(jq --null-input '[]')

for artifact in $artifacts; do
# Get and format the opcode info
OP_CODE_INFO=$($INSPECTOR info --json "$artifacts_path/$artifact")

# Simplified jq expression to output only package_name and opcodes from unconstrained_functions
REPORTS=$(echo $OP_CODE_INFO | jq -c '.programs[0] | del(.functions)' | jq -c --argjson old_reports $REPORTS '$old_reports + [.]')
done

echo $REPORTS | jq '{ programs: . }' > brillig_report.json

# Convert brillig report to benchmark format
output_file_brillig="benchmark-brillig.json"
jq -r '[.programs[] | .unconstrained_functions[] | {
"name": (if (.package_name // "") == "" then .name else "\(.package_name | sub("^null/"; ""))/\(.name)" end),
"unit": "opcodes",
"value": (.opcodes // 0)
}]' brillig_report.json > $output_file_brillig
22 changes: 19 additions & 3 deletions scripts/build-gates-report.sh
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,22 @@ for artifact in $artifacts; do
ITER=$(( $ITER + 1 ))
done

echo "]}" >> gates_report.json


echo "]}" >> gates_report.json

# Convert the gates report into separate benchmark files
output_file_opcodes="benchmark-opcodes.json"
output_file_circuit="benchmark-circuit.json"

# Convert gates report - opcodes
jq -r '[.programs[] | {
"name": "\(.package_name)/main",
"unit": "acir_opcodes",
"value": (.functions[0].acir_opcodes // 0)
}]' gates_report.json > $output_file_opcodes

# Convert gates report - circuit size
jq -r '[.programs[] | {
"name": "\(.package_name)/main",
"unit": "circuit_size",
"value": (.functions[0].circuit_size // 0)
}]' gates_report.json > $output_file_circuit
2 changes: 1 addition & 1 deletion scripts/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ yarn build
echo "Starting TypeScript RPC server..."
yarn start &
TS_SERVER_PID=$!
trap 'kill $TS_SERVER_PID' EXIT
trap 'kill $TS_SERVER_PID 2>/dev/null || true' EXIT

# Wait for server to start
sleep 2
Expand Down
Loading
Loading