-
Notifications
You must be signed in to change notification settings - Fork 302
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' into sync-noir
- Loading branch information
Showing
24 changed files
with
1,282 additions
and
4,132 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1 change: 1 addition & 0 deletions
1
barretenberg/cpp/src/barretenberg/ultra_vanilla_client_ivc/CMakeLists.txt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
barretenberg_module(ultra_vanilla_client_ivc stdlib_honk_verifier) |
90 changes: 90 additions & 0 deletions
90
barretenberg/cpp/src/barretenberg/ultra_vanilla_client_ivc/mock_circuit_producer.hpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
91 changes: 91 additions & 0 deletions
91
barretenberg/cpp/src/barretenberg/ultra_vanilla_client_ivc/ultra_vanilla_client_ivc.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
Oops, something went wrong.