Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Make public inputs the start of the UH and MH proof #12266

Open
wants to merge 33 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
712753e
adds new function to the transfer that allows for hashing without the…
lucasxia01 Feb 24, 2025
ec4e6b8
add test to test consume_element functionality
lucasxia01 Feb 25, 2025
e9e0dac
Merge branch 'master' into lx/transcript-allow-hashing-without-sending
lucasxia01 Feb 25, 2025
b93aee9
cleanup and change names
lucasxia01 Feb 25, 2025
78fa4ec
update oink prover and verifier to use add_to_hash_buffer
lucasxia01 Feb 25, 2025
a56d775
update oink rec verifier
lucasxia01 Feb 25, 2025
9f88bd8
update oink prover and verifier to use add_to_hash_buffer
lucasxia01 Feb 25, 2025
d7eb28d
update oink rec verifier
lucasxia01 Feb 25, 2025
4c5c057
Merge branch 'lx/public-inputs-at-proof-start' of github.com:AztecPro…
lucasxia01 Feb 26, 2025
6c1ddd0
Merge branch 'master' into lx/public-inputs-at-proof-start
lucasxia01 Feb 26, 2025
bb7b27a
fix test
lucasxia01 Feb 28, 2025
997c694
update constants for proof length
lucasxia01 Feb 28, 2025
08a3418
try to remove more issues
lucasxia01 Feb 28, 2025
d501112
fix more bugs related to using the proof to get the number of public …
lucasxia01 Feb 28, 2025
1d38474
fix mock proof creation
lucasxia01 Feb 28, 2025
c6c4818
remove client ivc public inputs offset
lucasxia01 Feb 28, 2025
6af9ec5
fix transcript serialization tests
lucasxia01 Mar 1, 2025
ab4d425
hopefully fix sol tests
lucasxia01 Mar 1, 2025
b019547
update Prover.tomls of protocol circuits
lucasxia01 Mar 1, 2025
8871399
update transcript structuring
lucasxia01 Mar 3, 2025
69789dd
add TODO
lucasxia01 Mar 3, 2025
92fa9ff
update Transcript.sol
lucasxia01 Mar 3, 2025
70e7b11
Merge remote-tracking branch 'origin/master' into lx/public-inputs-at…
lucasxia01 Mar 3, 2025
5ea2b5b
fix build
lucasxia01 Mar 3, 2025
2450abb
update the Prover.tomls of recursive protocol circuits
lucasxia01 Mar 3, 2025
0e3b766
update the contracts to do things properly
lucasxia01 Mar 3, 2025
7a91bb4
try to fix solidity, error is now a verify failure
lucasxia01 Mar 3, 2025
2c5b043
fixed client ivc test
lucasxia01 Mar 3, 2025
1b4b844
fixed UH rec verifier test
lucasxia01 Mar 3, 2025
d9f43eb
fix zk contract proof length
lucasxia01 Mar 4, 2025
0a40f16
fix verify_rollup_honk_proof
lucasxia01 Mar 4, 2025
29983e6
changed test base sol
lucasxia01 Mar 4, 2025
3be30b6
fixed challenges for solidity
lucasxia01 Mar 4, 2025
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
1 change: 1 addition & 0 deletions barretenberg/acir_tests/bootstrap.sh
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ function build {
# COMPILE=2 only compiles the test.
denoise "parallel --joblog joblog.txt --line-buffered 'COMPILE=2 ./run_test.sh \$(basename {})' ::: ./acir_tests/*"

# TODO(https://github.com/AztecProtocol/barretenberg/issues/1279): Fix this workflow.
echo "Regenerating verify_honk_proof and verify_rollup_honk_proof recursive inputs."
local bb=$(realpath ../cpp/build/bin/bb)
(cd ./acir_tests/assert_statement && \
Expand Down
15 changes: 4 additions & 11 deletions barretenberg/acir_tests/sol-test/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import solc from "solc";

// Size excluding number of public inputs
const NUMBER_OF_FIELDS_IN_PLONK_PROOF = 93;
const NUMBER_OF_FIELDS_IN_HONK_PROOF = 443;
const NUMBER_OF_FIELDS_IN_HONK_ZK_PROOF = 494;
const NUMBER_OF_FIELDS_IN_HONK_PROOF = 440;
const NUMBER_OF_FIELDS_IN_HONK_ZK_PROOF = 491;

const WRONG_PROOF_LENGTH = "0xed74ac0a";
const WRONG_PUBLIC_INPUTS_LENGTH = "0xfa066593";
Expand Down Expand Up @@ -172,11 +172,6 @@ const readPublicInputs = (proofAsFields) => {
const numPublicInputs = proofAsFields.length - NUMBER_OF_FIELDS_IN_PROOF;
let publicInputsOffset = 0;

// Honk proofs contain 3 pieces of metadata before the public inputs, while plonk does not
if (testingHonk) {
publicInputsOffset = 3;
}

for (let i = 0; i < numPublicInputs; i++) {
publicInputs.push(proofAsFields[publicInputsOffset + i]);
}
Expand Down Expand Up @@ -234,10 +229,8 @@ try {
if (testingHonk) {
// Cut off the serialised buffer size at start
proofStr = proofStr.substring(8);
// Get the part before and after the public inputs
const proofStart = proofStr.slice(0, 64 * 3);
const proofEnd = proofStr.substring(64 * 3 + 64 * numPublicInputs);
proofStr = proofStart + proofEnd;
// Get the part after the public inputs
proofStr = proofStr.substring(64 * numPublicInputs);
} else {
proofStr = proofStr.substring(64 * numPublicInputs);
}
Expand Down
2 changes: 1 addition & 1 deletion barretenberg/cpp/src/barretenberg/api/api_ultra_honk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ bool _verify(const bool honk_recursion_2, const std::filesystem::path& proof_pat
bool verified;
if (honk_recursion_2) {
const size_t HONK_PROOF_LENGTH = Flavor::PROOF_LENGTH_WITHOUT_PUB_INPUTS - IPA_PROOF_LENGTH;
const size_t num_public_inputs = static_cast<size_t>(uint64_t(proof[1]));
const size_t num_public_inputs = static_cast<size_t>(vk->num_public_inputs);
// The extra calculation is for the IPA proof length.
ASSERT(proof.size() == HONK_PROOF_LENGTH + IPA_PROOF_LENGTH + num_public_inputs);
const std::ptrdiff_t honk_proof_with_pub_inputs_length =
Expand Down
2 changes: 1 addition & 1 deletion barretenberg/cpp/src/barretenberg/api/prove_tube.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ void prove_tube(const std::string& output_path)
// circuit
// TODO(https://github.com/AztecProtocol/barretenberg/issues/1048): INSECURE - make this tube proof actually use
// these public inputs by turning proof into witnesses and calling set_public on each witness
auto num_inner_public_inputs = static_cast<uint32_t>(static_cast<uint256_t>(proof.mega_proof[1]));
auto num_inner_public_inputs = static_cast<uint32_t>(static_cast<uint256_t>(vk.mega->num_public_inputs));
num_inner_public_inputs -= bb::PAIRING_POINT_ACCUMULATOR_SIZE; // don't add the agg object

for (size_t i = 0; i < num_inner_public_inputs; i++) {
Expand Down
3 changes: 2 additions & 1 deletion barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,8 @@ HonkProof ClientIVC::construct_and_prove_hiding_circuit()
// circuit. So, these have to be preserved as public inputs to the hiding circuit (and, subsequently, as public
// inputs to the tube circuit) which are intermediate stages.
// TODO(https://github.com/AztecProtocol/barretenberg/issues/1048): link these properly, likely insecure
auto num_public_inputs = static_cast<uint32_t>(static_cast<uint256_t>(fold_proof[PUBLIC_INPUTS_SIZE_INDEX]));
auto num_public_inputs =
static_cast<uint32_t>(static_cast<uint256_t>(verification_queue[0].honk_verification_key->num_public_inputs));
num_public_inputs -= bb::PAIRING_POINT_ACCUMULATOR_SIZE; // exclude aggregation object
num_public_inputs -= bb::PROPAGATED_DATABUS_COMMITMENTS_SIZE; // exclude propagated databus commitments
for (size_t i = 0; i < num_public_inputs; i++) {
Expand Down
14 changes: 3 additions & 11 deletions barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -183,11 +183,6 @@ TEST_F(ClientIVCTests, BadProofFailure)
// Construct and accumulate a set of mocked private function execution circuits
size_t NUM_CIRCUITS = 4;
for (size_t idx = 0; idx < NUM_CIRCUITS; ++idx) {
if (idx == 3) { // At idx = 3, we've tampered with the one of the folding proofs so create the recursive
// folding verifier will throw an error.
EXPECT_ANY_THROW(circuit_producer.create_next_circuit(ivc, /*log2_num_gates=*/5));
break;
}
auto circuit = circuit_producer.create_next_circuit(ivc, /*log2_num_gates=*/5);
ivc.accumulate(circuit);

Expand All @@ -196,6 +191,7 @@ TEST_F(ClientIVCTests, BadProofFailure)
tamper_with_proof(ivc.verification_queue[0].proof); // tamper with first proof
}
}
EXPECT_FALSE(ivc.prove_and_verify());
}

// The IVC fails if the SECOND fold proof is tampered with
Expand All @@ -207,11 +203,6 @@ TEST_F(ClientIVCTests, BadProofFailure)
// Construct and accumulate a set of mocked private function execution circuits
size_t NUM_CIRCUITS = 4;
for (size_t idx = 0; idx < NUM_CIRCUITS; ++idx) {
if (idx == 3) { // At idx = 3, we've tampered with the one of the folding proofs so create the recursive
// folding verifier will throw an error.
EXPECT_ANY_THROW(circuit_producer.create_next_circuit(ivc, /*log2_num_gates=*/5));
break;
}
auto circuit = circuit_producer.create_next_circuit(ivc, /*log2_num_gates=*/5);
ivc.accumulate(circuit);

Expand All @@ -220,6 +211,7 @@ TEST_F(ClientIVCTests, BadProofFailure)
tamper_with_proof(ivc.verification_queue[1].proof); // tamper with second proof
}
}
EXPECT_FALSE(ivc.prove_and_verify());
}

// The IVC fails if the 3rd/FINAL fold proof is tampered with
Expand All @@ -239,7 +231,7 @@ TEST_F(ClientIVCTests, BadProofFailure)
EXPECT_EQ(ivc.verification_queue.size(), 1);
tamper_with_proof(ivc.verification_queue[0].proof); // tamper with the final fold proof

EXPECT_ANY_THROW(ivc.prove_and_verify());
EXPECT_FALSE(ivc.prove_and_verify());
}

EXPECT_TRUE(true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,6 @@ void create_dummy_vkey_and_proof(Builder& builder,
}

offset = bb::HONK_PROOF_PUBLIC_INPUT_OFFSET;
// first 3 things
builder.assert_equal(builder.add_variable(1 << log_circuit_size), proof_fields[0].witness_index);
builder.assert_equal(builder.add_variable(public_inputs_size), proof_fields[1].witness_index);
builder.assert_equal(builder.add_variable(Flavor::has_zero_row ? 1 : 0), proof_fields[2].witness_index);

// the inner public inputs
for (size_t i = 0; i < num_inner_public_inputs; i++) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,9 @@ ClientIVC::VerifierInputs create_mock_verification_queue_entry(const ClientIVC::
// Construct a mock Oink or PG proof
std::vector<FF> proof;
if (verification_type == ClientIVC::QUEUE_TYPE::OINK) {
proof = create_mock_oink_proof(dyadic_size, num_public_inputs, pub_inputs_offset);
proof = create_mock_oink_proof(num_public_inputs);
} else { // ClientIVC::QUEUE_TYPE::PG)
proof = create_mock_pg_proof(dyadic_size, num_public_inputs, pub_inputs_offset);
proof = create_mock_pg_proof(num_public_inputs);
}

// Construct a mock MegaHonk verification key
Expand All @@ -130,20 +130,13 @@ ClientIVC::VerifierInputs create_mock_verification_queue_entry(const ClientIVC::
* @brief Create a mock oink proof that has the correct structure but is not in general valid
*
*/
std::vector<ClientIVC::FF> create_mock_oink_proof(const size_t dyadic_size,
const size_t num_public_inputs,
const size_t pub_inputs_offset)
std::vector<ClientIVC::FF> create_mock_oink_proof(const size_t num_public_inputs)
{
using Flavor = ClientIVC::Flavor;
using FF = ClientIVC::FF;

std::vector<FF> proof;

// Populate proof metadata
proof.emplace_back(dyadic_size);
proof.emplace_back(num_public_inputs);
proof.emplace_back(pub_inputs_offset);

// Populate mock public inputs
for (size_t i = 0; i < num_public_inputs; ++i) {
proof.emplace_back(0);
Expand All @@ -165,15 +158,13 @@ std::vector<ClientIVC::FF> create_mock_oink_proof(const size_t dyadic_size,
* @brief Create a mock PG proof that has the correct structure but is not in general valid
*
*/
std::vector<ClientIVC::FF> create_mock_pg_proof(const size_t dyadic_size,
const size_t num_public_inputs,
const size_t pub_inputs_offset)
std::vector<ClientIVC::FF> create_mock_pg_proof(const size_t num_public_inputs)
{
using FF = ClientIVC::FF;
using DeciderProvingKeys = ClientIVC::DeciderProvingKeys;

// The first part of a PG proof is an Oink proof
std::vector<FF> proof = create_mock_oink_proof(dyadic_size, num_public_inputs, pub_inputs_offset);
std::vector<FF> proof = create_mock_oink_proof(num_public_inputs);

// Populate mock perturbator coefficients
for (size_t idx = 1; idx <= CONST_PG_LOG_N; idx++) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,9 @@ std::shared_ptr<ClientIVC> create_mock_ivc_from_constraints(const std::vector<Re

void mock_ivc_accumulation(const std::shared_ptr<ClientIVC>& ivc, ClientIVC::QUEUE_TYPE type, const bool is_kernel);

std::vector<ClientIVC::FF> create_mock_oink_proof(const size_t dyadic_size,
const size_t num_public_inputs,
const size_t pub_inputs_offset);
std::vector<ClientIVC::FF> create_mock_oink_proof(const size_t num_public_inputs);

std::vector<ClientIVC::FF> create_mock_pg_proof(const size_t dyadic_size,
const size_t num_public_inputs,
const size_t pub_inputs_offset);
std::vector<ClientIVC::FF> create_mock_pg_proof(const size_t num_public_inputs);

std::shared_ptr<ClientIVC::MegaVerificationKey> create_mock_honk_vk(const size_t dyadic_size,
const size_t num_public_inputs,
Expand Down
52 changes: 24 additions & 28 deletions barretenberg/cpp/src/barretenberg/dsl/acir_proofs/honk_contract.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -268,9 +268,6 @@ library Honk {


struct Proof {
uint256 circuitSize;
uint256 publicInputsSize;
uint256 publicInputsOffset;
// Free wires
Honk.G1ProofPoint w1;
Honk.G1ProofPoint w2;
Expand Down Expand Up @@ -310,15 +307,14 @@ struct Transcript {
}

library TranscriptLib {
function generateTranscript(Honk.Proof memory proof, bytes32[] calldata publicInputs, uint256 publicInputsSize)
function generateTranscript(Honk.Proof memory proof, bytes32[] calldata publicInputs, uint256 circuitSize, uint256 publicInputsSize, uint256 pubInputsOffset)
internal
pure
returns (Transcript memory t)
{
Fr previousChallenge;
(t.relationParameters, previousChallenge) =
generateRelationParametersChallenges(proof, publicInputs, publicInputsSize, previousChallenge);

generateRelationParametersChallenges(proof, publicInputs, circuitSize, publicInputsSize, pubInputsOffset, previousChallenge);

(t.alphas, previousChallenge) = generateAlphaChallenges(previousChallenge, proof);

Expand Down Expand Up @@ -348,25 +344,27 @@ library TranscriptLib {
function generateRelationParametersChallenges(
Honk.Proof memory proof,
bytes32[] calldata publicInputs,
uint256 circuitSize,
uint256 publicInputsSize,
uint256 pubInputsOffset,
Fr previousChallenge
) internal pure returns (Honk.RelationParameters memory rp, Fr nextPreviousChallenge) {
(rp.eta, rp.etaTwo, rp.etaThree, previousChallenge) =
generateEtaChallenge(proof, publicInputs, publicInputsSize);
generateEtaChallenge(proof, publicInputs, circuitSize, publicInputsSize, pubInputsOffset);

(rp.beta, rp.gamma, nextPreviousChallenge) = generateBetaAndGammaChallenges(previousChallenge, proof);

}

function generateEtaChallenge(Honk.Proof memory proof, bytes32[] calldata publicInputs, uint256 publicInputsSize)
function generateEtaChallenge(Honk.Proof memory proof, bytes32[] calldata publicInputs, uint256 circuitSize, uint256 publicInputsSize, uint256 pubInputsOffset)
internal
pure
returns (Fr eta, Fr etaTwo, Fr etaThree, Fr previousChallenge)
{
bytes32[] memory round0 = new bytes32[](3 + publicInputsSize + 12);
round0[0] = bytes32(proof.circuitSize);
round0[1] = bytes32(proof.publicInputsSize);
round0[2] = bytes32(proof.publicInputsOffset);
round0[0] = bytes32(circuitSize);
round0[1] = bytes32(publicInputsSize);
round0[2] = bytes32(pubInputsOffset);
for (uint256 i = 0; i < publicInputsSize; i++) {
round0[3 + i] = bytes32(publicInputs[i]);
}
Expand Down Expand Up @@ -554,24 +552,19 @@ library TranscriptLib {
}

function loadProof(bytes calldata proof) internal pure returns (Honk.Proof memory p) {
// Metadata
p.circuitSize = uint256(bytes32(proof[0x00:0x20]));
p.publicInputsSize = uint256(bytes32(proof[0x20:0x40]));
p.publicInputsOffset = uint256(bytes32(proof[0x40:0x60]));

// Commitments
p.w1 = bytesToG1ProofPoint(proof[0x60:0xe0]);
p.w1 = bytesToG1ProofPoint(proof[0x0:0x80]);

p.w2 = bytesToG1ProofPoint(proof[0xe0:0x160]);
p.w3 = bytesToG1ProofPoint(proof[0x160:0x1e0]);
p.w2 = bytesToG1ProofPoint(proof[0x80:0x100]);
p.w3 = bytesToG1ProofPoint(proof[0x100:0x180]);

// Lookup / Permutation Helper Commitments
p.lookupReadCounts = bytesToG1ProofPoint(proof[0x1e0:0x260]);
p.lookupReadTags = bytesToG1ProofPoint(proof[0x260:0x2e0]);
p.w4 = bytesToG1ProofPoint(proof[0x2e0:0x360]);
p.lookupInverses = bytesToG1ProofPoint(proof[0x360:0x3e0]);
p.zPerm = bytesToG1ProofPoint(proof[0x3e0:0x460]);
uint256 boundary = 0x460;
p.lookupReadCounts = bytesToG1ProofPoint(proof[0x180:0x200]);
p.lookupReadTags = bytesToG1ProofPoint(proof[0x200:0x280]);
p.w4 = bytesToG1ProofPoint(proof[0x280:0x300]);
p.lookupInverses = bytesToG1ProofPoint(proof[0x300:0x380]);
p.zPerm = bytesToG1ProofPoint(proof[0x380:0x400]);
uint256 boundary = 0x400;

// Sumcheck univariates
for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) {
Expand Down Expand Up @@ -1436,7 +1429,7 @@ abstract contract BaseHonkVerifier is IVerifier {
error ShpleminiFailed();

// Number of field elements in a ultra honk zero knowledge proof
uint256 constant PROOF_SIZE = 443;
uint256 constant PROOF_SIZE = 440;

function loadVerificationKey() internal pure virtual returns (Honk.VerificationKey memory);

Expand All @@ -1454,11 +1447,13 @@ abstract contract BaseHonkVerifier is IVerifier {
}

// Generate the fiat shamir challenges for the whole protocol
Transcript memory t = TranscriptLib.generateTranscript(p, publicInputs, vk.publicInputsSize);
// TODO(https://github.com/AztecProtocol/barretenberg/issues/1281): Add pubInputsOffset to VK or remove entirely.
Transcript memory t = TranscriptLib.generateTranscript(p, publicInputs, vk.circuitSize, vk.publicInputsSize, 1);

// Derive public input delta
// TODO(https://github.com/AztecProtocol/barretenberg/issues/1281): Add pubInputsOffset to VK or remove entirely.
t.relationParameters.publicInputsDelta = computePublicInputDelta(
publicInputs, t.relationParameters.beta, t.relationParameters.gamma, p.publicInputsOffset
publicInputs, t.relationParameters.beta, t.relationParameters.gamma, 1
);

// Sumcheck
Expand Down Expand Up @@ -1769,6 +1764,7 @@ contract HonkVerifier is BaseHonkVerifier(N, LOG_N, NUMBER_OF_PUBLIC_INPUTS) {

inline std::string get_honk_solidity_verifier(auto const& verification_key)
{
info("in get_honk_solidity_verifier");
std::ostringstream stream;
output_vk_sol_ultra_honk(stream, verification_key, "HonkVerificationKey");
return stream.str() + HONK_CONTRACT_SOURCE;
Expand Down
Loading