Skip to content

Commit

Permalink
Merge branch 'master' into sync-noir
Browse files Browse the repository at this point in the history
  • Loading branch information
TomAFrench authored Jan 2, 2025
2 parents 1d737fb + a1a4d76 commit b11da25
Show file tree
Hide file tree
Showing 24 changed files with 1,282 additions and 4,132 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -514,7 +514,7 @@ jobs:
- uses: actions/checkout@v4
with: { ref: "${{ github.event.pull_request.head.sha }}" }
- uses: ./.github/ci-setup-action
- name: Build Bench Binaries
- name: Build Boxes
uses: ./.github/ensure-builder
timeout-minutes: 40
with:
Expand Down
2 changes: 1 addition & 1 deletion barretenberg/cpp/pil/avm/mem.pil
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ namespace mem(256);
+ sel_op_slice;

// Maximum one memory operation enabled per row
sel_mem * (sel_mem - 1) = 0; // TODO: might be infered by the main trace
sel_mem * (sel_mem - 1) = 0; // TODO: might be inferred by the main trace

// Enforce the memory entries to be contiguous, i.e., as soon as
// sel_mem is disabled all subsequent rows have sel_mem disabled.
Expand Down
4 changes: 3 additions & 1 deletion barretenberg/cpp/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,10 @@ if (ENABLE_PIC AND CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_subdirectory(barretenberg/world_state_napi)
endif()

add_subdirectory(barretenberg/client_ivc)
add_subdirectory(barretenberg/bb)
add_subdirectory(barretenberg/boomerang_value_detection)
add_subdirectory(barretenberg/circuit_checker)
add_subdirectory(barretenberg/client_ivc)
add_subdirectory(barretenberg/commitment_schemes)
add_subdirectory(barretenberg/commitment_schemes_recursion)
add_subdirectory(barretenberg/common)
Expand All @@ -87,6 +87,7 @@ add_subdirectory(barretenberg/relations)
add_subdirectory(barretenberg/serialize)
add_subdirectory(barretenberg/solidity_helpers)
add_subdirectory(barretenberg/srs)
add_subdirectory(barretenberg/ultra_vanilla_client_ivc)
add_subdirectory(barretenberg/stdlib)
add_subdirectory(barretenberg/stdlib_circuit_builders)
add_subdirectory(barretenberg/sumcheck)
Expand Down Expand Up @@ -139,6 +140,7 @@ set(BARRETENBERG_TARGET_OBJECTS
$<TARGET_OBJECTS:protogalaxy_objects>
$<TARGET_OBJECTS:relations_objects>
$<TARGET_OBJECTS:srs_objects>
$<TARGET_OBJECTS:ultra_vanilla_client_ivc_objects>
$<TARGET_OBJECTS:stdlib_aes128_objects>
$<TARGET_OBJECTS:stdlib_blake2s_objects>
$<TARGET_OBJECTS:stdlib_blake3s_objects>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ bool Graph_<FF>::check_is_not_constant_variable(bb::UltraCircuitBuilder& ultra_c
}

/**
* @brief this method adds connection between 2 variables, if they are in one gate, they are not constrant variables,
* @brief this method adds connection between 2 variables, if they are in one gate, they are not constraint variables,
* and they have different indexes
* @tparam FF
* @param ultra_circuit_builder
Expand Down Expand Up @@ -821,4 +821,4 @@ template <typename FF> void Graph_<FF>::print_variables_edge_counts()
}
}

template class Graph_<bb::fr>;
template class Graph_<bb::fr>;
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ template <class Curve> class CommitmentKey {
scalar_multiplication::pippenger_runtime_state<Curve> pippenger_runtime_state;
std::shared_ptr<srs::factories::CrsFactory<Curve>> crs_factory;
std::shared_ptr<srs::factories::ProverCrs<Curve>> srs;
size_t dyadic_size;

CommitmentKey() = delete;

Expand All @@ -69,6 +70,7 @@ template <class Curve> class CommitmentKey {
: pippenger_runtime_state(get_num_needed_srs_points(num_points))
, crs_factory(srs::get_crs_factory<Curve>())
, srs(crs_factory->get_prover_crs(get_num_needed_srs_points(num_points)))
, dyadic_size(get_num_needed_srs_points(num_points))
{}

// Note: This constructor is to be used only by Plonk; For Honk the srs lives in the CommitmentKey
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ template <typename RecursiveFlavor> class RecursiveVerifierTest : public testing
using RecursiveVerifier = UltraRecursiveVerifier_<RecursiveFlavor>;
using VerificationKey = typename RecursiveVerifier::VerificationKey;

using AggState = aggregation_state<typename RecursiveFlavor::Curve>;
using VerifierOutput = bb::stdlib::recursion::honk::UltraRecursiveVerifierOutput<RecursiveFlavor>;
/**
* @brief Create a non-trivial arbitrary inner circuit, the proof of which will be recursively verified
*
Expand Down Expand Up @@ -252,11 +254,9 @@ template <typename RecursiveFlavor> class RecursiveVerifierTest : public testing
OuterBuilder outer_circuit;
RecursiveVerifier verifier{ &outer_circuit, verification_key };

aggregation_state<typename RecursiveFlavor::Curve> agg_obj =
init_default_aggregation_state<OuterBuilder, typename RecursiveFlavor::Curve>(outer_circuit);
bb::stdlib::recursion::honk::UltraRecursiveVerifierOutput<RecursiveFlavor> output =
verifier.verify_proof(inner_proof, agg_obj);
aggregation_state<typename RecursiveFlavor::Curve> pairing_points = output.agg_obj;
AggState agg_obj = init_default_aggregation_state<OuterBuilder, typename RecursiveFlavor::Curve>(outer_circuit);
VerifierOutput output = verifier.verify_proof(inner_proof, agg_obj);
AggState pairing_points = output.agg_obj;
if constexpr (HasIPAAccumulator<OuterFlavor>) {
outer_circuit.add_ipa_claim(output.ipa_opening_claim.get_witness_indices());
outer_circuit.ipa_proof = convert_stdlib_proof_to_native(output.ipa_proof);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ TYPED_TEST(SafeUintTest, TestMultiplyOperationOutOfRangeFails)
{
STDLIB_TYPE_ALIASES
auto builder = Builder();
// Since max is initally set to (1 << 2) - 1 = 3 (as bit range checks are easier than generic integer bounds),
// Since max is initially set to (1 << 2) - 1 = 3 (as bit range checks are easier than generic integer bounds),
// should allow largest power of 3 smaller than r iterations, which is 159. Hence below we should exceed r, and
// expect a throw
field_ct a(witness_ct(&builder, 2));
Expand Down
8 changes: 8 additions & 0 deletions barretenberg/cpp/src/barretenberg/ultra_honk/ultra_prover.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@
#include "barretenberg/ultra_honk/oink_prover.hpp"
namespace bb {

template <IsUltraFlavor Flavor>
UltraProver_<Flavor>::UltraProver_(const std::shared_ptr<DeciderPK>& proving_key,
const std::shared_ptr<CommitmentKey>& commitment_key)
: proving_key(std::move(proving_key))
, transcript(std::make_shared<Transcript>())
, commitment_key(commitment_key)
{}

/**
* @brief Create UltraProver_ from a decider proving key.
*
Expand Down
2 changes: 2 additions & 0 deletions barretenberg/cpp/src/barretenberg/ultra_honk/ultra_prover.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ template <IsUltraFlavor Flavor_> class UltraProver_ {

std::shared_ptr<CommitmentKey> commitment_key;

UltraProver_(const std::shared_ptr<DeciderPK>&, const std::shared_ptr<CommitmentKey>&);

explicit UltraProver_(const std::shared_ptr<DeciderPK>&,
const std::shared_ptr<Transcript>& transcript = std::make_shared<Transcript>());

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
barretenberg_module(ultra_vanilla_client_ivc stdlib_honk_verifier)
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@

#include "barretenberg/common/op_count.hpp"
#include "barretenberg/goblin/mock_circuits.hpp"
#include "barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp"
#include "barretenberg/ultra_honk/ultra_verifier.hpp"
#include "barretenberg/ultra_vanilla_client_ivc/ultra_vanilla_client_ivc.hpp"

using namespace bb;

namespace {

/**
* @brief Manage the construction of mock app/kernel circuits for the private function execution setting
* @details Per the medium complexity benchmark spec, the first app circuit is size 2^19. Subsequent app and kernel
* circuits are size 2^17. Circuits produced are alternatingly app and kernel. Mock databus data is passed between the
* circuits in a manor conistent with the real architecture in order to facilitate testing of databus consistency
* checks.
*/
class PrivateFunctionExecutionMockCircuitProducer {
using ClientCircuit = UltraVanillaClientIVC::ClientCircuit;
using Flavor = MegaFlavor;
using VerificationKey = Flavor::VerificationKey;

size_t circuit_counter = 0;

bool large_first_app = true; // if true, first app is 2^19, else 2^17

public:
PrivateFunctionExecutionMockCircuitProducer(bool large_first_app = true)
: large_first_app(large_first_app)
{}

/**
* @brief Create the next circuit (app/kernel) in a mocked private function execution stack
*/
ClientCircuit create_next_circuit(UltraVanillaClientIVC& ivc, bool force_is_kernel = false)
{
circuit_counter++;

// Assume only every second circuit is a kernel, unless force_is_kernel == true
bool is_kernel = (circuit_counter % 2 == 0) || force_is_kernel;

ClientCircuit circuit{ ivc.goblin.op_queue };
if (is_kernel) {
GoblinMockCircuits::construct_mock_folding_kernel(circuit); // construct mock base logic
mock_databus.populate_kernel_databus(circuit); // populate databus inputs/outputs
ivc.complete_kernel_circuit_logic(circuit); // complete with recursive verifiers etc
} else {
bool use_large_circuit = large_first_app && (circuit_counter == 1); // first circuit is size 2^19
GoblinMockCircuits::construct_mock_app_circuit(circuit, use_large_circuit); // construct mock app
mock_databus.populate_app_databus(circuit); // populate databus outputs
}
return circuit;
}

/**
* @brief Tamper with databus data to facilitate failure testing
*/
void tamper_with_databus() { mock_databus.tamper_with_app_return_data(); }

/**
* @brief Compute and return the verification keys for a mocked private function execution IVC
* @details For testing/benchmarking only. This method is robust at the cost of being extremely inefficient. It
* simply executes a full IVC for a given number of circuits and stores the verification keys along the way. (In
* practice these VKs will be known to a client prover in advance).
*
* @param num_circuits
* @param trace_structure Trace structuring must be known in advance because it effects the VKs
* @return set of num_circuits-many verification keys
*/
auto precompute_verification_keys(const size_t num_circuits, TraceSettings trace_settings)
{
UltraVanillaClientIVC ivc{
trace_settings
}; // temporary IVC instance needed to produce the complete kernel circuits

std::vector<std::shared_ptr<VerificationKey>> vkeys;

for (size_t idx = 0; idx < num_circuits; ++idx) {
ClientCircuit circuit = create_next_circuit(ivc); // create the next circuit
ivc.accumulate(circuit); // accumulate the circuit
vkeys.emplace_back(ivc.honk_vk); // save the VK for the circuit
}
circuit_counter = 0; // reset the internal circuit counter back to 0

return vkeys;
}
};

} // namespace
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
#include "barretenberg/ultra_vanilla_client_ivc/ultra_vanilla_client_ivc.hpp"
#include "barretenberg/ultra_honk/oink_prover.hpp"

namespace bb {

void UltraVanillaClientIVC::accumulate(Circuit& circuit, const Proof& proof, const std::shared_ptr<VK>& vk)
{
RecursiveVerifier verifier{ &circuit, std::make_shared<RecursiveVK>(&circuit, vk) };
Accumulator agg_obj = stdlib::recursion::init_default_aggregation_state<Circuit, stdlib::bn254<Circuit>>(circuit);
accumulator = verifier.verify_proof(proof, agg_obj).agg_obj;
}

HonkProof UltraVanillaClientIVC::prove(CircuitSource<Flavor>& source, const bool cache_vks)
{
for (size_t step = 0; step < source.num_circuits(); step++) {
auto [circuit, vk] = source.next();
if (step == 0) {
accumulator_indices = stdlib::recursion::init_default_agg_obj_indices(circuit);
} else {
accumulate(circuit, previous_proof, previous_vk);
accumulator_indices = accumulator.get_witness_indices();
}

circuit.add_pairing_point_accumulator(accumulator_indices);
accumulator_value = { accumulator.P0.get_value(), accumulator.P1.get_value() };

auto proving_key = std::make_shared<PK>(circuit);

if (step < source.num_circuits() - 1) {
UltraProver prover{ proving_key, commitment_key };
previous_proof = prover.construct_proof();
} else {
// TODO(https://github.com/AztecProtocol/barretenberg/issues/1176) Use UltraZKProver when it exists
UltraProver prover{ proving_key, commitment_key };
previous_proof = prover.construct_proof();
}

previous_vk = vk ? vk : std::make_shared<VK>(proving_key->proving_key);
if (cache_vks) {
vk_cache.push_back(previous_vk);
}
}
return previous_proof;
};

bool UltraVanillaClientIVC::verify(const Proof& proof, const std::shared_ptr<VK>& vk)
{

UltraVerifier verifer{ vk };
bool verified = verifer.verify_proof(proof);
vinfo("proof verified: ", verified);

using VerifierCommitmentKey = typename Flavor::VerifierCommitmentKey;
auto pcs_verification_key = std::make_shared<VerifierCommitmentKey>();
verified &= pcs_verification_key->pairing_check(accumulator_value[0], accumulator_value[1]);
vinfo("pairing verified: ", verified);
return verified;
}

/**
* @brief Construct and verify a proof for the IVC
* @note Use of this method only makes sense when the prover and verifier are the same entity, e.g. in
* development/testing.
*
*/
bool UltraVanillaClientIVC::prove_and_verify(CircuitSource<Flavor>& source, const bool cache_vks)
{
auto start = std::chrono::steady_clock::now();
prove(source, cache_vks);
auto end = std::chrono::steady_clock::now();
auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
vinfo("time to call UltraVanillaClientIVC::prove: ", diff.count(), " ms.");

start = end;
bool verified = verify(previous_proof, previous_vk);
end = std::chrono::steady_clock::now();

diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
vinfo("time to verify UltraVanillaClientIVC proof: ", diff.count(), " ms.");

return verified;
}

std::vector<std::shared_ptr<UltraFlavor::VerificationKey>> UltraVanillaClientIVC::compute_vks(
CircuitSource<Flavor>& source)
{
prove_and_verify(source, /*cache_vks=*/true);
return vk_cache;
};

} // namespace bb
Loading

0 comments on commit b11da25

Please sign in to comment.