Skip to content

Commit

Permalink
feat: Add verify proof calls to private kernels (#10533)
Browse files Browse the repository at this point in the history
Co-authored-by: ledwards2225 <[email protected]>
  • Loading branch information
2 people authored and lucasxia01 committed Dec 11, 2024
1 parent d79abdf commit c3d9fd7
Show file tree
Hide file tree
Showing 21 changed files with 80 additions and 63 deletions.
2 changes: 1 addition & 1 deletion aztec-nargo/compile_then_postprocess.sh
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ for artifact in $artifacts_to_process; do

echo "Generating verification key for function $fn_name"
# BB outputs the verification key to stdout as raw bytes, however, we need to base64 encode it before storing it in the artifact
verification_key=$($BB write_vk_mega_honk -h -b ${fn_artifact_path} -o - | base64)
verification_key=$($BB write_vk_for_ivc -h -b ${fn_artifact_path} -o - | base64)
rm $fn_artifact_path
jq ".functions[$fn_index].verification_key = \"$verification_key\"" $artifact > $artifact.tmp
mv $artifact.tmp $artifact
Expand Down
2 changes: 1 addition & 1 deletion barretenberg/cpp/src/barretenberg/constants.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ static constexpr uint32_t CONST_PG_LOG_N = 20;

static constexpr uint32_t CONST_ECCVM_LOG_N = 15;

static constexpr uint32_t MAX_LOOKUP_TABLES_SIZE = 70000;
static constexpr uint32_t MAX_LOOKUP_TABLES_SIZE = 75000;

static constexpr uint32_t MAX_DATABUS_SIZE = 10000;
} // namespace bb
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ void construct_lookup_table_polynomials(const RefArray<typename Flavor::Polynomi
// ignored, as used for regular constraints and padding to the next power of 2.
// TODO(https://github.com/AztecProtocol/barretenberg/issues/1033): construct tables and counts at top of trace
const size_t tables_size = circuit.get_tables_size();
ASSERT(tables_size <= MAX_LOOKUP_TABLES_SIZE); // if false, may need to increase constant
ASSERT(dyadic_circuit_size > tables_size + additional_offset);
size_t offset = dyadic_circuit_size - tables_size - additional_offset;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,10 @@ template <typename T> struct SharedShiftedVirtualZeroesArray {

T& operator[](size_t index)
{
ASSERT(index >= start_ && index < end_);
if (index < start_ || index >= end_) {
vinfo("index = ", index, ", start_ = ", start_, ", end_ = ", end_);
ASSERT(false);
}
return data()[index - start_];
}
// get() is more useful, but for completeness with the non-const operator[]
Expand Down
3 changes: 1 addition & 2 deletions noir-projects/Earthfile
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@ source:
COPY package.json yarn.lock .
RUN yarn

COPY mega_honk_circuits.json .
COPY ivc_integration_circuits.json .
COPY client_ivc_circuits.json .
COPY --dir aztec-nr noir-contracts noir-protocol-circuits mock-protocol-circuits scripts .

build-contracts:
Expand Down
8 changes: 8 additions & 0 deletions noir-projects/client_ivc_circuits.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[
"private_kernel_init",
"private_kernel_inner",
"private_kernel_reset.*",
"private_kernel_tail.*",
"app_creator",
"app_reader"
]
6 changes: 3 additions & 3 deletions noir-projects/gates_report.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ set -eu
# The script needs some slight updating as `nargo info` expects a complete JSON object, while this script expects a single object field
# representing a list of circuit reports for a program.
# The ACIR tests in barretenberg also expect every target bytecode to have the name `acir.gz` while this script expects the same name of the package
MEGA_HONK_CIRCUIT_PATTERNS=$(jq -r '.[]' mega_honk_circuits.json)
MEGA_HONK_CIRCUIT_PATTERNS=$(jq -r '.[]' client_ivc_circuits.json)

cd noir-protocol-circuits
PROTOCOL_CIRCUITS_DIR=$PWD
Expand All @@ -31,13 +31,13 @@ for pathname in "$PROTOCOL_CIRCUITS_DIR/target"/*.json; do
fi
done

# If it's mega honk, we need to use the gates_mega_honk command
# If it's mega honk, we need to use the gates_mega_honk command
if [ "$IS_MEGA_HONK_CIRCUIT" = "true" ]; then
GATES_INFO=$($BB_BIN gates_mega_honk -h -b "$pathname")
else
GATES_INFO=$($BB_BIN gates -h -b "$pathname")
fi

MAIN_FUNCTION_INFO=$(echo $GATES_INFO | jq -r '.functions[0] | .name = "main"')
echo "{\"package_name\": \"$ARTIFACT_NAME\", \"functions\": [$MAIN_FUNCTION_INFO]" >> gates_report.json

Expand Down
8 changes: 0 additions & 8 deletions noir-projects/ivc_integration_circuits.json

This file was deleted.

6 changes: 0 additions & 6 deletions noir-projects/mega_honk_circuits.json

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ async function generateVkForFunction(functionArtifact, outputFolder) {
);

try {
const writeVkCommand = `${BB_BIN_PATH} write_vk_mega_honk -h -b "${functionArtifactPath}" -o "${outputVkPath}" `;
const writeVkCommand = `${BB_BIN_PATH} write_vk_for_ivc -h -b "${functionArtifactPath}" -o "${outputVkPath}" `;

console.log("WRITE VK CMD: ", writeVkCommand);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ impl PrivateKernelInitCircuitPrivateInputs {
}

pub fn execute(self) -> PrivateKernelCircuitPublicInputs {
if !std::runtime::is_unconstrained() {
self.private_call.verify(true);
}

// Generate output.
let output = unsafe { self.generate_output() };

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ impl PrivateKernelInnerCircuitPrivateInputs {
}

pub fn execute(self) -> PrivateKernelCircuitPublicInputs {
if !std::runtime::is_unconstrained() {
self.previous_kernel.verify();
self.private_call.verify(false);
}

// Generate output.
let output = unsafe { self.generate_output() };

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ impl<let NH_RR_PENDING: u32, let NH_RR_SETTLED: u32, let NLL_RR_PENDING: u32, le
nullifier_siloing_amount: u32,
private_log_siloing_amount: u32,
) -> PrivateKernelCircuitPublicInputs {
if !std::runtime::is_unconstrained() {
self.previous_kernel.verify();
}

let previous_public_inputs = self.previous_kernel.public_inputs;
let validation_request_processor = PrivateValidationRequestProcessor {
validation_requests: previous_public_inputs.validation_requests,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ impl PrivateKernelTailCircuitPrivateInputs {
}

pub fn execute(self) -> KernelCircuitPublicInputs {
if !std::runtime::is_unconstrained() {
self.previous_kernel.verify();
}
// Generate output.
let output = unsafe { self.generate_output() };

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ impl PrivateKernelTailToPublicCircuitPrivateInputs {
}

pub fn execute(self) -> PrivateToPublicKernelCircuitPublicInputs {
if !std::runtime::is_unconstrained() {
self.previous_kernel.verify();
}
// Generate output.
let output = unsafe { self.generate_output() };

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use crate::{
abis::private_circuit_public_inputs::PrivateCircuitPublicInputs,
address::SaltedInitializationHash,
constants::{FUNCTION_TREE_HEIGHT, PROTOCOL_CONTRACT_TREE_HEIGHT},
constants::{
FUNCTION_TREE_HEIGHT, PROOF_TYPE_OINK, PROOF_TYPE_PG, PROTOCOL_CONTRACT_TREE_HEIGHT,
},
merkle_tree::membership::MembershipWitness,
proof::verification_key::ClientIVCVerificationKey,
public_keys::PublicKeys,
Expand All @@ -22,6 +24,18 @@ pub struct PrivateCallData {
pub acir_hash: Field,
}

impl PrivateCallData {
fn verify(self, is_first_app: bool) {
let proof_type = if is_first_app {
PROOF_TYPE_OINK
} else {
PROOF_TYPE_PG
};
// Client IVC public inputs are linked in the backend via the databus
std::verify_proof_with_type(self.vk.key, [], [], 0, proof_type);
}
}

pub struct PrivateCallDataWithoutPublicInputs {
pub vk: ClientIVCVerificationKey,

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use crate::{
abis::kernel_circuit_public_inputs::PrivateKernelCircuitPublicInputs,
constants::{PRIVATE_KERNEL_RESET_INDEX, VK_TREE_HEIGHT},
constants::{PRIVATE_KERNEL_RESET_INDEX, PROOF_TYPE_PG, VK_TREE_HEIGHT},
merkle_tree::membership::assert_check_membership,
proof::verification_key::ClientIVCVerificationKey,
proof::{traits::Verifiable, verification_key::ClientIVCVerificationKey},
utils::arrays::find_index_hint,
};

Expand Down Expand Up @@ -38,6 +38,13 @@ impl PrivateKernelData {
}
}

impl Verifiable for PrivateKernelData {
fn verify(self) {
// Client IVC public inputs are linked in the backend via the databus
std::verify_proof_with_type(self.vk.key, [], [], 0, PROOF_TYPE_PG);
}
}

pub struct PrivateKernelDataWithoutPublicInputs {
vk: ClientIVCVerificationKey,
vk_index: u32,
Expand Down
2 changes: 1 addition & 1 deletion noir-projects/noir-protocol-circuits/scripts/flamegraph.sh
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ fi
DEST="$SCRIPT_DIR/../dest"
mkdir -p $DEST

MEGA_HONK_CIRCUIT_PATTERNS=$(jq -r '.[]' "$SCRIPT_DIR/../../mega_honk_circuits.json")
MEGA_HONK_CIRCUIT_PATTERNS=$(jq -r '.[]' "$SCRIPT_DIR/../../client_ivc_circuits.json")

# Process each CIRCUIT_NAME.
for CIRCUIT_NAME in "${CIRCUIT_NAMES[@]}"; do
Expand Down
47 changes: 13 additions & 34 deletions noir-projects/scripts/generate_vk_json.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ const fs = require("fs/promises");
const child_process = require("child_process");
const crypto = require("crypto");

const megaHonkPatterns = require("../mega_honk_circuits.json");
const ivcIntegrationPatterns = require("../ivc_integration_circuits.json");
const clientIvcPatterns = require("../client_ivc_circuits.json");
const {
readVKFromS3,
writeVKToS3,
Expand Down Expand Up @@ -33,19 +32,13 @@ async function getBytecodeHash(artifactPath) {
return crypto.createHash("md5").update(bytecode).digest("hex");
}

async function getArtifactHash(
artifactPath,
isMegaHonk,
isIvcIntegration,
isRecursive
) {
async function getArtifactHash(artifactPath, isClientIvc, isRecursive) {
const bytecodeHash = await getBytecodeHash(artifactPath);
const barretenbergHash = await getBarretenbergHash();
return generateArtifactHash(
barretenbergHash,
bytecodeHash,
isMegaHonk,
isIvcIntegration,
isClientIvc,
isRecursive
);
}
Expand All @@ -68,26 +61,19 @@ async function hasArtifactHashChanged(artifactHash, vkDataPath) {
return true;
}

function isMegaHonkCircuit(artifactName) {
return megaHonkPatterns.some((pattern) =>
artifactName.match(new RegExp(pattern))
);
}
function isIvcIntegrationCircuit(artifactName) {
return ivcIntegrationPatterns.some((pattern) =>
function isClientIvcCircuit(artifactName) {
return clientIvcPatterns.some((pattern) =>
artifactName.match(new RegExp(pattern))
);
}

async function processArtifact(artifactPath, artifactName, outputFolder) {
const isMegaHonk = isMegaHonkCircuit(artifactName);
const isIvcIntegration = isIvcIntegrationCircuit(artifactName);
const isClientIvc = isClientIvcCircuit(artifactName);
const isRecursive = true;

const artifactHash = await getArtifactHash(
artifactPath,
isMegaHonk,
isIvcIntegration,
isClientIvc,
isRecursive
);

Expand All @@ -106,8 +92,7 @@ async function processArtifact(artifactPath, artifactName, outputFolder) {
outputFolder,
artifactPath,
artifactHash,
isMegaHonk,
isIvcIntegration,
isClientIvc,
isRecursive
);
await writeVKToS3(artifactName, artifactHash, JSON.stringify(vkData));
Expand All @@ -123,14 +108,11 @@ async function generateVKData(
outputFolder,
artifactPath,
artifactHash,
isMegaHonk,
isIvcIntegration,
isClientIvc,
isRecursive
) {
if (isMegaHonk) {
console.log("Generating new mega honk vk for", artifactName);
} else if (isIvcIntegration) {
console.log("Generating new IVC vk for", artifactName);
if (isClientIvc) {
console.log("Generating new client ivc vk for", artifactName);
} else {
console.log("Generating new vk for", artifactName);
}
Expand All @@ -142,8 +124,7 @@ async function generateVKData(
const jsonVkPath = vkJsonFileNameForArtifactName(outputFolder, artifactName);

function getVkCommand() {
if (isMegaHonk) return "write_vk_mega_honk";
if (isIvcIntegration) return "write_vk_for_ivc";
if (isClientIvc) return "write_vk_for_ivc";
return "write_vk_ultra_honk";
}

Expand All @@ -154,9 +135,7 @@ async function generateVKData(
console.log("WRITE VK CMD: ", writeVkCommand);

const vkAsFieldsCommand = `${BB_BIN_PATH} ${
isMegaHonk || isIvcIntegration
? "vk_as_fields_mega_honk"
: "vk_as_fields_ultra_honk"
isClientIvc ? "vk_as_fields_mega_honk" : "vk_as_fields_ultra_honk"
} -k "${binaryVkPath}" -o "${jsonVkPath}"`;

await new Promise((resolve, reject) => {
Expand Down
4 changes: 2 additions & 2 deletions noir-projects/scripts/verification_keys.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,11 @@ function generateS3Client() {
function generateArtifactHash(
barretenbergHash,
bytecodeHash,
isMegaHonk,
isClientIvc,
isRecursive
) {
return `${barretenbergHash}-${bytecodeHash}-${
isMegaHonk ? "mega-honk" : "ultra-honk"
isClientIvc ? "client-ivc" : "ultra-honk"
}-${isRecursive}`;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ export class BBNativePrivateKernelProver implements PrivateKernelProver {
path.join(directory, 'acir.msgpack'),
path.join(directory, 'witnesses.msgpack'),
this.log.info,
true,
);

if (provingResult.status === BB_RESULT.FAILURE) {
Expand Down

0 comments on commit c3d9fd7

Please sign in to comment.