Skip to content

Commit

Permalink
feat: add poseidon relations to UltraKeccak flavor and Solidity verif…
Browse files Browse the repository at this point in the history
…ier (#8243)

Add PoseidonRelation to UltraKeccak and reflect the changes in Solidity
verifier. This required :
- implementing the Poseidon relations in Solidity and port the Poseidon
parameters
- changing constants
-  adding the missing selectors in verification key
- regenerate the Lagrange denominators for the Barycentric evaluation
(Poseidon becomes the largest relation so the univariates in sumcheck
have length 8 rather than 7 so we need more precomputed stuff),
- removed hardcoded constants in Zeromorph to aid debugging when we
change the number of commitments again

Solidity verifier quirks: 
- moved the relations in a relation library and the transcript in a
transcript library which both have an external function because the
verifier contract became too big (this might get reverted when
optimising the contract)
- modified the Javascript test thingy that deploys the verifier contract
for flow tests. I had to separately deploy the two libraries link them
in the contract's bytecode and only then deploy the contract.

Also, now the ultra_honk_tests are typed and run both Ultra and
UltraKeccak flavor to have a way of debugging problems in proofs sent to
the Solidity contract at bberg level as well.

Closes:
AztecProtocol/barretenberg#1078
  • Loading branch information
maramihali authored Sep 6, 2024
1 parent a662fe3 commit f7e4bfb
Show file tree
Hide file tree
Showing 28 changed files with 1,996 additions and 4,352 deletions.
2 changes: 1 addition & 1 deletion barretenberg/acir_tests/flows/honk_sol.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ 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
# 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))
Expand Down
51 changes: 25 additions & 26 deletions barretenberg/acir_tests/sol-test/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ const { readFileSync, promises: fsPromises } = fs;
import { spawn } from "child_process";
import { ethers } from "ethers";
import solc from "solc";
import linker from "solc/linker.js";

const NUMBER_OF_FIELDS_IN_PLONK_PROOF = 93;
const NUMBER_OF_FIELDS_IN_HONK_PROOF = 393;
// This excludes the public inputs which are sent separately to the Solidity verifier
const NUMBER_OF_FIELDS_IN_HONK_PROOF = 423;

// 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 Down Expand Up @@ -73,28 +75,26 @@ export const compilationInput = {

// 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;
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,
};
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 @@ -133,7 +133,7 @@ const launchAnvil = async (port) => {
* Deploys the contract
* @param {ethers.Signer} signer
*/
const deploy = async (signer) => {
const deploy = async (signer, abi, bytecode) => {
const factory = new ethers.ContractFactory(abi, bytecode, signer);
const deployment = await factory.deploy();
const deployed = await deployment.waitForDeployment();
Expand All @@ -147,14 +147,14 @@ const deploy = async (signer) => {
*/
const readPublicInputs = (proofAsFields) => {
const publicInputs = [];
// A proof with no public inputs is 93 fields long
// Compute the number of public inputs, not accounted for in the constant NUMBER_OF_FIELDS_IN_PROOF
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[publicInputsOffset + i]);
Expand Down Expand Up @@ -215,7 +215,7 @@ try {
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));
const proofEnd = proofStr.substring(64 * 3 + 64 * numPublicInputs);
proofStr = proofStart + proofEnd;
} else {
proofStr = proofStr.substring(64 * numPublicInputs);
Expand All @@ -228,8 +228,7 @@ try {
const provider = await getProvider(randomPort);
const signer = new ethers.Wallet(key, provider);

// deploy
const address = await deploy(signer);
const address = await deploy(signer, abi, bytecode);
const contract = new ethers.Contract(address, abi, signer);

const result = await contract.test(proofStr, publicInputs);
Expand Down
3 changes: 1 addition & 2 deletions barretenberg/cpp/src/barretenberg/bb/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#include "barretenberg/serialize/cbind.hpp"
#include "barretenberg/stdlib/client_ivc_verifier/client_ivc_recursive_verifier.hpp"
#include "barretenberg/stdlib_circuit_builders/ultra_flavor.hpp"
#include "barretenberg/stdlib_circuit_builders/ultra_keccak.hpp"
#include "barretenberg/stdlib_circuit_builders/ultra_keccak_flavor.hpp"

#include <cstddef>
#ifndef DISABLE_AZTEC_VM
Expand Down Expand Up @@ -1085,7 +1085,6 @@ void prove_honk(const std::string& bytecodePath, const std::string& witnessPath,
// Construct Honk proof
Prover prover = compute_valid_prover<Flavor>(bytecodePath, witnessPath);
auto proof = prover.construct_proof();

if (outputPath == "-") {
writeRawBytesToStdout(to_buffer</*include_size=*/true>(proof));
vinfo("proof written to stdout");
Expand Down
Loading

0 comments on commit f7e4bfb

Please sign in to comment.