Skip to content

Commit

Permalink
Merge branch 'master' into mm/pg-refactor-new
Browse files Browse the repository at this point in the history
  • Loading branch information
maramihali authored Feb 19, 2024
2 parents ffaddfc + 2dd53fd commit e1c3710
Show file tree
Hide file tree
Showing 94 changed files with 4,466 additions and 4,024 deletions.
10 changes: 6 additions & 4 deletions barretenberg/acir_tests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,20 @@ The `all_cmds` flow tests all the supported commands on the binary. Slower, but
$ FLOW=all_cmds ./run_acir_tests.sh 1_mul
```

## Regenerating witness for `double_verify_proof`
## Regenerating witness for `double_verify_proof` and `double_verify_nested_proof`

`double_verify_proof` has inputs that are proof system specific such as the circuit verification key and the proofs themselves which are being recursively verified. Certain proof system changes can sometimes lead to the key or inner proofs now being invalid.

This means we have to generate the proof specific inputs using our backend and pass it back into `double_verify_proof` to regenerate the accurate witness. The following is a temporary solution to manually regenerate the inputs for `double_verify_proof` on a specific Noir branch.

First find `acir_tests/gen_inner_proof_inputs.sh`. Change the $BRANCH env var to your working branch and $PROOF_NAME to your first input you want to recursively verify. The script is going to generate the proof system specific verification key output and proof for the `assert_statement` test.
First find `acir_tests/gen_inner_proof_inputs.sh`. Change the $BRANCH env var to your working branch and $PROOF_NAME to your first input you want to recursively verify. The script is going to generate the proof system specific verification key output and proof for the `assert_statement_recursive` test.

To run:
```
./gen_inner_proof_inputs.sh
```
To generate a new input you can run the script again. To generate a new file under `assert_statement/proofs/` be sure to change the $PROOF_NAME inside of the script.
To generate a new input you can run the script again. To generate a new file under `assert_statement_recursive/proofs/` be sure to change the $PROOF_NAME inside of the script.

You can then copy these inputs over to your working branch in Noir and regenerate the witness for `double_verify_proof`. You can then change the branch in `run_acir_tests.sh` to this Noir working branch as well and `double_verify_proof` should pass.
You can then copy these inputs over to your working branch in Noir and regenerate the witness for `double_verify_proof`. You can then change the branch in `run_acir_tests.sh` to this Noir working branch as well and `double_verify_proof` should pass.

The same process should then be repeated, but now `double_verify_proof` will be the circuit for which we will be generating recursive inputs using `gen_inner_proof_inputs.sh`. The recursive artifacts should then supplied as inputs to `double_verify_nested_proof`.
41 changes: 19 additions & 22 deletions barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
* @brief IPA (inner-product argument) commitment scheme class. Conforms to the specification
* https://hackmd.io/q-A8y6aITWyWJrvsGGMWNA?view.
*
*
*/
namespace bb {
template <typename Curve> class IPA {
Expand Down Expand Up @@ -141,32 +142,30 @@ template <typename Curve> class IPA {
const Fr round_challenge = transcript->get_challenge<Fr>("IPA:round_challenge_" + index);
const Fr round_challenge_inv = round_challenge.invert();

auto G_lo = GroupElement::batch_mul_with_endomorphism(
std::span{ G_vec_local.begin(), G_vec_local.begin() + static_cast<long>(round_size) },
round_challenge_inv);
auto G_hi = GroupElement::batch_mul_with_endomorphism(
std::span{ G_vec_local.begin() + static_cast<long>(round_size),
G_vec_local.begin() + static_cast<long>(round_size * 2) },
round_challenge);
round_challenge_inv);

// Update the vectors a_vec, b_vec and G_vec.
// a_vec_next = a_vec_lo * round_challenge + a_vec_hi * round_challenge_inv
// b_vec_next = b_vec_lo * round_challenge_inv + b_vec_hi * round_challenge
// G_vec_next = G_vec_lo * round_challenge_inv + G_vec_hi * round_challenge
// a_vec_next = a_vec_lo + a_vec_hi * round_challenge
// b_vec_next = b_vec_lo + b_vec_hi * round_challenge_inv
// G_vec_next = G_vec_lo + G_vec_hi * round_challenge_inv
run_loop_in_parallel_if_effective(
round_size,
[&a_vec, &b_vec, round_challenge, round_challenge_inv, round_size](size_t start, size_t end) {
for (size_t j = start; j < end; j++) {
a_vec[j] *= round_challenge;
a_vec[j] += round_challenge_inv * a_vec[round_size + j];
b_vec[j] *= round_challenge_inv;
b_vec[j] += round_challenge * b_vec[round_size + j];
a_vec[j] += round_challenge * a_vec[round_size + j];
b_vec[j] += round_challenge_inv * b_vec[round_size + j];
}
},
/*finite_field_additions_per_iteration=*/4,
/*finite_field_multiplications_per_iteration=*/8,
/*finite_field_inversions_per_iteration=*/1);
GroupElement::batch_affine_add(G_lo, G_hi, G_vec_local);
GroupElement::batch_affine_add(
std::span{ G_vec_local.begin(), G_vec_local.begin() + static_cast<long>(round_size) },
G_hi,
G_vec_local);
}

transcript->send_to_verifier("IPA:a_0", a_vec[0]);
Expand Down Expand Up @@ -196,7 +195,7 @@ template <typename Curve> class IPA {
// Compute C_prime
GroupElement C_prime = opening_claim.commitment + (aux_generator * opening_claim.opening_pair.evaluation);

// Compute C_zero = C_prime + ∑_{j ∈ [k]} u_j^2L_j + ∑_{j ∈ [k]} u_j^{-2}R_j
// Compute C_zero = C_prime + ∑_{j ∈ [k]} u_j^{-1}L_j + ∑_{j ∈ [k]} u_jR_j
auto pippenger_size = 2 * log_poly_degree;
std::vector<Fr> round_challenges(log_poly_degree);
std::vector<Fr> round_challenges_inv(log_poly_degree);
Expand All @@ -211,8 +210,8 @@ template <typename Curve> class IPA {

msm_elements[2 * i] = element_L;
msm_elements[2 * i + 1] = element_R;
msm_scalars[2 * i] = round_challenges[i].sqr();
msm_scalars[2 * i + 1] = round_challenges_inv[i].sqr();
msm_scalars[2 * i] = round_challenges_inv[i];
msm_scalars[2 * i + 1] = round_challenges[i];
}

GroupElement LR_sums = bb::scalar_multiplication::pippenger_without_endomorphism_basis_points<Curve>(
Expand All @@ -222,31 +221,29 @@ template <typename Curve> class IPA {
/**
* Compute b_zero where b_zero can be computed using the polynomial:
*
* g(X) = ∏_{i ∈ [k]} (u_{k-i}^{-1} + u_{k-i}.X^{2^{i-1}}).
* g(X) = ∏_{i ∈ [k]} (1 + u_{k-i}^{-1}.X^{2^{i-1}}).
*
* b_zero = g(evaluation) = ∏_{i ∈ [k]} (u_{k-i}^{-1} + u_{k-i}. (evaluation)^{2^{i-1}})
* b_zero = g(evaluation) = ∏_{i ∈ [k]} (1 + u_{k-i}^{-1}. (evaluation)^{2^{i-1}})
*/
Fr b_zero = Fr::one();
for (size_t i = 0; i < log_poly_degree; i++) {
auto exponent = static_cast<uint64_t>(Fr(2).pow(i));
b_zero *= round_challenges_inv[log_poly_degree - 1 - i] +
(round_challenges[log_poly_degree - 1 - i] * opening_claim.opening_pair.challenge.pow(exponent));
b_zero *= Fr::one() + (round_challenges_inv[log_poly_degree - 1 - i] *
opening_claim.opening_pair.challenge.pow(exponent));
}

// Compute G_zero
// First construct s_vec
std::vector<Fr> s_vec(poly_degree);
run_loop_in_parallel_if_effective(
poly_degree,
[&s_vec, &round_challenges, &round_challenges_inv, log_poly_degree](size_t start, size_t end) {
[&s_vec, &round_challenges_inv, log_poly_degree](size_t start, size_t end) {
for (size_t i = start; i < end; i++) {
Fr s_vec_scalar = Fr::one();
for (size_t j = (log_poly_degree - 1); j != size_t(-1); j--) {
auto bit = (i >> j) & 1;
bool b = static_cast<bool>(bit);
if (b) {
s_vec_scalar *= round_challenges[log_poly_degree - 1 - j];
} else {
s_vec_scalar *= round_challenges_inv[log_poly_degree - 1 - j];
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

namespace bb::crypto::merkle_tree {

typedef uint256_t index_t;
using index_t = uint256_t;

/**
* @brief Used in parallel insertions in the the IndexedTree. Workers signal to other following workes as they move up
Expand All @@ -18,11 +18,13 @@ class LevelSignal {
public:
LevelSignal(size_t initial_level)
: signal_(initial_level){};
~LevelSignal(){};
~LevelSignal() = default;
LevelSignal(const LevelSignal& other)
: signal_(other.signal_.load())
{}
LevelSignal(const LevelSignal&& other) = delete;
LevelSignal(const LevelSignal&& other) noexcept
: signal_(other.signal_.load())
{}

/**
* @brief Causes the thread to wait until the required level has been signalled
Expand Down
14 changes: 10 additions & 4 deletions barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ void build_constraints(Builder& builder, AcirFormat const& constraint_system, bo
// TODO(https://github.com/AztecProtocol/barretenberg/issues/817): disable these for UGH for now since we're not yet
// dealing with proper recursion
if constexpr (IsGoblinBuilder<Builder>) {
if (constraint_system.recursion_constraints.size() > 0) {
if (!constraint_system.recursion_constraints.empty()) {
info("WARNING: this circuit contains recursion_constraints!");
}
} else {
Expand Down Expand Up @@ -148,8 +148,15 @@ void build_constraints(Builder& builder, AcirFormat const& constraint_system, bo
// If the proof has public inputs attached to it, we should handle setting the nested aggregation object
if (constraint.proof.size() > proof_size_no_pub_inputs) {
// The public inputs attached to a proof should match the aggregation object in size
ASSERT(constraint.proof.size() - proof_size_no_pub_inputs ==
RecursionConstraint::AGGREGATION_OBJECT_SIZE);
if (constraint.proof.size() - proof_size_no_pub_inputs !=
RecursionConstraint::AGGREGATION_OBJECT_SIZE) {
auto error_string = format(
"Public inputs are always stripped from proofs unless we have a recursive proof.\n"
"Thus, public inputs attached to a proof must match the recursive aggregation object in size "
"which is {}\n",
RecursionConstraint::AGGREGATION_OBJECT_SIZE);
throw_or_abort(error_string);
}
for (size_t i = 0; i < RecursionConstraint::AGGREGATION_OBJECT_SIZE; ++i) {
// Set the nested aggregation object indices to the current size of the public inputs
// This way we know that the nested aggregation object indices will always be the last
Expand All @@ -165,7 +172,6 @@ void build_constraints(Builder& builder, AcirFormat const& constraint_system, bo
constraint.proof.begin() +
static_cast<std::ptrdiff_t>(RecursionConstraint::AGGREGATION_OBJECT_SIZE));
}

current_output_aggregation_object = create_recursion_constraints(builder,
constraint,
current_input_aggregation_object,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,20 +53,32 @@ std::array<uint32_t, RecursionConstraint::AGGREGATION_OBJECT_SIZE> create_recurs
std::vector<bb::fr> dummy_proof =
export_dummy_transcript_in_recursion_format(manifest, inner_proof_contains_recursive_proof);

// Remove the public inputs from the dummy proof
dummy_proof.erase(dummy_proof.begin(),
dummy_proof.begin() + static_cast<std::ptrdiff_t>(input.public_inputs.size()));
for (size_t i = 0; i < input.proof.size(); ++i) {
const auto proof_field_idx = input.proof[i];
for (size_t i = 0; i < input.public_inputs.size(); ++i) {
const auto public_input_idx = input.public_inputs[i];
// if we do NOT have a witness assignment (i.e. are just building the proving/verification keys),
// we add our dummy proof values as Builder variables.
// we add our dummy public input values as Builder variables.
// if we DO have a valid witness assignment, we use the real witness assignment
bb::fr dummy_field = has_valid_witness_assignments ? builder.get_variable(proof_field_idx) : dummy_proof[i];
bb::fr dummy_field =
has_valid_witness_assignments ? builder.get_variable(public_input_idx) : dummy_proof[i];
// Create a copy constraint between our dummy field and the witness index provided by RecursionConstraint.
// This will make the RecursionConstraint idx equal to `dummy_field`.
// In the case of a valid witness assignment, this does nothing (as dummy_field = real value)
// In the case of no valid witness assignment, this makes sure that the RecursionConstraint witness indices
// will not trigger basic errors (check inputs are on-curve, check we are not inverting 0)
//
// Failing to do these copy constraints on public inputs will trigger these basic errors
// in the case of a nested proof, as an aggregation object is expected to be two G1 points even
// in the case of no valid witness assignments.
builder.assert_equal(builder.add_variable(dummy_field), public_input_idx);
}
// Remove the public inputs from the dummy proof
// The proof supplied to the recursion constraint will already be stripped of public inputs
// while the barretenberg API works with public inputs prepended to the proof.
dummy_proof.erase(dummy_proof.begin(),
dummy_proof.begin() + static_cast<std::ptrdiff_t>(input.public_inputs.size()));
for (size_t i = 0; i < input.proof.size(); ++i) {
const auto proof_field_idx = input.proof[i];
bb::fr dummy_field = has_valid_witness_assignments ? builder.get_variable(proof_field_idx) : dummy_proof[i];
builder.assert_equal(builder.add_variable(dummy_field), proof_field_idx);
}
for (size_t i = 0; i < input.key.size(); ++i) {
Expand Down Expand Up @@ -329,7 +341,12 @@ std::vector<bb::fr> export_dummy_transcript_in_recursion_format(const transcript
// is composed of two valid G1 points on the curve. Without this conditional we will get a
// runtime error that we are attempting to invert 0.
if (contains_recursive_proof) {
ASSERT(num_public_inputs == RecursionConstraint::AGGREGATION_OBJECT_SIZE);
// When setting up the ACIR we emplace back the nested aggregation object
// fetched from the proof onto the public inputs. Thus, we can expect the
// nested aggregation object to always be at the end of the public inputs.
for (size_t k = 0; k < num_public_inputs - RecursionConstraint::AGGREGATION_OBJECT_SIZE; ++k) {
fields.emplace_back(0);
}
for (size_t k = 0; k < RecursionConstraint::NUM_AGGREGATION_ELEMENTS; ++k) {
auto scalar = bb::fr::random_element();
const auto group_element = bb::g1::affine_element(bb::g1::one * scalar);
Expand Down
4 changes: 2 additions & 2 deletions l1-contracts/slither_output.md
Original file line number Diff line number Diff line change
Expand Up @@ -353,9 +353,9 @@ src/core/messagebridge/Inbox.sol#L148-L153
Impact: Informational
Confidence: Medium
- [ ] ID-41
Variable [Constants.L1_TO_L2_MESSAGE_LENGTH](src/core/libraries/ConstantsGen.sol#L96) is too similar to [Constants.L2_TO_L1_MESSAGE_LENGTH](src/core/libraries/ConstantsGen.sol#L97)
Variable [Constants.L1_TO_L2_MESSAGE_LENGTH](src/core/libraries/ConstantsGen.sol#L103) is too similar to [Constants.L2_TO_L1_MESSAGE_LENGTH](src/core/libraries/ConstantsGen.sol#L104)

src/core/libraries/ConstantsGen.sol#L96
src/core/libraries/ConstantsGen.sol#L103


- [ ] ID-42
Expand Down
15 changes: 11 additions & 4 deletions l1-contracts/src/core/libraries/ConstantsGen.sol
Original file line number Diff line number Diff line change
Expand Up @@ -26,20 +26,27 @@ library Constants {
uint256 internal constant MAX_READ_REQUESTS_PER_CALL = 32;
uint256 internal constant MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL = 1;
uint256 internal constant MAX_NEW_COMMITMENTS_PER_TX = 64;
uint256 internal constant MAX_NON_REVERTIBLE_COMMITMENTS_PER_TX = 8;
uint256 internal constant MAX_REVERTIBLE_COMMITMENTS_PER_TX = 56;
uint256 internal constant MAX_NEW_NULLIFIERS_PER_TX = 64;
uint256 internal constant MAX_NON_REVERTIBLE_NULLIFIERS_PER_TX = 8;
uint256 internal constant MAX_REVERTIBLE_NULLIFIERS_PER_TX = 56;
uint256 internal constant MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX = 8;
uint256 internal constant MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX = 8;
uint256 internal constant MAX_NEW_L2_TO_L1_MSGS_PER_TX = 2;
uint256 internal constant MAX_NON_REVERTIBLE_PUBLIC_CALL_STACK_LENGTH_PER_TX = 3;
uint256 internal constant MAX_REVERTIBLE_PUBLIC_CALL_STACK_LENGTH_PER_TX = 5;
uint256 internal constant MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX = 16;
uint256 internal constant MAX_NON_REVERTIBLE_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX = 1;
uint256 internal constant MAX_REVERTIBLE_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX = 15;
uint256 internal constant MAX_PUBLIC_DATA_READS_PER_TX = 16;
uint256 internal constant MAX_NON_REVERTIBLE_PUBLIC_DATA_READS_PER_TX = 1;
uint256 internal constant MAX_REVERTIBLE_PUBLIC_DATA_READS_PER_TX = 15;
uint256 internal constant MAX_NEW_L2_TO_L1_MSGS_PER_TX = 2;
uint256 internal constant MAX_NEW_CONTRACTS_PER_TX = 1;
uint256 internal constant MAX_READ_REQUESTS_PER_TX = 128;
uint256 internal constant MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX = 4;
uint256 internal constant NUM_ENCRYPTED_LOGS_HASHES_PER_TX = 1;
uint256 internal constant NUM_UNENCRYPTED_LOGS_HASHES_PER_TX = 1;
uint256 internal constant MAX_NEW_COMMITMENTS_PER_TX_META = 8;
uint256 internal constant MAX_NEW_NULLIFIERS_PER_TX_META = 8;
uint256 internal constant MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX_META = 2;
uint256 internal constant NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP = 16;
uint256 internal constant VK_TREE_HEIGHT = 3;
uint256 internal constant FUNCTION_TREE_HEIGHT = 5;
Expand Down
2 changes: 1 addition & 1 deletion noir-projects/aztec-nr/authwit/src/account.nr
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ impl AccountActions {
let fee_hash = fee_payload.hash();
assert(valid_fn(private_context, fee_hash));
fee_payload.execute_calls(private_context);
private_context.capture_max_non_revertible_side_effect_counter();
private_context.capture_min_revertible_side_effect_counter();

let app_hash = app_payload.hash();
assert(valid_fn(private_context, app_hash));
Expand Down
Loading

0 comments on commit e1c3710

Please sign in to comment.