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

feat: Add separate report for public function bytecode sizes #8750

Merged
merged 7 commits into from
Sep 25, 2024
Merged
Show file tree
Hide file tree
Changes from 6 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
41 changes: 41 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -696,6 +696,47 @@ jobs:
delete: ${{ !steps.gates_diff.outputs.markdown }}
message: ${{ steps.gates_diff.outputs.markdown }}

public-functions-size-report:
needs: [build-images, changes]
if: needs.changes.outputs.non-docs == 'true' && needs.changes.outputs.non-misc-ci == 'true'
runs-on: ${{ github.event.pull_request.user.login || github.actor }}-x86
permissions:
pull-requests: write
steps:
- uses: actions/checkout@v4
with: { ref: "${{ env.GIT_COMMIT }}" }
# Only allow one memory-hunger prover test to use this runner
- uses: ./.github/ci-setup-action
with:
concurrency_key: public-functions-size-report-x86
- name: "Aztec Public Functions Bytecode Size Report"
working-directory: ./noir-projects/
timeout-minutes: 40
run: |
earthly-ci \
--artifact +public-functions-report/public_functions_report.json
mv public_functions_report.json ../public_functions_report.json

- name: Compare public functions bytecode size reports
id: public_functions_sizes_diff
uses: noir-lang/noir-gates-diff@ef8aaf48fb833f3b6e3f91665bb23afb7e68c6e3
with:
report: public_functions_report.json
header: |
# Changes to public function bytecode sizes
brillig_report: true
brillig_report_bytes: true
summaryQuantile: 0 # Display any diff in bytecode size count

- name: Add bytecode size diff to sticky comment
if: github.event_name == 'pull_request' || github.event_name == 'pull_request_target'
uses: marocchino/sticky-pull-request-comment@v2
with:
header: public_functions_size
# delete the comment in case changes no longer impact circuit sizes
delete: ${{ !steps.public_functions_sizes_diff.outputs.markdown }}
message: ${{ steps.public_functions_sizes_diff.outputs.markdown }}

merge-check:
runs-on: ubuntu-20.04
needs:
Expand Down
9 changes: 9 additions & 0 deletions noir-projects/Earthfile
Original file line number Diff line number Diff line change
Expand Up @@ -124,3 +124,12 @@ gates-report:
RUN ./gates_report.sh

SAVE ARTIFACT ./noir-protocol-circuits/gates_report.json gates_report.json

public-functions-report:
FROM +build-contracts
WORKDIR /usr/src/noir-projects

RUN cd noir-contracts && node publicFunctionsSizeReport.js ./target/

SAVE ARTIFACT ./noir-contracts/public_functions_report.json public_functions_report.json

74 changes: 74 additions & 0 deletions noir-projects/noir-contracts/publicFunctionsSizeReport.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
const path = require("path");
const fs = require("fs");
const fsp = require("fs").promises;

// Simple script to extract the exact bytecode size of a contracts public functions.
// The output of this script is meant to be used with the noir-lang/noir-gates-diff project.
// The noir-gates-diff was made for comparing ACIR/Brillig opcodes.
// However, this script was made to re-use the noir-gates-diff for bytecode sizes as
// to minimize both the amount of changes needed in noir-gates-diff and in nargo.
async function main() {

let [targetDir] = process.argv.slice(2);
if (!targetDir) {
console.log(
"Usage: node extractPublicFunctionsAsNoirArtifacts.js <targetDir>"
);
return;
}

let artifactPaths = [];
fs.readdirSync(targetDir).forEach(file => {
// We want to exclude any backups that may be generated by the avm-transpiler
if (path.extname(file) === ".json") {
artifactPaths.push(path.join(targetDir, file));
}
});

let workspaceReport = {
programs: []
}
for (var i = 0; i < artifactPaths.length; i++) {
let contractArtifactPath = artifactPaths[i];
const contractArtifact = JSON.parse(
await fsp.readFile(contractArtifactPath, "utf8")
);
contractArtifact.functions.forEach(async func => {
if (func.custom_attributes.includes("public")) {
if (func.brillig_names.length != 1) {
console.log(
"Expected only a single Brillig function"
);
return;
}
let func_with_contract_name = contractArtifact.name + "::" + func.brillig_names[0];
let program_report = {
package_name: "",
functions: [{ name: "main", opcodes: 1 }],
unconstrained_functions: [],
}
// Programs are compared by package name, so we make a unique one for each function here
program_report.package_name = func_with_contract_name;
let bytecode_bytes = Buffer.from(func.bytecode, 'base64');
let func_report = {
name: "main",
opcodes: bytecode_bytes,
};
func_report.opcodes = bytecode_bytes.length;
program_report.unconstrained_functions.push(func_report);
workspaceReport.programs.push(program_report);
}
});
}

const outPath = path.join("public_functions_report.json");
// console.log(outPath);

console.log(`Writing to ${outPath}`);
await fsp.writeFile(outPath, JSON.stringify(workspaceReport, null, 2));
}

main().catch((err) => {
console.error(err);
process.exit(1);
});
Loading