Skip to content

Commit

Permalink
Merge 241508e into fccc9e5
Browse files Browse the repository at this point in the history
  • Loading branch information
Maddiaa0 authored Jul 25, 2024
2 parents fccc9e5 + 241508e commit 90ee64f
Show file tree
Hide file tree
Showing 20 changed files with 2,077 additions and 417 deletions.
17 changes: 17 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,21 @@ jobs:
timeout-minutes: 40
run: earthly-ci --no-output ./+barretenberg-acir-tests-sol

bb-acir-tests-sol-honk:
needs: [noir-build-acir-tests, changes]
runs-on: ${{ github.event.pull_request.user.login || github.actor }}-x86
if: ${{ needs.changes.outputs.barretenberg == 'true' || needs.changes.outputs.noir == 'true' }}
steps:
- uses: actions/checkout@v4
with: { ref: "${{ env.GIT_COMMIT }}" }
- uses: ./.github/ci-setup-action
with:
concurrency_key: barretenberg-acir-tests-sol-honk-x86
- name: "BB Solidity Acir Tests"
working-directory: ./barretenberg/
timeout-minutes: 40
run: earthly-ci --no-output ./+barretenberg-acir-tests-sol-honk

bb-acir-tests-bb-js:
needs: [noir-build-acir-tests, changes]
runs-on: ${{ github.event.pull_request.user.login || github.actor }}-x86
Expand Down Expand Up @@ -667,6 +682,7 @@ jobs:
- noir-build-acir-tests
- bb-acir-tests-bb
- bb-acir-tests-sol
- bb-acir-tests-sol-honk
- bb-acir-tests-bb-js
- noir-format
- noir-test
Expand Down Expand Up @@ -717,6 +733,7 @@ jobs:
- noir-build-acir-tests
- bb-acir-tests-bb
- bb-acir-tests-sol
- bb-acir-tests-sol-honk
- bb-acir-tests-bb-js
- noir-format
- noir-test
Expand Down
17 changes: 17 additions & 0 deletions barretenberg/Earthfile
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,23 @@ barretenberg-acir-tests-sol:
RUN (cd sol-test && yarn)
RUN PARALLEL=1 FLOW=sol ./run_acir_tests.sh assert_statement double_verify_proof double_verify_nested_proof

barretenberg-acir-tests-sol-honk:
FROM ../build-images/+from-registry

COPY ./cpp/+preset-sol/ /usr/src/barretenberg/cpp/build
COPY ./cpp/+preset-clang-assert/bin/bb /usr/src/barretenberg/cpp/build/bin/bb
COPY ./+acir-tests/ /usr/src/barretenberg/acir_tests
COPY ./+sol/ /usr/src/barretenberg/sol
COPY ../noir/+build-acir-tests/ /usr/src/acir_artifacts

WORKDIR /usr/src/barretenberg/acir_tests

ENV TEST_SRC /usr/src/acir_artifacts
ENV VERBOSE=1

RUN (cd sol-test && yarn)
RUN PARALLEL=1 FLOW=honk_sol ./run_acir_tests.sh assert_statement 1_mul slices

barretenberg-acir-tests-bb.js:
# Playwright not supported on base image ubuntu:noble, results in unmet dependencies
FROM ../build-images/+base-slim-node
Expand Down
22 changes: 22 additions & 0 deletions barretenberg/acir_tests/flows/honk_sol.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/bin/sh
set -eu

export PROOF="$(pwd)/proof"
export PROOF_AS_FIELDS="$(pwd)/proof_fields.json"

# Create a proof, write the solidity contract, write the proof as fields in order to extract the public inputs
$BIN prove_keccak_ultra_honk -o proof
$BIN write_vk_ultra_honk -o vk
$BIN proof_as_fields_honk -k vk -c $CRS_PATH -p $PROOF
$BIN contract_ultra_honk -k vk -c $CRS_PATH -b ./target/program.json -o Verifier.sol

# Export the paths to the environment variables for the js test runner
export VERIFIER_PATH="$(pwd)/Verifier.sol"
export TEST_PATH=$(realpath "../../sol-test/HonkTest.sol")
export TESTING_HONK="true"

# Use solcjs to compile the generated key contract with the template verifier and test contract
# index.js will start an anvil, on a random port
# Deploy the verifier then send a test transaction
export TEST_NAME=$(basename $(pwd))
node ../../sol-test/src/index.js
18 changes: 18 additions & 0 deletions barretenberg/acir_tests/sol-test/HonkTest.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// THIS FILE WILL NOT COMPILE BY ITSELF
// Compilation is handled in `src/index.js` where solcjs gathers the dependencies

pragma solidity >=0.8.4;

import {HonkVerifier} from "./Verifier.sol";

contract Test {
HonkVerifier verifier;

constructor() {
verifier = new HonkVerifier();
}

function test(bytes calldata proof, bytes32[] calldata publicInputs) view public returns(bool) {
return verifier.verify(proof, publicInputs);
}
}
77 changes: 59 additions & 18 deletions barretenberg/acir_tests/sol-test/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import { spawn } from "child_process";
import { ethers } from "ethers";
import solc from "solc";

const NUMBER_OF_FIELDS_IN_PROOF = 93;
const NUMBER_OF_FIELDS_IN_PLONK_PROOF = 93;
const NUMBER_OF_FIELDS_IN_HONK_PROOF = 393;

// We use the solcjs compiler version in this test, although it is slower than foundry, to run the test end to end
// it simplifies of parallelising the test suite
Expand All @@ -18,6 +19,14 @@ const NUMBER_OF_FIELDS_IN_PROOF = 93;
// 5. Run the test against the deployed contract
// 6. Kill the anvil instance

const getEnvVarCanBeUndefined = (envvar) => {
const varVal = process.env[envvar];
if (!varVal) {
return false;
}
return varVal;
};

const getEnvVar = (envvar) => {
const varVal = process.env[envvar];
if (!varVal) {
Expand All @@ -30,33 +39,23 @@ const getEnvVar = (envvar) => {
const testName = getEnvVar("TEST_NAME");

// Get solidity files, passed into environment from `flows/sol.sh`
const keyPath = getEnvVar("KEY_PATH");
const verifierPath = getEnvVar("VERIFIER_PATH");
const testPath = getEnvVar("TEST_PATH");
const basePath = getEnvVar("BASE_PATH");
const verifierPath = getEnvVar("VERIFIER_PATH");
const encoding = { encoding: "utf8" };
const [key, test, verifier, base] = await Promise.all([
fsPromises.readFile(keyPath, encoding),
const [test, verifier] = await Promise.all([
fsPromises.readFile(testPath, encoding),
fsPromises.readFile(verifierPath, encoding),
fsPromises.readFile(basePath, encoding),
]);

var input = {
export const compilationInput = {
language: "Solidity",
sources: {
"Key.sol": {
content: key,
},
"Test.sol": {
content: test,
},
"Verifier.sol": {
content: verifier,
},
"BaseUltraVerifier.sol": {
content: base,
},
},
settings: {
// we require the optimizer
Expand All @@ -72,7 +71,30 @@ var input = {
},
};

var output = JSON.parse(solc.compile(JSON.stringify(input)));
// If testing honk is set, then we compile the honk test suite
const testingHonk = getEnvVarCanBeUndefined("TESTING_HONK");
const NUMBER_OF_FIELDS_IN_PROOF = testingHonk ? NUMBER_OF_FIELDS_IN_HONK_PROOF : NUMBER_OF_FIELDS_IN_PLONK_PROOF;
if (!testingHonk) {

const keyPath = getEnvVar("KEY_PATH");
const basePath = getEnvVar("BASE_PATH");
const [key, base] = await Promise.all(
[
fsPromises.readFile(keyPath, encoding),
fsPromises.readFile(basePath, encoding),
]
);

compilationInput.sources["BaseUltraVerifier.sol"] = {
content: base,
};
compilationInput.sources["Key.sol"] = {
content: key,
};
}

var output = JSON.parse(solc.compile(JSON.stringify(compilationInput)));

const contract = output.contracts["Test.sol"]["Test"];
const bytecode = contract.evm.bytecode.object;
const abi = contract.abi;
Expand Down Expand Up @@ -127,8 +149,15 @@ const readPublicInputs = (proofAsFields) => {
const publicInputs = [];
// A proof with no public inputs is 93 fields long
const numPublicInputs = proofAsFields.length - NUMBER_OF_FIELDS_IN_PROOF;
let publicInputsOffset = 0;

// Honk proofs contain 3 pieces of metadata before the public inputs, while plonk does not
if (testingHonk) {
publicInputsOffset = 3;
}

for (let i = 0; i < numPublicInputs; i++) {
publicInputs.push(proofAsFields[i]);
publicInputs.push(proofAsFields[publicInputsOffset + i]);
}
return [numPublicInputs, publicInputs];
};
Expand Down Expand Up @@ -179,8 +208,20 @@ try {
const proofPath = getEnvVar("PROOF");
const proof = readFileSync(proofPath);

// Cut the number of public inputs off of the proof string
const proofStr = `0x${proof.toString("hex").substring(64 * numPublicInputs)}`;
// Cut the number of public inputs out of the proof string
let proofStr = proof.toString("hex");
if (testingHonk) {
// Cut off the serialised buffer size at start
proofStr = proofStr.substring(8);
// Get the part before and after the public inputs
const proofStart = proofStr.slice(0, 64 * 3);
const proofEnd = proofStr.substring((64 * 3) + (64 * numPublicInputs));
proofStr = proofStart + proofEnd;
} else {
proofStr = proofStr.substring(64 * numPublicInputs);
}

proofStr = "0x" + proofStr;

const key =
"0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80";
Expand Down
46 changes: 46 additions & 0 deletions barretenberg/cpp/src/barretenberg/bb/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,14 @@
#include "barretenberg/common/map.hpp"
#include "barretenberg/common/serialize.hpp"
#include "barretenberg/dsl/acir_format/acir_format.hpp"
#include "barretenberg/dsl/acir_proofs/honk_contract.hpp"
#include "barretenberg/honk/proof_system/types/proof.hpp"
#include "barretenberg/plonk/proof_system/proving_key/serialize.hpp"
#include "barretenberg/serialize/cbind.hpp"
#include "barretenberg/stdlib/honk_recursion/verifier/client_ivc_recursive_verifier.hpp"
#include "barretenberg/stdlib_circuit_builders/ultra_flavor.hpp"
#include "barretenberg/stdlib_circuit_builders/ultra_keccak.hpp"

#include <cstddef>
#ifndef DISABLE_AZTEC_VM
#include "barretenberg/vm/avm_trace/avm_common.hpp"
Expand Down Expand Up @@ -791,6 +795,40 @@ void contract(const std::string& output_path, const std::string& vk_path)
}
}

/**
* @brief Writes a Honk Solidity verifier contract for an ACIR circuit to a file
*
* Communication:
* - stdout: The Solidity verifier contract is written to stdout as a string
* - Filesystem: The Solidity verifier contract is written to the path specified by outputPath
*
* Note: The fact that the contract was computed is for an ACIR circuit is not of importance
* because this method uses the verification key to compute the Solidity verifier contract
*
* @param output_path Path to write the contract to
* @param vk_path Path to the file containing the serialized verification key
*/
void contract_honk(const std::string& output_path, const std::string& vk_path)
{
using VerificationKey = UltraFlavor::VerificationKey;
using VerifierCommitmentKey = bb::VerifierCommitmentKey<curve::BN254>;

auto g2_data = get_bn254_g2_data(CRS_PATH);
srs::init_crs_factory({}, g2_data);
auto vk = std::make_shared<VerificationKey>(from_buffer<VerificationKey>(read_file(vk_path)));
vk->pcs_verification_key = std::make_shared<VerifierCommitmentKey>();

std::string contract = get_honk_solidity_verifier(std::move(vk));

if (output_path == "-") {
writeStringToStdout(contract);
vinfo("contract written to stdout");
} else {
write_file(output_path, { contract.begin(), contract.end() });
vinfo("contract written to: ", output_path);
}
}

/**
* @brief Converts a proof from a byte array into a list of field elements
*
Expand Down Expand Up @@ -1360,6 +1398,9 @@ int main(int argc, char* argv[])
} else if (command == "contract") {
std::string output_path = get_option(args, "-o", "./target/contract.sol");
contract(output_path, vk_path);
} else if (command == "contract_ultra_honk") {
std::string output_path = get_option(args, "-o", "./target/contract.sol");
contract_honk(output_path, vk_path);
} else if (command == "write_vk") {
std::string output_path = get_option(args, "-o", "./target/vk");
write_vk(bytecode_path, output_path);
Expand Down Expand Up @@ -1390,8 +1431,13 @@ int main(int argc, char* argv[])
} else if (command == "prove_ultra_honk") {
std::string output_path = get_option(args, "-o", "./proofs/proof");
prove_honk<UltraFlavor>(bytecode_path, witness_path, output_path);
} else if (command == "prove_keccak_ultra_honk") {
std::string output_path = get_option(args, "-o", "./proofs/proof");
prove_honk<UltraKeccakFlavor>(bytecode_path, witness_path, output_path);
} else if (command == "verify_ultra_honk") {
return verify_honk<UltraFlavor>(proof_path, vk_path) ? 0 : 1;
} else if (command == "verify_keccak_ultra_honk") {
return verify_honk<UltraKeccakFlavor>(proof_path, vk_path) ? 0 : 1;
} else if (command == "write_vk_ultra_honk") {
std::string output_path = get_option(args, "-o", "./target/vk");
write_vk_honk<UltraFlavor>(bytecode_path, output_path);
Expand Down
Loading

0 comments on commit 90ee64f

Please sign in to comment.