Skip to content
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
10 changes: 7 additions & 3 deletions barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ std::pair<ClientIVC::PairingPoints, ClientIVC::TableCommitments> ClientIVC::
merge_commitments.T_prev_commitments = T_prev_commitments;

switch (verifier_inputs.type) {
case QUEUE_TYPE::PG_TAIL:
case QUEUE_TYPE::PG: {
// Construct stdlib verifier accumulator from the native counterpart computed on a previous round
auto stdlib_verifier_accum = std::make_shared<RecursiveDeciderVerificationKey>(&circuit, verifier_accumulator);
Expand All @@ -127,6 +128,7 @@ std::pair<ClientIVC::PairingPoints, ClientIVC::TableCommitments> ClientIVC::

break;
}

case QUEUE_TYPE::OINK: {
// Construct an incomplete stdlib verifier accumulator from the corresponding stdlib verification key
auto verifier_accum =
Expand Down Expand Up @@ -338,12 +340,14 @@ void ClientIVC::accumulate(ClientCircuit& circuit,
fold_output = folding_prover.prove();
vinfo("constructed folding proof");

// If this is the final circuit to be folded, set queue entry type to PG_FINAL and run the decider prover
bool is_final_fold = (num_circuits_accumulated == num_circuits - 1);
if (is_final_fold) {
if (num_circuits_accumulated == num_circuits - 1) {
// we are folding in the "Tail" kernel, so the verification_queue entry should have type PG_FINAL
queue_entry.type = QUEUE_TYPE::PG_FINAL;
decider_proof = decider_prove();
vinfo("constructed decider proof");
} else if (num_circuits_accumulated == num_circuits - 2) {
// we are folding in the "Inner/Reset" kernel, so the verification_queue entry should have type PG_TAIL
queue_entry.type = QUEUE_TYPE::PG_TAIL;
} else {
queue_entry.type = QUEUE_TYPE::PG;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ class ClientIVC {
MSGPACK_FIELDS(mega, eccvm, translator);
};

enum class QUEUE_TYPE { OINK, PG, PG_FINAL }; // for specifying type of proof in the verification queue
enum class QUEUE_TYPE { OINK, PG, PG_FINAL, PG_TAIL }; // for specifying type of proof in the verification queue

// An entry in the native verification queue
struct VerifierInputs {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -749,6 +749,7 @@ void handle_blackbox_func_call(Acir::Opcode::BlackBoxFuncCall const& arg, AcirFo
break;
case OINK:
case PG:
case PG_TAIL:
case PG_FINAL:
af.ivc_recursion_constraints.push_back(c);
af.original_opcode_indices.ivc_recursion_constraints.push_back(opcode_index);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ std::shared_ptr<ClientIVC> create_mock_ivc_from_constraints(const std::vector<Re
uint32_t oink_type = static_cast<uint32_t>(PROOF_TYPE::OINK);
uint32_t pg_type = static_cast<uint32_t>(PROOF_TYPE::PG);
uint32_t pg_final_type = static_cast<uint32_t>(PROOF_TYPE::PG_FINAL);
uint32_t pg_tail_type = static_cast<uint32_t>(PROOF_TYPE::PG_TAIL);

// There is a fixed set of valid combinations of IVC recursion constraints for Aztec kernel circuits:

Expand All @@ -55,13 +56,20 @@ std::shared_ptr<ClientIVC> create_mock_ivc_from_constraints(const std::vector<Re
return ivc;
}

// Case: RESET or TAIL kernel; single PG recursive verification of a kernel
// Case: RESET kernel; single PG recursive verification of a kernel
if (constraints.size() == 1 && constraints[0].proof_type == pg_type) {
ivc->verifier_accumulator = create_mock_decider_vk<ClientIVC::Flavor>();
mock_ivc_accumulation(ivc, ClientIVC::QUEUE_TYPE::PG, /*is_kernel=*/true);
return ivc;
}

// Case: TAIL kernel; single PG recursive verification of a kernel
if (constraints.size() == 1 && constraints[0].proof_type == pg_tail_type) {
ivc->verifier_accumulator = create_mock_decider_vk<ClientIVC::Flavor>();
mock_ivc_accumulation(ivc, ClientIVC::QUEUE_TYPE::PG_TAIL, /*is_kernel=*/true);
return ivc;
}

// Case: INNER kernel; two PG recursive verifications, kernel and app in that order
if (constraints.size() == 2) {
BB_ASSERT_EQ(constraints[0].proof_type, pg_type);
Expand Down Expand Up @@ -120,6 +128,7 @@ ClientIVC::VerifierInputs create_mock_verification_queue_entry(const ClientIVC::
break;
case ClientIVC::QUEUE_TYPE::PG:
case ClientIVC::QUEUE_TYPE::PG_FINAL:
case ClientIVC::QUEUE_TYPE::PG_TAIL:
proof = create_mock_pg_proof<Flavor, KernelIO>();
break;
default:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,9 @@ class IvcRecursionConstraintTest : public ::testing::Test {
case QUEUE_TYPE::PG_FINAL:
proof_type = PG_FINAL;
break;
case QUEUE_TYPE::PG_TAIL:
proof_type = PG_TAIL;
break;
default:
throw std::runtime_error("Invalid proof type");
}
Expand Down Expand Up @@ -254,7 +257,8 @@ TEST_F(IvcRecursionConstraintTest, AccumulateTwo)
TEST_F(IvcRecursionConstraintTest, AccumulateFour)
{
TraceSettings trace_settings{ SMALL_TEST_STRUCTURE };
auto ivc = std::make_shared<ClientIVC>(/*num_circuits=*/4, trace_settings);
// 4 ciruits and the tail kernel
auto ivc = std::make_shared<ClientIVC>(/*num_circuits=*/5, trace_settings);

// construct a mock app_circuit
Builder app_circuit_0 = construct_mock_app_circuit(ivc);
Expand All @@ -278,6 +282,12 @@ TEST_F(IvcRecursionConstraintTest, AccumulateFour)
EXPECT_TRUE(CircuitChecker::check(kernel_1));
ivc->accumulate(kernel_1);

// Now we add the tail kernel
EXPECT_EQ(ivc->verification_queue.size(), 1);
EXPECT_EQ(ivc->verification_queue[0].type, QUEUE_TYPE::PG_TAIL);
AcirProgram tail_program = construct_mock_kernel_program(ivc->verification_queue);
Builder tail_kernel = acir_format::create_circuit<Builder>(tail_program, metadata);
ivc->accumulate(tail_kernel, construct_kernel_vk_from_acir_program(tail_program, trace_settings));
EXPECT_TRUE(ivc->prove_and_verify());
}

Expand Down Expand Up @@ -345,7 +355,7 @@ TEST_F(IvcRecursionConstraintTest, GenerateResetKernelVKFromConstraints)

{ // Construct and accumulate a mock RESET/TAIL kernel (PG recursion for kernel accumulation)
EXPECT_TRUE(ivc->verification_queue.size() == 1);
EXPECT_TRUE(ivc->verification_queue[0].type == bb::ClientIVC::QUEUE_TYPE::PG);
EXPECT_TRUE(ivc->verification_queue[0].type == bb::ClientIVC::QUEUE_TYPE::PG_TAIL);
AcirProgram program = construct_mock_kernel_program(ivc->verification_queue);
Builder kernel = acir_format::create_circuit<Builder>(program, metadata);
ivc->accumulate(kernel);
Expand Down Expand Up @@ -379,7 +389,9 @@ TEST_F(IvcRecursionConstraintTest, GenerateInnerKernelVKFromConstraints)
// First, construct the kernel VK by running the full IVC (accumulate one app and one kernel)
std::shared_ptr<MegaFlavor::VerificationKey> expected_kernel_vk;
{
auto ivc = std::make_shared<ClientIVC>(/*num_circuits=*/4, trace_settings);
// we have to set the number of circuits one more than the number of circuits we're accumulating as otherwise
// the last circuit will be seen as a tail
auto ivc = std::make_shared<ClientIVC>(/*num_circuits=*/5, trace_settings);

const ProgramMetadata metadata{ ivc };

Expand All @@ -401,7 +413,6 @@ TEST_F(IvcRecursionConstraintTest, GenerateInnerKernelVKFromConstraints)

{ // Construct and accumulate a mock INNER kernel (PG recursion for kernel accumulation)
EXPECT_TRUE(ivc->verification_queue.size() == 2);
EXPECT_TRUE(ivc->verification_queue[0].type == bb::ClientIVC::QUEUE_TYPE::PG);
EXPECT_TRUE(ivc->verification_queue[1].type == bb::ClientIVC::QUEUE_TYPE::PG);
AcirProgram program = construct_mock_kernel_program(ivc->verification_queue);
Builder kernel = acir_format::create_circuit<Builder>(program, metadata);
Expand Down Expand Up @@ -455,7 +466,7 @@ TEST_F(IvcRecursionConstraintTest, GenerateHidingKernelVKFromConstraints)

{ // Construct and accumulate a mock TAIL kernel (PG recursion for kernel accumulation)
EXPECT_TRUE(ivc->verification_queue.size() == 1);
EXPECT_TRUE(ivc->verification_queue[0].type == bb::ClientIVC::QUEUE_TYPE::PG);
EXPECT_TRUE(ivc->verification_queue[0].type == bb::ClientIVC::QUEUE_TYPE::PG_TAIL);
AcirProgram program = construct_mock_kernel_program(ivc->verification_queue);
Builder kernel = acir_format::create_circuit<Builder>(program, metadata);
ivc->accumulate(kernel);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ namespace acir_format {
// ACIR
// Keep this enum values in sync with their noir counterpart constants defined in
// noir-protocol-circuits/crates/types/src/constants.nr
enum PROOF_TYPE { PLONK, HONK, OINK, PG, AVM, ROLLUP_HONK, ROOT_ROLLUP_HONK, HONK_ZK, PG_FINAL };
enum PROOF_TYPE { PLONK, HONK, OINK, PG, AVM, ROLLUP_HONK, ROOT_ROLLUP_HONK, HONK_ZK, PG_FINAL, PG_TAIL };

/**
* @brief RecursionConstraint struct contains information required to recursively verify a proof!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,13 @@ impl PreviousKernelValidator {
PreviousKernelValidator { previous_kernel }
}

pub fn verify_proof<let N: u32>(self: Self, allowed_indices: [u32; N]) {
pub fn verify_proof<let N: u32>(
self: Self,
allowed_indices: [u32; N],
is_last_inner_kernel: bool,
) {
if !dep::std::runtime::is_unconstrained() {
self.previous_kernel.verify();
self.previous_kernel.verify(is_last_inner_kernel);
self.previous_kernel.validate_vk_in_vk_tree(allowed_indices);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ impl PrivateKernelInnerCircuitPrivateInputs {

let previous_kernel_validator = PreviousKernelValidator::new(self.previous_kernel);

previous_kernel_validator.verify_proof(ALLOWED_PREVIOUS_CIRCUITS);
previous_kernel_validator.verify_proof(ALLOWED_PREVIOUS_CIRCUITS, false);

let private_call_data_validator = PrivateCallDataValidator::new(self.private_call);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ impl<let NH_RR_PENDING: u32, let NH_RR_SETTLED: u32, let NLL_RR_PENDING: u32, le
// Validate inputs.
let previous_kernel_validator = PreviousKernelValidator::new(self.previous_kernel);

previous_kernel_validator.verify_proof(ALLOWED_PREVIOUS_CIRCUITS);
previous_kernel_validator.verify_proof(ALLOWED_PREVIOUS_CIRCUITS, false);

// Generate output.
// Safety: The output is validated below by ResetOutputValidator.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ impl PrivateKernelTailCircuitPrivateInputs {
// Validate inputs.
let mut previous_kernel_validator = PreviousKernelValidator::new(self.previous_kernel);

previous_kernel_validator.verify_proof(ALLOWED_PREVIOUS_CIRCUITS);
previous_kernel_validator.verify_proof(ALLOWED_PREVIOUS_CIRCUITS, true);

previous_kernel_validator.validate_for_private_tail();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ impl PrivateKernelTailToPublicCircuitPrivateInputs {
// Validate inputs.
let mut previous_kernel_validator = PreviousKernelValidator::new(self.previous_kernel);

previous_kernel_validator.verify_proof(ALLOWED_PREVIOUS_CIRCUITS);
previous_kernel_validator.verify_proof(ALLOWED_PREVIOUS_CIRCUITS, true);

previous_kernel_validator.validate_for_private_tail_to_public();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ impl PreviousKernelValidatorBuilder {

pub fn verify_proof<let N: u32>(self, allowed_vk_indices: [u32; N]) {
let previous_kernel = self.previous_kernel.to_private_kernel_data();
PreviousKernelValidator::new(previous_kernel).verify_proof(allowed_vk_indices);
PreviousKernelValidator::new(previous_kernel).verify_proof(allowed_vk_indices, false);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use crate::{
abis::kernel_circuit_public_inputs::PrivateKernelCircuitPublicInputs,
constants::{MEGA_VK_LENGTH_IN_FIELDS, PRIVATE_KERNEL_RESET_INDEX, PROOF_TYPE_PG},
proof::{traits::Verifiable, vk_data::VkData},
constants::{
MEGA_VK_LENGTH_IN_FIELDS, PRIVATE_KERNEL_RESET_INDEX, PROOF_TYPE_PG, PROOF_TYPE_PG_TAIL,
},
proof::vk_data::VkData,
utils::arrays::find_index_hint,
};

Expand Down Expand Up @@ -38,19 +40,18 @@ impl PrivateKernelData {
// Note: The hash of the verification key is checked in `verify_proof_with_type` against the given vk hash.
self.vk_data.validate_in_vk_tree(self.public_inputs.constants.vk_tree_root);
}
}

impl Verifiable for PrivateKernelData {
/// Verifies the proof against the verification key and public inputs.
/// The vk hash is also checked in the backend to match the key.
fn verify(self) {
pub fn verify(self, is_last_inner_kernel: bool) {
let mut proof_type = PROOF_TYPE_PG;
// Client IVC public inputs are linked in the backend via the databus
if is_last_inner_kernel {
proof_type = PROOF_TYPE_PG_TAIL;
}
std::verify_proof_with_type(
self.vk_data.vk.key,
[],
[],
self.vk_data.vk.hash,
PROOF_TYPE_PG,
proof_type,
);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1078,7 +1078,9 @@ pub global PROOF_TYPE_PG: u32 = 3;
pub global PROOF_TYPE_AVM: u32 = 4;
pub global PROOF_TYPE_ROLLUP_HONK: u32 = 5;
pub global PROOF_TYPE_ROOT_ROLLUP_HONK: u32 = 6;
pub global PROOF_TYPE_PG_FINAL: u32 = 7;
// worktodo comment here where 7 is
pub global PROOF_TYPE_PG_FINAL: u32 = 8;
pub global PROOF_TYPE_PG_TAIL: u32 = 9;

pub global TWO_POW_64: Field = 18446744073709551616;
// AVM_WRITTEN_PUBLIC_DATA_SLOTS_TREE_HEIGHT = LOG2(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX + 1)
Expand Down
Loading