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 verify proof calls to private kernels #10533

Merged
merged 17 commits into from
Dec 11, 2024
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
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
Loading