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

fix!: Barretenberg binaries now take in the encoded circuit instead of a json file #1618

Merged
merged 8 commits into from
Aug 18, 2023
Merged
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
6 changes: 3 additions & 3 deletions circuits/cpp/barretenberg/acir_tests/run_acir_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ function test() {
return
fi

if [[ ! -f ./$1/target/$dir_name.json || ! -f ./$1/target/witness.tr ]]; then
if [[ ! -f ./$1/target/$dir_name.bytecode || ! -f ./$1/target/witness.tr ]]; then
echo -e "\033[33mSKIPPED\033[0m (uncompiled)"
return
fi
Expand All @@ -49,9 +49,9 @@ function test() {

set +e
if [ -n "$VERBOSE" ]; then
$BB prove_and_verify -v -c $CRS_PATH -j ./target/$dir_name.json
$BB prove_and_verify -v -c $CRS_PATH -b ./target/$dir_name.bytecode
else
$BB prove_and_verify -c $CRS_PATH -j ./target/$dir_name.json > /dev/null 2>&1
$BB prove_and_verify -c $CRS_PATH -b ./target/$dir_name.bytecode > /dev/null 2>&1
fi
result=$?
set -e
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,9 @@

/**
* We can assume for now we're running on a unix like system and use the following to extract the bytecode.
* Maybe we should consider bytecode being output into its own independent file alongside the JSON?
*/
inline std::vector<uint8_t> get_bytecode(const std::string& jsonPath)
inline std::vector<uint8_t> get_bytecode(const std::string& bytecodePath)
{
std::string command =
"awk -F'\"bytecode\":' '{print $2}' " + jsonPath + " | awk -F'\"' '{print $2}' | base64 -d | gunzip";
std::string command = "base64 -d " + bytecodePath + " | gunzip";
return exec_pipe(command);
}
33 changes: 18 additions & 15 deletions circuits/cpp/barretenberg/cpp/src/barretenberg/bb/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,37 +30,40 @@ acir_format::WitnessVector get_witness(std::string const& witness_path)
return acir_format::witness_buf_to_witness_data(witness_data);
}

acir_format::acir_format get_constraint_system(std::string const& json_path)
acir_format::acir_format get_constraint_system(std::string const& bytecode_path)
{
auto bytecode = get_bytecode(json_path);
auto bytecode = get_bytecode(bytecode_path);
return acir_format::circuit_buf_to_acir_format(bytecode);
}

bool proveAndVerify(const std::string& jsonPath, const std::string& witnessPath, bool recursive)
bool proveAndVerify(const std::string& bytecodePath, const std::string& witnessPath, bool recursive)
{
auto acir_composer = new acir_proofs::AcirComposer(MAX_CIRCUIT_SIZE, verbose);
auto constraint_system = get_constraint_system(jsonPath);
auto constraint_system = get_constraint_system(bytecodePath);
auto witness = get_witness(witnessPath);
auto proof = acir_composer->create_proof(srs::get_crs_factory(), constraint_system, witness, recursive);
auto verified = acir_composer->verify_proof(proof, recursive);
info("verified: ", verified);
return verified;
}

void prove(const std::string& jsonPath, const std::string& witnessPath, bool recursive, const std::string& outputPath)
void prove(const std::string& bytecodePath,
const std::string& witnessPath,
bool recursive,
const std::string& outputPath)
{
auto acir_composer = new acir_proofs::AcirComposer(MAX_CIRCUIT_SIZE, verbose);
auto constraint_system = get_constraint_system(jsonPath);
auto constraint_system = get_constraint_system(bytecodePath);
auto witness = get_witness(witnessPath);
auto proof = acir_composer->create_proof(srs::get_crs_factory(), constraint_system, witness, recursive);
write_file(outputPath, proof);
info("proof written to: ", outputPath);
}

void gateCount(const std::string& jsonPath)
void gateCount(const std::string& bytecodePath)
{
auto acir_composer = new acir_proofs::AcirComposer(MAX_CIRCUIT_SIZE, verbose);
auto constraint_system = get_constraint_system(jsonPath);
auto constraint_system = get_constraint_system(bytecodePath);
acir_composer->create_circuit(constraint_system);
info("gates: ", acir_composer->get_total_circuit_size());
}
Expand All @@ -75,10 +78,10 @@ bool verify(const std::string& proof_path, bool recursive, const std::string& vk
return verified;
}

void writeVk(const std::string& jsonPath, const std::string& outputPath)
void writeVk(const std::string& bytecodePath, const std::string& outputPath)
{
auto acir_composer = new acir_proofs::AcirComposer(MAX_CIRCUIT_SIZE, verbose);
auto constraint_system = get_constraint_system(jsonPath);
auto constraint_system = get_constraint_system(bytecodePath);
acir_composer->init_proving_key(srs::get_crs_factory(), constraint_system);
auto vk = acir_composer->init_verification_key();
write_file(outputPath, to_buffer(*vk));
Expand Down Expand Up @@ -148,7 +151,7 @@ int main(int argc, char* argv[])

std::string command = args[0];

std::string json_path = getOption(args, "-j", "./target/main.json");
std::string bytecode_path = getOption(args, "-b", "./target/main.bytecode");
std::string witness_path = getOption(args, "-w", "./target/witness.tr");
std::string proof_path = getOption(args, "-p", "./proofs/proof");
std::string vk_path = getOption(args, "-k", "./target/vk");
Expand All @@ -157,20 +160,20 @@ int main(int argc, char* argv[])
init();

if (command == "prove_and_verify") {
return proveAndVerify(json_path, witness_path, recursive) ? 0 : 1;
return proveAndVerify(bytecode_path, witness_path, recursive) ? 0 : 1;
} else if (command == "prove") {
std::string output_path = getOption(args, "-o", "./proofs/proof");
prove(json_path, witness_path, recursive, output_path);
prove(bytecode_path, witness_path, recursive, output_path);
} else if (command == "gates") {
gateCount(json_path);
gateCount(bytecode_path);
} else if (command == "verify") {
verify(proof_path, recursive, vk_path);
} else if (command == "contract") {
std::string output_path = getOption(args, "-o", "./target/contract.sol");
contract(output_path, vk_path);
} else if (command == "write_vk") {
std::string output_path = getOption(args, "-o", "./target/vk");
writeVk(json_path, output_path);
writeVk(bytecode_path, output_path);
} else if (command == "proof_as_fields") {
std::string output_path = getOption(args, "-o", proof_path + "_fields.json");
proofAsFields(proof_path, vk_path, output_path);
Expand Down
1 change: 1 addition & 0 deletions circuits/cpp/barretenberg/ts/bin-test/target/main.bytecode
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
H4sIAAAAAAAA/+3YY4xkaRhA4e6xp8e2bavHtj2ztjG2bdu2bWttjm3P9uyp9OnNZP/uJrOb9E2enNxblU5V3qrvVn8dg4OCYgaFH9HtB5aHgqIgKqL5eIyg8OfHQmzEQVzEQ3wkQEKEIBESIwmSIhmSIwVSIhVSIw3SIh3SIwMyIhMyIwuyIhuyIwdyIhdyIw/yIh/yowAKohAKowiKohiKowRKohRKowzKohzKowJCURGVUBlVUBXVUB01UBO1UBt1UBf1UB8N0BCN0BhN0BTN0Bwt0BKt0Bpt0Bbt0B4d0BEv4EW8hJfxCl7Fa3gdb+BNvIW38Q7exXt431lGd5btnOuH+Agf4xN8ik7ojC7oim7ojh7oiV7ojT7oi37ojwEYiEEYjCEYimEYjhEYiVEYjTEYi3EYjwmYiEmYjCmYimmYjhmYiVmYjTmYi3mYjwVYiEVYjCVYimVYjhVYiVVYjTVYi3VYjw3YiE3YjC3Yim3Yjh3YiV3YjT3Yi33YjwM4iEM4jCM4imM4jhM4iVPOIYqzCByfeS3w/Qrx2hf4El/ha3yDb/EdvscP+BE/4Wf8gl/xG3737wW+qxGzPo0zOItzOI8LuIhLuIwruIpruI4buIlbuI07uIt7uI8HeIhHeIwn+ANheBoU/gaDEQVREQ3RESOw1iAWYiMO4iIe4iMBEiIEiZAYSZAUyZAcKZASqZAaaZAW6ZAeGZARmZAZWZAV2ZAdOZATuZAbeZAX+ZAfBVAQhVAYRVAUxVAcJVASpVAaZVAW5VAeFRAaHD7jwHr47Foa5vzDnHmYswpzboHGsDFtLBvbxrFxbTwb3yawCW2ITWQT2yQ2qU1mk9sUNqVNZVPbNDatTWfT2ww2o81kM9ssNqvNZrPbHDanzWVz2zw2r81n89sCtqAtZAvbIraoLWaL2xK2pC1lS9sytqwtZ8vbCjbUVrSVbGVbxVa11Wx1W8PWtLVsbVvH1rX1bH3bwDa0jWxj28Q2tc1sc9vCtrStbGvbxra17Wx728F2tC/YF+1L9mX7in3VvmZft2/YN+1b9m37jn3Xvmfftx888zoDx4eef2Q/tp/YT20n29l2sV1tN9vd9rA9bS/b2/axfW0/298OsAPtIDvYDrFD7TA73I6wI+0oO9qOsWPtODveTrAT7SQ72U6xU+00O93OsDPtLDvbzrFz7Tw73y6wC+0iu9gusUvtMrvcrrAr7Sq72q6xa+06u95usBvtJrvZbrFb7Ta73e6wO+0uu9vusXvtPrvfHrAH7SF72B6xR+0xe9yesCftKfvsb4/A+ef2rx8gFXlGJVRGFVRFNVRHDdRELdRGHdRFPdRHg8gbX+SNz4bayBtfeP9rN77Tnp+xZ+05e95esBftJXvZXrFX7TV73d6wN+0te9vesXftPXvfPrAP7SP72D6xEf+ARHhqAwtQoME2io1qo9noNoaNaWPZ2DaOjWvj2fg2gU1oQ2wim9gmsUltMpvcprApbSqb2qaxaW06m95msBltJpvZZrFZbTab3eawOW0um9vmsXltPpvfFrAFbSFb2BaxRW0xW9yWsCVtKVvalrFlbTlb3lawoRHzDwo//n7jC372xhe4UMlWtlVsVVvNVrc1bE1by9a2dWxdW8/Wtw0iPii+joacN0JjNEFTNENztEBLtEJrtEFbtEN7dAgOf8N+7iN374L+/7t3kbt1z2e3LrBQBBaJf7ojF7kD93x24CKOf2td/ROKWJ6DKhkAAA==
1 change: 0 additions & 1 deletion circuits/cpp/barretenberg/ts/bin-test/target/main.json

This file was deleted.

79 changes: 33 additions & 46 deletions circuits/cpp/barretenberg/ts/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,28 +11,15 @@ const debug = createDebug('bb.js');
// Maximum we support.
const MAX_CIRCUIT_SIZE = 2 ** 19;

function getJsonData(jsonPath: string) {
const json = readFileSync(jsonPath, 'utf-8');
const parsed = JSON.parse(json);
return parsed;
}

function getBytecode(jsonPath: string) {
const parsed = getJsonData(jsonPath);
const buffer = Buffer.from(parsed.bytecode, 'base64');
function getBytecode(bytecodePath: string) {
const encodedCircuit = readFileSync(bytecodePath, 'utf-8');
const buffer = Buffer.from(encodedCircuit, 'base64');
const decompressed = gunzipSync(buffer);
return decompressed;
}

async function getGates(jsonPath: string, api: BarretenbergApiAsync) {
const parsed = getJsonData(jsonPath);
if (parsed.gates) {
return +parsed.gates;
}
const { total } = await computeCircuitSize(jsonPath, api);
const jsonData = getJsonData(jsonPath);
jsonData.gates = total;
writeFileSync(jsonPath, JSON.stringify(jsonData));
async function getGates(bytecodePath: string, api: BarretenbergApiAsync) {
const { total } = await computeCircuitSize(bytecodePath, api);
return total;
}

Expand All @@ -42,17 +29,17 @@ function getWitness(witnessPath: string) {
return decompressed;
}

async function computeCircuitSize(jsonPath: string, api: BarretenbergApiAsync) {
async function computeCircuitSize(bytecodePath: string, api: BarretenbergApiAsync) {
debug(`computing circuit size...`);
const bytecode = getBytecode(jsonPath);
const bytecode = getBytecode(bytecodePath);
const [exact, total, subgroup] = await api.acirGetCircuitSizes(bytecode);
return { exact, total, subgroup };
}

async function init(jsonPath: string, crsPath: string) {
async function init(bytecodePath: string, crsPath: string) {
const api = await newBarretenbergApiAsync();

const circuitSize = await getGates(jsonPath, api);
const circuitSize = await getGates(bytecodePath, api);
const subgroupSize = Math.pow(2, Math.ceil(Math.log2(circuitSize)));
if (subgroupSize > MAX_CIRCUIT_SIZE) {
throw new Error(`Circuit size of ${subgroupSize} exceeds max supported of ${MAX_CIRCUIT_SIZE}`);
Expand Down Expand Up @@ -88,11 +75,11 @@ async function initLite() {
return { api, acirComposer };
}

export async function proveAndVerify(jsonPath: string, witnessPath: string, crsPath: string, isRecursive: boolean) {
const { api, acirComposer } = await init(jsonPath, crsPath);
export async function proveAndVerify(bytecodePath: string, witnessPath: string, crsPath: string, isRecursive: boolean) {
const { api, acirComposer } = await init(bytecodePath, crsPath);
try {
debug(`creating proof...`);
const bytecode = getBytecode(jsonPath);
const bytecode = getBytecode(bytecodePath);
const witness = getWitness(witnessPath);
const proof = await api.acirCreateProof(acirComposer, bytecode, witness, isRecursive);

Expand All @@ -106,16 +93,16 @@ export async function proveAndVerify(jsonPath: string, witnessPath: string, crsP
}

export async function prove(
jsonPath: string,
bytecodePath: string,
witnessPath: string,
crsPath: string,
isRecursive: boolean,
outputPath: string,
) {
const { api, acirComposer } = await init(jsonPath, crsPath);
const { api, acirComposer } = await init(bytecodePath, crsPath);
try {
debug(`creating proof...`);
const bytecode = getBytecode(jsonPath);
const bytecode = getBytecode(bytecodePath);
const witness = getWitness(witnessPath);
const proof = await api.acirCreateProof(acirComposer, bytecode, witness, isRecursive);
debug(`done.`);
Expand All @@ -127,10 +114,10 @@ export async function prove(
}
}

export async function gateCount(jsonPath: string) {
export async function gateCount(bytecodePath: string) {
const api = await newBarretenbergApiAsync(1);
try {
console.log(`gates: ${await getGates(jsonPath, api)}`);
console.log(`gates: ${await getGates(bytecodePath, api)}`);
} finally {
await api.destroy();
}
Expand Down Expand Up @@ -164,11 +151,11 @@ export async function contract(outputPath: string, vkPath: string) {
}
}

export async function writeVk(jsonPath: string, crsPath: string, outputPath: string) {
const { api, acirComposer } = await init(jsonPath, crsPath);
export async function writeVk(bytecodePath: string, crsPath: string, outputPath: string) {
const { api, acirComposer } = await init(bytecodePath, crsPath);
try {
debug('initing proving key...');
const bytecode = getBytecode(jsonPath);
const bytecode = getBytecode(bytecodePath);
await api.acirInitProvingKey(acirComposer, bytecode);

debug('initing verification key...');
Expand Down Expand Up @@ -231,34 +218,34 @@ function handleGlobalOptions() {
program
.command('prove_and_verify')
.description('Generate a proof and verify it. Process exits with success or failure code.')
.option('-j, --json-path <path>', 'Specify the JSON path', './target/main.json')
.option('-b, --bytecode-path <path>', 'Specify the bytecode path', './target/main.bytecode')
.option('-w, --witness-path <path>', 'Specify the witness path', './target/witness.tr')
.option('-r, --recursive', 'prove and verify using recursive prover and verifier', false)
.action(async ({ jsonPath, witnessPath, recursive, crsPath }) => {
.action(async ({ bytecodePath, witnessPath, recursive, crsPath }) => {
handleGlobalOptions();
const result = await proveAndVerify(jsonPath, witnessPath, crsPath, recursive);
const result = await proveAndVerify(bytecodePath, witnessPath, crsPath, recursive);
process.exit(result ? 0 : 1);
});

program
.command('prove')
.description('Generate a proof and write it to a file.')
.option('-j, --json-path <path>', 'Specify the JSON path', './target/main.json')
.option('-b, --bytecode-path <path>', 'Specify the bytecode path', './target/main.bytecode')
.option('-w, --witness-path <path>', 'Specify the witness path', './target/witness.tr')
.option('-r, --recursive', 'prove using recursive prover', false)
.option('-o, --output-path <path>', 'Specify the proof output path', './proofs/proof')
.action(async ({ jsonPath, witnessPath, recursive, outputPath, crsPath }) => {
.action(async ({ bytecodePath, witnessPath, recursive, outputPath, crsPath }) => {
handleGlobalOptions();
await prove(jsonPath, witnessPath, crsPath, recursive, outputPath);
await prove(bytecodePath, witnessPath, crsPath, recursive, outputPath);
});

program
.command('gates')
.description('Print gate count to standard output.')
.option('-j, --json-path <path>', 'Specify the JSON path', './target/main.json')
.action(async ({ jsonPath }) => {
.option('-b, --bytecode-path <path>', 'Specify the bytecode path', './target/main.bytecode')
.action(async ({ bytecodePath: bytecodePath }) => {
handleGlobalOptions();
await gateCount(jsonPath);
await gateCount(bytecodePath);
});

program
Expand All @@ -276,7 +263,7 @@ program
program
.command('contract')
.description('Output solidity verification key contract.')
.option('-j, --json-path <path>', 'Specify the JSON path', './target/main.json')
.option('-b, --bytecode-path <path>', 'Specify the bytecode path', './target/main.bytecode')
.option('-o, --output-path <path>', 'Specify the path to write the contract', '-')
.requiredOption('-k, --vk <path>', 'path to a verification key. avoids recomputation.')
.action(async ({ outputPath, vk }) => {
Expand All @@ -287,11 +274,11 @@ program
program
.command('write_vk')
.description('Output verification key.')
.option('-j, --json-path <path>', 'Specify the JSON path', './target/main.json')
.option('-b, --bytecode-path <path>', 'Specify the bytecode path', './target/main.bytecode')
.requiredOption('-o, --output-path <path>', 'Specify the path to write the key')
.action(async ({ jsonPath, outputPath, crsPath }) => {
.action(async ({ bytecodePath, outputPath, crsPath }) => {
handleGlobalOptions();
await writeVk(jsonPath, crsPath, outputPath);
await writeVk(bytecodePath, crsPath, outputPath);
});

program
Expand Down