diff --git a/cpp/src/barretenberg/honk/composer/composer_helper/ultra_honk_composer_helper.cpp b/cpp/src/barretenberg/honk/composer/composer_helper/ultra_honk_composer_helper.cpp index db09f3192f..c3697aff7d 100644 --- a/cpp/src/barretenberg/honk/composer/composer_helper/ultra_honk_composer_helper.cpp +++ b/cpp/src/barretenberg/honk/composer/composer_helper/ultra_honk_composer_helper.cpp @@ -131,6 +131,21 @@ void UltraHonkComposerHelper::compute_witness(CircuitConstructor& circuit_constr proving_key->sorted_3 = s_3; proving_key->sorted_4 = s_4; + // Copy memory read/write record data into proving key. Prover needs to know which gates contain a read/write + // 'record' witness on the 4th wire. This wire value can only be fully computed once the first 3 wire polynomials + // have been committed to. The 4th wire on these gates will be a random linear combination of the first 3 wires, + // using the plookup challenge `eta` + proving_key->memory_read_records = std::vector(); + proving_key->memory_write_records = std::vector(); + proving_key->memory_read_records.reserve(circuit_constructor.memory_read_records.size()); + proving_key->memory_write_records.reserve(circuit_constructor.memory_write_records.size()); + std::copy(circuit_constructor.memory_read_records.begin(), + circuit_constructor.memory_read_records.end(), + std::back_inserter(proving_key->memory_read_records)); + std::copy(circuit_constructor.memory_write_records.begin(), + circuit_constructor.memory_write_records.end(), + std::back_inserter(proving_key->memory_write_records)); + computed_witness = true; } @@ -279,17 +294,6 @@ std::shared_ptr UltraHonkComposerHe proving_key->table_3 = poly_q_table_column_3; proving_key->table_4 = poly_q_table_column_4; - // Copy memory read/write record data into proving key. Prover needs to know which gates contain a read/write - // 'record' witness on the 4th wire. This wire value can only be fully computed once the first 3 wire polynomials - // have been committed to. The 4th wire on these gates will be a random linear combination of the first 3 wires, - // using the plookup challenge `eta` - std::copy(circuit_constructor.memory_read_records.begin(), - circuit_constructor.memory_read_records.end(), - std::back_inserter(proving_key->memory_read_records)); - std::copy(circuit_constructor.memory_write_records.begin(), - circuit_constructor.memory_write_records.end(), - std::back_inserter(proving_key->memory_write_records)); - proving_key->recursive_proof_public_input_indices = std::vector(recursive_proof_public_input_indices.begin(), recursive_proof_public_input_indices.end()); diff --git a/cpp/src/barretenberg/plonk/composer/composer_helper/ultra_plonk_composer_helper.cpp b/cpp/src/barretenberg/plonk/composer/composer_helper/ultra_plonk_composer_helper.cpp index f3d917ef8a..3189ff8a66 100644 --- a/cpp/src/barretenberg/plonk/composer/composer_helper/ultra_plonk_composer_helper.cpp +++ b/cpp/src/barretenberg/plonk/composer/composer_helper/ultra_plonk_composer_helper.cpp @@ -139,6 +139,21 @@ void UltraPlonkComposerHelper::compute_witness(CircuitConstructor& circuit_const circuit_proving_key->polynomial_store.put("s_3_lagrange", std::move(s_3)); circuit_proving_key->polynomial_store.put("s_4_lagrange", std::move(s_4)); + // Copy memory read/write record data into proving key. Prover needs to know which gates contain a read/write + // 'record' witness on the 4th wire. This wire value can only be fully computed once the first 3 wire polynomials + // have been committed to. The 4th wire on these gates will be a random linear combination of the first 3 wires, + // using the plookup challenge `eta` + circuit_proving_key->memory_read_records = std::vector(); + circuit_proving_key->memory_write_records = std::vector(); + circuit_proving_key->memory_read_records.reserve(circuit_constructor.memory_read_records.size()); + circuit_proving_key->memory_write_records.reserve(circuit_constructor.memory_write_records.size()); + std::copy(circuit_constructor.memory_read_records.begin(), + circuit_constructor.memory_read_records.end(), + std::back_inserter(circuit_proving_key->memory_read_records)); + std::copy(circuit_constructor.memory_write_records.begin(), + circuit_constructor.memory_write_records.end(), + std::back_inserter(circuit_proving_key->memory_write_records)); + computed_witness = true; } @@ -453,17 +468,6 @@ std::shared_ptr UltraPlonkComposerHelper::compute_proving_key(Circu circuit_proving_key->polynomial_store.put("z_lookup_fft", std::move(z_lookup_fft)); circuit_proving_key->polynomial_store.put("s_fft", std::move(s_fft)); - // Copy memory read/write record data into proving key. Prover needs to know which gates contain a read/write - // 'record' witness on the 4th wire. This wire value can only be fully computed once the first 3 wire polynomials - // have been committed to. The 4th wire on these gates will be a random linear combination of the first 3 wires, - // using the plookup challenge `eta` - std::copy(circuit_constructor.memory_read_records.begin(), - circuit_constructor.memory_read_records.end(), - std::back_inserter(circuit_proving_key->memory_read_records)); - std::copy(circuit_constructor.memory_write_records.begin(), - circuit_constructor.memory_write_records.end(), - std::back_inserter(circuit_proving_key->memory_write_records)); - circuit_proving_key->recursive_proof_public_input_indices = std::vector(recursive_proof_public_input_indices.begin(), recursive_proof_public_input_indices.end()); diff --git a/cpp/src/barretenberg/proof_system/circuit_constructors/ultra_circuit_constructor.cpp b/cpp/src/barretenberg/proof_system/circuit_constructors/ultra_circuit_constructor.cpp index 2f5e246121..89903893dd 100644 --- a/cpp/src/barretenberg/proof_system/circuit_constructors/ultra_circuit_constructor.cpp +++ b/cpp/src/barretenberg/proof_system/circuit_constructors/ultra_circuit_constructor.cpp @@ -2389,6 +2389,8 @@ void UltraCircuitConstructor::process_RAM_array(const size_t ram_id, const size_ std::sort(std::execution::par_unseq, ram_array.records.begin(), ram_array.records.end()); #endif + std::vector sorted_ram_records; + // Iterate over all but final RAM record. for (size_t i = 0; i < ram_array.records.size(); ++i) { const RamRecord& record = ram_array.records[i]; @@ -2409,6 +2411,9 @@ void UltraCircuitConstructor::process_RAM_array(const size_t ram_id, const size_ .gate_index = 0, }; + // create a list of sorted ram records + sorted_ram_records.emplace_back(sorted_record); + // We don't apply the RAM consistency check gate to the final record, // as this gate expects a RAM record to be present at the next gate if (i < ram_array.records.size() - 1) { @@ -2454,10 +2459,10 @@ void UltraCircuitConstructor::process_RAM_array(const size_t ram_id, const size_ // Step 2: Create gates that validate correctness of RAM timestamps std::vector timestamp_deltas; - for (size_t i = 0; i < ram_array.records.size() - 1; ++i) { + for (size_t i = 0; i < sorted_ram_records.size() - 1; ++i) { // create_RAM_timestamp_gate(sorted_records[i], sorted_records[i + 1]) - const auto& current = ram_array.records[i]; - const auto& next = ram_array.records[i + 1]; + const auto& current = sorted_ram_records[i]; + const auto& next = sorted_ram_records[i + 1]; const bool share_index = current.index == next.index; @@ -2483,7 +2488,7 @@ void UltraCircuitConstructor::process_RAM_array(const size_t ram_id, const size_ // add the index/timestamp values of the last sorted record in an empty add gate. // (the previous gate will access the wires on this gate and requires them to be those of the last record) - const auto& last = ram_array.records[ram_array.records.size() - 1]; + const auto& last = sorted_ram_records[ram_array.records.size() - 1]; create_big_add_gate({ last.index_witness, last.timestamp_witness,