From cb800b34ca769e3ff35efd529804880315b26585 Mon Sep 17 00:00:00 2001 From: Ryan Kim Date: Tue, 27 Aug 2024 17:47:55 +0900 Subject: [PATCH 01/25] refac(c/zk): remove unused type alias --- tachyon/c/zk/air/sp1/baby_bear_poseidon2_field_merkle_tree.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/tachyon/c/zk/air/sp1/baby_bear_poseidon2_field_merkle_tree.cc b/tachyon/c/zk/air/sp1/baby_bear_poseidon2_field_merkle_tree.cc index d384bd140..e3929cf17 100644 --- a/tachyon/c/zk/air/sp1/baby_bear_poseidon2_field_merkle_tree.cc +++ b/tachyon/c/zk/air/sp1/baby_bear_poseidon2_field_merkle_tree.cc @@ -4,7 +4,6 @@ using namespace tachyon; -using F = math::BabyBear; using Tree = c::zk::air::plonky3::baby_bear::Tree; tachyon_sp1_baby_bear_poseidon2_field_merkle_tree* From 30fdea59887e38e2c3456ba0cb28a6a5d5493770 Mon Sep 17 00:00:00 2001 From: Ryan Kim Date: Tue, 27 Aug 2024 17:56:31 +0900 Subject: [PATCH 02/25] chore(c/zk): fix typo --- .../zk/air/sp1/baby_bear_poseidon2_field_merkle_tree.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tachyon/c/zk/air/sp1/baby_bear_poseidon2_field_merkle_tree.h b/tachyon/c/zk/air/sp1/baby_bear_poseidon2_field_merkle_tree.h index 19b7538e4..6bfc3f654 100644 --- a/tachyon/c/zk/air/sp1/baby_bear_poseidon2_field_merkle_tree.h +++ b/tachyon/c/zk/air/sp1/baby_bear_poseidon2_field_merkle_tree.h @@ -20,21 +20,21 @@ extern "C" { * * Creates a deep copy of the given field merkle tree structure. * - * @param challenger A const pointer to the field merkle tree structure to - * clone. + * @param tree A const pointer to the field merkle tree structure + * to clone. * @return A pointer to the cloned field merkle tree structure. */ TACHYON_C_EXPORT tachyon_sp1_baby_bear_poseidon2_field_merkle_tree* tachyon_sp1_baby_bear_poseidon2_field_merkle_tree_clone( - const tachyon_sp1_baby_bear_poseidon2_field_merkle_tree* challenger); + const tachyon_sp1_baby_bear_poseidon2_field_merkle_tree* tree); /** * @brief Destroys a field merkle tree, freeing its resources. * - * @param pcs A pointer to the field merkle tree to destroy. + * @param tree A pointer to the field merkle tree to destroy. */ TACHYON_C_EXPORT void tachyon_sp1_baby_bear_poseidon2_field_merkle_tree_destroy( - tachyon_sp1_baby_bear_poseidon2_field_merkle_tree* field_merkle_tree); + tachyon_sp1_baby_bear_poseidon2_field_merkle_tree* tree); #ifdef __cplusplus } // extern "C" From 154009c33954d52a9a52d4e5f861ac57b80cb710 Mon Sep 17 00:00:00 2001 From: Ryan Kim Date: Tue, 27 Aug 2024 18:11:41 +0900 Subject: [PATCH 03/25] refac!: take the field merkle tree vector as a method argument BREAKING CHANGE: Updates the C API and Rust binding for `TwoAdicFriPCS` to require the Field Merkle tree vector as a method argument. This ensures that the vector remains alive for the lifetime of `TwoAdicFriPCS`. --- .../commitments/fri/two_adic_fri_impl.h | 6 +-- tachyon/c/zk/air/sp1/BUILD.bazel | 20 +++++++ ...by_bear_poseidon2_field_merkle_tree_vec.cc | 33 ++++++++++++ ...aby_bear_poseidon2_field_merkle_tree_vec.h | 52 +++++++++++++++++++ ...eidon2_field_merkle_tree_vec_type_traits.h | 39 ++++++++++++++ .../sp1/baby_bear_poseidon2_two_adic_fri.cc | 7 ++- .../sp1/baby_bear_poseidon2_two_adic_fri.h | 5 +- ...by_bear_poseidon2_two_adic_fri_unittest.cc | 10 +++- vendors/sp1/BUILD.bazel | 11 ++++ .../baby_bear_poseidon2_prover_data_vec.h | 39 ++++++++++++++ .../baby_bear_poseidon2_two_adic_fri_pcs.h | 4 +- vendors/sp1/src/baby_bear_poseidon2.rs | 44 +++++++++++++++- .../baby_bear_poseidon2_prover_data_vec.cc | 19 +++++++ .../baby_bear_poseidon2_two_adic_fri_pcs.cc | 6 ++- 14 files changed, 282 insertions(+), 13 deletions(-) create mode 100644 tachyon/c/zk/air/sp1/baby_bear_poseidon2_field_merkle_tree_vec.cc create mode 100644 tachyon/c/zk/air/sp1/baby_bear_poseidon2_field_merkle_tree_vec.h create mode 100644 tachyon/c/zk/air/sp1/baby_bear_poseidon2_field_merkle_tree_vec_type_traits.h create mode 100644 vendors/sp1/include/baby_bear_poseidon2_prover_data_vec.h create mode 100644 vendors/sp1/src/baby_bear_poseidon2_prover_data_vec.cc diff --git a/tachyon/c/crypto/commitments/fri/two_adic_fri_impl.h b/tachyon/c/crypto/commitments/fri/two_adic_fri_impl.h index b3de75695..e54cf061a 100644 --- a/tachyon/c/crypto/commitments/fri/two_adic_fri_impl.h +++ b/tachyon/c/crypto/commitments/fri/two_adic_fri_impl.h @@ -39,16 +39,16 @@ class TwoAdicFRIImpl using Base::Commit; - void Commit(Commitment* commitment, ProverData** prover_data_out) { + void Commit(Commitment* commitment, ProverData** prover_data_out, + std::vector>* prover_data_by_round) { std::unique_ptr prover_data(new ProverData); CHECK(this->mmcs_.Commit(std::move(ldes_), commitment, prover_data.get())); *prover_data_out = prover_data.get(); - prover_data_by_round_.push_back(std::move(prover_data)); + prover_data_by_round->push_back(std::move(prover_data)); } protected: std::vector> ldes_; - std::vector> prover_data_by_round_; }; } // namespace tachyon::c::crypto diff --git a/tachyon/c/zk/air/sp1/BUILD.bazel b/tachyon/c/zk/air/sp1/BUILD.bazel index 5f4cdb433..c11aa03ae 100644 --- a/tachyon/c/zk/air/sp1/BUILD.bazel +++ b/tachyon/c/zk/air/sp1/BUILD.bazel @@ -7,6 +7,8 @@ filegroup( srcs = [ "baby_bear_poseidon2_constants.h", "baby_bear_poseidon2_duplex_challenger.h", + "baby_bear_poseidon2_field_merkle_tree.h", + "baby_bear_poseidon2_field_merkle_tree_vec.h", "baby_bear_poseidon2_two_adic_fri.h", ], ) @@ -51,6 +53,23 @@ tachyon_cc_library( ], ) +tachyon_cc_library( + name = "baby_bear_poseidon2_field_merkle_tree_vec", + srcs = ["baby_bear_poseidon2_field_merkle_tree_vec.cc"], + hdrs = [ + "baby_bear_poseidon2_field_merkle_tree_vec.h", + "baby_bear_poseidon2_field_merkle_tree_vec_type_traits.h", + ], + deps = [ + ":baby_bear_poseidon2_constants", + "//tachyon/base/containers:container_util", + "//tachyon/c:export", + "//tachyon/c/base:type_traits_forward", + "//tachyon/crypto/commitments/merkle_tree/field_merkle_tree", + "//tachyon/math/finite_fields/baby_bear", + ], +) + tachyon_cc_library( name = "baby_bear_poseidon2_two_adic_fri", srcs = ["baby_bear_poseidon2_two_adic_fri.cc"], @@ -61,6 +80,7 @@ tachyon_cc_library( deps = [ ":baby_bear_poseidon2_constants", ":baby_bear_poseidon2_field_merkle_tree", + ":baby_bear_poseidon2_field_merkle_tree_vec", "//tachyon/c:export", "//tachyon/c/base:type_traits_forward", "//tachyon/c/crypto/commitments/fri:two_adic_fri_impl", diff --git a/tachyon/c/zk/air/sp1/baby_bear_poseidon2_field_merkle_tree_vec.cc b/tachyon/c/zk/air/sp1/baby_bear_poseidon2_field_merkle_tree_vec.cc new file mode 100644 index 000000000..608b3753e --- /dev/null +++ b/tachyon/c/zk/air/sp1/baby_bear_poseidon2_field_merkle_tree_vec.cc @@ -0,0 +1,33 @@ +#include "tachyon/c/zk/air/sp1/baby_bear_poseidon2_field_merkle_tree_vec.h" + +#include +#include + +#include "tachyon/base/containers/container_util.h" +#include "tachyon/c/zk/air/sp1/baby_bear_poseidon2_field_merkle_tree_vec_type_traits.h" + +using namespace tachyon; + +using Tree = c::zk::air::plonky3::baby_bear::Tree; +using TreeVec = std::vector>; + +tachyon_sp1_baby_bear_poseidon2_field_merkle_tree_vec* +tachyon_sp1_baby_bear_poseidon2_field_merkle_tree_vec_create() { + return c::base::c_cast(new TreeVec()); +} + +tachyon_sp1_baby_bear_poseidon2_field_merkle_tree_vec* +tachyon_sp1_baby_bear_poseidon2_field_merkle_tree_vec_clone( + const tachyon_sp1_baby_bear_poseidon2_field_merkle_tree_vec* tree_vec) { + const TreeVec& native_tree_vec = c::base::native_cast(*tree_vec); + TreeVec* cloned = new TreeVec(); + *cloned = base::Map(native_tree_vec, [](const std::unique_ptr& tree) { + return std::make_unique(*tree); + }); + return c::base::c_cast(cloned); +} + +void tachyon_sp1_baby_bear_poseidon2_field_merkle_tree_vec_destroy( + tachyon_sp1_baby_bear_poseidon2_field_merkle_tree_vec* tree) { + delete c::base::native_cast(tree); +} diff --git a/tachyon/c/zk/air/sp1/baby_bear_poseidon2_field_merkle_tree_vec.h b/tachyon/c/zk/air/sp1/baby_bear_poseidon2_field_merkle_tree_vec.h new file mode 100644 index 000000000..0f19e6c6b --- /dev/null +++ b/tachyon/c/zk/air/sp1/baby_bear_poseidon2_field_merkle_tree_vec.h @@ -0,0 +1,52 @@ +/** + * @file baby_bear_poseidon2_field_merkle_tree_vec.h + * @brief Defines the interface for the field merkle tree used within the + * SP1(BabyBear + Poseidon2) proof system. + */ + +#ifndef TACHYON_C_ZK_AIR_SP1_BABY_BEAR_POSEIDON2_FIELD_MERKLE_TREE_VEC_H_ +#define TACHYON_C_ZK_AIR_SP1_BABY_BEAR_POSEIDON2_FIELD_MERKLE_TREE_VEC_H_ + +#include "tachyon/c/export.h" + +struct tachyon_sp1_baby_bear_poseidon2_field_merkle_tree_vec {}; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Creates a new field merkle tree vector. + * + * @return A pointer to the newly created field merkle tree vector. + */ +TACHYON_C_EXPORT tachyon_sp1_baby_bear_poseidon2_field_merkle_tree_vec* +tachyon_sp1_baby_bear_poseidon2_field_merkle_tree_vec_create(); + +/** + * @brief Clones an existing field merkle tree vector structure. + * + * Creates a deep copy of the given field merkle tree vector structure. + * + * @param tree_vec A const pointer to the field merkle tree vector structure + * to clone. + * @return A pointer to the cloned field merkle tree vector structure. + */ +TACHYON_C_EXPORT tachyon_sp1_baby_bear_poseidon2_field_merkle_tree_vec* +tachyon_sp1_baby_bear_poseidon2_field_merkle_tree_vec_clone( + const tachyon_sp1_baby_bear_poseidon2_field_merkle_tree_vec* tree_vec); + +/** + * @brief Destroys a field merkle tree vector, freeing its resources. + * + * @param pcs A pointer to the field merkle tree vector to destroy. + */ +TACHYON_C_EXPORT void +tachyon_sp1_baby_bear_poseidon2_field_merkle_tree_vec_destroy( + tachyon_sp1_baby_bear_poseidon2_field_merkle_tree_vec* tree_vec); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // TACHYON_C_ZK_AIR_SP1_BABY_BEAR_POSEIDON2_FIELD_MERKLE_TREE_VEC_H_ diff --git a/tachyon/c/zk/air/sp1/baby_bear_poseidon2_field_merkle_tree_vec_type_traits.h b/tachyon/c/zk/air/sp1/baby_bear_poseidon2_field_merkle_tree_vec_type_traits.h new file mode 100644 index 000000000..e64cad0e2 --- /dev/null +++ b/tachyon/c/zk/air/sp1/baby_bear_poseidon2_field_merkle_tree_vec_type_traits.h @@ -0,0 +1,39 @@ +#ifndef TACHYON_C_ZK_AIR_SP1_BABY_BEAR_POSEIDON2_FIELD_MERKLE_TREE_VEC_TYPE_TRAITS_H_ +#define TACHYON_C_ZK_AIR_SP1_BABY_BEAR_POSEIDON2_FIELD_MERKLE_TREE_VEC_TYPE_TRAITS_H_ + +#include +#include + +#include "tachyon/c/base/type_traits_forward.h" +#include "tachyon/c/zk/air/sp1/baby_bear_poseidon2_constants.h" +#include "tachyon/c/zk/air/sp1/baby_bear_poseidon2_field_merkle_tree_vec.h" +#include "tachyon/crypto/commitments/merkle_tree/field_merkle_tree/field_merkle_tree.h" +#include "tachyon/math/finite_fields/baby_bear/baby_bear.h" + +namespace tachyon::c { +namespace zk::air::plonky3::baby_bear { + +using Tree = + tachyon::crypto::FieldMerkleTree; + +} // namespace zk::air::plonky3::baby_bear + +namespace base { + +template <> +struct TypeTraits< + std::vector>> { + using CType = tachyon_sp1_baby_bear_poseidon2_field_merkle_tree_vec; +}; + +template <> +struct TypeTraits { + using NativeType = + std::vector>; +}; + +} // namespace base +} // namespace tachyon::c + +#endif // TACHYON_C_ZK_AIR_SP1_BABY_BEAR_POSEIDON2_FIELD_MERKLE_TREE_VEC_TYPE_TRAITS_H_ diff --git a/tachyon/c/zk/air/sp1/baby_bear_poseidon2_two_adic_fri.cc b/tachyon/c/zk/air/sp1/baby_bear_poseidon2_two_adic_fri.cc index 9840fff1f..a2130c7fa 100644 --- a/tachyon/c/zk/air/sp1/baby_bear_poseidon2_two_adic_fri.cc +++ b/tachyon/c/zk/air/sp1/baby_bear_poseidon2_two_adic_fri.cc @@ -5,6 +5,7 @@ #include "tachyon/c/math/finite_fields/baby_bear/baby_bear_type_traits.h" #include "tachyon/c/math/matrix/baby_bear_row_major_matrix_type_traits.h" #include "tachyon/c/zk/air/sp1/baby_bear_poseidon2_field_merkle_tree_type_traits.h" +#include "tachyon/c/zk/air/sp1/baby_bear_poseidon2_field_merkle_tree_vec_type_traits.h" #include "tachyon/c/zk/air/sp1/baby_bear_poseidon2_two_adic_fri_type_traits.h" using namespace tachyon; @@ -113,8 +114,10 @@ tachyon_baby_bear* tachyon_sp1_baby_bear_poseidon2_two_adic_fri_coset_lde_batch( void tachyon_sp1_baby_bear_poseidon2_two_adic_fri_commit( tachyon_sp1_baby_bear_poseidon2_two_adic_fri* pcs, tachyon_baby_bear* commitment, - tachyon_sp1_baby_bear_poseidon2_field_merkle_tree** prover_data) { + tachyon_sp1_baby_bear_poseidon2_field_merkle_tree** prover_data, + tachyon_sp1_baby_bear_poseidon2_field_merkle_tree_vec* prover_data_vec) { using Commitment = MMCS::Commitment; c::base::native_cast(pcs)->Commit(reinterpret_cast(commitment), - reinterpret_cast(prover_data)); + reinterpret_cast(prover_data), + c::base::native_cast(prover_data_vec)); } diff --git a/tachyon/c/zk/air/sp1/baby_bear_poseidon2_two_adic_fri.h b/tachyon/c/zk/air/sp1/baby_bear_poseidon2_two_adic_fri.h index d3ed357db..1aae795e4 100644 --- a/tachyon/c/zk/air/sp1/baby_bear_poseidon2_two_adic_fri.h +++ b/tachyon/c/zk/air/sp1/baby_bear_poseidon2_two_adic_fri.h @@ -14,6 +14,7 @@ #include "tachyon/c/math/matrix/baby_bear_row_major_matrix.h" #include "tachyon/c/zk/air/sp1/baby_bear_poseidon2_constants.h" #include "tachyon/c/zk/air/sp1/baby_bear_poseidon2_field_merkle_tree.h" +#include "tachyon/c/zk/air/sp1/baby_bear_poseidon2_field_merkle_tree_vec.h" struct tachyon_sp1_baby_bear_poseidon2_two_adic_fri {}; @@ -78,11 +79,13 @@ tachyon_sp1_baby_bear_poseidon2_two_adic_fri_coset_lde_batch( * @param pcs A pointer to the two adic fri. * @param commitment A pointer to store the commitment. * @param prover_data A pointer to store the field merkle tree. + * @param prover_data_vec A pointer to the field merkle tree vector. */ TACHYON_C_EXPORT void tachyon_sp1_baby_bear_poseidon2_two_adic_fri_commit( tachyon_sp1_baby_bear_poseidon2_two_adic_fri* pcs, tachyon_baby_bear* commitment, - tachyon_sp1_baby_bear_poseidon2_field_merkle_tree** prover_data); + tachyon_sp1_baby_bear_poseidon2_field_merkle_tree** prover_data, + tachyon_sp1_baby_bear_poseidon2_field_merkle_tree_vec* prover_data_vec); #ifdef __cplusplus } // extern "C" diff --git a/tachyon/c/zk/air/sp1/baby_bear_poseidon2_two_adic_fri_unittest.cc b/tachyon/c/zk/air/sp1/baby_bear_poseidon2_two_adic_fri_unittest.cc index 17d8f6b2e..083c5acf6 100644 --- a/tachyon/c/zk/air/sp1/baby_bear_poseidon2_two_adic_fri_unittest.cc +++ b/tachyon/c/zk/air/sp1/baby_bear_poseidon2_two_adic_fri_unittest.cc @@ -22,14 +22,20 @@ class TwoAdicFRITest : public testing::Test { public: void SetUp() override { pcs_ = tachyon_sp1_baby_bear_poseidon2_two_adic_fri_create(1, 10, 8); + prover_data_vec_ = + tachyon_sp1_baby_bear_poseidon2_field_merkle_tree_vec_create(); } void TearDown() override { tachyon_sp1_baby_bear_poseidon2_two_adic_fri_destroy(pcs_); + tachyon_sp1_baby_bear_poseidon2_field_merkle_tree_vec_destroy( + prover_data_vec_); } protected: tachyon_sp1_baby_bear_poseidon2_two_adic_fri* pcs_ = nullptr; + tachyon_sp1_baby_bear_poseidon2_field_merkle_tree_vec* prover_data_vec_ = + nullptr; }; } // namespace @@ -61,8 +67,8 @@ TEST_F(TwoAdicFRITest, APIs) { kCols, c::base::c_cast(shift), &new_rows); tachyon_baby_bear commitment[TACHYON_PLONKY3_BABY_BEAR_POSEIDON2_CHUNK]; tachyon_sp1_baby_bear_poseidon2_field_merkle_tree* prover_data = nullptr; - tachyon_sp1_baby_bear_poseidon2_two_adic_fri_commit(pcs_, commitment, - &prover_data); + tachyon_sp1_baby_bear_poseidon2_two_adic_fri_commit( + pcs_, commitment, &prover_data, prover_data_vec_); Commitment native_commitment; ProverData native_prover_data; diff --git a/vendors/sp1/BUILD.bazel b/vendors/sp1/BUILD.bazel index e5db9908b..3049e052a 100644 --- a/vendors/sp1/BUILD.bazel +++ b/vendors/sp1/BUILD.bazel @@ -17,6 +17,7 @@ tachyon_rust_library( ":baby_bear_poseidon2_cxx_bridge", ":baby_bear_poseidon2_duplex_challenger", ":baby_bear_poseidon2_prover_data", + ":baby_bear_poseidon2_prover_data_vec", ":baby_bear_poseidon2_two_adic_fri_pcs", "//tachyon/rs:tachyon_rs", ], @@ -64,6 +65,7 @@ tachyon_cc_library( hdrs = [ "include/baby_bear_poseidon2_duplex_challenger.h", "include/baby_bear_poseidon2_prover_data.h", + "include/baby_bear_poseidon2_prover_data_vec.h", "include/baby_bear_poseidon2_two_adic_fri_pcs.h", ], deps = [ @@ -91,6 +93,15 @@ tachyon_cc_library( ], ) +tachyon_cc_library( + name = "baby_bear_poseidon2_prover_data_vec", + srcs = ["src/baby_bear_poseidon2_prover_data_vec.cc"], + deps = [ + ":baby_bear_poseidon2_api_hdrs", + ":baby_bear_poseidon2_cxx_bridge/include", + ], +) + tachyon_cc_library( name = "baby_bear_poseidon2_two_adic_fri_pcs", srcs = ["src/baby_bear_poseidon2_two_adic_fri_pcs.cc"], diff --git a/vendors/sp1/include/baby_bear_poseidon2_prover_data_vec.h b/vendors/sp1/include/baby_bear_poseidon2_prover_data_vec.h new file mode 100644 index 000000000..8ff9e0dac --- /dev/null +++ b/vendors/sp1/include/baby_bear_poseidon2_prover_data_vec.h @@ -0,0 +1,39 @@ +#ifndef VENDORS_SP1_INCLUDE_BABY_BEAR_POSEIDON2_PROVER_DATA_VEC_H_ +#define VENDORS_SP1_INCLUDE_BABY_BEAR_POSEIDON2_PROVER_DATA_VEC_H_ + +#include + +#include "tachyon/c/zk/air/sp1/baby_bear_poseidon2_field_merkle_tree_vec.h" + +namespace tachyon::sp1_api::baby_bear_poseidon2 { + +struct TachyonBabyBear; + +class ProverDataVec { + public: + explicit ProverDataVec( + tachyon_sp1_baby_bear_poseidon2_field_merkle_tree_vec* tree_vec) + : tree_vec_(tree_vec) {} + ProverDataVec(const ProverDataVec& other) = delete; + ProverDataVec& operator=(const ProverDataVec& other) = delete; + ~ProverDataVec(); + + tachyon_sp1_baby_bear_poseidon2_field_merkle_tree_vec* tree_vec() { + return tree_vec_; + } + const tachyon_sp1_baby_bear_poseidon2_field_merkle_tree_vec* tree_vec() + const { + return tree_vec_; + } + + std::unique_ptr clone() const; + + private: + tachyon_sp1_baby_bear_poseidon2_field_merkle_tree_vec* tree_vec_ = nullptr; +}; + +std::unique_ptr new_prover_data_vec(); + +} // namespace tachyon::sp1_api::baby_bear_poseidon2 + +#endif // VENDORS_SP1_INCLUDE_BABY_BEAR_POSEIDON2_PROVER_DATA_VEC_H_ diff --git a/vendors/sp1/include/baby_bear_poseidon2_two_adic_fri_pcs.h b/vendors/sp1/include/baby_bear_poseidon2_two_adic_fri_pcs.h index 1153b0674..e3ce8e152 100644 --- a/vendors/sp1/include/baby_bear_poseidon2_two_adic_fri_pcs.h +++ b/vendors/sp1/include/baby_bear_poseidon2_two_adic_fri_pcs.h @@ -14,6 +14,7 @@ namespace tachyon::sp1_api::baby_bear_poseidon2 { class CommitResult; class ProverData; +class ProverDataVec; struct TachyonBabyBear; class TwoAdicFriPcs { @@ -28,7 +29,8 @@ class TwoAdicFriPcs { rust::Slice coset_lde_batch( rust::Slice values, size_t cols, const TachyonBabyBear& shift) const; - std::unique_ptr commit() const; + std::unique_ptr commit( + const ProverDataVec& prover_data_vec) const; private: tachyon_sp1_baby_bear_poseidon2_two_adic_fri* pcs_; diff --git a/vendors/sp1/src/baby_bear_poseidon2.rs b/vendors/sp1/src/baby_bear_poseidon2.rs index 0bf928182..ba74f463e 100644 --- a/vendors/sp1/src/baby_bear_poseidon2.rs +++ b/vendors/sp1/src/baby_bear_poseidon2.rs @@ -43,6 +43,15 @@ pub mod ffi { fn clone(&self) -> UniquePtr; } + unsafe extern "C++" { + include!("vendors/sp1/include/baby_bear_poseidon2_prover_data_vec.h"); + + type ProverDataVec; + + fn new_prover_data_vec() -> UniquePtr; + fn clone(&self) -> UniquePtr; + } + unsafe extern "C++" { include!("vendors/sp1/include/baby_bear_poseidon2_two_adic_fri_pcs.h"); @@ -60,7 +69,7 @@ pub mod ffi { cols: usize, shift: &TachyonBabyBear, ) -> &mut [TachyonBabyBear]; - fn commit(&self) -> UniquePtr; + fn commit(&self, prover_data_vec: &ProverDataVec) -> UniquePtr; } } @@ -179,9 +188,39 @@ impl ProverData { } } +pub struct ProverDataVec { + inner: cxx::UniquePtr, + _marker: PhantomData, +} + +impl Clone for ProverDataVec { + fn clone(&self) -> Self { + Self { + inner: self.inner.clone(), + _marker: PhantomData, + } + } +} + +impl Debug for ProverDataVec { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("ProverDataVec").finish() + } +} + +impl ProverDataVec { + pub fn new(inner: cxx::UniquePtr) -> Self { + Self { + inner, + _marker: PhantomData, + } + } +} + pub struct TwoAdicFriPcs { log_n: usize, inner: cxx::UniquePtr, + prover_data_vec: ProverDataVec, _marker: PhantomData<(Val, Dft, InputMmcs, FriMmcs)>, } @@ -206,6 +245,7 @@ where fri_config.num_queries, fri_config.proof_of_work_bits, ), + prover_data_vec: ProverDataVec::new(ffi::new_prover_data_vec()), _marker: PhantomData, } } @@ -236,7 +276,7 @@ where } pub fn do_commit(&self) -> ProverData { - ProverData::new(self.inner.commit()) + ProverData::new(self.inner.commit(&self.prover_data_vec.inner)) } } diff --git a/vendors/sp1/src/baby_bear_poseidon2_prover_data_vec.cc b/vendors/sp1/src/baby_bear_poseidon2_prover_data_vec.cc new file mode 100644 index 000000000..c7341f138 --- /dev/null +++ b/vendors/sp1/src/baby_bear_poseidon2_prover_data_vec.cc @@ -0,0 +1,19 @@ +#include "vendors/sp1/include/baby_bear_poseidon2_prover_data_vec.h" + +namespace tachyon::sp1_api::baby_bear_poseidon2 { + +ProverDataVec::~ProverDataVec() { + tachyon_sp1_baby_bear_poseidon2_field_merkle_tree_vec_destroy(tree_vec_); +} + +std::unique_ptr ProverDataVec::clone() const { + return std::make_unique( + tachyon_sp1_baby_bear_poseidon2_field_merkle_tree_vec_clone(tree_vec_)); +} + +std::unique_ptr new_prover_data_vec() { + return std::make_unique( + tachyon_sp1_baby_bear_poseidon2_field_merkle_tree_vec_create()); +} + +} // namespace tachyon::sp1_api::baby_bear_poseidon2 diff --git a/vendors/sp1/src/baby_bear_poseidon2_two_adic_fri_pcs.cc b/vendors/sp1/src/baby_bear_poseidon2_two_adic_fri_pcs.cc index 58303c4b5..4920cf3ca 100644 --- a/vendors/sp1/src/baby_bear_poseidon2_two_adic_fri_pcs.cc +++ b/vendors/sp1/src/baby_bear_poseidon2_two_adic_fri_pcs.cc @@ -32,11 +32,13 @@ rust::Slice TwoAdicFriPcs::coset_lde_batch( return {reinterpret_cast(data), new_rows * cols}; } -std::unique_ptr TwoAdicFriPcs::commit() const { +std::unique_ptr TwoAdicFriPcs::commit( + const ProverDataVec& prover_data_vec) const { std::unique_ptr ret(new ProverData); tachyon_sp1_baby_bear_poseidon2_two_adic_fri_commit( const_cast(pcs_), - ret->commitment(), ret->tree_ptr()); + ret->commitment(), ret->tree_ptr(), + const_cast(prover_data_vec).tree_vec()); return ret; } From 133bdaaed20a358693d93f984007370d734cb106 Mon Sep 17 00:00:00 2001 From: Ryan Kim Date: Wed, 28 Aug 2024 16:33:47 +0900 Subject: [PATCH 04/25] refac(sp1): remove unneeded `Debug` trait constraint --- vendors/sp1/src/baby_bear_poseidon2.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vendors/sp1/src/baby_bear_poseidon2.rs b/vendors/sp1/src/baby_bear_poseidon2.rs index ba74f463e..12a19f228 100644 --- a/vendors/sp1/src/baby_bear_poseidon2.rs +++ b/vendors/sp1/src/baby_bear_poseidon2.rs @@ -105,7 +105,7 @@ impl DuplexChallenger CanObserve for DuplexChallenger where - F: Copy + Debug, + F: Copy, P: CryptographicPermutation<[F; WIDTH]>, { fn observe(&mut self, value: F) { @@ -118,7 +118,7 @@ where impl CanObserve<[F; N]> for DuplexChallenger where - F: Copy + Debug, + F: Copy, P: CryptographicPermutation<[F; WIDTH]>, { fn observe(&mut self, values: [F; N]) { @@ -131,7 +131,7 @@ where impl CanObserve>> for DuplexChallenger where - F: Copy + Debug, + F: Copy, P: CryptographicPermutation<[F; WIDTH]>, { fn observe(&mut self, valuess: Vec>) { From 04d6871316dab539e54852aa2aea57dbe779e010 Mon Sep 17 00:00:00 2001 From: Ryan Kim Date: Wed, 28 Aug 2024 16:46:14 +0900 Subject: [PATCH 05/25] feat(sp1): allow `DuplexChallenger` to sample extension fields See https://github.com/Plonky3/Plonky3/blob/eeb4e37/challenger/src/duplex_challenger.rs#L122-L142. --- vendors/sp1/src/baby_bear_poseidon2.rs | 9 ++++++--- vendors/sp1/src/challenger.rs | 14 +++++++++++++- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/vendors/sp1/src/baby_bear_poseidon2.rs b/vendors/sp1/src/baby_bear_poseidon2.rs index 12a19f228..14cb30be7 100644 --- a/vendors/sp1/src/baby_bear_poseidon2.rs +++ b/vendors/sp1/src/baby_bear_poseidon2.rs @@ -143,14 +143,17 @@ where } } -impl CanSample +impl CanSample for DuplexChallenger where F: Field, + EF: ExtensionField, P: CryptographicPermutation<[F; WIDTH]>, { - fn sample(&mut self) -> F { - *unsafe { std::mem::transmute::<_, Box>(self.inner.pin_mut().sample()) } + fn sample(&mut self) -> EF { + EF::from_base_fn(|_| *unsafe { + std::mem::transmute::<_, Box>(self.inner.pin_mut().sample()) + }) } } diff --git a/vendors/sp1/src/challenger.rs b/vendors/sp1/src/challenger.rs index b33dc6d4f..b6bddd070 100644 --- a/vendors/sp1/src/challenger.rs +++ b/vendors/sp1/src/challenger.rs @@ -3,10 +3,11 @@ mod test { use crate::baby_bear_poseidon2::DuplexChallenger as TachyonDuplexChallenger; use p3_baby_bear::BabyBear; use p3_challenger::{CanObserve, CanSample, DuplexChallenger}; - use p3_field::AbstractField; + use p3_field::{extension::BinomialExtensionField, AbstractField}; use sp1_core::utils::baby_bear_poseidon2::{my_perm, Perm}; type F = BabyBear; + type EF = BinomialExtensionField; #[test] fn test_duplex_challenger() { @@ -39,5 +40,16 @@ mod test { ) ); } + + for _ in 0..10 { + assert_eq!( + as CanSample>::sample( + &mut tachyon_duplex_challenger + ), + as CanSample>::sample( + &mut duplex_challenger + ) + ); + } } } From f34a409a43fdfec94e87088aa58bb311fd543d70 Mon Sep 17 00:00:00 2001 From: Ryan Kim Date: Wed, 28 Aug 2024 16:59:17 +0900 Subject: [PATCH 06/25] feat(sp1): add missing traits for `DuplexChallenger` Implements necessary traits for `DuplexChallenger`, enabling a seamless replacement of Plonky3's `DuplexChallenger` with Tachyon's version. See below links: - https://github.com/Plonky3/Plonky3/blob/eeb4e37/challenger/src/duplex_challenger.rs#L54-L60 - https://github.com/Plonky3/Plonky3/blob/eeb4e37/challenger/src/duplex_challenger.rs#L93-L104 - https://github.com/Plonky3/Plonky3/blob/eeb4e37/challenger/src/duplex_challenger.rs#L144-L157 - https://github.com/Plonky3/Plonky3/blob/eeb4e37/challenger/src/grinding_challenger.rs#L22-L40 --- Cargo.Bazel.lock | 6 ++- Cargo.lock | 1 + vendors/sp1/Cargo.toml | 1 + vendors/sp1/src/baby_bear_poseidon2.rs | 66 +++++++++++++++++++++++++- vendors/sp1/src/two_adic_fri_pcs.rs | 10 ++-- 5 files changed, 78 insertions(+), 6 deletions(-) diff --git a/Cargo.Bazel.lock b/Cargo.Bazel.lock index 09737038c..1259a0f78 100644 --- a/Cargo.Bazel.lock +++ b/Cargo.Bazel.lock @@ -1,5 +1,5 @@ { - "checksum": "9871a4efaf95d41779221d5e5a0d86242b4e5832107cd0c8e50ccc004fb34199", + "checksum": "cea03189298ccac5555669cf0374dddee03d3105364e2cc46f2d04aa4ed8ad0c", "crates": { "addchain 0.2.0": { "name": "addchain", @@ -18232,6 +18232,10 @@ { "id": "sp1-prover 1.0.1", "target": "sp1_prover" + }, + { + "id": "tracing 0.1.40", + "target": "tracing" } ], "selects": {} diff --git a/Cargo.lock b/Cargo.lock index 2e86e81e7..f79570f47 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3545,6 +3545,7 @@ dependencies = [ "sp1-primitives", "sp1-prover", "tachyon_rs", + "tracing", ] [[package]] diff --git a/vendors/sp1/Cargo.toml b/vendors/sp1/Cargo.toml index 6d710de90..44c643b42 100644 --- a/vendors/sp1/Cargo.toml +++ b/vendors/sp1/Cargo.toml @@ -31,6 +31,7 @@ p3-util = "0.1.3-succinct" sp1-core = { git = "https://github.com/kroma-network/sp1.git", rev = "dd032eb" } sp1-prover = { git = "https://github.com/kroma-network/sp1.git", rev = "dd032eb" } sp1-primitives = { git = "https://github.com/kroma-network/sp1.git", rev = "dd032eb" } +tracing = "0.1.37" tachyon_rs = { path = "../../tachyon/rs" } [dev-dependencies] diff --git a/vendors/sp1/src/baby_bear_poseidon2.rs b/vendors/sp1/src/baby_bear_poseidon2.rs index 14cb30be7..918aad495 100644 --- a/vendors/sp1/src/baby_bear_poseidon2.rs +++ b/vendors/sp1/src/baby_bear_poseidon2.rs @@ -1,19 +1,21 @@ use std::{fmt::Debug, marker::PhantomData}; use p3_baby_bear::BabyBear; -use p3_challenger::{CanObserve, CanSample, GrindingChallenger}; +use p3_challenger::{CanObserve, CanSample, CanSampleBits, FieldChallenger, GrindingChallenger}; use p3_commit::{Mmcs, OpenedValues, Pcs, PolynomialSpace, TwoAdicMultiplicativeCoset}; use p3_dft::TwoAdicSubgroupDft; -use p3_field::{ExtensionField, Field, PackedField, PackedValue, TwoAdicField}; +use p3_field::{ExtensionField, Field, PackedField, PackedValue, PrimeField64, TwoAdicField}; use p3_fri::{FriConfig, TwoAdicFriPcsProof, VerificationError}; use p3_matrix::{ bitrev::BitReversableMatrix, dense::{DenseMatrix, RowMajorMatrix}, Matrix, }; +use p3_maybe_rayon::prelude::*; use p3_symmetric::{CryptographicPermutation, Hash}; use p3_util::log2_strict_usize; use tachyon_rs::math::finite_fields::baby_bear::BabyBear as TachyonBabyBearImpl; +use tracing::instrument; pub struct TachyonBabyBear(pub TachyonBabyBearImpl); @@ -78,6 +80,10 @@ pub struct DuplexChallenger { _marker: PhantomData<(F, P)>, } +// NOTE(chokobole): This is needed by `GrindingChallenger` trait. +// See https://github.com/Plonky3/Plonky3/blob/eeb4e37/challenger/src/grinding_challenger.rs#L8-L9. +unsafe impl Sync for ffi::DuplexChallenger {} + impl Clone for DuplexChallenger { fn clone(&self) -> Self { Self { @@ -102,6 +108,14 @@ impl DuplexChallenger FieldChallenger + for DuplexChallenger +where + F: PrimeField64, + P: CryptographicPermutation<[F; WIDTH]>, +{ +} + impl CanObserve for DuplexChallenger where @@ -128,6 +142,19 @@ where } } +impl CanObserve> + for DuplexChallenger +where + F: Copy, + P: CryptographicPermutation<[F; WIDTH]>, +{ + fn observe(&mut self, values: Hash) { + for value in values { + self.observe(value); + } + } +} + impl CanObserve>> for DuplexChallenger where @@ -157,6 +184,41 @@ where } } +impl CanSampleBits + for DuplexChallenger +where + F: PrimeField64, + P: CryptographicPermutation<[F; WIDTH]>, +{ + fn sample_bits(&mut self, bits: usize) -> usize { + debug_assert!(bits < (usize::BITS as usize)); + debug_assert!((1 << bits) < F::ORDER_U64); + let rand_f: F = self.sample(); + let rand_usize = rand_f.as_canonical_u64() as usize; + rand_usize & ((1 << bits) - 1) + } +} + +impl GrindingChallenger + for DuplexChallenger +where + F: PrimeField64, + P: CryptographicPermutation<[F; WIDTH]>, +{ + type Witness = F; + + #[instrument(name = "grind for proof-of-work witness", skip_all)] + fn grind(&mut self, bits: usize) -> Self::Witness { + let witness = (0..F::ORDER_U64) + .into_par_iter() + .map(|i| F::from_canonical_u64(i)) + .find_any(|witness| self.clone().check_witness(bits, *witness)) + .expect("failed to find witness"); + assert!(self.check_witness(bits, witness)); + witness + } +} + pub struct ProverData { inner: cxx::UniquePtr, pub ldes: Vec>, diff --git a/vendors/sp1/src/two_adic_fri_pcs.rs b/vendors/sp1/src/two_adic_fri_pcs.rs index 6f16864dc..09fd58e60 100644 --- a/vendors/sp1/src/two_adic_fri_pcs.rs +++ b/vendors/sp1/src/two_adic_fri_pcs.rs @@ -10,11 +10,15 @@ mod test { use rand::{Rng, SeedableRng}; use rand_chacha::ChaCha20Rng; use sp1_core::utils::baby_bear_poseidon2::{ - default_fri_config, my_perm, Challenge, ChallengeMmcs, Challenger, Dft, MyCompress, MyHash, - Val, ValMmcs, + default_fri_config, my_perm, Challenge, ChallengeMmcs, Dft, MyCompress, MyHash, Perm, Val, + ValMmcs, }; - use crate::baby_bear_poseidon2::TwoAdicFriPcs as TachyonTwoAdicFriPcs; + use crate::baby_bear_poseidon2::{ + DuplexChallenger as TachyonDuplexChallenger, TwoAdicFriPcs as TachyonTwoAdicFriPcs, + }; + + type Challenger = TachyonDuplexChallenger; fn seeded_rng() -> impl Rng { ChaCha20Rng::seed_from_u64(0) From 356130430ed54e0c5deb3c458624635191eaeca6 Mon Sep 17 00:00:00 2001 From: Ryan Kim Date: Thu, 29 Aug 2024 10:53:38 +0900 Subject: [PATCH 07/25] feat(base): add `Container4DTo(Hex)String()` This utility is helpful for debugging the `OpenedValues` which is an argument of the method `TwoAdicFriPCS::CreateOpeningProof()` --- tachyon/base/strings/string_util.h | 31 ++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/tachyon/base/strings/string_util.h b/tachyon/base/strings/string_util.h index dde65ba14..fdd4de77d 100644 --- a/tachyon/base/strings/string_util.h +++ b/tachyon/base/strings/string_util.h @@ -183,6 +183,21 @@ std::string Container3DToString(const Container& data) { return ss.str(); } +template +std::string Container4DToString(const Container& data) { + size_t size = std::size(data); + + if (size == 0) return "[]"; + + std::stringstream ss; + ss << "["; + for (size_t i = 0; i < size - 1; ++i) { + ss << Container3DToString(data[i]) << ", "; + } + ss << Container3DToString(data[size - 1]) << "]"; + return ss.str(); +} + template std::string ContainerToHexString(const Container& data, bool pad_zero = false) { size_t size = std::size(data); @@ -230,6 +245,22 @@ std::string Container3DToHexString(const Container& data, return ss.str(); } +template +std::string Container4DToHexString(const Container& data, + bool pad_zero = false) { + size_t size = std::size(data); + + if (size == 0) return "[]"; + + std::stringstream ss; + ss << "["; + for (size_t i = 0; i < size - 1; ++i) { + ss << Container3DToHexString(data[i], pad_zero) << ", "; + } + ss << Container3DToHexString(data[size - 1], pad_zero) << "]"; + return ss.str(); +} + } // namespace tachyon::base #endif // TACHYON_BASE_STRINGS_STRING_UTIL_H_ From 54987905b49039ca8a3290e818def3222564a13c Mon Sep 17 00:00:00 2001 From: Ryan Kim Date: Thu, 29 Aug 2024 14:05:14 +0900 Subject: [PATCH 08/25] feat(math): remove unused feature --- tachyon/math/finite_fields/prime_field_base.h | 24 ------------------- 1 file changed, 24 deletions(-) diff --git a/tachyon/math/finite_fields/prime_field_base.h b/tachyon/math/finite_fields/prime_field_base.h index 08b3684ce..210045dcc 100644 --- a/tachyon/math/finite_fields/prime_field_base.h +++ b/tachyon/math/finite_fields/prime_field_base.h @@ -193,7 +193,6 @@ class Copyable< using value_type = typename T::value_type; using BigInt = typename T::BigIntTy; - static bool s_allow_value_greater_than_or_equal_to_modulus; static bool s_is_in_montgomery; static bool WriteTo(const T& prime_field, Buffer* buffer) { @@ -216,11 +215,6 @@ class Copyable< static bool ReadFrom(const ReadOnlyBuffer& buffer, T* prime_field) { value_type v; if (!buffer.Read(&v)) return false; - if (s_allow_value_greater_than_or_equal_to_modulus) { - if (v >= T::Config::kModulus) { - v %= T::Config::kModulus; - } - } if constexpr (T::Config::kUseMontgomery) { if (s_is_in_montgomery) { *prime_field = T::FromMontgomery(v); @@ -240,12 +234,6 @@ class Copyable< } }; -// static -template -bool Copyable, T>>>:: - s_allow_value_greater_than_or_equal_to_modulus = false; - // static template bool Copyable, @@ -259,7 +247,6 @@ class RapidJsonValueConverter< using value_type = typename T::value_type; using BigInt = typename T::BigIntTy; - static bool s_allow_value_greater_than_or_equal_to_modulus; static bool s_is_in_montgomery; template @@ -289,11 +276,6 @@ class RapidJsonValueConverter< if (!RapidJsonValueConverter::To(json_value, key, &v, error)) return false; - if (s_allow_value_greater_than_or_equal_to_modulus) { - if (v >= T::Config::kModulus) { - v %= T::Config::kModulus; - } - } if constexpr (T::Config::kUseMontgomery) { if (s_is_in_montgomery) { *value = T::FromMontgomery(v); @@ -305,12 +287,6 @@ class RapidJsonValueConverter< } }; -// static -template -bool RapidJsonValueConverter< - T, std::enable_if_t, T>>>:: - s_allow_value_greater_than_or_equal_to_modulus = false; - // static template bool RapidJsonValueConverter< From ab93fec0c1f38133f49cb5d8ec3f703e63981288 Mon Sep 17 00:00:00 2001 From: Ryan Kim Date: Fri, 30 Aug 2024 14:48:40 +0900 Subject: [PATCH 09/25] refac(crypto): add `OpeningPoints` and `OpeningPointsForRound` type --- tachyon/crypto/commitments/fri/two_adic_fri.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/tachyon/crypto/commitments/fri/two_adic_fri.h b/tachyon/crypto/commitments/fri/two_adic_fri.h index 5cd4c028c..e0b3790ef 100644 --- a/tachyon/crypto/commitments/fri/two_adic_fri.h +++ b/tachyon/crypto/commitments/fri/two_adic_fri.h @@ -53,7 +53,8 @@ class TwoAdicFRI { using InputProof = std::vector>; using FRIProof = crypto::FRIProof; - using Points = std::vector>; + using OpeningPointsForRound = std::vector>; + using OpeningPoints = std::vector; using OpenedValuesForMat = std::vector>; using OpenedValuesForRound = std::vector; @@ -88,7 +89,7 @@ class TwoAdicFRI { [[nodiscard]] bool CreateOpeningProof( const std::vector& prover_data_by_round, - const std::vector& points_by_round, Challenger& challenger, + const OpeningPoints& points_by_round, Challenger& challenger, OpenedValues* openings, FRIProof* proof) { TRACE_EVENT("ProofGeneration", "TwoAdicFRI::CreateOpeningProof"); ExtF alpha = challenger.template SampleExtElement(); @@ -121,7 +122,7 @@ class TwoAdicFRI { for (size_t round = 0; round < num_rounds; ++round) { absl::Span> matrices = matrices_by_round[round]; - const Points& points = points_by_round[round]; + const OpeningPointsForRound& points = points_by_round[round]; OpenedValuesForRound opened_values_for_round(matrices.size()); for (size_t matrix_idx = 0; matrix_idx < matrices.size(); ++matrix_idx) { const math::RowMajorMatrix& mat = matrices[matrix_idx]; @@ -310,7 +311,7 @@ class TwoAdicFRI { absl::flat_hash_map> ComputeInverseDenominators( const std::vector>>& matrices_by_round, - const std::vector& points_by_round, F coset_shift) { + const OpeningPoints& points_by_round, F coset_shift) { TRACE_EVENT("Utils", "ComputeInverseDenominators"); size_t num_rounds = matrices_by_round.size(); @@ -319,7 +320,7 @@ class TwoAdicFRI { for (size_t round = 0; round < num_rounds; ++round) { absl::Span> matrices = matrices_by_round[round]; - const Points& points = points_by_round[round]; + const OpeningPointsForRound& points = points_by_round[round]; for (const math::RowMajorMatrix& matrix : matrices) { uint32_t log_num_rows = base::bits::CheckedLog2(static_cast(matrix.rows())); From aa1e2e8ae51629c3d4dc91103580218cf6f68cf1 Mon Sep 17 00:00:00 2001 From: Ryan Kim Date: Thu, 29 Aug 2024 14:22:41 +0900 Subject: [PATCH 10/25] feat(c/zk): add c API for 4-dimensional vector of `math::BabyBear4` This c API addition introduces support for a 4-dimensional vector of `math::BabyBear4`, aliased as `OpenedValues`. It is used as the return value for `TwoAdicFriPCS::Open()`. --- tachyon/c/zk/air/sp1/BUILD.bazel | 20 ++++++ .../sp1/baby_bear_poseidon2_opened_values.cc | 42 ++++++++++++ .../sp1/baby_bear_poseidon2_opened_values.h | 66 +++++++++++++++++++ ...bear_poseidon2_opened_values_type_traits.h | 26 ++++++++ ...y_bear_poseidon2_opened_values_unittest.cc | 53 +++++++++++++++ 5 files changed, 207 insertions(+) create mode 100644 tachyon/c/zk/air/sp1/baby_bear_poseidon2_opened_values.cc create mode 100644 tachyon/c/zk/air/sp1/baby_bear_poseidon2_opened_values.h create mode 100644 tachyon/c/zk/air/sp1/baby_bear_poseidon2_opened_values_type_traits.h create mode 100644 tachyon/c/zk/air/sp1/baby_bear_poseidon2_opened_values_unittest.cc diff --git a/tachyon/c/zk/air/sp1/BUILD.bazel b/tachyon/c/zk/air/sp1/BUILD.bazel index c11aa03ae..2090c0d70 100644 --- a/tachyon/c/zk/air/sp1/BUILD.bazel +++ b/tachyon/c/zk/air/sp1/BUILD.bazel @@ -9,6 +9,7 @@ filegroup( "baby_bear_poseidon2_duplex_challenger.h", "baby_bear_poseidon2_field_merkle_tree.h", "baby_bear_poseidon2_field_merkle_tree_vec.h", + "baby_bear_poseidon2_opened_values.h", "baby_bear_poseidon2_two_adic_fri.h", ], ) @@ -70,6 +71,22 @@ tachyon_cc_library( ], ) +tachyon_cc_library( + name = "baby_bear_poseidon2_opened_values", + srcs = ["baby_bear_poseidon2_opened_values.cc"], + hdrs = [ + "baby_bear_poseidon2_opened_values.h", + "baby_bear_poseidon2_opened_values_type_traits.h", + ], + deps = [ + "//tachyon/base:auto_reset", + "//tachyon/base/buffer", + "//tachyon/c:export", + "//tachyon/c/base:type_traits_forward", + "//tachyon/c/math/finite_fields/baby_bear:baby_bear4", + ], +) + tachyon_cc_library( name = "baby_bear_poseidon2_two_adic_fri", srcs = ["baby_bear_poseidon2_two_adic_fri.cc"], @@ -112,9 +129,12 @@ tachyon_cc_unittest( name = "sp1_unittests", srcs = [ "baby_bear_poseidon2_duplex_challenger_unittest.cc", + "baby_bear_poseidon2_opened_values_unittest.cc", "baby_bear_poseidon2_two_adic_fri_unittest.cc", ], deps = [ + # TODO(chokobole): This will be added to sp1 target. + ":baby_bear_poseidon2_opened_values", ":sp1", "//tachyon/math/finite_fields/test:finite_field_test", ], diff --git a/tachyon/c/zk/air/sp1/baby_bear_poseidon2_opened_values.cc b/tachyon/c/zk/air/sp1/baby_bear_poseidon2_opened_values.cc new file mode 100644 index 000000000..a9d73f46f --- /dev/null +++ b/tachyon/c/zk/air/sp1/baby_bear_poseidon2_opened_values.cc @@ -0,0 +1,42 @@ +#include "tachyon/c/zk/air/sp1/baby_bear_poseidon2_opened_values.h" + +#include + +#include "tachyon/base/auto_reset.h" +#include "tachyon/base/buffer/buffer.h" +#include "tachyon/c/zk/air/sp1/baby_bear_poseidon2_opened_values_type_traits.h" + +using namespace tachyon; + +using OpenedValues = + std::vector>>>; + +tachyon_sp1_baby_bear_poseidon2_opened_values* +tachyon_sp1_baby_bear_poseidon2_opened_values_create() { + return c::base::c_cast(new OpenedValues()); +} + +tachyon_sp1_baby_bear_poseidon2_opened_values* +tachyon_sp1_baby_bear_poseidon2_opened_values_clone( + const tachyon_sp1_baby_bear_poseidon2_opened_values* opened_values) { + return c::base::c_cast( + new OpenedValues(c::base::native_cast(*opened_values))); +} + +void tachyon_sp1_baby_bear_poseidon2_opened_values_destroy( + tachyon_sp1_baby_bear_poseidon2_opened_values* opened_values) { + delete c::base::native_cast(opened_values); +} + +void tachyon_sp1_baby_bear_poseidon2_opened_values_serialize( + const tachyon_sp1_baby_bear_poseidon2_opened_values* opened_values, + uint8_t* data, size_t* data_len) { + if (data == nullptr) { + *data_len = base::EstimateSize(c::base::native_cast(*opened_values)); + return; + } + base::AutoReset auto_reset( + &base::Copyable::s_is_in_montgomery, true); + base::Buffer buffer(data, *data_len); + CHECK(buffer.Write(c::base::native_cast(*opened_values))); +} diff --git a/tachyon/c/zk/air/sp1/baby_bear_poseidon2_opened_values.h b/tachyon/c/zk/air/sp1/baby_bear_poseidon2_opened_values.h new file mode 100644 index 000000000..21f2eccd9 --- /dev/null +++ b/tachyon/c/zk/air/sp1/baby_bear_poseidon2_opened_values.h @@ -0,0 +1,66 @@ +/** + * @file baby_bear_poseidon2_opened_values.h + * @brief Defines the interface for the set of opened values used within the + * SP1(BabyBear + Poseidon2) proof system. + */ + +#ifndef TACHYON_C_ZK_AIR_SP1_BABY_BEAR_POSEIDON2_OPENED_VALUES_H_ +#define TACHYON_C_ZK_AIR_SP1_BABY_BEAR_POSEIDON2_OPENED_VALUES_H_ + +#include +#include + +#include "tachyon/c/export.h" +#include "tachyon/c/math/finite_fields/baby_bear/baby_bear4.h" + +struct tachyon_sp1_baby_bear_poseidon2_opened_values {}; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Creates a new set of opened values. + * + * @return A pointer to the newly created set of opened values. + */ +TACHYON_C_EXPORT tachyon_sp1_baby_bear_poseidon2_opened_values* +tachyon_sp1_baby_bear_poseidon2_opened_values_create(); + +/** + * @brief Clones an existing set of opened values. + * + * Creates a deep copy of the given set of opened values. + * + * @param opened_values A const pointer to the set of opened values to + * clone. + * @return A pointer to the cloned set of opened values. + */ +TACHYON_C_EXPORT tachyon_sp1_baby_bear_poseidon2_opened_values* +tachyon_sp1_baby_bear_poseidon2_opened_values_clone( + const tachyon_sp1_baby_bear_poseidon2_opened_values* opened_values); + +/** + * @brief Destroys a set of opened values, freeing its resources. + * + * @param opened_values A pointer to the set of opened values to destroy. + */ +TACHYON_C_EXPORT void tachyon_sp1_baby_bear_poseidon2_opened_values_destroy( + tachyon_sp1_baby_bear_poseidon2_opened_values* opened_values); + +/** + * @brief Serializes a set of opened values to the byte array. + * + * @param opened_values A const pointer to the set of opened values. + * @param data A pointer to the byte array. + * @param data_len A pointer to store the length of the byte array. + */ +TACHYON_C_EXPORT void tachyon_sp1_baby_bear_poseidon2_opened_values_serialize( + const tachyon_sp1_baby_bear_poseidon2_opened_values* opened_values, + uint8_t* data, size_t* data_len); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // TACHYON_C_ZK_AIR_SP1_BABY_BEAR_POSEIDON2_OPENED_VALUES_H_ diff --git a/tachyon/c/zk/air/sp1/baby_bear_poseidon2_opened_values_type_traits.h b/tachyon/c/zk/air/sp1/baby_bear_poseidon2_opened_values_type_traits.h new file mode 100644 index 000000000..d55b19465 --- /dev/null +++ b/tachyon/c/zk/air/sp1/baby_bear_poseidon2_opened_values_type_traits.h @@ -0,0 +1,26 @@ +#ifndef TACHYON_C_ZK_AIR_SP1_BABY_BEAR_POSEIDON2_OPENED_VALUES_TYPE_TRAITS_H_ +#define TACHYON_C_ZK_AIR_SP1_BABY_BEAR_POSEIDON2_OPENED_VALUES_TYPE_TRAITS_H_ + +#include + +#include "tachyon/c/base/type_traits_forward.h" +#include "tachyon/c/zk/air/sp1/baby_bear_poseidon2_opened_values.h" +#include "tachyon/math/finite_fields/baby_bear/baby_bear4.h" + +namespace tachyon::c::base { + +template <> +struct TypeTraits>>>> { + using CType = tachyon_sp1_baby_bear_poseidon2_opened_values; +}; + +template <> +struct TypeTraits { + using NativeType = std::vector< + std::vector>>>; +}; + +} // namespace tachyon::c::base + +#endif // TACHYON_C_ZK_AIR_SP1_BABY_BEAR_POSEIDON2_OPENED_VALUES_TYPE_TRAITS_H_ diff --git a/tachyon/c/zk/air/sp1/baby_bear_poseidon2_opened_values_unittest.cc b/tachyon/c/zk/air/sp1/baby_bear_poseidon2_opened_values_unittest.cc new file mode 100644 index 000000000..cad106cd4 --- /dev/null +++ b/tachyon/c/zk/air/sp1/baby_bear_poseidon2_opened_values_unittest.cc @@ -0,0 +1,53 @@ +#include "tachyon/c/zk/air/sp1/baby_bear_poseidon2_opened_values.h" + +#include + +#include "gtest/gtest.h" + +#include "tachyon/base/auto_reset.h" +#include "tachyon/base/buffer/read_only_buffer.h" +#include "tachyon/base/random.h" +#include "tachyon/c/zk/air/sp1/baby_bear_poseidon2_opened_values_type_traits.h" +#include "tachyon/math/finite_fields/test/finite_field_test.h" + +namespace tachyon::math { + +namespace { + +using ExtF = BabyBear4; +using OpenedValues = std::vector>>>; + +class OpenedValuesTest : public FiniteFieldTest {}; + +size_t GetRandom() { return base::Uniform(base::Range(1, 3)); } + +} // namespace + +TEST_F(OpenedValuesTest, Serialize) { + OpenedValues opened_values = base::CreateVector(GetRandom(), []() { + return base::CreateVector(GetRandom(), []() { + return base::CreateVector(GetRandom(), []() { + return base::CreateVector(GetRandom(), []() { return ExtF::Random(); }); + }); + }); + }); + size_t data_len; + tachyon_sp1_baby_bear_poseidon2_opened_values_serialize( + c::base::c_cast(&opened_values), nullptr, &data_len); + ASSERT_NE(data_len, size_t{0}); + + std::vector data(data_len); + tachyon_sp1_baby_bear_poseidon2_opened_values_serialize( + c::base::c_cast(&opened_values), const_cast(data.data()), + &data_len); + ASSERT_EQ(data.size(), data_len); + + base::ReadOnlyBuffer buffer(data.data(), data_len); + OpenedValues opened_values_deser; + base::AutoReset auto_reset( + &base::Copyable::s_is_in_montgomery, true); + ASSERT_TRUE(buffer.Read(&opened_values_deser)); + EXPECT_EQ(opened_values, opened_values_deser); +} + +} // namespace tachyon::math From cc508dc7eaa6b2f4ad2df802a17e6b31370943c6 Mon Sep 17 00:00:00 2001 From: Ryan Kim Date: Thu, 29 Aug 2024 14:26:46 +0900 Subject: [PATCH 11/25] feat(c/zk): add c API for 3-dimensional vector of `math::BabyBear4` This c API addition introduces support for a 3-dimensional vector of `math::BabyBear4`, aliased as `OpeningPoints`. It is used as an argument for `TwoAdicFriPCS::Open()`. --- tachyon/c/zk/air/sp1/BUILD.bazel | 15 ++++ .../sp1/baby_bear_poseidon2_opening_points.cc | 45 +++++++++++ .../sp1/baby_bear_poseidon2_opening_points.h | 80 +++++++++++++++++++ ...ear_poseidon2_opening_points_type_traits.h | 26 ++++++ 4 files changed, 166 insertions(+) create mode 100644 tachyon/c/zk/air/sp1/baby_bear_poseidon2_opening_points.cc create mode 100644 tachyon/c/zk/air/sp1/baby_bear_poseidon2_opening_points.h create mode 100644 tachyon/c/zk/air/sp1/baby_bear_poseidon2_opening_points_type_traits.h diff --git a/tachyon/c/zk/air/sp1/BUILD.bazel b/tachyon/c/zk/air/sp1/BUILD.bazel index 2090c0d70..1bdfd37bc 100644 --- a/tachyon/c/zk/air/sp1/BUILD.bazel +++ b/tachyon/c/zk/air/sp1/BUILD.bazel @@ -10,6 +10,7 @@ filegroup( "baby_bear_poseidon2_field_merkle_tree.h", "baby_bear_poseidon2_field_merkle_tree_vec.h", "baby_bear_poseidon2_opened_values.h", + "baby_bear_poseidon2_opening_points.h", "baby_bear_poseidon2_two_adic_fri.h", ], ) @@ -87,6 +88,20 @@ tachyon_cc_library( ], ) +tachyon_cc_library( + name = "baby_bear_poseidon2_opening_points", + srcs = ["baby_bear_poseidon2_opening_points.cc"], + hdrs = [ + "baby_bear_poseidon2_opening_points.h", + "baby_bear_poseidon2_opening_points_type_traits.h", + ], + deps = [ + "//tachyon/c:export", + "//tachyon/c/base:type_traits_forward", + "//tachyon/c/math/finite_fields/baby_bear:baby_bear4", + ], +) + tachyon_cc_library( name = "baby_bear_poseidon2_two_adic_fri", srcs = ["baby_bear_poseidon2_two_adic_fri.cc"], diff --git a/tachyon/c/zk/air/sp1/baby_bear_poseidon2_opening_points.cc b/tachyon/c/zk/air/sp1/baby_bear_poseidon2_opening_points.cc new file mode 100644 index 000000000..3ee5311f0 --- /dev/null +++ b/tachyon/c/zk/air/sp1/baby_bear_poseidon2_opening_points.cc @@ -0,0 +1,45 @@ +#include "tachyon/c/zk/air/sp1/baby_bear_poseidon2_opening_points.h" + +#include + +#include "tachyon/c/math/finite_fields/baby_bear/baby_bear4_type_traits.h" +#include "tachyon/c/zk/air/sp1/baby_bear_poseidon2_opening_points_type_traits.h" + +using namespace tachyon; + +using OpeningPoints = std::vector>>; + +tachyon_sp1_baby_bear_poseidon2_opening_points* +tachyon_sp1_baby_bear_poseidon2_opening_points_create(size_t rounds) { + return c::base::c_cast(new OpeningPoints(rounds)); +} + +tachyon_sp1_baby_bear_poseidon2_opening_points* +tachyon_sp1_baby_bear_poseidon2_opening_points_clone( + const tachyon_sp1_baby_bear_poseidon2_opening_points* opening_points) { + return c::base::c_cast( + new OpeningPoints(c::base::native_cast(*opening_points))); +} + +void tachyon_sp1_baby_bear_poseidon2_opening_points_destroy( + tachyon_sp1_baby_bear_poseidon2_opening_points* opening_points) { + delete c::base::native_cast(opening_points); +} + +void tachyon_sp1_baby_bear_poseidon2_opening_points_allocate( + tachyon_sp1_baby_bear_poseidon2_opening_points* opening_points, + size_t round, size_t rows, size_t cols) { + std::vector>& mat = + c::base::native_cast(*opening_points)[round]; + mat.resize(rows); + for (size_t r = 0; r < rows; ++r) { + mat[r].resize(cols); + } +} + +void tachyon_sp1_baby_bear_poseidon2_opening_points_set( + tachyon_sp1_baby_bear_poseidon2_opening_points* opening_points, + size_t round, size_t row, size_t col, const tachyon_baby_bear4* point) { + c::base::native_cast(*opening_points)[round][row][col] = + c::base::native_cast(*point); +} diff --git a/tachyon/c/zk/air/sp1/baby_bear_poseidon2_opening_points.h b/tachyon/c/zk/air/sp1/baby_bear_poseidon2_opening_points.h new file mode 100644 index 000000000..fb73c54e9 --- /dev/null +++ b/tachyon/c/zk/air/sp1/baby_bear_poseidon2_opening_points.h @@ -0,0 +1,80 @@ +/** + * @file baby_bear_poseidon2_opening_points.h + * @brief Defines the interface for the set of opening points used within + * the SP1(BabyBear + Poseidon2) proof system. + */ + +#ifndef TACHYON_C_ZK_AIR_SP1_BABY_BEAR_POSEIDON2_OPENING_POINTS_H_ +#define TACHYON_C_ZK_AIR_SP1_BABY_BEAR_POSEIDON2_OPENING_POINTS_H_ + +#include + +#include "tachyon/c/export.h" +#include "tachyon/c/math/finite_fields/baby_bear/baby_bear4.h" + +struct tachyon_sp1_baby_bear_poseidon2_opening_points {}; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Creates a new set of opening points. + * + * @param rounds The number of rounds. + * @return A pointer to the newly created set of opening points. + */ +TACHYON_C_EXPORT tachyon_sp1_baby_bear_poseidon2_opening_points* +tachyon_sp1_baby_bear_poseidon2_opening_points_create(size_t rounds); + +/** + * @brief Clones an existing set of opening points. + * + * Creates a deep copy of the given set of opening points. + * + * @param opening_points A const pointer to the set of opening points to + * clone. + * @return A pointer to the cloned set of opening points. + */ +TACHYON_C_EXPORT tachyon_sp1_baby_bear_poseidon2_opening_points* +tachyon_sp1_baby_bear_poseidon2_opening_points_clone( + const tachyon_sp1_baby_bear_poseidon2_opening_points* opening_points); + +/** + * @brief Destroys a set of opening points, freeing its resources. + * + * @param opening_points A pointer to the set of opening points to destroy. + */ +TACHYON_C_EXPORT void tachyon_sp1_baby_bear_poseidon2_opening_points_destroy( + tachyon_sp1_baby_bear_poseidon2_opening_points* opening_points); + +/** + * @brief Allocates memory for the set of opening points. + * + * @param opening_points A pointer to the set of opening points. + * @param round The round index of the point. + * @param rows The number of rows. + * @param cols The number of columns. + */ +TACHYON_C_EXPORT void tachyon_sp1_baby_bear_poseidon2_opening_points_allocate( + tachyon_sp1_baby_bear_poseidon2_opening_points* opening_points, + size_t round, size_t rows, size_t cols); + +/** + * @brief Sets point. + * + * @param opening_points A pointer to the set of opening points. + * @param round The round index of the point. + * @param row The row index of the point. + * @param col The column index of the point. + * @param col A const pointer to the point. + */ +TACHYON_C_EXPORT void tachyon_sp1_baby_bear_poseidon2_opening_points_set( + tachyon_sp1_baby_bear_poseidon2_opening_points* opening_points, + size_t round, size_t row, size_t col, const tachyon_baby_bear4* point); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // TACHYON_C_ZK_AIR_SP1_BABY_BEAR_POSEIDON2_OPENING_POINTS_H_ diff --git a/tachyon/c/zk/air/sp1/baby_bear_poseidon2_opening_points_type_traits.h b/tachyon/c/zk/air/sp1/baby_bear_poseidon2_opening_points_type_traits.h new file mode 100644 index 000000000..a284c4880 --- /dev/null +++ b/tachyon/c/zk/air/sp1/baby_bear_poseidon2_opening_points_type_traits.h @@ -0,0 +1,26 @@ +#ifndef TACHYON_C_ZK_AIR_SP1_BABY_BEAR_POSEIDON2_OPENING_POINTS_TYPE_TRAITS_H_ +#define TACHYON_C_ZK_AIR_SP1_BABY_BEAR_POSEIDON2_OPENING_POINTS_TYPE_TRAITS_H_ + +#include + +#include "tachyon/c/base/type_traits_forward.h" +#include "tachyon/c/zk/air/sp1/baby_bear_poseidon2_opening_points.h" +#include "tachyon/math/finite_fields/baby_bear/baby_bear4.h" + +namespace tachyon::c::base { + +template <> +struct TypeTraits< + std::vector>>> { + using CType = tachyon_sp1_baby_bear_poseidon2_opening_points; +}; + +template <> +struct TypeTraits { + using NativeType = + std::vector>>; +}; + +} // namespace tachyon::c::base + +#endif // TACHYON_C_ZK_AIR_SP1_BABY_BEAR_POSEIDON2_OPENING_POINTS_TYPE_TRAITS_H_ From 92010da955343c67db4ff18073932c3e646cae15 Mon Sep 17 00:00:00 2001 From: Ryan Kim Date: Fri, 30 Aug 2024 13:34:47 +0900 Subject: [PATCH 12/25] feat(c/zk): add c API for `crypto::FRIProof` --- tachyon/c/zk/air/sp1/BUILD.bazel | 8 ++- .../air/sp1/baby_bear_poseidon2_fri_proof.cc | 23 ++++++++ .../air/sp1/baby_bear_poseidon2_fri_proof.h | 54 +++++++++++++++++++ ...aby_bear_poseidon2_fri_proof_type_traits.h | 25 +++++++++ 4 files changed, 109 insertions(+), 1 deletion(-) create mode 100644 tachyon/c/zk/air/sp1/baby_bear_poseidon2_fri_proof.cc create mode 100644 tachyon/c/zk/air/sp1/baby_bear_poseidon2_fri_proof.h create mode 100644 tachyon/c/zk/air/sp1/baby_bear_poseidon2_fri_proof_type_traits.h diff --git a/tachyon/c/zk/air/sp1/BUILD.bazel b/tachyon/c/zk/air/sp1/BUILD.bazel index 1bdfd37bc..ccdf8371f 100644 --- a/tachyon/c/zk/air/sp1/BUILD.bazel +++ b/tachyon/c/zk/air/sp1/BUILD.bazel @@ -9,6 +9,7 @@ filegroup( "baby_bear_poseidon2_duplex_challenger.h", "baby_bear_poseidon2_field_merkle_tree.h", "baby_bear_poseidon2_field_merkle_tree_vec.h", + "baby_bear_poseidon2_fri_proof.h", "baby_bear_poseidon2_opened_values.h", "baby_bear_poseidon2_opening_points.h", "baby_bear_poseidon2_two_adic_fri.h", @@ -104,8 +105,13 @@ tachyon_cc_library( tachyon_cc_library( name = "baby_bear_poseidon2_two_adic_fri", - srcs = ["baby_bear_poseidon2_two_adic_fri.cc"], + srcs = [ + "baby_bear_poseidon2_fri_proof.cc", + "baby_bear_poseidon2_two_adic_fri.cc", + ], hdrs = [ + "baby_bear_poseidon2_fri_proof.h", + "baby_bear_poseidon2_fri_proof_type_traits.h", "baby_bear_poseidon2_two_adic_fri.h", "baby_bear_poseidon2_two_adic_fri_type_traits.h", ], diff --git a/tachyon/c/zk/air/sp1/baby_bear_poseidon2_fri_proof.cc b/tachyon/c/zk/air/sp1/baby_bear_poseidon2_fri_proof.cc new file mode 100644 index 000000000..9c2a1fbd4 --- /dev/null +++ b/tachyon/c/zk/air/sp1/baby_bear_poseidon2_fri_proof.cc @@ -0,0 +1,23 @@ +#include "tachyon/c/zk/air/sp1/baby_bear_poseidon2_fri_proof.h" + +#include "tachyon/c/zk/air/sp1/baby_bear_poseidon2_fri_proof_type_traits.h" + +using namespace tachyon; + +using Proof = crypto::FRIProof; + +tachyon_sp1_baby_bear_poseidon2_fri_proof* +tachyon_sp1_baby_bear_poseidon2_fri_proof_create() { + return c::base::c_cast(new Proof()); +} + +tachyon_sp1_baby_bear_poseidon2_fri_proof* +tachyon_sp1_baby_bear_poseidon2_fri_proof_clone( + const tachyon_sp1_baby_bear_poseidon2_fri_proof* fri_proof) { + return c::base::c_cast(new Proof(c::base::native_cast(*fri_proof))); +} + +void tachyon_sp1_baby_bear_poseidon2_fri_proof_destroy( + tachyon_sp1_baby_bear_poseidon2_fri_proof* fri_proof) { + delete c::base::native_cast(fri_proof); +} diff --git a/tachyon/c/zk/air/sp1/baby_bear_poseidon2_fri_proof.h b/tachyon/c/zk/air/sp1/baby_bear_poseidon2_fri_proof.h new file mode 100644 index 000000000..537898510 --- /dev/null +++ b/tachyon/c/zk/air/sp1/baby_bear_poseidon2_fri_proof.h @@ -0,0 +1,54 @@ +/** + * @file baby_bear_poseidon2_fri_proof.h + * @brief Defines the interface for the fri proof used within the + * SP1(BabyBear + Poseidon2) proof system. + */ + +#ifndef TACHYON_C_ZK_AIR_SP1_BABY_BEAR_POSEIDON2_FRI_PROOF_H_ +#define TACHYON_C_ZK_AIR_SP1_BABY_BEAR_POSEIDON2_FRI_PROOF_H_ + +#include +#include + +#include "tachyon/c/export.h" + +struct tachyon_sp1_baby_bear_poseidon2_fri_proof {}; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Creates a new fri proof. + * + * @return A pointer to the newly created fri proof. + */ +TACHYON_C_EXPORT tachyon_sp1_baby_bear_poseidon2_fri_proof* +tachyon_sp1_baby_bear_poseidon2_fri_proof_create(); + +/** + * @brief Clones an existing fri proof. + * + * Creates a deep copy of the given fri proof. + * + * @param fri_proof A const pointer to the fri proof to + * clone. + * @return A pointer to the cloned fri proof. + */ +TACHYON_C_EXPORT tachyon_sp1_baby_bear_poseidon2_fri_proof* +tachyon_sp1_baby_bear_poseidon2_fri_proof_clone( + const tachyon_sp1_baby_bear_poseidon2_fri_proof* fri_proof); + +/** + * @brief Destroys a fri proof, freeing its resources. + * + * @param proof A pointer to the fri proof to destroy. + */ +TACHYON_C_EXPORT void tachyon_sp1_baby_bear_poseidon2_fri_proof_destroy( + tachyon_sp1_baby_bear_poseidon2_fri_proof* proof); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // TACHYON_C_ZK_AIR_SP1_BABY_BEAR_POSEIDON2_FRI_PROOF_H_ diff --git a/tachyon/c/zk/air/sp1/baby_bear_poseidon2_fri_proof_type_traits.h b/tachyon/c/zk/air/sp1/baby_bear_poseidon2_fri_proof_type_traits.h new file mode 100644 index 000000000..26cb8d315 --- /dev/null +++ b/tachyon/c/zk/air/sp1/baby_bear_poseidon2_fri_proof_type_traits.h @@ -0,0 +1,25 @@ +#ifndef TACHYON_C_ZK_AIR_SP1_BABY_BEAR_POSEIDON2_FRI_PROOF_TYPE_TRAITS_H_ +#define TACHYON_C_ZK_AIR_SP1_BABY_BEAR_POSEIDON2_FRI_PROOF_TYPE_TRAITS_H_ + +#include "tachyon/c/base/type_traits_forward.h" +#include "tachyon/c/zk/air/sp1/baby_bear_poseidon2_fri_proof.h" +#include "tachyon/c/zk/air/sp1/baby_bear_poseidon2_two_adic_fri_type_traits.h" +#include "tachyon/crypto/commitments/fri/fri_proof.h" + +namespace tachyon::c::base { + +template <> +struct TypeTraits< + tachyon::crypto::FRIProof> { + using CType = tachyon_sp1_baby_bear_poseidon2_fri_proof; +}; + +template <> +struct TypeTraits { + using NativeType = + tachyon::crypto::FRIProof; +}; + +} // namespace tachyon::c::base + +#endif // TACHYON_C_ZK_AIR_SP1_BABY_BEAR_POSEIDON2_FRI_PROOF_TYPE_TRAITS_H_ From bc6ecd31593e6c06bb5e01e80e42e7cfd7d1173f Mon Sep 17 00:00:00 2001 From: Ryan Kim Date: Fri, 30 Aug 2024 16:33:41 +0900 Subject: [PATCH 13/25] feat(c/crypto): add `TwoAdicFriImpl::CreateOpeningProof()` --- tachyon/c/crypto/commitments/fri/BUILD.bazel | 5 +++- .../commitments/fri/two_adic_fri_impl.h | 23 +++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/tachyon/c/crypto/commitments/fri/BUILD.bazel b/tachyon/c/crypto/commitments/fri/BUILD.bazel index 19d904d3b..73d44c7eb 100644 --- a/tachyon/c/crypto/commitments/fri/BUILD.bazel +++ b/tachyon/c/crypto/commitments/fri/BUILD.bazel @@ -5,5 +5,8 @@ package(default_visibility = ["//visibility:public"]) tachyon_cc_library( name = "two_adic_fri_impl", hdrs = ["two_adic_fri_impl.h"], - deps = ["//tachyon/crypto/commitments/fri:two_adic_fri"], + deps = [ + "//tachyon/base/containers:container_util", + "//tachyon/crypto/commitments/fri:two_adic_fri", + ], ) diff --git a/tachyon/c/crypto/commitments/fri/two_adic_fri_impl.h b/tachyon/c/crypto/commitments/fri/two_adic_fri_impl.h index e54cf061a..570429e7a 100644 --- a/tachyon/c/crypto/commitments/fri/two_adic_fri_impl.h +++ b/tachyon/c/crypto/commitments/fri/two_adic_fri_impl.h @@ -5,6 +5,7 @@ #include #include +#include "tachyon/base/containers/container_util.h" #include "tachyon/crypto/commitments/fri/two_adic_fri.h" namespace tachyon::c::crypto { @@ -21,6 +22,9 @@ class TwoAdicFRIImpl using Commitment = typename Base::Commitment; using ProverData = typename Base::ProverData; using Domain = typename Base::Domain; + using OpeningPoints = typename Base::OpeningPoints; + using OpenedValues = typename Base::OpenedValues; + using FRIProof = typename Base::FRIProof; using Base::Base; @@ -47,6 +51,25 @@ class TwoAdicFRIImpl prover_data_by_round->push_back(std::move(prover_data)); } + void CreateOpeningProof( + const std::vector>& prover_data_by_round_in, + const OpeningPoints& points_by_round, Challenger& challenger, + OpenedValues* opened_values_by_round, FRIProof* proof) { + auto& prover_data_by_round = + const_cast>&>( + prover_data_by_round_in); + std::vector prover_data_by_round_tmp = tachyon::base::Map( + prover_data_by_round, [](std::unique_ptr& prover_data) { + return ProverData(std::move(*prover_data)); + }); + CHECK(Base::CreateOpeningProof(prover_data_by_round_tmp, points_by_round, + challenger, opened_values_by_round, proof)); + prover_data_by_round = tachyon::base::Map( + prover_data_by_round_tmp, [](ProverData& prover_data) { + return std::make_unique(std::move(prover_data)); + }); + } + protected: std::vector> ldes_; }; From 919458713a972b74b15e2343a307cb154283bc28 Mon Sep 17 00:00:00 2001 From: Ryan Kim Date: Fri, 30 Aug 2024 16:38:12 +0900 Subject: [PATCH 14/25] feat(c/zk): add `tachyon_sp1_baby_bear_poseidon2_two_adic_fri_open()` --- tachyon/c/zk/air/sp1/BUILD.bazel | 12 ++--- .../sp1/baby_bear_poseidon2_two_adic_fri.cc | 24 +++++++++ .../sp1/baby_bear_poseidon2_two_adic_fri.h | 24 +++++++++ ...by_bear_poseidon2_two_adic_fri_unittest.cc | 52 +++++++++++++++---- 4 files changed, 96 insertions(+), 16 deletions(-) diff --git a/tachyon/c/zk/air/sp1/BUILD.bazel b/tachyon/c/zk/air/sp1/BUILD.bazel index ccdf8371f..9ca30c1f9 100644 --- a/tachyon/c/zk/air/sp1/BUILD.bazel +++ b/tachyon/c/zk/air/sp1/BUILD.bazel @@ -117,12 +117,16 @@ tachyon_cc_library( ], deps = [ ":baby_bear_poseidon2_constants", + ":baby_bear_poseidon2_duplex_challenger", ":baby_bear_poseidon2_field_merkle_tree", ":baby_bear_poseidon2_field_merkle_tree_vec", + ":baby_bear_poseidon2_opened_values", + ":baby_bear_poseidon2_opening_points", "//tachyon/c:export", "//tachyon/c/base:type_traits_forward", "//tachyon/c/crypto/commitments/fri:two_adic_fri_impl", "//tachyon/c/math/finite_fields/baby_bear", + "//tachyon/c/math/finite_fields/baby_bear:baby_bear4", "//tachyon/c/math/matrix:baby_bear_row_major_matrix", "//tachyon/crypto/challenger:duplex_challenger", "//tachyon/crypto/commitments/fri:two_adic_fri", @@ -133,17 +137,13 @@ tachyon_cc_library( "//tachyon/crypto/hashes/sponge:truncated_permutation", "//tachyon/crypto/hashes/sponge/poseidon2", "//tachyon/crypto/hashes/sponge/poseidon2:poseidon2_plonky3_external_matrix", - "//tachyon/math/finite_fields/baby_bear:baby_bear4", "//tachyon/math/finite_fields/baby_bear:poseidon2", ], ) tachyon_cc_library( name = "sp1", - deps = [ - ":baby_bear_poseidon2_duplex_challenger", - ":baby_bear_poseidon2_two_adic_fri", - ], + deps = [":baby_bear_poseidon2_two_adic_fri"], ) tachyon_cc_unittest( @@ -154,8 +154,6 @@ tachyon_cc_unittest( "baby_bear_poseidon2_two_adic_fri_unittest.cc", ], deps = [ - # TODO(chokobole): This will be added to sp1 target. - ":baby_bear_poseidon2_opened_values", ":sp1", "//tachyon/math/finite_fields/test:finite_field_test", ], diff --git a/tachyon/c/zk/air/sp1/baby_bear_poseidon2_two_adic_fri.cc b/tachyon/c/zk/air/sp1/baby_bear_poseidon2_two_adic_fri.cc index a2130c7fa..a7b7e32d1 100644 --- a/tachyon/c/zk/air/sp1/baby_bear_poseidon2_two_adic_fri.cc +++ b/tachyon/c/zk/air/sp1/baby_bear_poseidon2_two_adic_fri.cc @@ -2,10 +2,15 @@ #include +#include "tachyon/c/math/finite_fields/baby_bear/baby_bear4_type_traits.h" #include "tachyon/c/math/finite_fields/baby_bear/baby_bear_type_traits.h" #include "tachyon/c/math/matrix/baby_bear_row_major_matrix_type_traits.h" +#include "tachyon/c/zk/air/sp1/baby_bear_poseidon2_duplex_challenger_type_traits.h" #include "tachyon/c/zk/air/sp1/baby_bear_poseidon2_field_merkle_tree_type_traits.h" #include "tachyon/c/zk/air/sp1/baby_bear_poseidon2_field_merkle_tree_vec_type_traits.h" +#include "tachyon/c/zk/air/sp1/baby_bear_poseidon2_fri_proof_type_traits.h" +#include "tachyon/c/zk/air/sp1/baby_bear_poseidon2_opened_values_type_traits.h" +#include "tachyon/c/zk/air/sp1/baby_bear_poseidon2_opening_points_type_traits.h" #include "tachyon/c/zk/air/sp1/baby_bear_poseidon2_two_adic_fri_type_traits.h" using namespace tachyon; @@ -121,3 +126,22 @@ void tachyon_sp1_baby_bear_poseidon2_two_adic_fri_commit( reinterpret_cast(prover_data), c::base::native_cast(prover_data_vec)); } + +void tachyon_sp1_baby_bear_poseidon2_two_adic_fri_open( + tachyon_sp1_baby_bear_poseidon2_two_adic_fri* pcs, + const tachyon_sp1_baby_bear_poseidon2_field_merkle_tree_vec* + prover_data_by_round, + const tachyon_sp1_baby_bear_poseidon2_opening_points* points_by_round, + tachyon_sp1_baby_bear_poseidon2_duplex_challenger* challenger, + tachyon_sp1_baby_bear_poseidon2_opened_values** opened_values, + tachyon_sp1_baby_bear_poseidon2_fri_proof** proof) { + c::base::native_cast(pcs)->CreateOpeningProof( + c::base::native_cast(*prover_data_by_round), + c::base::native_cast(*points_by_round), c::base::native_cast(*challenger), + c::base::native_cast( + reinterpret_cast( + *opened_values)), + c::base::native_cast( + reinterpret_cast( + *proof))); +} diff --git a/tachyon/c/zk/air/sp1/baby_bear_poseidon2_two_adic_fri.h b/tachyon/c/zk/air/sp1/baby_bear_poseidon2_two_adic_fri.h index 1aae795e4..85f4d70cc 100644 --- a/tachyon/c/zk/air/sp1/baby_bear_poseidon2_two_adic_fri.h +++ b/tachyon/c/zk/air/sp1/baby_bear_poseidon2_two_adic_fri.h @@ -11,10 +11,15 @@ #include #include "tachyon/c/export.h" +#include "tachyon/c/math/finite_fields/baby_bear/baby_bear4.h" #include "tachyon/c/math/matrix/baby_bear_row_major_matrix.h" #include "tachyon/c/zk/air/sp1/baby_bear_poseidon2_constants.h" +#include "tachyon/c/zk/air/sp1/baby_bear_poseidon2_duplex_challenger.h" #include "tachyon/c/zk/air/sp1/baby_bear_poseidon2_field_merkle_tree.h" #include "tachyon/c/zk/air/sp1/baby_bear_poseidon2_field_merkle_tree_vec.h" +#include "tachyon/c/zk/air/sp1/baby_bear_poseidon2_fri_proof.h" +#include "tachyon/c/zk/air/sp1/baby_bear_poseidon2_opened_values.h" +#include "tachyon/c/zk/air/sp1/baby_bear_poseidon2_opening_points.h" struct tachyon_sp1_baby_bear_poseidon2_two_adic_fri {}; @@ -87,6 +92,25 @@ TACHYON_C_EXPORT void tachyon_sp1_baby_bear_poseidon2_two_adic_fri_commit( tachyon_sp1_baby_bear_poseidon2_field_merkle_tree** prover_data, tachyon_sp1_baby_bear_poseidon2_field_merkle_tree_vec* prover_data_vec); +/** + * @brief Creates an opening proof with prover data and points. + * + * @param pcs A pointer to the two adic fri pcs. + * @param prover_data_by_round A const pointer to the field merkle tree vector. + * @param points_by_round A const pointer to the opening points. + * @param challenger A pointer to the duplex challenger. + * @param opened_values A pointer to store the opened values. + * @param proof A pointer to store the fri proof. + */ +TACHYON_C_EXPORT void tachyon_sp1_baby_bear_poseidon2_two_adic_fri_open( + tachyon_sp1_baby_bear_poseidon2_two_adic_fri* pcs, + const tachyon_sp1_baby_bear_poseidon2_field_merkle_tree_vec* + prover_data_by_round, + const tachyon_sp1_baby_bear_poseidon2_opening_points* points_by_round, + tachyon_sp1_baby_bear_poseidon2_duplex_challenger* challenger, + tachyon_sp1_baby_bear_poseidon2_opened_values** opened_values, + tachyon_sp1_baby_bear_poseidon2_fri_proof** proof); + #ifdef __cplusplus } // extern "C" #endif diff --git a/tachyon/c/zk/air/sp1/baby_bear_poseidon2_two_adic_fri_unittest.cc b/tachyon/c/zk/air/sp1/baby_bear_poseidon2_two_adic_fri_unittest.cc index 083c5acf6..79621d773 100644 --- a/tachyon/c/zk/air/sp1/baby_bear_poseidon2_two_adic_fri_unittest.cc +++ b/tachyon/c/zk/air/sp1/baby_bear_poseidon2_two_adic_fri_unittest.cc @@ -5,8 +5,13 @@ #include "gtest/gtest.h" +#include "tachyon/c/math/finite_fields/baby_bear/baby_bear4_type_traits.h" #include "tachyon/c/math/finite_fields/baby_bear/baby_bear_type_traits.h" #include "tachyon/c/math/matrix/baby_bear_row_major_matrix_type_traits.h" +#include "tachyon/c/zk/air/sp1/baby_bear_poseidon2_duplex_challenger_type_traits.h" +#include "tachyon/c/zk/air/sp1/baby_bear_poseidon2_fri_proof_type_traits.h" +#include "tachyon/c/zk/air/sp1/baby_bear_poseidon2_opened_values_type_traits.h" +#include "tachyon/c/zk/air/sp1/baby_bear_poseidon2_opening_points_type_traits.h" #include "tachyon/c/zk/air/sp1/baby_bear_poseidon2_two_adic_fri_type_traits.h" namespace tachyon { @@ -14,6 +19,7 @@ namespace tachyon { namespace { using F = math::BabyBear; +using ExtF = math::BabyBear4; using MMCS = c::zk::air::plonky3::baby_bear::MMCS; using Coset = c::zk::air::plonky3::baby_bear::Coset; using PCS = c::zk::air::plonky3::baby_bear::PCS; @@ -24,25 +30,39 @@ class TwoAdicFRITest : public testing::Test { pcs_ = tachyon_sp1_baby_bear_poseidon2_two_adic_fri_create(1, 10, 8); prover_data_vec_ = tachyon_sp1_baby_bear_poseidon2_field_merkle_tree_vec_create(); + opening_points_ = tachyon_sp1_baby_bear_poseidon2_opening_points_create(1); + challenger_ = tachyon_sp1_baby_bear_poseidon2_duplex_challenger_create(); + opened_values_ = tachyon_sp1_baby_bear_poseidon2_opened_values_create(); + proof_ = tachyon_sp1_baby_bear_poseidon2_fri_proof_create(); } void TearDown() override { tachyon_sp1_baby_bear_poseidon2_two_adic_fri_destroy(pcs_); tachyon_sp1_baby_bear_poseidon2_field_merkle_tree_vec_destroy( prover_data_vec_); + tachyon_sp1_baby_bear_poseidon2_opening_points_destroy(opening_points_); + tachyon_sp1_baby_bear_poseidon2_duplex_challenger_destroy(challenger_); + tachyon_sp1_baby_bear_poseidon2_opened_values_destroy(opened_values_); + tachyon_sp1_baby_bear_poseidon2_fri_proof_destroy(proof_); } protected: tachyon_sp1_baby_bear_poseidon2_two_adic_fri* pcs_ = nullptr; tachyon_sp1_baby_bear_poseidon2_field_merkle_tree_vec* prover_data_vec_ = nullptr; + tachyon_sp1_baby_bear_poseidon2_opening_points* opening_points_ = nullptr; + tachyon_sp1_baby_bear_poseidon2_duplex_challenger* challenger_ = nullptr; + tachyon_sp1_baby_bear_poseidon2_opened_values* opened_values_ = nullptr; + tachyon_sp1_baby_bear_poseidon2_fri_proof* proof_ = nullptr; }; } // namespace TEST_F(TwoAdicFRITest, APIs) { - constexpr size_t kRows = 32; - constexpr size_t kCols = 5; + constexpr size_t kRowsForInput = 32; + constexpr size_t kColsForInput = 5; + constexpr size_t kRowsForOpening = 2; + constexpr size_t kColsForOpening = 2; using Commitment = typename MMCS::Commitment; using ProverData = typename MMCS::ProverData; @@ -51,10 +71,10 @@ TEST_F(TwoAdicFRITest, APIs) { tachyon_sp1_baby_bear_poseidon2_two_adic_fri_create(1, 10, 8); PCS* native_pcs = c::base::native_cast(another_pcs); - Coset coset = native_pcs->GetNaturalDomainForDegree(kRows); + Coset coset = native_pcs->GetNaturalDomainForDegree(kRowsForInput); - std::vector matrix_data = - base::CreateVector(kRows * kCols, []() { return F::Random(); }); + std::vector matrix_data = base::CreateVector(kRowsForInput * kColsForInput, + []() { return F::Random(); }); std::vector matrix_data_clone = matrix_data; tachyon_sp1_baby_bear_poseidon2_two_adic_fri_allocate_ldes(pcs_, 1); @@ -63,8 +83,8 @@ TEST_F(TwoAdicFRITest, APIs) { size_t new_rows; tachyon_baby_bear* new_matrix_data = tachyon_sp1_baby_bear_poseidon2_two_adic_fri_coset_lde_batch( - pcs_, c::base::c_cast(const_cast(matrix_data.data())), kRows, - kCols, c::base::c_cast(shift), &new_rows); + pcs_, c::base::c_cast(const_cast(matrix_data.data())), + kRowsForInput, kColsForInput, c::base::c_cast(shift), &new_rows); tachyon_baby_bear commitment[TACHYON_PLONKY3_BABY_BEAR_POSEIDON2_CHUNK]; tachyon_sp1_baby_bear_poseidon2_field_merkle_tree* prover_data = nullptr; tachyon_sp1_baby_bear_poseidon2_two_adic_fri_commit( @@ -76,7 +96,7 @@ TEST_F(TwoAdicFRITest, APIs) { cosets.push_back(std::move(coset)); std::vector> matrices; matrices.push_back(Eigen::Map>( - matrix_data_clone.data(), kRows, kCols)); + matrix_data_clone.data(), kRowsForInput, kColsForInput)); ASSERT_TRUE(native_pcs->Commit(cosets, matrices, &native_commitment, &native_prover_data)); @@ -85,9 +105,23 @@ TEST_F(TwoAdicFRITest, APIs) { } math::RowMajorMatrix leaf = Eigen::Map>( - c::base::native_cast(new_matrix_data), new_rows, kCols); + c::base::native_cast(new_matrix_data), new_rows, kColsForInput); EXPECT_EQ(leaf, native_prover_data.leaves()[0]); + ExtF point = ExtF::Random(); + + tachyon_sp1_baby_bear_poseidon2_opening_points_allocate( + opening_points_, 0, kRowsForOpening, kColsForOpening); + for (size_t r = 0; r < kRowsForOpening; ++r) { + for (size_t c = 0; c < kColsForOpening; ++c) { + tachyon_sp1_baby_bear_poseidon2_opening_points_set( + opening_points_, 0, r, c, c::base::c_cast(&point)); + } + } + tachyon_sp1_baby_bear_poseidon2_two_adic_fri_open( + pcs_, prover_data_vec_, opening_points_, challenger_, &opened_values_, + &proof_); + tachyon_sp1_baby_bear_poseidon2_two_adic_fri_destroy(another_pcs); } From 58e9aabd1b16a87decc31db80227921486e7dfce Mon Sep 17 00:00:00 2001 From: Ryan Kim Date: Fri, 30 Aug 2024 16:38:35 +0900 Subject: [PATCH 15/25] feat(rs): add `Fp4` --- tachyon/rs/src/math/finite_fields/mod.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tachyon/rs/src/math/finite_fields/mod.rs b/tachyon/rs/src/math/finite_fields/mod.rs index 9d329461b..e93916bcb 100644 --- a/tachyon/rs/src/math/finite_fields/mod.rs +++ b/tachyon/rs/src/math/finite_fields/mod.rs @@ -14,6 +14,15 @@ pub struct Fp2 { pub c1: PrimeField, } +#[repr(C)] +#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, Zeroize)] +pub struct Fp4 { + pub c0: PrimeField, + pub c1: PrimeField, + pub c2: PrimeField, + pub c3: PrimeField, +} + #[repr(C)] #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, Zeroize)] pub struct Fp6 { From 7cff0c6c3d888b37f4f48a56107902bcb1c72bbc Mon Sep 17 00:00:00 2001 From: Wonyong Kim Date: Fri, 30 Aug 2024 22:00:07 +0900 Subject: [PATCH 16/25] refac(math): refactor `ExtensionFieldBase::GetExtendedPackedPowers()` --- .../math/finite_fields/extension_field_base.h | 38 +++++++++---------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/tachyon/math/finite_fields/extension_field_base.h b/tachyon/math/finite_fields/extension_field_base.h index 7076f200b..4ff2900fb 100644 --- a/tachyon/math/finite_fields/extension_field_base.h +++ b/tachyon/math/finite_fields/extension_field_base.h @@ -67,30 +67,28 @@ class ExtensionFieldBase { size_t size) { using BaseField = typename T::BaseField; using PackedField = typename PackedFieldTraits::PackedField; - uint32_t degree = T::ExtensionDegree(); - T pow = T::One(); - std::array, PackedField::N + 1> - powers_base_field = - base::CreateArray([&base, &pow]() { - auto ret = pow.ToBaseFields(); - pow *= base; - return ret; - }); - - // Transpose first WIDTH powers + constexpr uint32_t kDegree = T::ExtensionDegree(); + + // if |PackedField::N| = 8: + // |first_n_powers[i]| = {1, aᵢ, ..., a⁷ᵢ} ExtendedPackedField first_n_powers; - // Broadcast self^WIDTH + T pow = T::One(); + for (size_t i = 0; i < PackedField::N; ++i) { + for (uint32_t j = 0; j < kDegree; ++j) { + first_n_powers[j][i] = pow[j]; + } + pow *= base; + } + + // |multiplier[j]| = {a⁸ⱼ, a⁸ⱼ, ..., a⁸ⱼ, a⁸ⱼ} ExtendedPackedField multiplier; - for (uint32_t deg = 0; deg < degree; ++deg) { - first_n_powers[deg] = - PackedField::From([&powers_base_field, deg](size_t j) { - return powers_base_field[j][deg]; - }); - multiplier[deg] = PackedField::From([&powers_base_field, deg](size_t j) { - return powers_base_field[PackedField::N][deg]; - }); + for (size_t i = 0; i < PackedField::N; ++i) { + for (uint32_t j = 0; j < kDegree; ++j) { + multiplier[j][i] = pow[j]; + } } + // |ret[i]| = {(a⁸ᵢ)ⁱ, aᵢ * (a⁸ᵢ)ⁱ, ..., a⁷ᵢ * (a⁸ᵢ)ⁱ} std::vector ret; ret.reserve(size); ret.emplace_back(first_n_powers); From a3783e447c02de356235b0594075b367869b8077 Mon Sep 17 00:00:00 2001 From: Wonyong Kim Date: Fri, 30 Aug 2024 22:41:14 +0900 Subject: [PATCH 17/25] fix(math): fix `PackRowHorizontallyPadded()` Ensure `col` is incremented by `PackedField::N` in each iteration. --- tachyon/math/matrix/BUILD.bazel | 1 + tachyon/math/matrix/matrix_utils.h | 36 ++++++++++++------------------ 2 files changed, 15 insertions(+), 22 deletions(-) diff --git a/tachyon/math/matrix/BUILD.bazel b/tachyon/math/matrix/BUILD.bazel index d072fd367..1b00d66c4 100644 --- a/tachyon/math/matrix/BUILD.bazel +++ b/tachyon/math/matrix/BUILD.bazel @@ -47,6 +47,7 @@ tachyon_cc_library( deps = [ ":matrix_types", "//tachyon/base:bits", + "//tachyon/base:compiler_specific", "//tachyon/base:openmp_util", "//tachyon/base:profiler", "//tachyon/base/containers:container_util", diff --git a/tachyon/math/matrix/matrix_utils.h b/tachyon/math/matrix/matrix_utils.h index 9baa09eb6..3be15dcbb 100644 --- a/tachyon/math/matrix/matrix_utils.h +++ b/tachyon/math/matrix/matrix_utils.h @@ -8,6 +8,7 @@ #include "third_party/eigen3/Eigen/Core" #include "tachyon/base/bits.h" +#include "tachyon/base/compiler_specific.h" #include "tachyon/base/containers/container_util.h" #include "tachyon/base/openmp_util.h" #include "tachyon/base/profiler.h" @@ -62,29 +63,20 @@ template ::PackedField> std::vector PackRowHorizontallyPadded( const Eigen::Block& matrix_row) { - size_t cols = static_cast(matrix_row.cols()); using F = typename FiniteFieldTraits::PrimeField; - size_t num_full_packed = cols / PackedField::N; - bool full = cols % PackedField::N == 0; - - std::vector ret; - ret.reserve(full ? num_full_packed : num_full_packed + 1); - for (size_t col = 0; col < num_full_packed; ++col) { - ret.push_back(PackedField::From( - [col, &matrix_row](size_t c) { return matrix_row(0, col + c); })); - } - // Add last padded |PackedField| element. - if (!full) { - size_t remaining_start_idx = num_full_packed * PackedField::N; - ret.push_back( - PackedField::From([cols, remaining_start_idx, &matrix_row](size_t i) { - if (remaining_start_idx + i < cols) - return matrix_row(0, remaining_start_idx + i); - else - return F::Zero(); - })); - } - return ret; + + size_t cols = static_cast(matrix_row.cols()); + size_t size = (cols + PackedField::N - 1) / PackedField::N; + return base::CreateVector(size, [cols, &matrix_row](size_t i) { + size_t col = i * PackedField::N; + return PackedField::From([col, cols, &matrix_row](size_t c) { + if (LIKELY(col + c < cols)) { + return matrix_row[col + c]; + } else { + return F::Zero(); + } + }); + }); } // Packs |PackedField::N| rows, starting at the given row index. Each From d8a780088abd95b6e3d6dcef152aa21ad2025f44 Mon Sep 17 00:00:00 2001 From: Wonyong Kim Date: Fri, 30 Aug 2024 22:42:08 +0900 Subject: [PATCH 18/25] refac(math): refactor `PackRowVertically()` --- tachyon/math/matrix/matrix_utils.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tachyon/math/matrix/matrix_utils.h b/tachyon/math/matrix/matrix_utils.h index 3be15dcbb..21f230884 100644 --- a/tachyon/math/matrix/matrix_utils.h +++ b/tachyon/math/matrix/matrix_utils.h @@ -88,12 +88,12 @@ std::vector PackRowVertically( const Eigen::MatrixBase& matrix, size_t row) { using Scalar = typename Eigen::internal::traits::Scalar; if constexpr (FiniteFieldTraits::kIsExtensionField) { - size_t num = - matrix.cols() * ExtensionFieldTraits::kDegreeOverBasePrimeField; + constexpr size_t kDegree = + ExtensionFieldTraits::kDegreeOverBasePrimeField; + size_t num = matrix.cols() * kDegree; return base::CreateVector(num, [row, &matrix](size_t n) { - size_t col = n / ExtensionFieldTraits::kDegreeOverBasePrimeField; - size_t idx = - n - col * ExtensionFieldTraits::kDegreeOverBasePrimeField; + size_t col = n / kDegree; + size_t idx = n - col * kDegree; return PackedField::From([row, col, idx, &matrix](size_t i) { return matrix((row + i) % matrix.rows(), col)[idx]; }); From b44e2d1bcc937f5811bba8b779c6db72e268af84 Mon Sep 17 00:00:00 2001 From: Wonyong Kim Date: Fri, 30 Aug 2024 23:02:17 +0900 Subject: [PATCH 19/25] refac(math): refactor `DotExtPowers()` --- tachyon/math/matrix/matrix_utils.h | 39 ++++++++++++------------------ 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/tachyon/math/matrix/matrix_utils.h b/tachyon/math/matrix/matrix_utils.h index 21f230884..ceec9f23a 100644 --- a/tachyon/math/matrix/matrix_utils.h +++ b/tachyon/math/matrix/matrix_utils.h @@ -195,29 +195,22 @@ std::vector DotExtPowers(const Eigen::MatrixBase& mat, ExtField::GetExtendedPackedPowers( base, ((static_cast(mat.cols()) + packed_n - 1) / packed_n) * packed_n); - std::vector ret = base::CreateVectorParallel( - rows, [&mat, &packed_ext_powers](Eigen::Index r) { - std::vector row_packed = - PackRowHorizontallyPadded(mat.row(r)); - ExtendedPackedField packed_sum_of_packed(ExtendedPackedField::Zero()); - for (size_t i = 0; i < row_packed.size(); ++i) { - packed_sum_of_packed += packed_ext_powers[i] * row_packed[i]; - } - std::array - packed_sum_of_packed_decomposed = - packed_sum_of_packed.ToBaseFields(); - std::array base_field_sums = - base::CreateArray( - [&packed_sum_of_packed_decomposed](size_t d) { - return std::accumulate( - packed_sum_of_packed_decomposed[d].values().begin(), - packed_sum_of_packed_decomposed[d].values().end(), - F::Zero()); - }); - - return ExtField::FromBasePrimeFields(base_field_sums); - }); - return ret; + return base::CreateVectorParallel(rows, [&mat, + &packed_ext_powers](Eigen::Index r) { + std::vector row_packed = PackRowHorizontallyPadded(mat.row(r)); + ExtendedPackedField packed_sum_of_packed(ExtendedPackedField::Zero()); + for (size_t i = 0; i < row_packed.size(); ++i) { + packed_sum_of_packed += packed_ext_powers[i] * row_packed[i]; + } + ExtField ret(ExtField::Zero()); + for (size_t i = 0; i < ExtField::ExtensionDegree(); ++i) { + const PackedField& packed = packed_sum_of_packed[i]; + for (size_t j = 0; j < PackedField::N; ++j) { + ret[i] += packed[j]; + } + } + return ret; + }); } } // namespace tachyon::math From 7d266fe173ef4aa748a0dd07e02a8cb6dcb74571 Mon Sep 17 00:00:00 2001 From: Wonyong Kim Date: Fri, 30 Aug 2024 23:10:11 +0900 Subject: [PATCH 20/25] refac(crypto): change `ComputeInverseDenominators()` to static --- tachyon/crypto/commitments/fri/two_adic_fri.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tachyon/crypto/commitments/fri/two_adic_fri.h b/tachyon/crypto/commitments/fri/two_adic_fri.h index e0b3790ef..c9b0fbf5d 100644 --- a/tachyon/crypto/commitments/fri/two_adic_fri.h +++ b/tachyon/crypto/commitments/fri/two_adic_fri.h @@ -308,7 +308,8 @@ class TwoAdicFRI { friend class c::crypto::TwoAdicFRIImpl; - absl::flat_hash_map> ComputeInverseDenominators( + static absl::flat_hash_map> + ComputeInverseDenominators( const std::vector>>& matrices_by_round, const OpeningPoints& points_by_round, F coset_shift) { From 524dc1b240b5d652db6a0a297d6b567563649c70 Mon Sep 17 00:00:00 2001 From: Wonyong Kim Date: Fri, 30 Aug 2024 23:54:58 +0900 Subject: [PATCH 21/25] refac: use unpacking for decomposing return values of `try_emplace()` --- .../math/polynomials/multivariate/linear_combination.h | 9 ++++----- tachyon/zk/lookup/halo2/permute_expression_pair.h | 6 +++--- tachyon/zk/plonk/halo2/synthesizer.h | 5 +++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/tachyon/math/polynomials/multivariate/linear_combination.h b/tachyon/math/polynomials/multivariate/linear_combination.h index 2a60513b2..89b42d96a 100644 --- a/tachyon/math/polynomials/multivariate/linear_combination.h +++ b/tachyon/math/polynomials/multivariate/linear_combination.h @@ -68,13 +68,12 @@ class LinearCombination { base::Map(evaluations, [this](const std::shared_ptr& evaluation) { CHECK_EQ(evaluation->Degree(), num_variables_); const MLE* evaluation_ptr = evaluation.get(); - auto it = lookup_table_.try_emplace(evaluation_ptr, - flattened_ml_evaluations_.size()); - // if inserted - if (it.second) { + const auto [it, inserted] = lookup_table_.try_emplace( + evaluation_ptr, flattened_ml_evaluations_.size()); + if (inserted) { flattened_ml_evaluations_.push_back(evaluation); } - return (*it.first).second; + return it->second; }); terms_.push_back({coefficient, std::move(indexes)}); } diff --git a/tachyon/zk/lookup/halo2/permute_expression_pair.h b/tachyon/zk/lookup/halo2/permute_expression_pair.h index 15de2fe94..5e75937d9 100644 --- a/tachyon/zk/lookup/halo2/permute_expression_pair.h +++ b/tachyon/zk/lookup/halo2/permute_expression_pair.h @@ -44,11 +44,11 @@ template for (RowIndex i = 0; i < usable_rows; ++i) { const F& coeff = in.table()[i]; // if key doesn't exist, insert the key and value 1 for the key. - auto it = leftover_table_map.try_emplace(coeff, RowIndex{1}); + auto [it, inserted] = leftover_table_map.try_emplace(coeff, RowIndex{1}); // no inserted value, meaning the key exists. - if (!it.second) { + if (!inserted) { // Increase value by 1 if not inserted. - ++((*it.first).second); + ++(it->second); } } diff --git a/tachyon/zk/plonk/halo2/synthesizer.h b/tachyon/zk/plonk/halo2/synthesizer.h index 1d80fd601..924cffc7b 100644 --- a/tachyon/zk/plonk/halo2/synthesizer.h +++ b/tachyon/zk/plonk/halo2/synthesizer.h @@ -157,8 +157,9 @@ class Synthesizer { F challenge = prover->GetWriter()->SqueezeChallenge(); VLOG(2) << "Halo2(challenge[" << i << "]): " << challenge.ToHexString(true); - auto it = challenges_.try_emplace(i, std::move(challenge)); - CHECK(it.second); + const auto [_, inserted] = + challenges_.try_emplace(i, std::move(challenge)); + CHECK(inserted); } } } From 081d4f2306afa4d91545d0ce367d6e96d4480568 Mon Sep 17 00:00:00 2001 From: Wonyong Kim Date: Fri, 30 Aug 2024 23:12:56 +0900 Subject: [PATCH 22/25] perf(crypto): reduce the number of search counts --- tachyon/crypto/commitments/fri/two_adic_fri.h | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/tachyon/crypto/commitments/fri/two_adic_fri.h b/tachyon/crypto/commitments/fri/two_adic_fri.h index c9b0fbf5d..769af9249 100644 --- a/tachyon/crypto/commitments/fri/two_adic_fri.h +++ b/tachyon/crypto/commitments/fri/two_adic_fri.h @@ -328,12 +328,10 @@ class TwoAdicFRI { max_log_num_rows = std::max(max_log_num_rows, log_num_rows); for (const std::vector& point_list : points) { for (const ExtF& point : point_list) { - auto find_iter = max_log_num_rows_for_point.find(point); - if (find_iter != max_log_num_rows_for_point.end()) { - find_iter->second = - std::max(max_log_num_rows_for_point[point], log_num_rows); - } else { - max_log_num_rows_for_point.try_emplace(point, log_num_rows); + const auto [it, inserted] = + max_log_num_rows_for_point.try_emplace(point, log_num_rows); + if (!inserted) { + it->second = std::max(it->second, log_num_rows); } } } From ef3dad457a72df47b0aa503c59b4a9ea10cd6d7f Mon Sep 17 00:00:00 2001 From: Wonyong Kim Date: Fri, 30 Aug 2024 23:15:43 +0900 Subject: [PATCH 23/25] perf(crypto): reserve size for `absl::flat_hash_map` --- tachyon/crypto/commitments/fri/two_adic_fri.h | 1 + 1 file changed, 1 insertion(+) diff --git a/tachyon/crypto/commitments/fri/two_adic_fri.h b/tachyon/crypto/commitments/fri/two_adic_fri.h index 769af9249..09ac1684e 100644 --- a/tachyon/crypto/commitments/fri/two_adic_fri.h +++ b/tachyon/crypto/commitments/fri/two_adic_fri.h @@ -345,6 +345,7 @@ class TwoAdicFRI { size_t{1} << max_log_num_rows, w, coset_shift); absl::flat_hash_map> ret; + ret.reserve(max_log_num_rows_for_point.size()); for (auto it = max_log_num_rows_for_point.begin(); it != max_log_num_rows_for_point.end(); ++it) { const ExtF& point = it->first; From 82a31261585494b69a5b031b6716cab895329614 Mon Sep 17 00:00:00 2001 From: Wonyong Kim Date: Sun, 1 Sep 2024 16:20:17 +0900 Subject: [PATCH 24/25] perf(crypto): parallelize `base::Map()` in `ComputeInverseDenominators()` --- tachyon/crypto/commitments/fri/BUILD.bazel | 1 + tachyon/crypto/commitments/fri/two_adic_fri.h | 16 ++++++++++++---- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/tachyon/crypto/commitments/fri/BUILD.bazel b/tachyon/crypto/commitments/fri/BUILD.bazel index 5aa4f5faf..e6fb4af3f 100644 --- a/tachyon/crypto/commitments/fri/BUILD.bazel +++ b/tachyon/crypto/commitments/fri/BUILD.bazel @@ -73,6 +73,7 @@ tachyon_cc_library( ":two_adic_multiplicative_coset", ":verify", "//tachyon/base:bits", + "//tachyon/base:parallelize", "//tachyon/base:profiler", "//tachyon/crypto/commitments:mixed_matrix_commitment_scheme_traits_forward", "//tachyon/math/finite_fields:extension_field_traits_forward", diff --git a/tachyon/crypto/commitments/fri/two_adic_fri.h b/tachyon/crypto/commitments/fri/two_adic_fri.h index 09ac1684e..513a17413 100644 --- a/tachyon/crypto/commitments/fri/two_adic_fri.h +++ b/tachyon/crypto/commitments/fri/two_adic_fri.h @@ -15,6 +15,7 @@ #include "absl/container/flat_hash_map.h" #include "tachyon/base/bits.h" +#include "tachyon/base/parallelize.h" #include "tachyon/base/profiler.h" #include "tachyon/crypto/commitments/fri/fri_proof.h" #include "tachyon/crypto/commitments/fri/prove.h" @@ -341,6 +342,7 @@ class TwoAdicFRI { // Compute the largest subgroup we will use, in bitrev order. F w; CHECK(F::GetRootOfUnity(size_t{1} << max_log_num_rows, &w)); + // TODO(chokobole): Change type of |subgroup| to |std::vector|. std::vector subgroup = F::GetBitRevIndexSuccessivePowers( size_t{1} << max_log_num_rows, w, coset_shift); @@ -350,10 +352,16 @@ class TwoAdicFRI { it != max_log_num_rows_for_point.end(); ++it) { const ExtF& point = it->first; uint32_t log_num_rows = it->second; - std::vector temp = base::Map( - absl::MakeSpan(subgroup.data(), (size_t{1} << log_num_rows)), - [&point](F x) { return ExtF(x) - point; }); - CHECK(ExtF::BatchInverseInPlace(temp)); + std::vector temp(size_t{1} << log_num_rows); + base::Parallelize( + temp, [&subgroup, &point](absl::Span chunk, size_t chunk_offset, + size_t chunk_size) { + size_t start = chunk_offset * chunk_size; + for (size_t i = start; i < start + chunk.size(); ++i) { + chunk[i - start] = ExtF(subgroup[i]) - point; + } + CHECK(ExtF::BatchInverseInPlace(chunk)); + }); ret[point] = std::move(temp); } return ret; From 12388a0fa2b5620ab5f6113850cfb0f6cb8c65fa Mon Sep 17 00:00:00 2001 From: Ryan Kim Date: Fri, 30 Aug 2024 16:32:41 +0900 Subject: [PATCH 25/25] feat(sp1): add rust binding for `TwoAdicFriPcs::Open()` --- Cargo.Bazel.lock | 6 +- Cargo.lock | 1 + vendors/sp1/BUILD.bazel | 33 ++++ vendors/sp1/Cargo.toml | 4 + .../baby_bear_poseidon2_duplex_challenger.h | 4 + .../include/baby_bear_poseidon2_fri_proof.h | 28 +++ .../baby_bear_poseidon2_opening_points.h | 40 ++++ .../baby_bear_poseidon2_opening_proof.h | 37 ++++ .../baby_bear_poseidon2_two_adic_fri_pcs.h | 7 + vendors/sp1/src/baby_bear_poseidon2.rs | 187 +++++++++++++++++- .../sp1/src/baby_bear_poseidon2_fri_proof.cc | 14 ++ .../src/baby_bear_poseidon2_opening_points.cc | 33 ++++ .../src/baby_bear_poseidon2_opening_proof.cc | 38 ++++ .../baby_bear_poseidon2_two_adic_fri_pcs.cc | 11 ++ vendors/sp1/src/lib.rs | 1 + vendors/sp1/src/two_adic_fri_pcs.rs | 25 +++ vendors/sp1/src/util.rs | 41 ++++ 17 files changed, 502 insertions(+), 8 deletions(-) create mode 100644 vendors/sp1/include/baby_bear_poseidon2_fri_proof.h create mode 100644 vendors/sp1/include/baby_bear_poseidon2_opening_points.h create mode 100644 vendors/sp1/include/baby_bear_poseidon2_opening_proof.h create mode 100644 vendors/sp1/src/baby_bear_poseidon2_fri_proof.cc create mode 100644 vendors/sp1/src/baby_bear_poseidon2_opening_points.cc create mode 100644 vendors/sp1/src/baby_bear_poseidon2_opening_proof.cc create mode 100644 vendors/sp1/src/util.rs diff --git a/Cargo.Bazel.lock b/Cargo.Bazel.lock index 1259a0f78..708460267 100644 --- a/Cargo.Bazel.lock +++ b/Cargo.Bazel.lock @@ -1,5 +1,5 @@ { - "checksum": "cea03189298ccac5555669cf0374dddee03d3105364e2cc46f2d04aa4ed8ad0c", + "checksum": "a9fbed09c049bf53d1422ae2fb19a3cea5955abe3cd56efe8444f998567af7ee", "crates": { "addchain 0.2.0": { "name": "addchain", @@ -18221,6 +18221,10 @@ "id": "p3-util 0.1.3-succinct", "target": "p3_util" }, + { + "id": "serde 1.0.204", + "target": "serde" + }, { "id": "sp1-core 1.0.1", "target": "sp1_core" diff --git a/Cargo.lock b/Cargo.lock index f79570f47..e95b9c685 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3541,6 +3541,7 @@ dependencies = [ "p3-util", "rand 0.8.5", "rand_chacha", + "serde", "sp1-core", "sp1-primitives", "sp1-prover", diff --git a/vendors/sp1/BUILD.bazel b/vendors/sp1/BUILD.bazel index 3049e052a..ff4bba615 100644 --- a/vendors/sp1/BUILD.bazel +++ b/vendors/sp1/BUILD.bazel @@ -16,6 +16,9 @@ tachyon_rust_library( deps = all_crate_deps(normal = True) + [ ":baby_bear_poseidon2_cxx_bridge", ":baby_bear_poseidon2_duplex_challenger", + ":baby_bear_poseidon2_fri_proof", + ":baby_bear_poseidon2_opening_points", + ":baby_bear_poseidon2_opening_proof", ":baby_bear_poseidon2_prover_data", ":baby_bear_poseidon2_prover_data_vec", ":baby_bear_poseidon2_two_adic_fri_pcs", @@ -64,6 +67,9 @@ tachyon_cc_library( name = "baby_bear_poseidon2_api_hdrs", hdrs = [ "include/baby_bear_poseidon2_duplex_challenger.h", + "include/baby_bear_poseidon2_fri_proof.h", + "include/baby_bear_poseidon2_opening_points.h", + "include/baby_bear_poseidon2_opening_proof.h", "include/baby_bear_poseidon2_prover_data.h", "include/baby_bear_poseidon2_prover_data_vec.h", "include/baby_bear_poseidon2_two_adic_fri_pcs.h", @@ -84,6 +90,33 @@ tachyon_cc_library( ], ) +tachyon_cc_library( + name = "baby_bear_poseidon2_fri_proof", + srcs = ["src/baby_bear_poseidon2_fri_proof.cc"], + deps = [ + ":baby_bear_poseidon2_api_hdrs", + ":baby_bear_poseidon2_cxx_bridge/include", + ], +) + +tachyon_cc_library( + name = "baby_bear_poseidon2_opening_points", + srcs = ["src/baby_bear_poseidon2_opening_points.cc"], + deps = [ + ":baby_bear_poseidon2_api_hdrs", + ":baby_bear_poseidon2_cxx_bridge/include", + ], +) + +tachyon_cc_library( + name = "baby_bear_poseidon2_opening_proof", + srcs = ["src/baby_bear_poseidon2_opening_proof.cc"], + deps = [ + ":baby_bear_poseidon2_api_hdrs", + ":baby_bear_poseidon2_cxx_bridge/include", + ], +) + tachyon_cc_library( name = "baby_bear_poseidon2_prover_data", srcs = ["src/baby_bear_poseidon2_prover_data.cc"], diff --git a/vendors/sp1/Cargo.toml b/vendors/sp1/Cargo.toml index 44c643b42..84a6ae260 100644 --- a/vendors/sp1/Cargo.toml +++ b/vendors/sp1/Cargo.toml @@ -28,6 +28,10 @@ p3-maybe-rayon = "0.1.3-succinct" p3-poseidon2 = "0.1.3-succinct" p3-symmetric = "0.1.3-succinct" p3-util = "0.1.3-succinct" +serde = { version = "1.0", default-features = false, features = [ + "derive", + "alloc", +] } sp1-core = { git = "https://github.com/kroma-network/sp1.git", rev = "dd032eb" } sp1-prover = { git = "https://github.com/kroma-network/sp1.git", rev = "dd032eb" } sp1-primitives = { git = "https://github.com/kroma-network/sp1.git", rev = "dd032eb" } diff --git a/vendors/sp1/include/baby_bear_poseidon2_duplex_challenger.h b/vendors/sp1/include/baby_bear_poseidon2_duplex_challenger.h index 7dc543588..3853f8cde 100644 --- a/vendors/sp1/include/baby_bear_poseidon2_duplex_challenger.h +++ b/vendors/sp1/include/baby_bear_poseidon2_duplex_challenger.h @@ -21,6 +21,10 @@ class DuplexChallenger { DuplexChallenger& operator=(const DuplexChallenger& other) = delete; ~DuplexChallenger(); + tachyon_sp1_baby_bear_poseidon2_duplex_challenger* challenger() { + return challenger_; + } + void observe(const TachyonBabyBear& value); rust::Box sample(); std::unique_ptr clone() const; diff --git a/vendors/sp1/include/baby_bear_poseidon2_fri_proof.h b/vendors/sp1/include/baby_bear_poseidon2_fri_proof.h new file mode 100644 index 000000000..0c22731f4 --- /dev/null +++ b/vendors/sp1/include/baby_bear_poseidon2_fri_proof.h @@ -0,0 +1,28 @@ +#ifndef VENDORS_SP1_INCLUDE_BABY_BEAR_POSEIDON2_FRI_PROOF_H_ +#define VENDORS_SP1_INCLUDE_BABY_BEAR_POSEIDON2_FRI_PROOF_H_ + +#include + +#include "rust/cxx.h" + +#include "tachyon/c/zk/air/sp1/baby_bear_poseidon2_fri_proof.h" + +namespace tachyon::sp1_api::baby_bear_poseidon2 { + +class FriProof { + public: + explicit FriProof(tachyon_sp1_baby_bear_poseidon2_fri_proof* proof) + : proof_(proof) {} + FriProof(const FriProof& other) = delete; + FriProof& operator=(const FriProof& other) = delete; + ~FriProof(); + + std::unique_ptr clone() const; + + private: + tachyon_sp1_baby_bear_poseidon2_fri_proof* proof_; +}; + +} // namespace tachyon::sp1_api::baby_bear_poseidon2 + +#endif // VENDORS_SP1_INCLUDE_BABY_BEAR_POSEIDON2_FRI_PROOF_H_ diff --git a/vendors/sp1/include/baby_bear_poseidon2_opening_points.h b/vendors/sp1/include/baby_bear_poseidon2_opening_points.h new file mode 100644 index 000000000..d7cc0a954 --- /dev/null +++ b/vendors/sp1/include/baby_bear_poseidon2_opening_points.h @@ -0,0 +1,40 @@ +#ifndef VENDORS_SP1_INCLUDE_BABY_BEAR_POSEIDON2_OPENING_POINTS_H_ +#define VENDORS_SP1_INCLUDE_BABY_BEAR_POSEIDON2_OPENING_POINTS_H_ + +#include + +#include + +#include "tachyon/c/math/finite_fields/baby_bear/baby_bear4.h" +#include "tachyon/c/zk/air/sp1/baby_bear_poseidon2_opening_points.h" + +namespace tachyon::sp1_api::baby_bear_poseidon2 { + +struct TachyonBabyBear4; + +class OpeningPoints { + public: + explicit OpeningPoints( + tachyon_sp1_baby_bear_poseidon2_opening_points* opening_points) + : opening_points_(opening_points) {} + OpeningPoints(const OpeningPoints& other) = delete; + OpeningPoints& operator=(const OpeningPoints& other) = delete; + ~OpeningPoints(); + + const tachyon_sp1_baby_bear_poseidon2_opening_points* opening_points() const { + return opening_points_; + } + + std::unique_ptr clone() const; + void allocate(size_t round, size_t rows, size_t cols); + void set(size_t round, size_t row, size_t col, const TachyonBabyBear4& point); + + private: + tachyon_sp1_baby_bear_poseidon2_opening_points* opening_points_ = nullptr; +}; + +std::unique_ptr new_opening_points(size_t rounds); + +} // namespace tachyon::sp1_api::baby_bear_poseidon2 + +#endif // VENDORS_SP1_INCLUDE_BABY_BEAR_POSEIDON2_OPENING_POINTS_H_ diff --git a/vendors/sp1/include/baby_bear_poseidon2_opening_proof.h b/vendors/sp1/include/baby_bear_poseidon2_opening_proof.h new file mode 100644 index 000000000..6a7f7ff8e --- /dev/null +++ b/vendors/sp1/include/baby_bear_poseidon2_opening_proof.h @@ -0,0 +1,37 @@ +#ifndef VENDORS_SP1_INCLUDE_BABY_BEAR_POSEIDON2_OPENING_PROOF_H_ +#define VENDORS_SP1_INCLUDE_BABY_BEAR_POSEIDON2_OPENING_PROOF_H_ + +#include + +#include "rust/cxx.h" + +#include "tachyon/c/zk/air/sp1/baby_bear_poseidon2_fri_proof.h" +#include "tachyon/c/zk/air/sp1/baby_bear_poseidon2_opened_values.h" + +namespace tachyon::sp1_api::baby_bear_poseidon2 { + +class FriProof; + +class OpeningProof { + public: + OpeningProof(); + OpeningProof(const OpeningProof& other) = delete; + OpeningProof& operator=(const OpeningProof& other) = delete; + ~OpeningProof(); + + tachyon_sp1_baby_bear_poseidon2_opened_values** opened_values_ptr() { + return &opened_values_; + } + tachyon_sp1_baby_bear_poseidon2_fri_proof** proof_ptr() { return &proof_; } + + rust::Vec serialize_to_opened_values() const; + std::unique_ptr take_fri_proof(); + + private: + tachyon_sp1_baby_bear_poseidon2_opened_values* opened_values_; + tachyon_sp1_baby_bear_poseidon2_fri_proof* proof_; +}; + +} // namespace tachyon::sp1_api::baby_bear_poseidon2 + +#endif // VENDORS_SP1_INCLUDE_BABY_BEAR_POSEIDON2_OPENING_PROOF_H_ diff --git a/vendors/sp1/include/baby_bear_poseidon2_two_adic_fri_pcs.h b/vendors/sp1/include/baby_bear_poseidon2_two_adic_fri_pcs.h index e3ce8e152..015e2219c 100644 --- a/vendors/sp1/include/baby_bear_poseidon2_two_adic_fri_pcs.h +++ b/vendors/sp1/include/baby_bear_poseidon2_two_adic_fri_pcs.h @@ -13,9 +13,13 @@ namespace tachyon::sp1_api::baby_bear_poseidon2 { class CommitResult; +class DuplexChallenger; +class OpeningPoints; +class OpeningProof; class ProverData; class ProverDataVec; struct TachyonBabyBear; +struct TachyonBabyBear4; class TwoAdicFriPcs { public: @@ -31,6 +35,9 @@ class TwoAdicFriPcs { const TachyonBabyBear& shift) const; std::unique_ptr commit( const ProverDataVec& prover_data_vec) const; + std::unique_ptr do_open(const ProverDataVec& prover_data_vec, + const OpeningPoints& opening_points, + DuplexChallenger& challenger) const; private: tachyon_sp1_baby_bear_poseidon2_two_adic_fri* pcs_; diff --git a/vendors/sp1/src/baby_bear_poseidon2.rs b/vendors/sp1/src/baby_bear_poseidon2.rs index 918aad495..c09a49db8 100644 --- a/vendors/sp1/src/baby_bear_poseidon2.rs +++ b/vendors/sp1/src/baby_bear_poseidon2.rs @@ -1,11 +1,11 @@ -use std::{fmt::Debug, marker::PhantomData}; +use std::{fmt::Debug, io::Cursor, marker::PhantomData, pin::Pin}; use p3_baby_bear::BabyBear; use p3_challenger::{CanObserve, CanSample, CanSampleBits, FieldChallenger, GrindingChallenger}; use p3_commit::{Mmcs, OpenedValues, Pcs, PolynomialSpace, TwoAdicMultiplicativeCoset}; use p3_dft::TwoAdicSubgroupDft; use p3_field::{ExtensionField, Field, PackedField, PackedValue, PrimeField64, TwoAdicField}; -use p3_fri::{FriConfig, TwoAdicFriPcsProof, VerificationError}; +use p3_fri::{FriConfig, VerificationError}; use p3_matrix::{ bitrev::BitReversableMatrix, dense::{DenseMatrix, RowMajorMatrix}, @@ -14,15 +14,20 @@ use p3_matrix::{ use p3_maybe_rayon::prelude::*; use p3_symmetric::{CryptographicPermutation, Hash}; use p3_util::log2_strict_usize; -use tachyon_rs::math::finite_fields::baby_bear::BabyBear as TachyonBabyBearImpl; +use serde::{Deserialize, Serialize}; +use tachyon_rs::math::finite_fields::{baby_bear::BabyBear as TachyonBabyBearImpl, Fp4}; use tracing::instrument; +use crate::util::Readable; + pub struct TachyonBabyBear(pub TachyonBabyBearImpl); +pub struct TachyonBabyBear4(pub Fp4); #[cxx::bridge(namespace = "tachyon::sp1_api::baby_bear_poseidon2")] pub mod ffi { extern "Rust" { type TachyonBabyBear; + type TachyonBabyBear4; } unsafe extern "C++" { @@ -36,6 +41,40 @@ pub mod ffi { fn clone(&self) -> UniquePtr; } + unsafe extern "C++" { + include!("vendors/sp1/include/baby_bear_poseidon2_fri_proof.h"); + + type FriProof; + + fn clone(&self) -> UniquePtr; + } + + unsafe extern "C++" { + include!("vendors/sp1/include/baby_bear_poseidon2_opening_points.h"); + + type OpeningPoints; + + fn new_opening_points(rounds: usize) -> UniquePtr; + fn clone(&self) -> UniquePtr; + fn allocate(self: Pin<&mut OpeningPoints>, rounds: usize, rows: usize, cols: usize); + fn set( + self: Pin<&mut OpeningPoints>, + round: usize, + row: usize, + col: usize, + point: &TachyonBabyBear4, + ); + } + + unsafe extern "C++" { + include!("vendors/sp1/include/baby_bear_poseidon2_opening_proof.h"); + + type OpeningProof; + + fn serialize_to_opened_values(&self) -> Vec; + fn take_fri_proof(self: Pin<&mut OpeningProof>) -> UniquePtr; + } + unsafe extern "C++" { include!("vendors/sp1/include/baby_bear_poseidon2_prover_data.h"); @@ -72,6 +111,12 @@ pub mod ffi { shift: &TachyonBabyBear, ) -> &mut [TachyonBabyBear]; fn commit(&self, prover_data_vec: &ProverDataVec) -> UniquePtr; + fn do_open( + &self, + prover_data_vec: &ProverDataVec, + opening_points: &OpeningPoints, + challenger: Pin<&mut DuplexChallenger>, + ) -> UniquePtr; } } @@ -219,6 +264,107 @@ where } } +pub trait HasCXXDuplexChallenger { + fn get_inner_pin_mut(&mut self) -> Pin<&mut ffi::DuplexChallenger>; +} + +impl HasCXXDuplexChallenger + for DuplexChallenger +{ + fn get_inner_pin_mut(&mut self) -> Pin<&mut ffi::DuplexChallenger> { + self.inner.pin_mut() + } +} + +pub struct FriProof { + inner: cxx::UniquePtr, +} + +impl Serialize for FriProof { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + todo!("Not implemented yet") + } +} + +impl<'de> Deserialize<'de> for FriProof { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + todo!("Not implemented yet") + } +} + +impl Clone for FriProof { + fn clone(&self) -> Self { + Self { + inner: self.inner.clone(), + } + } +} + +impl FriProof { + pub fn new(inner: cxx::UniquePtr) -> Self { + Self { inner } + } +} + +pub struct OpeningPoints { + inner: cxx::UniquePtr, + _marker: PhantomData, +} + +impl Clone for OpeningPoints { + fn clone(&self) -> Self { + Self { + inner: self.inner.clone(), + _marker: PhantomData, + } + } +} + +impl OpeningPoints { + pub fn new(inner: cxx::UniquePtr) -> Self { + Self { + inner, + _marker: PhantomData, + } + } + + pub fn allocate(&mut self, round: usize, rows: usize, cols: usize) { + self.inner.pin_mut().allocate(round, rows, cols) + } + + pub fn set(&mut self, round: usize, row: usize, col: usize, point: &Val) { + self.inner + .pin_mut() + .set(round, row, col, unsafe { std::mem::transmute(point) }) + } +} +pub struct OpeningProof { + inner: cxx::UniquePtr, +} + +impl OpeningProof { + pub fn new(inner: cxx::UniquePtr) -> Self { + Self { inner } + } + + pub fn serialize_to_opened_values(&self) -> OpenedValues { + let buffer = self.inner.serialize_to_opened_values(); + let mut reader = Cursor::new(buffer); + let values = OpenedValues::<[u32; 4]>::read_from(&mut reader).unwrap(); + unsafe { std::mem::transmute(values) } + } + + pub fn take_fri_proof(&mut self) -> FriProof { + FriProof::new(self.inner.pin_mut().take_fri_proof()) + } +} + pub struct ProverData { inner: cxx::UniquePtr, pub ldes: Vec>, @@ -343,6 +489,18 @@ where pub fn do_commit(&self) -> ProverData { ProverData::new(self.inner.commit(&self.prover_data_vec.inner)) } + + pub fn do_open( + &self, + opening_points: &OpeningPoints, + challenger: Pin<&mut ffi::DuplexChallenger>, + ) -> OpeningProof { + OpeningProof::new(self.inner.do_open( + &self.prover_data_vec.inner, + &opening_points.inner, + challenger, + )) + } } impl Pcs @@ -353,8 +511,10 @@ where InputMmcs: Mmcs, FriMmcs: Mmcs, Challenge: TwoAdicField + ExtensionField, - Challenger: - CanObserve + CanSample + GrindingChallenger, + Challenger: CanObserve + + CanSample + + GrindingChallenger + + HasCXXDuplexChallenger, >::ProverData>: Clone, { type Domain = TwoAdicMultiplicativeCoset; @@ -364,7 +524,7 @@ where 8, >; type ProverData = crate::baby_bear_poseidon2::ProverData; - type Proof = TwoAdicFriPcsProof; + type Proof = FriProof; type Error = VerificationError; fn natural_domain_for_degree(&self, degree: usize) -> Self::Domain { @@ -419,7 +579,20 @@ where )>, challenger: &mut Challenger, ) -> (OpenedValues, Self::Proof) { - todo!() + let mut opening_points = OpeningPoints::new(ffi::new_opening_points(rounds.len())); + for (round, (_, matrix)) in rounds.iter().enumerate() { + opening_points.allocate(round, matrix.len(), matrix[0].len()); + for (row, rows) in matrix.iter().enumerate() { + for (col, challenge) in rows.iter().enumerate() { + opening_points.set(round, row, col, challenge); + } + } + } + let mut opening_proof = self.do_open(&opening_points, challenger.get_inner_pin_mut()); + ( + opening_proof.serialize_to_opened_values(), + opening_proof.take_fri_proof(), + ) } fn verify( diff --git a/vendors/sp1/src/baby_bear_poseidon2_fri_proof.cc b/vendors/sp1/src/baby_bear_poseidon2_fri_proof.cc new file mode 100644 index 000000000..b789197ac --- /dev/null +++ b/vendors/sp1/src/baby_bear_poseidon2_fri_proof.cc @@ -0,0 +1,14 @@ +#include "vendors/sp1/include/baby_bear_poseidon2_fri_proof.h" + +namespace tachyon::sp1_api::baby_bear_poseidon2 { + +FriProof::~FriProof() { + tachyon_sp1_baby_bear_poseidon2_fri_proof_destroy(proof_); +} + +std::unique_ptr FriProof::clone() const { + return std::make_unique( + tachyon_sp1_baby_bear_poseidon2_fri_proof_clone(proof_)); +} + +} // namespace tachyon::sp1_api::baby_bear_poseidon2 diff --git a/vendors/sp1/src/baby_bear_poseidon2_opening_points.cc b/vendors/sp1/src/baby_bear_poseidon2_opening_points.cc new file mode 100644 index 000000000..28857e554 --- /dev/null +++ b/vendors/sp1/src/baby_bear_poseidon2_opening_points.cc @@ -0,0 +1,33 @@ +#include "vendors/sp1/include/baby_bear_poseidon2_opening_points.h" + +#include "vendors/sp1/src/baby_bear_poseidon2.rs.h" + +namespace tachyon::sp1_api::baby_bear_poseidon2 { + +OpeningPoints::~OpeningPoints() { + tachyon_sp1_baby_bear_poseidon2_opening_points_destroy(opening_points_); +} + +std::unique_ptr OpeningPoints::clone() const { + return std::make_unique( + tachyon_sp1_baby_bear_poseidon2_opening_points_clone(opening_points_)); +} + +void OpeningPoints::allocate(size_t round, size_t rows, size_t cols) { + tachyon_sp1_baby_bear_poseidon2_opening_points_allocate(opening_points_, + round, rows, cols); +} + +void OpeningPoints::set(size_t round, size_t row, size_t col, + const TachyonBabyBear4& point) { + tachyon_sp1_baby_bear_poseidon2_opening_points_set( + opening_points_, round, row, col, + reinterpret_cast(&point)); +} + +std::unique_ptr new_opening_points(size_t rounds) { + return std::make_unique( + tachyon_sp1_baby_bear_poseidon2_opening_points_create(rounds)); +} + +} // namespace tachyon::sp1_api::baby_bear_poseidon2 diff --git a/vendors/sp1/src/baby_bear_poseidon2_opening_proof.cc b/vendors/sp1/src/baby_bear_poseidon2_opening_proof.cc new file mode 100644 index 000000000..800e9a52a --- /dev/null +++ b/vendors/sp1/src/baby_bear_poseidon2_opening_proof.cc @@ -0,0 +1,38 @@ +#include "vendors/sp1/include/baby_bear_poseidon2_opening_proof.h" + +#include + +#include "vendors/sp1/src/baby_bear_poseidon2.rs.h" + +namespace tachyon::sp1_api::baby_bear_poseidon2 { + +OpeningProof::OpeningProof() + : opened_values_(tachyon_sp1_baby_bear_poseidon2_opened_values_create()), + proof_(tachyon_sp1_baby_bear_poseidon2_fri_proof_create()) {} + +OpeningProof::~OpeningProof() { + tachyon_sp1_baby_bear_poseidon2_opened_values_destroy(opened_values_); + if (proof_) { + tachyon_sp1_baby_bear_poseidon2_fri_proof_destroy(proof_); + } +} + +rust::Vec OpeningProof::serialize_to_opened_values() const { + size_t size; + tachyon_sp1_baby_bear_poseidon2_opened_values_serialize(opened_values_, + nullptr, &size); + rust::Vec ret; + ret.reserve(size); + for (size_t i = 0; i < size; ++i) { + ret.push_back(0); + } + tachyon_sp1_baby_bear_poseidon2_opened_values_serialize(opened_values_, + ret.data(), &size); + return ret; +} + +std::unique_ptr OpeningProof::take_fri_proof() { + return std::make_unique(std::exchange(proof_, nullptr)); +} + +} // namespace tachyon::sp1_api::baby_bear_poseidon2 diff --git a/vendors/sp1/src/baby_bear_poseidon2_two_adic_fri_pcs.cc b/vendors/sp1/src/baby_bear_poseidon2_two_adic_fri_pcs.cc index 4920cf3ca..1c6c38784 100644 --- a/vendors/sp1/src/baby_bear_poseidon2_two_adic_fri_pcs.cc +++ b/vendors/sp1/src/baby_bear_poseidon2_two_adic_fri_pcs.cc @@ -42,6 +42,17 @@ std::unique_ptr TwoAdicFriPcs::commit( return ret; } +std::unique_ptr TwoAdicFriPcs::do_open( + const ProverDataVec& prover_data_vec, const OpeningPoints& opening_points, + DuplexChallenger& challenger) const { + std::unique_ptr ret(new OpeningProof); + tachyon_sp1_baby_bear_poseidon2_two_adic_fri_open( + const_cast(pcs_), + prover_data_vec.tree_vec(), opening_points.opening_points(), + challenger.challenger(), ret->opened_values_ptr(), ret->proof_ptr()); + return ret; +} + std::unique_ptr new_two_adic_fri_pcs(size_t log_blowup, size_t num_queries, size_t proof_of_work_bits) { diff --git a/vendors/sp1/src/lib.rs b/vendors/sp1/src/lib.rs index df152a224..6438bad12 100644 --- a/vendors/sp1/src/lib.rs +++ b/vendors/sp1/src/lib.rs @@ -1,6 +1,7 @@ pub mod baby_bear_poseidon2; pub mod challenger; pub mod two_adic_fri_pcs; +pub mod util; #[cfg(test)] mod test { diff --git a/vendors/sp1/src/two_adic_fri_pcs.rs b/vendors/sp1/src/two_adic_fri_pcs.rs index 09fd58e60..0b21e3dae 100644 --- a/vendors/sp1/src/two_adic_fri_pcs.rs +++ b/vendors/sp1/src/two_adic_fri_pcs.rs @@ -1,5 +1,6 @@ #[cfg(test)] mod test { + use p3_challenger::FieldChallenger; use p3_commit::Pcs; use p3_commit::PolynomialSpace; use p3_dft::TwoAdicSubgroupDft; @@ -121,6 +122,30 @@ mod test { ); } } + + let mut challenger = Challenger::new(); + let zeta: Challenge = challenger.sample_ext_element(); + let mut tachyon_challenger = challenger.clone(); + + let points_by_round = log_degrees_by_round + .iter() + .map(|log_degrees| vec![vec![zeta]; log_degrees.len()]) + .collect::>(); + let data_and_points = data_by_round + .iter() + .zip(points_by_round.clone()) + .collect::>(); + let (opening_by_round, proof) = pcs.open(data_and_points, &mut challenger); + + let tachyon_data_and_points = tachyon_data_by_round + .iter() + .zip(points_by_round) + .collect::>(); + let (tachyon_opening_by_round, tachyon_proof) = + tachyon_pcs.open(tachyon_data_and_points, &mut tachyon_challenger); + + assert_eq!(opening_by_round, tachyon_opening_by_round); + // TODO(chokobole): `std::mem::forget` was used to prevent it from double-free. We need to figure out a more elegant solution. std::mem::forget(tachyon_data_by_round); } diff --git a/vendors/sp1/src/util.rs b/vendors/sp1/src/util.rs new file mode 100644 index 000000000..8ffde00f8 --- /dev/null +++ b/vendors/sp1/src/util.rs @@ -0,0 +1,41 @@ +use std::{ + io::{Read, Result}, + mem::size_of, +}; + +fn read_vec(reader: &mut R) -> Result> +where + T: Readable, + R: Read, +{ + let mut len = [0u8; size_of::()]; + reader.read_exact(&mut len)?; + + let len = usize::from_ne_bytes(len); + + (0..len) + .map(|_| T::read_from(reader)) + .collect::>>() +} + +pub trait Readable: Sized { + fn read_from(reader: &mut R) -> Result; +} + +impl Readable for Vec { + fn read_from(reader: &mut R) -> Result { + read_vec(reader) + } +} + +impl Readable for [u32; D] { + fn read_from(reader: &mut R) -> Result { + let data = [0u32; D]; + Ok(unsafe { + let mut slice = + std::slice::from_raw_parts_mut(data.as_ptr() as *mut u8, data.len() * 4); + reader.read_exact(&mut slice)?; + std::mem::transmute(data) + }) + } +}