Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
14 changes: 14 additions & 0 deletions barretenberg/cpp/src/barretenberg/bbapi/bbapi_chonk.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "barretenberg/bbapi/bbapi_chonk.hpp"
#include "barretenberg/chonk/chonk_verifier.hpp"
#include "barretenberg/chonk/mock_circuit_producer.hpp"
#include "barretenberg/chonk/proof_compression.hpp"
#include "barretenberg/common/log.hpp"
#include "barretenberg/common/serialize.hpp"
#include "barretenberg/common/throw_or_abort.hpp"
Expand Down Expand Up @@ -253,4 +254,17 @@ ChonkStats::Response ChonkStats::execute([[maybe_unused]] BBApiRequest& request)
return response;
}

ChonkCompressProof::Response ChonkCompressProof::execute(const BBApiRequest& /*request*/) &&
{
BB_BENCH_NAME(MSGPACK_SCHEMA_NAME);
return { .compressed_proof = ProofCompressor::compress_chonk_proof(proof) };
}

ChonkDecompressProof::Response ChonkDecompressProof::execute(const BBApiRequest& /*request*/) &&
{
BB_BENCH_NAME(MSGPACK_SCHEMA_NAME);
size_t mega_num_pub = ProofCompressor::compressed_mega_num_public_inputs(compressed_proof.size());
return { .proof = ProofCompressor::decompress_chonk_proof(compressed_proof, mega_num_pub) };
}

} // namespace bb::bbapi
44 changes: 44 additions & 0 deletions barretenberg/cpp/src/barretenberg/bbapi/bbapi_chonk.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -239,4 +239,48 @@ struct ChonkStats {
bool operator==(const ChonkStats&) const = default;
};

/**
* @struct ChonkCompressProof
* @brief Compress a Chonk proof to a compact byte representation
*
* @details Uses point compression and uniform 32-byte encoding to reduce proof size (~1.72x).
*/
struct ChonkCompressProof {
static constexpr const char MSGPACK_SCHEMA_NAME[] = "ChonkCompressProof";

struct Response {
static constexpr const char MSGPACK_SCHEMA_NAME[] = "ChonkCompressProofResponse";
std::vector<uint8_t> compressed_proof;
MSGPACK_FIELDS(compressed_proof);
bool operator==(const Response&) const = default;
};

ChonkProof proof;
Response execute(const BBApiRequest& request = {}) &&;
MSGPACK_FIELDS(proof);
bool operator==(const ChonkCompressProof&) const = default;
};

/**
* @struct ChonkDecompressProof
* @brief Decompress a compressed Chonk proof back to field elements
*
* @details Derives mega_num_public_inputs from the compressed size automatically.
*/
struct ChonkDecompressProof {
static constexpr const char MSGPACK_SCHEMA_NAME[] = "ChonkDecompressProof";

struct Response {
static constexpr const char MSGPACK_SCHEMA_NAME[] = "ChonkDecompressProofResponse";
ChonkProof proof;
MSGPACK_FIELDS(proof);
bool operator==(const Response&) const = default;
};

std::vector<uint8_t> compressed_proof;
Response execute(const BBApiRequest& request = {}) &&;
MSGPACK_FIELDS(compressed_proof);
bool operator==(const ChonkDecompressProof&) const = default;
};

} // namespace bb::bbapi
4 changes: 4 additions & 0 deletions barretenberg/cpp/src/barretenberg/bbapi/bbapi_execute.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ using Command = NamedUnion<CircuitProve,
CircuitWriteSolidityVerifier,
ChonkCheckPrecomputedVk,
ChonkStats,
ChonkCompressProof,
ChonkDecompressProof,
Poseidon2Hash,
Poseidon2Permutation,
PedersenCommit,
Expand Down Expand Up @@ -82,6 +84,8 @@ using CommandResponse = NamedUnion<ErrorResponse,
CircuitWriteSolidityVerifier::Response,
ChonkCheckPrecomputedVk::Response,
ChonkStats::Response,
ChonkCompressProof::Response,
ChonkDecompressProof::Response,
Poseidon2Hash::Response,
Poseidon2Permutation::Response,
PedersenCommit::Response,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <chrono>

#include "barretenberg/chonk/chonk_verifier.hpp"
#include "barretenberg/chonk/proof_compression.hpp"
#include "barretenberg/chonk/test_bench_shared.hpp"
#include "barretenberg/common/google_bb_bench.hpp"

Expand Down Expand Up @@ -58,10 +59,43 @@ BENCHMARK_DEFINE_F(ChonkBench, Full)(benchmark::State& state)
}
}

/**
* @brief Benchmark proof compression (prover-side cost)
*/
BENCHMARK_DEFINE_F(ChonkBench, ProofCompress)(benchmark::State& state)
{
size_t NUM_APP_CIRCUITS = 1;
auto precomputed_vks = precompute_vks(NUM_APP_CIRCUITS);
auto [proof, vk_and_hash] = accumulate_and_prove_with_precomputed_vks(NUM_APP_CIRCUITS, precomputed_vks);

for (auto _ : state) {
benchmark::DoNotOptimize(ProofCompressor::compress_chonk_proof(proof));
}
}

/**
* @brief Benchmark proof decompression (verifier-side cost)
*/
BENCHMARK_DEFINE_F(ChonkBench, ProofDecompress)(benchmark::State& state)
{
size_t NUM_APP_CIRCUITS = 1;
auto precomputed_vks = precompute_vks(NUM_APP_CIRCUITS);
auto [proof, vk_and_hash] = accumulate_and_prove_with_precomputed_vks(NUM_APP_CIRCUITS, precomputed_vks);

auto compressed = ProofCompressor::compress_chonk_proof(proof);
size_t mega_num_pub_inputs = proof.mega_proof.size() - ChonkProof::HIDING_KERNEL_PROOF_LENGTH_WITHOUT_PUBLIC_INPUTS;

for (auto _ : state) {
benchmark::DoNotOptimize(ProofCompressor::decompress_chonk_proof(compressed, mega_num_pub_inputs));
}
}

#define ARGS Arg(ChonkBench::NUM_ITERATIONS_MEDIUM_COMPLEXITY)->Arg(2)

BENCHMARK_REGISTER_F(ChonkBench, Full)->Unit(benchmark::kMillisecond)->ARGS;
BENCHMARK_REGISTER_F(ChonkBench, VerificationOnly)->Unit(benchmark::kMillisecond);
BENCHMARK_REGISTER_F(ChonkBench, ProofCompress)->Unit(benchmark::kMillisecond);
BENCHMARK_REGISTER_F(ChonkBench, ProofDecompress)->Unit(benchmark::kMillisecond);

} // namespace

Expand Down
32 changes: 32 additions & 0 deletions barretenberg/cpp/src/barretenberg/chonk/chonk.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
#include "barretenberg/chonk/chonk.hpp"
#include "barretenberg/chonk/chonk_verifier.hpp"
#include "barretenberg/chonk/mock_circuit_producer.hpp"
#include "barretenberg/chonk/proof_compression.hpp"
#include "barretenberg/chonk/test_bench_shared.hpp"
#include "barretenberg/common/assert.hpp"
#include "barretenberg/common/log.hpp"
#include "barretenberg/common/mem.hpp"
#include "barretenberg/common/test.hpp"
#include "barretenberg/ecc/curves/grumpkin/grumpkin.hpp"
Expand Down Expand Up @@ -563,3 +565,33 @@ TEST_F(ChonkTests, MTailPropagationConsistency)
{
ChonkTests::test_hiding_kernel_io_propagation(HidingKernelIOField::ECC_OP_TABLES);
}

TEST_F(ChonkTests, ProofCompressionRoundtrip)
{
TestSettings settings{ .log2_num_gates = SMALL_LOG_2_NUM_GATES };
auto [proof, vk_and_hash] = accumulate_and_prove_ivc(/*num_app_circuits=*/1, settings);

auto original_flat = proof.to_field_elements();
info("Original proof size: ", original_flat.size(), " Fr elements (", original_flat.size() * 32, " bytes)");

auto compressed = ProofCompressor::compress_chonk_proof(proof);
double ratio = static_cast<double>(original_flat.size() * 32) / static_cast<double>(compressed.size());
info("Compressed proof size: ", compressed.size(), " bytes");
info("Compression ratio: ", ratio, "x");

// Compression should achieve at least 1.5x (commitments 4 Fr → 32 bytes, scalars 1:1)
EXPECT_GE(ratio, 1.5) << "Compression ratio " << ratio << "x is below the expected minimum of 1.5x";

size_t mega_num_pub_inputs = proof.mega_proof.size() - ChonkProof::HIDING_KERNEL_PROOF_LENGTH_WITHOUT_PUBLIC_INPUTS;
ChonkProof decompressed = ProofCompressor::decompress_chonk_proof(compressed, mega_num_pub_inputs);

// Verify element-by-element roundtrip
auto decompressed_flat = decompressed.to_field_elements();
ASSERT_EQ(decompressed_flat.size(), original_flat.size());
for (size_t i = 0; i < original_flat.size(); i++) {
ASSERT_EQ(decompressed_flat[i], original_flat[i]) << "Mismatch at element " << i;
}

// Verify the decompressed proof
EXPECT_TRUE(verify_chonk(decompressed, vk_and_hash));
}
Loading
Loading