From 5bbf5803a5c3f054ac1163e87d8caf1e1f7739b5 Mon Sep 17 00:00:00 2001 From: Areg Vrtanesyan Date: Fri, 4 Mar 2022 03:24:32 +0400 Subject: [PATCH 1/7] Created libaura Moved sigma --- .idea/misc.xml | 6 + .idea/modules.xml | 8 + .idea/vcs.xml | 6 + .idea/workspace.xml | 77 ++++++ src/Makefile.am | 23 +- src/Makefile.test.include | 1 + src/libaura/hoom_prover.h | 36 +++ src/libaura/params.cpp | 74 +++++ src/libaura/params.h | 34 +++ src/libaura/r1_proof.h | 78 ++++++ src/libaura/r1_proof_generator.h | 76 +++++ src/libaura/r1_proof_generator.hpp | 110 ++++++++ src/libaura/r1_proof_verifier.h | 38 +++ src/libaura/r1_proof_verifier.hpp | 105 +++++++ src/libaura/sigma_primitives.h | 56 ++++ src/libaura/sigma_primitives.hpp | 95 +++++++ src/libaura/sigmaplus_proof.h | 73 +++++ src/libaura/sigmaplus_prover.h | 34 +++ src/libaura/sigmaplus_prover.hpp | 149 ++++++++++ src/libaura/sigmaplus_verifier.h | 54 ++++ src/libaura/sigmaplus_verifier.hpp | 414 ++++++++++++++++++++++++++++ src/libaura/test/protocol_tests.cpp | 212 ++++++++++++++ 22 files changed, 1758 insertions(+), 1 deletion(-) create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml create mode 100644 .idea/workspace.xml create mode 100644 src/libaura/hoom_prover.h create mode 100644 src/libaura/params.cpp create mode 100644 src/libaura/params.h create mode 100644 src/libaura/r1_proof.h create mode 100644 src/libaura/r1_proof_generator.h create mode 100644 src/libaura/r1_proof_generator.hpp create mode 100644 src/libaura/r1_proof_verifier.h create mode 100644 src/libaura/r1_proof_verifier.hpp create mode 100644 src/libaura/sigma_primitives.h create mode 100644 src/libaura/sigma_primitives.hpp create mode 100644 src/libaura/sigmaplus_proof.h create mode 100644 src/libaura/sigmaplus_prover.h create mode 100644 src/libaura/sigmaplus_prover.hpp create mode 100644 src/libaura/sigmaplus_verifier.h create mode 100644 src/libaura/sigmaplus_verifier.hpp create mode 100644 src/libaura/test/protocol_tests.cpp diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000000..830d3c82f5 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000000..31d0a43b42 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000000..94a25f7f4c --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 0000000000..e330fb020d --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1644842195939 + + + + + + \ No newline at end of file diff --git a/src/Makefile.am b/src/Makefile.am index a7ca9cdbe5..49df49a5c9 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -114,6 +114,7 @@ LIBBITCOIN_CONSENSUS=libbitcoin_consensus.a LIBBITCOIN_CLI=libbitcoin_cli.a LIBBITCOIN_UTIL=libbitcoin_util.a LIBLELANTUS=liblelantus.a +LIBAURA=libaura.a LIBBITCOIN_CRYPTO=crypto/libbitcoin_crypto.a LIBBITCOINQT=qt/libfiroqt.a LIBSECP256K1=secp256k1/libsecp256k1.la @@ -145,7 +146,8 @@ EXTRA_LIBRARIES += \ $(LIBBITCOIN_WALLET) \ $(LIBBITCOIN_ZMQ) \ $(LIBFIRO_SIGMA) \ - $(LIBLELANTUS) + $(LIBLELANTUS) \ + $(LIBAURA) lib_LTLIBRARIES = $(LIBBITCOINCONSENSUS) @@ -750,6 +752,24 @@ libsigma_a_SOURCES = \ sigma/params.cpp \ sigma/openssl_context.h +libaura_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -Werror +libaura_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) -Werror +libaura_a_SOURCES = \ + libaura/r1_proof.h \ + libaura/r1_proof_generator.h \ + libaura/r1_proof_generator.hpp \ + libaura/r1_proof_verifier.h \ + libaura/r1_proof_verifier.hpp \ + libaura/sigmaplus_proof.h \ + libaura/sigmaplus_prover.h \ + libaura/sigmaplus_prover.hpp \ + libaura/sigmaplus_verifier.h \ + libaura/sigmaplus_verifier.hpp \ + libaura/sigma_primitives.h \ + libaura/sigma_primitives.hpp \ + libaura/params.h\ + libaura/params.cpp + if GLIBC_BACK_COMPAT libbitcoin_util_a_SOURCES += compat/glibc_compat.cpp AM_LDFLAGS += $(COMPAT_LDFLAGS) @@ -789,6 +809,7 @@ firod_LDADD = \ $(LIBBITCOIN_WALLET) \ $(LIBFIRO_SIGMA) \ $(LIBLELANTUS) \ + $(LIBAURA) \ $(LIBBITCOIN_ZMQ) \ $(LIBBITCOIN_CONSENSUS) \ $(LIBBITCOIN_CRYPTO) \ diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 0dcd9a556f..f7b7b21333 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -97,6 +97,7 @@ BITCOIN_TESTS = \ sigma/test/r1_test.cpp \ sigma/test/serialize_test.cpp \ sigma/test/sigma_primitive_types_test.cpp \ + libaura/test/protocol_tests.cpp \ test/addrman_tests.cpp \ test/allocator_tests.cpp \ test/amount_tests.cpp \ diff --git a/src/libaura/hoom_prover.h b/src/libaura/hoom_prover.h new file mode 100644 index 0000000000..ce7dae2c1e --- /dev/null +++ b/src/libaura/hoom_prover.h @@ -0,0 +1,36 @@ +#ifndef FIRO_AURA_HOOM_PROVER_H +#define FIRO_AURA_HOOM_PROVER_H + +#include "hoom_proof.h" + +#include + +namespace aura { + +template +class HierarchicOOMProver{ + +public: + HierarchicOOMProver(const GroupElement& g, + const std::vector& h_gens, + int t_n, int t_m, int m_n, int m_m); + void proof(const std::vector& commits, + std::size_t l, + const Exponent& r, + bool fPadding, + HierarchicOOMProof& proof_out); + +private: + GroupElement g_; + std::vector h_; + int t_n_; + int t_m_; + int m_n_; + int m_m_; +}; + +} // namespace aura + +#include "hoom_prover.hpp" + +#endif // FIRO_AURA_SIGMA_SIGMAPLUS_PROVER_H diff --git a/src/libaura/params.cpp b/src/libaura/params.cpp new file mode 100644 index 0000000000..a1f4cbabec --- /dev/null +++ b/src/libaura/params.cpp @@ -0,0 +1,74 @@ +#include "chainparams.h" +#include "params.h" + +namespace aura { + +Params* Params::instance; +Params* Params::get_default() { + if(instance != nullptr) + return instance; + else { + //fixing generator G; + GroupElement g; + + if(!(::Params().GetConsensus().IsTestnet())) { + unsigned char buff[32] = {0}; + GroupElement base; + base.set_base_g(); + base.sha256(buff); + g.generate(buff); + } + else + g = GroupElement("9216064434961179932092223867844635691966339998754536116709681652691785432045", + "33986433546870000256104618635743654523665060392313886665479090285075695067131"); + + //fixing n and m; N = n^m = 16,384 + int n = 4; + int m = 7; + instance = new Params(g, n, m); + return instance; + } +} + +Params::Params(const GroupElement& g, int n, int m) : + g_(g), + m_(m), + n_(n) +{ + unsigned char buff0[32] = {0}; + g.sha256(buff0); + GroupElement h0; + h0.generate(buff0); + h_.reserve(28); + h_.emplace_back(h0); + for(int i = 1; i < n*m; ++i) { + h_.push_back(GroupElement()); + unsigned char buff[32] = {0}; + h_[i - 1].sha256(buff); + h_[i].generate(buff); + } +} + +Params::~Params(){ + delete instance; +} + +const GroupElement& Params::get_g() const{ + return g_; +} +const GroupElement& Params::get_h0() const{ + return h_[0]; +} + +const std::vector& Params::get_h() const{ + return h_; +} + +uint64_t Params::get_n() const{ + return n_; +} +uint64_t Params::get_m() const{ + return m_; +} + +} //namespace aura diff --git a/src/libaura/params.h b/src/libaura/params.h new file mode 100644 index 0000000000..3d034a5a64 --- /dev/null +++ b/src/libaura/params.h @@ -0,0 +1,34 @@ +#ifndef FIRO_AURA_PARAMS_H +#define FIRO_AURA_PARAMS_H +#include +#include +#include + +using namespace secp_primitives; + +namespace aura { + +class Params { +public: + static Params* get_default(); + const GroupElement& get_g() const; + const GroupElement& get_h0() const; + const std::vector& get_h() const; + uint64_t get_n() const; + uint64_t get_m() const; + +private: + Params(const GroupElement& g, int n, int m); + ~Params(); + +private: + static Params* instance; + GroupElement g_; + std::vector h_; + int m_; + int n_; +}; + +}//namespace aura + +#endif //FIRO_AURA_PARAMS_H diff --git a/src/libaura/r1_proof.h b/src/libaura/r1_proof.h new file mode 100644 index 0000000000..642da4fad7 --- /dev/null +++ b/src/libaura/r1_proof.h @@ -0,0 +1,78 @@ +#ifndef FIRO_AURA_SIGMA_R1_PROOF_H +#define FIRO_AURA_SIGMA_R1_PROOF_H + +#include +#include +#include +#include "../../serialize.h" + +namespace aura { + +template +class R1Proof { +public: + GroupElement A_; + GroupElement C_; + GroupElement D_; + std::vector f_; + Exponent ZA_; + Exponent ZC_; + +public: + R1Proof() = default; + +public: + bool operator==(R1Proof const &other) const { + return A_ == other.A_ && + C_ == other.C_ && + D_ == other.D_ && + f_ == other.f_ && + ZA_ == other.ZA_ && + ZC_ == other.ZC_; + } + + bool operator!=(R1Proof const &other) const { + return !(*this == other); + } + +public: + inline int memoryRequired(int n, int m) const { + return A_.memoryRequired() * 3 + ZA_.memoryRequired() * (m*(n - 1) + 2); + } + + inline unsigned char* serialize(unsigned char* buffer) const { + unsigned char* current = A_.serialize(buffer); + current = C_.serialize(current); + current = D_.serialize(current); + for (std::size_t i = 0; i < f_.size(); ++i) + current = f_[i].serialize(current); + current = ZA_.serialize(current); + return ZC_.serialize(current); + } + inline unsigned const char* deserialize(unsigned const char* buffer, int n, int m) { + unsigned const char* current = A_.deserialize(buffer); + current = C_.deserialize(current); + current = D_.deserialize(current); + int f_size = m * (n - 1); + f_.resize(f_size); + for(int i = 0; i < f_size; ++i) + current = f_[i].deserialize(current); + current = ZA_.deserialize(current); + return ZC_.deserialize(current); + } + + ADD_SERIALIZE_METHODS; + template + inline void SerializationOp(Stream& s, Operation ser_action) { + READWRITE(A_); + READWRITE(C_); + READWRITE(D_); + READWRITE(f_); + READWRITE(ZA_); + READWRITE(ZC_); + } +}; + +} // namespace aura + +#endif // FIRO_AURA_SIGMA_R1_PROOF_H diff --git a/src/libaura/r1_proof_generator.h b/src/libaura/r1_proof_generator.h new file mode 100644 index 0000000000..528bd30567 --- /dev/null +++ b/src/libaura/r1_proof_generator.h @@ -0,0 +1,76 @@ +#ifndef FIRO_AURA_SIGMA_R1_PROOF_GENERATOR_H +#define FIRO_AURA_SIGMA_R1_PROOF_GENERATOR_H + +#include "r1_proof.h" +#include "sigma_primitives.h" + +namespace aura { + +template +class R1ProofGenerator{ + +public: + R1ProofGenerator(const GroupElement& g, + const std::vector& h_gens, + const std::vector& b, + const Exponent& r, + int n, + int m); + + // Returns commitment B. + const GroupElement& get_B() const; + + /** \brief Generates r1 proof by randomly selecting the values of vector a. + * \param[out] proof_out - R1 proof generated. + * \param[in] skip_final_response If set to true, will only generate the initial message of the proof. + */ + void proof(R1Proof& proof_out, bool skip_final_response = false); + + /** \brief Generates R1 proof, which proves that the given matrix b of size n*m contains bits, and for each row exactly 1 bit is set to 1. + * \param[out] a_out - List of randomly generated scalars. These values are used in the rest of sigma proof. + * \param[out] proof_out - R1 proof generated. + * \param[in] skip_final_response If set to true, will only generate the initial message of the proof. + */ + void proof(std::vector& a_out, + R1Proof& proof_out, + bool skip_final_response = false); + + /** \brief Finishes generation of R1 proof, the part after receiving the challenge x. + * \param[in] a - List of randomly generated scalars. These values are used in the rest of sigma proof. + * \param[in] challenge_x Value of challenge X. + * \param[out] proof_out - R1 proof generated. + */ + void generate_final_response(const std::vector& a, + const Exponent& challenge_x, + R1Proof& proof_out); +private: + + Exponent rA_; + Exponent rC_; + Exponent rD_; + + // Generators for the commitment. Size of h_ must be n*m. + const GroupElement& g_; + const std::vector& h_; + + // n*m values of a matrix describing index l of the coin being spent. + // Each value in this vector is a bit, I.E. 0 or 1. + std::vector b_; + + // Randomness of commitment B_Commit. + Exponent r; + + // Main commitment B for the [nxm] matrix of b_. + GroupElement B_Commit; + + // Size of the matrix for commitment. Number of coins N < n^m. + int n_; + int m_; + +}; + +} // namespace aura + +#include "r1_proof_generator.hpp" + +#endif // FIRO_AURA_SIGMA_R1_PROOF_GENERATOR_H diff --git a/src/libaura/r1_proof_generator.hpp b/src/libaura/r1_proof_generator.hpp new file mode 100644 index 0000000000..157143423c --- /dev/null +++ b/src/libaura/r1_proof_generator.hpp @@ -0,0 +1,110 @@ +namespace aura { + +template +R1ProofGenerator::R1ProofGenerator( + const GroupElement& g, + const std::vector& h_gens, + const std::vector& b, + const Exponent& r, + int n , + int m) + : g_(g) + , h_(h_gens) + , b_(b) + , r(r) + , n_(n) + , m_(m) +{ + SigmaPrimitives::commit(g_, h_, b_, r, B_Commit); +} + +template +const GroupElement& R1ProofGenerator::get_B() const { + return B_Commit; +} + +template +void R1ProofGenerator::proof( + R1Proof& proof_out, bool skip_final_response) { + std::vector a; + proof(a, proof_out, skip_final_response); +} + +template +void R1ProofGenerator::proof( + std::vector& a_out, + R1Proof& proof_out, + bool skip_final_response) { + rC_.randomize(); + rD_.randomize(); + a_out.resize(n_ * m_); + for(int j = 0; j < m_; ++j) { + for(int i = 1; i < n_; ++i) { + a_out[j * n_ + i].randomize(); + a_out[j * n_] -= a_out[j * n_ + i]; + } + } + + // proof_out.B_ = B_Commit; + + //compute A + GroupElement A; + while(!A.isMember() || A.isInfinity()) { + rA_.randomize(); + SigmaPrimitives::commit(g_, h_, a_out, rA_, A); + } + proof_out.A_ = A; + + //compute C + std::vector c; + c.resize(n_ * m_); + for(int i = 0; i < n_ * m_; ++i) { + c[i] = (a_out[i] * (Exponent(uint64_t(1)) - (Exponent(uint64_t(2)) * b_[i]))); + } + GroupElement C; + while(!C.isMember() || C.isInfinity()) { + rC_.randomize(); + SigmaPrimitives::commit(g_, h_, c, rC_, C); + } + proof_out.C_ = C; + + //compute D + std::vector d; + d.resize(n_ * m_); + for(int i = 0; i < n_ * m_; i++) { + d[i] = ((a_out[i].square()).negate()); + } + GroupElement D; + while(!D.isMember() || D.isInfinity()) { + rD_.randomize(); + SigmaPrimitives::commit(g_, h_, d, rD_, D); + } + proof_out.D_ = D; + + if (!skip_final_response) { + Exponent x; + std::vector group_elements = {A, B_Commit, C, D}; + SigmaPrimitives::generate_challenge(group_elements, x); + generate_final_response(a_out, x, proof_out); + } +} + +template +void R1ProofGenerator::generate_final_response( + const std::vector& a, + const Exponent& challenge_x, + R1Proof& proof_out) { + //f + proof_out.f_.clear(); + proof_out.f_.reserve(m_ * (n_ - 1)); + for(int j = 0; j < m_; j++) { + for(int i = 1; i < n_; i++) + proof_out.f_.emplace_back(b_[(j * n_) + i] * challenge_x + a[(j * n_) + i]); + } + + //zA + proof_out.ZA_ = r * challenge_x + rA_; + proof_out.ZC_ = rC_ * challenge_x + rD_; +} + +} //namespace aura diff --git a/src/libaura/r1_proof_verifier.h b/src/libaura/r1_proof_verifier.h new file mode 100644 index 0000000000..071709319d --- /dev/null +++ b/src/libaura/r1_proof_verifier.h @@ -0,0 +1,38 @@ +#ifndef FIRO_AURA_SIGMA_R1_PROOF_VERIFIER_H +#define FIRO_AURA_SIGMA_R1_PROOF_VERIFIER_H + +namespace aura { + +template +class R1ProofVerifier { + +public: + R1ProofVerifier(const GroupElement& g, + const std::vector& h_gens, + const GroupElement& B, int n , int m); + + bool verify(const R1Proof& proof, + bool skip_final_response_verification = false) const; + + bool verify(const R1Proof& proof, + std::vector& f_out, + bool skip_final_response_verification = false) const; + + bool verify_final_response( + const R1Proof& proof, + const Exponent& challenge_x, + std::vector& f_out) const; + +private: + const GroupElement& g_; + const std::vector& h_; + GroupElement B_Commit; + int n_; + int m_; +}; + +} // namespace aura + +#include "r1_proof_verifier.hpp" + +#endif // FIRO_AURA_SIGMA_R1_PROOF_VERIFIER_H diff --git a/src/libaura/r1_proof_verifier.hpp b/src/libaura/r1_proof_verifier.hpp new file mode 100644 index 0000000000..d59e871fe3 --- /dev/null +++ b/src/libaura/r1_proof_verifier.hpp @@ -0,0 +1,105 @@ +namespace aura { + +template +R1ProofVerifier::R1ProofVerifier( + const GroupElement& g, + const std::vector& h_gens, + const GroupElement& B, + int n , + int m) + : g_(g) + , h_(h_gens) + , B_Commit(B) + , n_(n) + , m_(m){ +} + +template +bool R1ProofVerifier::verify( + const R1Proof& proof, + bool skip_final_response_verification) const { + std::vector f; + return verify(proof, f, skip_final_response_verification); +} + +template +bool R1ProofVerifier::verify( + const R1Proof& proof, + std::vector& f_out, + bool skip_final_response_verification) const{ + + if(!(proof.A_.isMember() && + B_Commit.isMember() && + proof.C_.isMember() && + proof.D_.isMember()) || + (proof.A_.isInfinity() || + B_Commit.isInfinity() || + proof.C_.isInfinity() || + proof.D_.isInfinity())) + return false; + const std::vector& f = proof.f_; + for (std::size_t i = 0; i < f.size(); i++) { + if(!f[i].isMember() || f[i].isZero()) + return false; + } + + if(!(proof.ZA_.isMember() && + proof.ZC_.isMember()) || + (proof.ZA_.isZero() || + proof.ZC_.isZero())) + return false; + + if (!skip_final_response_verification) { + Exponent x; + std::vector group_elements = {proof.A_, B_Commit, proof.C_, proof.D_}; + SigmaPrimitives::generate_challenge(group_elements, x); + return verify_final_response(proof, x, f_out); + } + return true; +} + +template +bool R1ProofVerifier::verify_final_response( + const R1Proof& proof, + const Exponent& challenge_x, + std::vector& f_out) const { + const std::vector& f = proof.f_; + + for(unsigned int j = 0; j < f.size(); ++j) { + if(f[j] == challenge_x) + return false; + } + + f_out.clear(); + f_out.reserve(n_ * m_); + for(int j = 0; j < m_; ++j) { + f_out.push_back(Exponent(uint64_t(0))); + Exponent temp; + int k = n_ - 1; + for(int i = 0; i < k; ++i) { + temp += f[j * k + i]; + f_out.emplace_back(f[j * k + i]); + } + f_out[j * n_] = challenge_x - temp; + } + + GroupElement one; + SigmaPrimitives::commit(g_, h_, f_out, proof.ZA_, one); + if((B_Commit * challenge_x + proof.A_) != one) + return false; + + std::vector f_outprime; + f_outprime.reserve(f_out.size()); + for (std::size_t i = 0; i < f_out.size(); i++) { + f_outprime.emplace_back(f_out[i] * (challenge_x - f_out[i])); + } + + GroupElement two; + SigmaPrimitives::commit(g_, h_, f_outprime, proof.ZC_, two); + if ((proof.C_ * challenge_x + proof.D_) != two) + return false; + + return true; +} + +} // namespace aura diff --git a/src/libaura/sigma_primitives.h b/src/libaura/sigma_primitives.h new file mode 100644 index 0000000000..f8d47d6117 --- /dev/null +++ b/src/libaura/sigma_primitives.h @@ -0,0 +1,56 @@ +#ifndef FIRO_AURA_SIGMA_SIGMA_PRIMITIVES_H +#define FIRO_AURA_SIGMA_SIGMA_PRIMITIVES_H + +#include "../secp256k1/include/MultiExponent.h" +#include "../secp256k1/include/GroupElement.h" +#include "../secp256k1/include/Scalar.h" + +#include +#include + +namespace aura { + +template +struct NthPower { + Exponent num; + Exponent pow; + + NthPower(const Exponent& num_) : num(num_), pow(uint64_t(1)) {} + NthPower(const Exponent& num_, const Exponent& pow_) : num(num_), pow(pow_) {} + + void go_next() { + pow *= num; + } +}; + +template +class SigmaPrimitives { + +public: + static void commit(const GroupElement& g, + const std::vector& h, + const std::vector& exp, + const Exponent& r, + GroupElement& result_out); + + static GroupElement commit(const GroupElement& g, const Exponent m, const GroupElement h, const Exponent r); + + static void convert_to_sigma(uint64_t num, uint64_t n, uint64_t m, std::vector& out); + + static std::vector convert_to_nal(uint64_t num, uint64_t n, uint64_t m); + + static void generate_challenge(const std::vector& group_elements, + Exponent& result_out); + + /** \brief Adds a factor of (x*x + a) to the given polynomial in coefficients. + * \param[in,out] coefficients Coefficients of the polynomial created. + */ + static void new_factor(const Exponent& x, const Exponent& a, std::vector& coefficients); + + }; + +} // namespace aura + +#include "sigma_primitives.hpp" + +#endif // FIRO_AURA_SIGMA_SIGMA_PRIMITIVES_H diff --git a/src/libaura/sigma_primitives.hpp b/src/libaura/sigma_primitives.hpp new file mode 100644 index 0000000000..cbba97895f --- /dev/null +++ b/src/libaura/sigma_primitives.hpp @@ -0,0 +1,95 @@ +#include "../../crypto/sha256.h" + +namespace aura { + +template +void SigmaPrimitives::commit(const GroupElement& g, + const std::vector& h, + const std::vector& exp, + const Exponent& r, + GroupElement& result_out) { + secp_primitives::MultiExponent mult(h, exp); + result_out += g * r + mult.get_multiple(); +} + +template +GroupElement SigmaPrimitives::commit( + const GroupElement& g, + const Exponent m, + const GroupElement h, + const Exponent r){ + return g * m + h * r; +} + +template +void SigmaPrimitives::convert_to_sigma( + uint64_t num, + uint64_t n, + uint64_t m, + std::vector& out) { + uint64_t rem; + uint64_t j = 0; + + for (j = 0; j < m; ++j) + { + rem = num % n; + num /= n; + for (uint64_t i = 0; i < n; ++i) { + if(i == rem) + out.push_back(Exponent(uint64_t(1))); + else + out.push_back(Exponent(uint64_t(0))); + } + } +} + +template +std::vector SigmaPrimitives::convert_to_nal( + uint64_t num, + uint64_t n, + uint64_t m) { + std::vector result; + uint64_t rem; + uint64_t j = 0; + while (num != 0) + { + rem = num % n; + num /= n; + result.push_back(rem); + j++; + } + result.resize(m); + return result; +} + +template +void SigmaPrimitives::generate_challenge( + const std::vector& group_elements, + Exponent& result_out) { + if (group_elements.empty()) + throw std::runtime_error("Group elements empty while generating a challenge."); + CSHA256 hash; + std::vector data(group_elements.size() * group_elements[0].memoryRequired()); + unsigned char* current = data.data(); + for (size_t i = 0; i < group_elements.size(); ++i) { + current = group_elements[i].serialize(current); + } + hash.Write(data.data(), data.size()); + unsigned char result_data[CSHA256::OUTPUT_SIZE]; + hash.Finalize(result_data); + result_out = result_data; +} + +template +void SigmaPrimitives::new_factor( + const Exponent& x, + const Exponent& a, + std::vector& coefficients) { + std::size_t degree = coefficients.size(); + coefficients.push_back(x * coefficients[degree-1]); + for (std::size_t d = degree-1; d >= 1; --d) + coefficients[d] = a * coefficients[d] + x * coefficients[d-1]; + coefficients[0] *= a; +} + +} // namespace aura diff --git a/src/libaura/sigmaplus_proof.h b/src/libaura/sigmaplus_proof.h new file mode 100644 index 0000000000..f88220ac8d --- /dev/null +++ b/src/libaura/sigmaplus_proof.h @@ -0,0 +1,73 @@ +#ifndef FIRO_AURA_SIGMA_SIGMAPLUS_PROOF_H +#define FIRO_AURA_SIGMA_SIGMAPLUS_PROOF_H + +#include "params.h" +#include "r1_proof.h" + +namespace aura { + +template +class SigmaPlusProof { +public: + int n; + int m; + GroupElement B_; + R1Proof r1Proof_; + std::vector Gk_; + Exponent z_; + +public: + SigmaPlusProof(int n, int m): n(n), m(m) {}; + +public: + bool operator==(const SigmaPlusProof& other) const { + return n == other.n && + m == other.m && + B_ == other.B_ && + r1Proof_ == other.r1Proof_ && + Gk_ == other.Gk_ && + z_ == other.z_; + } + + bool operator!=(const SigmaPlusProof& other) const { + return !(*this == other); + } + +public: + inline int memoryRequired() const { + return B_.memoryRequired() + + r1Proof_.memoryRequired(n, m) + + B_.memoryRequired() * m + + z_.memoryRequired(); + } + + inline unsigned char* serialize(unsigned char* buffer) const { + unsigned char* current = B_.serialize(buffer); + current = r1Proof_.serialize(current); + for (std::size_t i = 0; i < Gk_.size(); ++i) + current = Gk_[i].serialize(current); + return z_.serialize(current); + } + + inline unsigned const char* deserialize(unsigned const char* buffer) { + unsigned const char* current = B_.deserialize(buffer); + current = r1Proof_.deserialize(current, n, m); + Gk_.resize(m); + for(int i = 0; i < m; ++i) + current = Gk_[i].deserialize(current); + return z_.deserialize(current); + } + + ADD_SERIALIZE_METHODS; + template + inline void SerializationOp(Stream& s, Operation ser_action) { + READWRITE(B_); + READWRITE(r1Proof_); + READWRITE(Gk_); + READWRITE(z_); + } +}; + +} //namespace aura + +#endif // FIRO_AURA_SIGMA_SIGMAPLUS_PROOF_H diff --git a/src/libaura/sigmaplus_prover.h b/src/libaura/sigmaplus_prover.h new file mode 100644 index 0000000000..b3b65fe9b2 --- /dev/null +++ b/src/libaura/sigmaplus_prover.h @@ -0,0 +1,34 @@ +#ifndef FIRO_AURA_SIGMA_SIGMAPLUS_PROVER_H +#define FIRO_AURA_SIGMA_SIGMAPLUS_PROVER_H + +#include "r1_proof_generator.h" +#include "sigmaplus_proof.h" + +#include + +namespace aura { + +template +class SigmaPlusProver{ + +public: + SigmaPlusProver(const GroupElement& g, + const std::vector& h_gens, int n, int m); + void proof(const std::vector& commits, + std::size_t l, + const Exponent& r, + bool fPadding, + SigmaPlusProof& proof_out); + +private: + GroupElement g_; + std::vector h_; + int n_; + int m_; +}; + +} // namespace aura + +#include "sigmaplus_prover.hpp" + +#endif // FIRO_AURA_SIGMA_SIGMAPLUS_PROVER_H diff --git a/src/libaura/sigmaplus_prover.hpp b/src/libaura/sigmaplus_prover.hpp new file mode 100644 index 0000000000..da6da803f6 --- /dev/null +++ b/src/libaura/sigmaplus_prover.hpp @@ -0,0 +1,149 @@ +#include +namespace aura { + +template +SigmaPlusProver::SigmaPlusProver( + const GroupElement& g, + const std::vector& h_gens, + int n, + int m) + : g_(g) + , h_(h_gens) + , n_(n) + , m_(m) { +} + +template +void SigmaPlusProver::proof( + const std::vector& commits, + std::size_t l, + const Exponent& r, + bool fPadding, + SigmaPlusProof& proof_out) { + std::size_t setSize = commits.size(); + assert(setSize > 0); + + Exponent rB; + rB.randomize(); + + // Create table sigma of nxm bits. + std::vector sigma; + SigmaPrimitives::convert_to_sigma(l, n_, m_, sigma); + + // Values of Ro_k from Figure 5. + std::vector Pk; + Pk.resize(m_); + for (int k = 0; k < m_; ++k) { + Pk[k].randomize(); + } + R1ProofGenerator r1prover(g_, h_, sigma, rB, n_, m_); + proof_out.B_ = r1prover.get_B(); + std::vector a; + r1prover.proof(a, proof_out.r1Proof_, true /*Skip generation of final response*/); + + // Compute coefficients of Polynomials P_I(x), for all I from [0..N]. + std::size_t N = setSize; + std::vector > P_i_k; + P_i_k.resize(N); + + // last polynomial is special case if fPadding is true + for (std::size_t i = 0; i < (fPadding ? N-1 : N); ++i) { + std::vector& coefficients = P_i_k[i]; + std::vector I = SigmaPrimitives::convert_to_nal(i, n_, m_); + coefficients.push_back(a[I[0]]); + coefficients.push_back(sigma[I[0]]); + for (int j = 1; j < m_; ++j) { + SigmaPrimitives::new_factor(sigma[j * n_ + I[j]], a[j * n_ + I[j]], coefficients); + } + } + + if (fPadding) { + /* + * To optimize calculation of sum of all polynomials indices 's' = setSize-1 through 'n^m-1' we use the + * fact that sum of all of elements in each row of 'a' array is zero. Computation is done by going + * through n-ary representation of 's' and increasing "digit" at each position to 'n-1' one by one. + * During every step digits at higher positions are fixed and digits at lower positions go through all + * possible combinations with a total corresponding polynomial sum of 'x^j'. + * + * The math behind optimization (TeX notation): + * + * \sum_{i=s+1}^{N-1}p_i(x) = + * \sum_{j=0}^{m-1} + * \left[ + * \left( \sum_{i=s_j+1}^{n-1}(\delta_{l_j,i}x+a_{j,i}) \right) + * \left( \prod_{k=j}^{m-1}(\delta_{l_k,s_k}x+a_{k,s_k}) \right) + * x^j + * \right] + */ + + std::vector I = SigmaPrimitives::convert_to_nal(N-1, n_, m_); + std::vector lj = SigmaPrimitives::convert_to_nal(l, n_, m_); + + std::vector p_i_sum; + p_i_sum.emplace_back(uint64_t(1)); + std::vector> partial_p_s; + + // Pre-calculate product parts and calculate p_s(x) at the same time, put the latter into p_i_sum + for (int j = m_ - 1; j >= 0; j--) { + partial_p_s.push_back(p_i_sum); + SigmaPrimitives::new_factor(sigma[j * n_ + I[j]], a[j * n_ + I[j]], p_i_sum); + } + + for (int j = 0; j < m_; j++) { + // \sum_{i=s_j+1}^{n-1}(\delta_{l_j,i}x+a_{j,i}) + Exponent a_sum(uint64_t(0)); + for (int i = I[j] + 1; i < n_; i++) + a_sum += a[j * n_ + i]; + Exponent x_sum(uint64_t(lj[j] >= I[j]+1 ? 1 : 0)); + + // Multiply by \prod_{k=j}^{m-1}(\delta_{l_k,s_k}x+a_{k,s_k}) + std::vector &polynomial = partial_p_s[m_ - j - 1]; + SigmaPrimitives::new_factor(x_sum, a_sum, polynomial); + + // Multiply by x^j and add to the result + for (int k = 0; k < m_ - j; k++) + p_i_sum[j + k] += polynomial[k]; + } + + P_i_k[N-1] = p_i_sum; + } + + //computing G_k`s; + std::vector Gk; + Gk.reserve(m_); + for (int k = 0; k < m_; ++k) { + std::vector P_i; + P_i.reserve(N); + for (size_t i = 0; i < N; ++i) { + P_i.emplace_back(P_i_k[i][k]); + } + secp_primitives::MultiExponent mult(commits, P_i); + GroupElement c_k = mult.get_multiple(); + c_k += SigmaPrimitives::commit(g_, Exponent(uint64_t(0)), h_[0], Pk[k]); + Gk.emplace_back(c_k); + } + proof_out.Gk_ = Gk; + + // Compute value of challenge X, then continue R1 proof and sigma final response proof. + std::vector group_elements = { + proof_out.r1Proof_.A_, proof_out.B_, proof_out.r1Proof_.C_, proof_out.r1Proof_.D_}; + + group_elements.insert(group_elements.end(), Gk.begin(), Gk.end()); + Exponent x; + SigmaPrimitives::generate_challenge(group_elements, x); + r1prover.generate_final_response(a, x, proof_out.r1Proof_); + + //computing z + Exponent z; + z = r * x.exponent(uint64_t(m_)); + Exponent sum; + Exponent x_k(uint64_t(1)); + for (int k = 0; k < m_; ++k) { + sum += (Pk[k] * x_k); + x_k *= x; + } + z -= sum; + proof_out.z_ = z; +} + +} // namespace aura diff --git a/src/libaura/sigmaplus_verifier.h b/src/libaura/sigmaplus_verifier.h new file mode 100644 index 0000000000..0a5e70c80d --- /dev/null +++ b/src/libaura/sigmaplus_verifier.h @@ -0,0 +1,54 @@ +#ifndef FIRO_AURA_SIGMA_SIGMAPLUS_VERIFIER_H +#define FIRO_AURA_SIGMA_SIGMAPLUS_VERIFIER_H + +#include "r1_proof_verifier.h" +#include "util.h" + +namespace aura { +template +class SigmaPlusVerifier{ + +public: + SigmaPlusVerifier(const GroupElement& g, + const std::vector& h_gens, + int n, int m_); + + bool verify(const std::vector& commits, + const SigmaPlusProof& proof, + bool fPadding) const; + + bool batch_verify(const std::vector& commits, + const std::vector& serials, + const std::vector& fPadding, + const std::vector& setSizes, + const std::vector>& proofs) const; + + bool membership_checks(const SigmaPlusProof& proof) const; + bool compute_fs(const SigmaPlusProof& proof, const Exponent& x, std::vector& f_) const; + bool abcd_checks(const SigmaPlusProof& proof, const Exponent& x, const std::vector& f_) const; + + void compute_fis(int j, const std::vector& f, std::vector& f_i_) const; + void compute_fis(const Exponent& f_i, int j, const std::vector& f, typename std::vector::iterator& ptr, typename std::vector::iterator end_ptr) const; + void compute_batch_fis( + const Exponent& f_i, + int j, + const std::vector& f, + const Exponent& y, + Exponent& e, + typename std::vector::iterator& ptr, + typename std::vector::iterator start_ptr, + typename std::vector::iterator end_ptr) const; + + +private: + GroupElement g_; + std::vector h_; + int n; + int m; +}; + +} // namespace aura + +#include "sigmaplus_verifier.hpp" + +#endif // FIRO_AURA_SIGMA_SIGMAPLUS_VERIFIER_H diff --git a/src/libaura/sigmaplus_verifier.hpp b/src/libaura/sigmaplus_verifier.hpp new file mode 100644 index 0000000000..14a0061382 --- /dev/null +++ b/src/libaura/sigmaplus_verifier.hpp @@ -0,0 +1,414 @@ + +#include +namespace aura{ + +template +SigmaPlusVerifier::SigmaPlusVerifier( + const GroupElement& g, + const std::vector& h_gens, + int n, + int m) + : g_(g) + , h_(h_gens) + , n(n) + , m(m){ +} + +template +bool SigmaPlusVerifier::verify( + const std::vector& commits, + const SigmaPlusProof& proof, + bool fPadding) const { + + R1ProofVerifier r1ProofVerifier(g_, h_, proof.B_, n, m); + std::vector f; + const R1Proof& r1Proof = proof.r1Proof_; + if (!r1ProofVerifier.verify(r1Proof, f, true /* Skip verification of final response */)) { + LogPrintf("Sigma spend failed due to r1 proof incorrect."); + return false; + } + + if (!proof.B_.isMember() || proof.B_.isInfinity()) { + LogPrintf("Sigma spend failed due to value of B outside of group."); + return false; + } + + const std::vector & Gk = proof.Gk_; + for (int k = 0; k < m; ++k) { + if (!Gk[k].isMember() || Gk[k].isInfinity()) { + LogPrintf("Sigma spend failed due to value of GK[i] outside of group."); + return false; + } + } + + // Compute value of challenge X, then continue R1 proof and sigma final response proof. + std::vector group_elements = { + r1Proof.A_, proof.B_, r1Proof.C_, r1Proof.D_}; + + group_elements.insert(group_elements.end(), Gk.begin(), Gk.end()); + Exponent challenge_x; + SigmaPrimitives::generate_challenge(group_elements, challenge_x); + + // Now verify the final response of r1 proof. Values of "f" are finalized only after this call. + if (!r1ProofVerifier.verify_final_response(r1Proof, challenge_x, f)) { + LogPrintf("Sigma spend failed due to incorrect final response."); + return false; + } + + if(!proof.z_.isMember() || proof.z_.isZero()) { + LogPrintf("Sigma spend failed due to value of Z outside of group."); + return false; + } + + if (commits.empty()) { + LogPrintf("No mints in the anonymity set"); + return false; + } + + std::size_t N = commits.size(); + std::vector f_i_; + f_i_.resize(N); + + compute_fis(m, f, f_i_); + + if (fPadding) { + /* + * Optimization for getting power for last 'commits' array element is done similarly to the one used in creating + * a proof. The fact that sum of any row in 'f' array is 'x' (challenge value) is used. + * + * Math (in TeX notation): + * + * \sum_{i=s+1}^{N-1} \prod_{j=0}^{m-1}f_{j,i_j} = + * \sum_{j=0}^{m-1} + * \left[ + * \left( \sum_{i=s_j+1}^{n-1}f_{j,i} \right) + * \left( \prod_{k=j}^{m-1}f_{k,s_k} \right) + * x^j + * \right] + */ + + Exponent pow(uint64_t(1)); + std::vector I = SigmaPrimitives::convert_to_nal(N - 1, n, m); + std::vector f_part_product; // partial product of f array elements for lastIndex + for (int j = m - 1; j >= 0; j--) { + f_part_product.push_back(pow); + pow *= f[j * n + I[j]]; + } + + Exponent xj(uint64_t(1));; // x^j + for (int j = 0; j < m; j++) { + Exponent fi_sum(uint64_t(0)); + for (int i = I[j] + 1; i < n; i++) + fi_sum += f[j*n + i]; + pow += fi_sum * xj * f_part_product[m - j - 1]; + xj *= challenge_x; + } + f_i_[N - 1] = pow; + } + + secp_primitives::MultiExponent mult(commits, f_i_); + GroupElement t1 = mult.get_multiple(); + + GroupElement t2; + Exponent x_k(uint64_t(1)); + for(int k = 0; k < m; ++k){ + t2 += (Gk[k] * (x_k.negate())); + x_k *= challenge_x; + } + + GroupElement left(t1 + t2); + if (left != SigmaPrimitives::commit(g_, Exponent(uint64_t(0)), h_[0], proof.z_)) { + LogPrintf("Sigma spend failed due to final proof verification failure."); + return false; + } + + return true; +} + +template +bool SigmaPlusVerifier::batch_verify( + const std::vector& commits, + const std::vector& serials, + const std::vector& fPadding, + const std::vector& setSizes, + const std::vector>& proofs) const { + + int M = proofs.size(); + int N = commits.size(); + + if (commits.empty()) + return false; + + for(int t = 0; t < M; ++t) { + if (!membership_checks(proofs[t])) { + LogPrintf("Sigma spend failed due to membership check failed."); + return false; + } + } + std::vector challenges; + challenges.resize(M); + + std::vector> f_; + f_.resize(M); + for (int t = 0; t < M; ++t) + { + std::vector group_elements = { + proofs[t].r1Proof_.A_, proofs[t].B_, proofs[t].r1Proof_.C_, proofs[t].r1Proof_.D_}; + + group_elements.insert(group_elements.end(), proofs[t].Gk_.begin(), proofs[t].Gk_.end()); + SigmaPrimitives::generate_challenge(group_elements, challenges[t]); + + if(!compute_fs(proofs[t], challenges[t], f_[t]) || !abcd_checks(proofs[t], challenges[t], f_[t])) { + LogPrintf("Sigma spend failed due to compute_fs or abcd_checks failed."); + return false; + } + } + + std::vector y; + y.resize(M); + for (int t = 0; t < M; ++t) + y[t].randomize(); + + std::vector f_i_t; + f_i_t.resize(N); + GroupElement right; + Scalar exp; + + std::vector > I_; + I_.resize(N); + for (int i = 0; i < N ; ++i) + I_[i] = SigmaPrimitives::convert_to_nal(i, n, m); + + for (int t = 0; t < M; ++t) + { + right += (SigmaPrimitives::commit(g_, Scalar(uint64_t(0)), h_[0], proofs[t].z_)) * y[t]; + Scalar e; + size_t size = setSizes[t]; + size_t start = N - size; + + Scalar f_i(uint64_t(1)); + std::vector::iterator ptr = f_i_t.begin() + start; + compute_batch_fis(f_i, m, f_[t], y[t], e, ptr, ptr, ptr + size - 1); + + if(fPadding[t]) { + /* + * Optimization for getting power for last 'commits' array element is done similarly to the one used in creating + * a proof. The fact that sum of any row in 'f' array is 'x' (challenge value) is used. + * + * Math (in TeX notation): + * + * \sum_{i=s+1}^{N-1} \prod_{j=0}^{m-1}f_{j,i_j} = + * \sum_{j=0}^{m-1} + * \left[ + * \left( \sum_{i=s_j+1}^{n-1}f_{j,i} \right) + * \left( \prod_{k=j}^{m-1}f_{k,s_k} \right) + * x^j + * \right] + */ + + Scalar pow(uint64_t(1)); + std::vector f_part_product; // partial product of f array elements for lastIndex + for (int j = m - 1; j >= 0; j--) { + f_part_product.push_back(pow); + pow *= f_[t][j * n + I_[size - 1][j]]; + } + + NthPower xj(challenges[t]); + for (std::size_t j = 0; j < m; j++) { + Scalar fi_sum(uint64_t(0)); + for (std::size_t i = I_[size - 1][j] + 1; i < n; i++) + fi_sum += f_[t][j * n + i]; + pow += fi_sum * xj.pow * f_part_product[m - j - 1]; + xj.go_next(); + } + + f_i_t[N - 1] += pow * y[t]; + e += pow; + } else { + f_i = (uint64_t(1)); + for (std::size_t j = 0; j < m; ++j) + { + f_i *= f_[t][j*n + I_[size - 1][j]]; + } + + f_i_t[N - 1] += f_i * y[t]; + e += f_i; + } + + e *= serials[t] * y[t]; + exp += e; + } + + secp_primitives::MultiExponent mult(commits, f_i_t); + GroupElement t1 = mult.get_multiple(); + + std::vector> x_t_k_neg; + x_t_k_neg.resize(M); + for (int t = 0; t < M; ++t) { + x_t_k_neg[t].reserve(m); + NthPower x_k(challenges[t]); + for (uint64_t k = 0; k < m; ++k) { + x_t_k_neg[t].emplace_back(x_k.pow.negate()); + x_k.go_next(); + } + } + + GroupElement t2; + for (int t = 0; t < M; ++t) { + const std::vector & Gk = proofs[t].Gk_; + GroupElement term; + for (std::size_t k = 0; k < m; ++k) + { + term += ((Gk[k]) * x_t_k_neg[t][k]); + } + term *= y[t]; + t2 += term; + } + GroupElement left(t1 + t2); + + right += g_ * exp; + if(left != right) + return false; + + return true; +} + +template +bool SigmaPlusVerifier::membership_checks(const SigmaPlusProof& proof) const { + if(!(proof.r1Proof_.A_.isMember() && + proof.B_.isMember() && + proof.r1Proof_.C_.isMember() && + proof.r1Proof_.D_.isMember()) || + (proof.r1Proof_.A_.isInfinity() || + proof.B_.isInfinity() || + proof.r1Proof_.C_.isInfinity() || + proof.r1Proof_.D_.isInfinity())) + return false; + + for (std::size_t i = 0; i < proof.r1Proof_.f_.size(); i++) + { + if (!proof.r1Proof_.f_[i].isMember() || proof.r1Proof_.f_[i].isZero()) + return false; + } + const std::vector & Gk = proof.Gk_; + for (std::size_t k = 0; k < m; ++k) + { + if (!Gk[k].isMember() || Gk[k].isInfinity()) + return false; + } + if(!(proof.r1Proof_.ZA_.isMember() && + proof.r1Proof_.ZC_.isMember() && + proof.z_.isMember()) || + (proof.r1Proof_.ZA_.isZero() || + proof.r1Proof_.ZC_.isZero() || + proof.z_.isZero())) + return false; + return true; +} + +template +bool SigmaPlusVerifier::compute_fs( + const SigmaPlusProof& proof, + const Exponent& x, + std::vector& f_) const { + for(unsigned int j = 0; j < proof.r1Proof_.f_.size(); ++j) { + if(proof.r1Proof_.f_[j] == x) + return false; + } + + f_.reserve(n * m); + for (std::size_t j = 0; j < m; ++j) + { + f_.push_back(Scalar(uint64_t(0))); + Scalar temp; + int k = n - 1; + for (int i = 0; i < k; ++i) + { + temp += proof.r1Proof_.f_[j * k + i]; + f_.emplace_back(proof.r1Proof_.f_[j * k + i]); + } + f_[j * n] = x - temp; + } + return true; +} + +template +bool SigmaPlusVerifier::abcd_checks( + const SigmaPlusProof& proof, + const Exponent& x, + const std::vector& f_) const { + Exponent c; + c.randomize(); + + // Aggregating two checks into one, B^x * A = Comm(..) and C^x * D = Comm(..) + std::vector f_plus_f_prime; + f_plus_f_prime.reserve(f_.size()); + for(std::size_t i = 0; i < f_.size(); i++) + f_plus_f_prime.emplace_back(f_[i] * c + f_[i] * (x - f_[i])); + + GroupElement right; + SigmaPrimitives::commit(g_, h_, f_plus_f_prime, proof.r1Proof_.ZA_ * c + proof.r1Proof_.ZC_, right); + if(((proof.B_ * x + proof.r1Proof_.A_) * c + proof.r1Proof_.C_ * x + proof.r1Proof_.D_) != right) + return false; + return true; +} + +template +void SigmaPlusVerifier::compute_fis(int j, const std::vector& f, std::vector& f_i_) const { + Exponent f_i(uint64_t(1)); + typename std::vector::iterator ptr = f_i_.begin(); + compute_fis(f_i, m, f, ptr, f_i_.end()); +} + +template +void SigmaPlusVerifier::compute_fis(const Exponent& f_i, int j, const std::vector& f, typename std::vector::iterator& ptr, typename std::vector::iterator end_ptr) const { + j--; + if (j == -1) + { + if(ptr < end_ptr) + *ptr++ += f_i; + return; + } + + Scalar t; + + for (int i = 0; i < n; i++) + { + t = f[j * n + i]; + t *= f_i; + + compute_fis(t, j, f, ptr, end_ptr); + } +} + +template +void SigmaPlusVerifier::compute_batch_fis( + const Exponent& f_i, + int j, + const std::vector& f, + const Exponent& y, + Exponent& e, + typename std::vector::iterator& ptr, + typename std::vector::iterator start_ptr, + typename std::vector::iterator end_ptr)const { + j--; + if (j == -1) + { + if(ptr >= start_ptr && ptr < end_ptr){ + *ptr++ += f_i * y; + e += f_i; + } + return; + } + + Exponent t; + + for (int i = 0; i < n; i++) + { + t = f[j * n + i]; + t *= f_i; + compute_batch_fis(t, j, f, y, e, ptr, start_ptr, end_ptr); + } +} + +} // namespace aura \ No newline at end of file diff --git a/src/libaura/test/protocol_tests.cpp b/src/libaura/test/protocol_tests.cpp new file mode 100644 index 0000000000..40a29e1be9 --- /dev/null +++ b/src/libaura/test/protocol_tests.cpp @@ -0,0 +1,212 @@ +#include "../params.h" +#include "../sigmaplus_prover.h" +#include "../sigmaplus_verifier.h" + +#include + +#include "../../test/fixtures.h" + +BOOST_FIXTURE_TEST_SUITE(aura_protocol_tests, ZerocoinTestingSetup200) + +BOOST_AUTO_TEST_CASE(one_out_of_n) +{ + auto params = aura::Params::get_default(); + int N = 16384; + int n = params->get_n(); + int m = params->get_m(); + int index = 0; + + secp_primitives::GroupElement g; + g.randomize(); + std::vector h_gens; + h_gens.resize(n * m); + for(int i = 0; i < n * m; ++i ){ + h_gens[i].randomize(); + } + secp_primitives::Scalar r; + r.randomize(); + aura::SigmaPlusProver prover(g,h_gens, n, m); + + std::vector commits; + for(int i = 0; i < N; ++i){ + if(i == index){ + secp_primitives::GroupElement c; + secp_primitives::Scalar zero(uint64_t(0)); + c = aura::SigmaPrimitives::commit(g, zero, h_gens[0], r); + commits.push_back(c); + + } + else{ + commits.push_back(secp_primitives::GroupElement()); + commits[i].randomize(); + } + } + aura::SigmaPlusProof proof(n, m); + + prover.proof(commits, index, r, true, proof); + + aura::SigmaPlusVerifier verifier(g, h_gens, n, m); + + BOOST_CHECK(verifier.verify(commits, proof, true)); +} + +BOOST_AUTO_TEST_CASE(one_out_of_n_padding) +{ + auto params = aura::Params::get_default(); + int N = 10000; + int n = params->get_n(); + int m = params->get_m(); + int index = 9999; + + secp_primitives::GroupElement g; + g.randomize(); + std::vector h_gens; + h_gens.resize(n * m); + for(int i = 0; i < n * m; ++i ){ + h_gens[i].randomize(); + } + secp_primitives::Scalar r; + r.randomize(); + aura::SigmaPlusProver prover(g,h_gens, n, m); + + std::vector commits; + for(int i = 0; i < N; ++i){ + if(i == index){ + secp_primitives::GroupElement c; + secp_primitives::Scalar zero(uint64_t(0)); + c = aura::SigmaPrimitives::commit(g, zero, h_gens[0], r); + commits.push_back(c); + + } + else{ + commits.push_back(secp_primitives::GroupElement()); + commits[i].randomize(); + } + } + aura::SigmaPlusProof proof(n, m); + + prover.proof(commits, index, r, true, proof); + + aura::SigmaPlusVerifier verifier(g, h_gens, n, m); + + BOOST_CHECK(verifier.verify(commits, proof, true)); + + aura::SigmaPlusProof proofNew(n, m); + prover.proof(commits, 11111, r, true, proofNew); + BOOST_CHECK(verifier.verify(commits, proofNew, true)); +} + +BOOST_AUTO_TEST_CASE(prove_and_verify_in_different_set) +{ + auto params = aura::Params::get_default(); + int N = 16384; + int n = params->get_n(); + int m = params->get_m(); + int index = 0; + + secp_primitives::GroupElement g; + g.randomize(); + std::vector h_gens; + h_gens.resize(n * m); + for(int i = 0; i < n * m; ++i ){ + h_gens[i].randomize(); + } + secp_primitives::Scalar r; + r.randomize(); + aura::SigmaPlusProver prover(g,h_gens, n, m); + + std::vector commits; + for(int i = 0; i < N; ++i){ + if(i == index){ + secp_primitives::GroupElement c; + secp_primitives::Scalar zero(uint64_t(0)); + c = aura::SigmaPrimitives::commit(g, zero, h_gens[0], r); + commits.push_back(c); + + } + else{ + commits.push_back(secp_primitives::GroupElement()); + commits[i].randomize(); + } + } + + aura::SigmaPlusProof proof(n, m); + + prover.proof(commits, index, r, true, proof); + + aura::SigmaPlusVerifier verifier(g, h_gens, n, m); + + // Add more commit + secp_primitives::GroupElement c; + secp_primitives::Scalar zero(uint64_t(0)); + c = aura::SigmaPrimitives::commit(g, zero, h_gens[0], r); + commits.push_back(c); + + BOOST_CHECK(!verifier.verify(commits, proof, true)); +} + +BOOST_AUTO_TEST_CASE(prove_coin_out_of_index) +{ + auto params = aura::Params::get_default(); + int N = 16384; + int n = params->get_n(); + int m = params->get_m(); + + secp_primitives::GroupElement g; + g.randomize(); + std::vector h_gens; + h_gens.resize(n * m); + for(int i = 0; i < n * m; ++i ){ + h_gens[i].randomize(); + } + secp_primitives::Scalar r; + r.randomize(); + aura::SigmaPlusProver prover(g,h_gens, n, m); + + std::vector commits; + for(int i = 0; i < N; ++i){ + commits.push_back(secp_primitives::GroupElement()); + commits[i].randomize(); + } + + aura::SigmaPlusProof proof(n, m); + + prover.proof(commits, commits.size(), r, true, proof); + + aura::SigmaPlusVerifier verifier(g, h_gens, n, m); + BOOST_CHECK(!verifier.verify(commits, proof, true)); +} + +BOOST_AUTO_TEST_CASE(prove_coin_not_in_set) +{ + auto params = aura::Params::get_default(); + int N = 16384; + int n = params->get_n(); + int m = params->get_m(); + int index = 0; + secp_primitives::GroupElement g; + g.randomize(); + std::vector h_gens; + h_gens.resize(n * m); + for(int i = 0; i < n * m; ++i ){ + h_gens[i].randomize(); + } + secp_primitives::Scalar r; + r.randomize(); + aura::SigmaPlusProver prover(g,h_gens, n, m); + + std::vector commits; + for(int i = 0; i < N; ++i){ + commits.push_back(secp_primitives::GroupElement()); + commits[i].randomize(); + } + + aura::SigmaPlusProof proof(n, m); + + prover.proof(commits, index, r, true, proof); + + aura::SigmaPlusVerifier verifier(g, h_gens, n, m); + BOOST_CHECK(!verifier.verify(commits, proof, true)); +} + +BOOST_AUTO_TEST_SUITE_END() From 6c84b45a57edf3f7106f6d700699d1b3333fb3b9 Mon Sep 17 00:00:00 2001 From: Areg Vrtanesyan Date: Sun, 6 Mar 2022 12:30:54 +0400 Subject: [PATCH 2/7] Added HOOM header files and fixes --- .idea/workspace.xml | 5 ++- src/Makefile.test.include | 2 +- src/libaura/hoom_proof.h | 75 +++++++++++++++++++++++++++++++++++++ src/libaura/hoom_prover.h | 4 +- src/libaura/hoom_verifier.h | 37 ++++++++++++++++++ 5 files changed, 117 insertions(+), 6 deletions(-) create mode 100644 src/libaura/hoom_proof.h create mode 100644 src/libaura/hoom_verifier.h diff --git a/.idea/workspace.xml b/.idea/workspace.xml index e330fb020d..1ecd13284c 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -10,8 +10,9 @@ - + + diff --git a/src/Makefile.test.include b/src/Makefile.test.include index f7b7b21333..8f25458691 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -238,7 +238,7 @@ test_test_bitcoin_LDADD = $(LIBBITCOIN_SERVER) tor/src/core/libtor-app.a \ tor/src/ext/keccak-tiny/libkeccak-tiny.a test_test_bitcoin_SOURCES = $(BITCOIN_TESTS) $(JSON_TEST_FILES) $(RAW_TEST_FILES) test_test_bitcoin_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -I$(builddir)/test/ $(TESTDEFS) $(EVENT_CFLAGS) $(LIBBLSSIG_INCLUDES) -test_test_bitcoin_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBFIRO_SIGMA) $(LIBLELANTUS) $(LIBUNIVALUE) $(LIBLEVELDB) $(LIBLEVELDB_SSE42) $(LIBMEMENV) \ +test_test_bitcoin_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBFIRO_SIGMA) $(LIBAURA) $(LIBLELANTUS) $(LIBUNIVALUE) $(LIBLEVELDB) $(LIBLEVELDB_SSE42) $(LIBMEMENV) \ $(BACKTRACE_LIB) $(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB) $(LIBSECP256K1) $(EVENT_PTHREADS_LIBS) $(ZMQ_LIBS) $(ZLIB_LIBS) test_test_bitcoin_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) if ENABLE_WALLET diff --git a/src/libaura/hoom_proof.h b/src/libaura/hoom_proof.h new file mode 100644 index 0000000000..8558a117b7 --- /dev/null +++ b/src/libaura/hoom_proof.h @@ -0,0 +1,75 @@ +#ifndef FIRO_AURA_HOOM_PROOF_H +#define FIRO_AURA_HOOM_PROOF_H + +#include "params.h" +#include "sigmaplus_proof.h" + +namespace aura { + +template +class HOOMProof { +public: + int t_n_; + int t_m_; + int m_n_; + int m_m_; + std::vector d_; + SigmaPlusProof d_Proof_; + SigmaPlusProof D_Proof_; + +public: + HOOMProof(int t_n_, int t_m_, int m_n_, int m_m_): + t_n_(t_n_), t_m_(t_m_) m_n_(m_n_), m_m_(m_m_) {}; + +public: + bool operator==(const SigmaPlusProof& other) const { + return t_n_ == other.t_n_ && + t_m_ == other.t_m_ && + m_n_ == other.t_n_ && + m_m_ == other.t_m_ && + d_ == other.d_ && + d_Proof_ == other.d_Proof_ && + D_Proof_ == other.D_Proof_ && + } + + bool operator!=(const SigmaPlusProof& other) const { + return !(*this == other); + } + +public: + inline int memoryRequired() const { + return d_.memoryRequired() + + d_Proof_.memoryRequired(n, m) + + D_Proof_.memoryRequired(n, m); + } + +/* inline unsigned char* serialize(unsigned char* buffer) const { + unsigned char* current = B_.serialize(buffer); + current = r1Proof_.serialize(current); + for (std::size_t i = 0; i < Gk_.size(); ++i) + current = Gk_[i].serialize(current); + return z_.serialize(current); + } + + inline unsigned const char* deserialize(unsigned const char* buffer) { + unsigned const char* current = B_.deserialize(buffer); + current = r1Proof_.deserialize(current, n, m); + Gk_.resize(m); + for(int i = 0; i < m; ++i) + current = Gk_[i].deserialize(current); + return z_.deserialize(current); + } + + ADD_SERIALIZE_METHODS; + template + inline void SerializationOp(Stream& s, Operation ser_action) { + READWRITE(B_); + READWRITE(r1Proof_); + READWRITE(Gk_); + READWRITE(z_); + } */ +}; + +} //namespace aura + +#endif // FIRO_AURA_HOOM_PROOF_H diff --git a/src/libaura/hoom_prover.h b/src/libaura/hoom_prover.h index ce7dae2c1e..27aec926d1 100644 --- a/src/libaura/hoom_prover.h +++ b/src/libaura/hoom_prover.h @@ -15,10 +15,8 @@ class HierarchicOOMProver{ const std::vector& h_gens, int t_n, int t_m, int m_n, int m_m); void proof(const std::vector& commits, - std::size_t l, const Exponent& r, - bool fPadding, - HierarchicOOMProof& proof_out); + HOOMProof& proof_out); private: GroupElement g_; diff --git a/src/libaura/hoom_verifier.h b/src/libaura/hoom_verifier.h new file mode 100644 index 0000000000..ffa9679ec4 --- /dev/null +++ b/src/libaura/hoom_verifier.h @@ -0,0 +1,37 @@ +#ifndef FIRO_AURA_HOOM_VERIFIER_H +#define FIRO_AURA_HOOM_VERIFIER_H + +#include "sigmaplus_verifier.h" +#include "util.h" + +namespace aura { +template +class HOOMVerifier{ + +public: + SigmaPlusVerifier(const GroupElement& g, + const std::vector& h_gens, + int t_n, int t_m, int m_n, int m_m); + + bool verify(const std::vector& commits, + const HOOMProof& proof) const; + + bool batch_verify(const std::vector& commits, + const std::vector& serials, + const std::vector>& proofs) const; + + +private: + GroupElement g_; + std::vector h_; + int t_n_; + int t_m_; + int m_n_; + int m_m_; +}; + +} // namespace aura + +#include "sigmaplus_verifier.hpp" + +#endif // FIRO_AURA_HOOM_VERIFIER_H From 82457b74f0dda8ca0e45b0a1e913ba7d21e36386 Mon Sep 17 00:00:00 2001 From: Areg Vrtanesyan Date: Mon, 14 Mar 2022 07:34:18 +0400 Subject: [PATCH 3/7] Wrote HOOM verifier and prover functionality --- .idea/workspace.xml | 10 ++- src/Makefile.am | 4 +- .../{sigma_primitives.h => aura_primitives.h} | 4 +- ...gma_primitives.hpp => aura_primitives.hpp} | 8 +++ src/libaura/hoom_prover.h | 2 +- src/libaura/hoom_prover.hpp | 65 +++++++++++++++++++ src/libaura/hoom_verifier.h | 2 +- src/libaura/hoom_verifier.hpp | 47 ++++++++++++++ src/libaura/r1_proof_generator.h | 2 +- 9 files changed, 136 insertions(+), 8 deletions(-) rename src/libaura/{sigma_primitives.h => aura_primitives.h} (91%) rename src/libaura/{sigma_primitives.hpp => aura_primitives.hpp} (89%) create mode 100644 src/libaura/hoom_prover.hpp create mode 100644 src/libaura/hoom_verifier.hpp diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 1ecd13284c..d60d2b9286 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -11,8 +11,12 @@ - + + + + + diff --git a/src/Makefile.am b/src/Makefile.am index 49df49a5c9..c88de2ff75 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -765,8 +765,8 @@ libaura_a_SOURCES = \ libaura/sigmaplus_prover.hpp \ libaura/sigmaplus_verifier.h \ libaura/sigmaplus_verifier.hpp \ - libaura/sigma_primitives.h \ - libaura/sigma_primitives.hpp \ + libaura/aura_primitives.h \ + libaura/aura_primitives.hpp \ libaura/params.h\ libaura/params.cpp diff --git a/src/libaura/sigma_primitives.h b/src/libaura/aura_primitives.h similarity index 91% rename from src/libaura/sigma_primitives.h rename to src/libaura/aura_primitives.h index f8d47d6117..f35717e285 100644 --- a/src/libaura/sigma_primitives.h +++ b/src/libaura/aura_primitives.h @@ -47,10 +47,12 @@ class SigmaPrimitives { */ static void new_factor(const Exponent& x, const Exponent& a, std::vector& coefficients); + static GroupElement HelperFunction(const std::vector& commits, const std::vector & x); + }; } // namespace aura -#include "sigma_primitives.hpp" +#include "aura_primitives.hpp" #endif // FIRO_AURA_SIGMA_SIGMA_PRIMITIVES_H diff --git a/src/libaura/sigma_primitives.hpp b/src/libaura/aura_primitives.hpp similarity index 89% rename from src/libaura/sigma_primitives.hpp rename to src/libaura/aura_primitives.hpp index cbba97895f..bf8c1d70ca 100644 --- a/src/libaura/sigma_primitives.hpp +++ b/src/libaura/aura_primitives.hpp @@ -92,4 +92,12 @@ void SigmaPrimitives::new_factor( coefficients[0] *= a; } + template + GroupElement SigmaPrimitives::HelperFunction( + const std::vector& commits, + const std::vector & x) { + secp_primitives::MultiExponent mult(commits, x); + return mult.get_multiple(); + } + } // namespace aura diff --git a/src/libaura/hoom_prover.h b/src/libaura/hoom_prover.h index 27aec926d1..4e3d8ad38b 100644 --- a/src/libaura/hoom_prover.h +++ b/src/libaura/hoom_prover.h @@ -15,7 +15,7 @@ class HierarchicOOMProver{ const std::vector& h_gens, int t_n, int t_m, int m_n, int m_m); void proof(const std::vector& commits, - const Exponent& r, + const Exponent& l, HOOMProof& proof_out); private: diff --git a/src/libaura/hoom_prover.hpp b/src/libaura/hoom_prover.hpp new file mode 100644 index 0000000000..610141d232 --- /dev/null +++ b/src/libaura/hoom_prover.hpp @@ -0,0 +1,65 @@ +#include +namespace aura { + + template + HierarchicOOMProver(const GroupElement& g, + const std::vector& h_gens, + int t_n, int t_m, int m_n, int m_m) + : g_(g) + , h_(h_gens) + , t_n_(t_n) + , t_m_(t_m) + , m_n_(m_n) + , m_m_(m_m) { + } + + template + void proof(const std::vector& commits, + const Exponent& l, + HOOMProof& proof_out) { + int t_ = pow(t_n_, t_m_); + int m_ = pow(m_n_, m_m_); + std::vector r; + r.resize(m_); + for (int k = 0; k < m_; ++k) { + r[k].randomize(); + } + proof_out.d_.resize(m_); + int ptr = l / m_ * m_; + for (int k = 0; k < m_; ++k) { + d_[k] = commits[ptr + k] + h_[0] * r[k]; + } + + aura::SigmaPlusProver d_prover(g_, h_, m_n_, m_m_); + aura::SigmaPlusProof d_proof(m_n_, m_m_); + d_prover.proof(d, l - ptr, false, d_proof); + proof_out.d_Proof_ = d_proof; + std::vector x; + x.resize(m_); + + std::vector group_elements = {g, h_[0] * t_n_, h_[0] * t_m_, h_[0] * m_n_, h_[0] * m_m_}; + group_elements.insert(group_elements.end(), proof_out.d_.begin(), proof_out.d_.end()); + proof_out.D_Proof_.resize(t_); + for (int k = 0; k < m_; ++k) { + SigmaPrimitives::generate_challenge(group_elements, x[k]); + group_elements.pushback(h_[0] * x[k]); + } + std::vector C_; + C_.resize(m_); + std::vector D_; + D_.resize(t_); + GroupElement D; + D = SigmaPrimitives::HelperFunction(proof_out.d_, x); + for (int k = 0; k < t_; ++k) { + std::copy(commits.begin() + k * m_, commits.begin() + (k + 1) * m_ - 1, C_.begin()) + D_[k] = SigmaPrimitives::HelperFunction(C_, x) + D * -1; + } + + aura::SigmaPlusProver D_prover(g_, h_, t_n_, t_m_); + aura::SigmaPlusProof D_proof(t_n_, t_m_); + D_prover.proof(D_, l / m_, false, D_proof); + proof_out.D_Proof_ = D_proof; + + } + +} // namespace aura diff --git a/src/libaura/hoom_verifier.h b/src/libaura/hoom_verifier.h index ffa9679ec4..2e686d5fac 100644 --- a/src/libaura/hoom_verifier.h +++ b/src/libaura/hoom_verifier.h @@ -32,6 +32,6 @@ class HOOMVerifier{ } // namespace aura -#include "sigmaplus_verifier.hpp" +#include "hoom_verifier.hpp" #endif // FIRO_AURA_HOOM_VERIFIER_H diff --git a/src/libaura/hoom_verifier.hpp b/src/libaura/hoom_verifier.hpp new file mode 100644 index 0000000000..4b1e2d6075 --- /dev/null +++ b/src/libaura/hoom_verifier.hpp @@ -0,0 +1,47 @@ +#include +namespace aura { +template +class HOOMVerifier{ + + template + HOOMVerifier(const GroupElement& g, + const std::vector& h_gens, + int t_n, int t_m, int m_n, int m_m) + : g_(g) + , h_(h_gens) + , t_n_(t_n) + , t_m_(t_m) + , m_n_(m_n) + , m_m_(m_m) { + } + + template + bool verify(const std::vector& commits + const std::vector>& proof){ + int t_ = pow(t_n_, t_m_); + int m_ = pow(m_n_, m_m_); + aura::SigmaPlusVerifier d_verifier(g, h_gens, m_n_, m_m_); + aura::SigmaPlusVerifier D_verifier(g, h_gens, t_n_, t_m_); + + std::vector group_elements = {g, h_[0] * t_n_, h_[0] * t_m_, h_[0] * m_n_, h_[0] * m_m_}; + group_elements.insert(group_elements.end(), proof.d_.begin(), proof.d_.end()); + proof_out.D_Proof_.resize(t_); + for (int k = 0; k < m_; ++k) { + SigmaPrimitives::generate_challenge(group_elements, x[k]); + group_elements.pushback(h_[0] * x[k]); + } + std::vector C_; + C_.resize(m_); + std::vector D_; + D_.resize(t_); + GroupElement D; + D = SigmaPrimitives::HelperFunction(proof_out.d_, x); + for (int k = 0; k < t_; ++k) { + std::copy(commits.begin() + k * m_, commits.begin() + (k + 1) * m_ - 1, C_.begin()) + D_[k] = SigmaPrimitives::HelperFunction(C_, x) + D * -1; + } + return d_verifier.verify(proof.d_, proof.d_Proof_, true) && D_verifier.verify(D_, proof.D_Proof_, true); + } +}; + +} // namespace aura diff --git a/src/libaura/r1_proof_generator.h b/src/libaura/r1_proof_generator.h index 528bd30567..9c2aaac896 100644 --- a/src/libaura/r1_proof_generator.h +++ b/src/libaura/r1_proof_generator.h @@ -2,7 +2,7 @@ #define FIRO_AURA_SIGMA_R1_PROOF_GENERATOR_H #include "r1_proof.h" -#include "sigma_primitives.h" +#include "aura_primitives.h" namespace aura { From efd0a260f820153333e3aa8400678032145a1ceb Mon Sep 17 00:00:00 2001 From: Areg Vrtanesyan Date: Tue, 15 Mar 2022 18:12:17 +0400 Subject: [PATCH 4/7] Finished writing tests --- .idea/workspace.xml | 17 +++++---- src/Makefile.test.include | 1 + src/libaura/hoom_proof.h | 12 +++---- src/libaura/hoom_prover.h | 7 ++-- src/libaura/hoom_prover.hpp | 30 ++++++++-------- src/libaura/hoom_verifier.h | 4 +-- src/libaura/hoom_verifier.hpp | 41 ++++++++++----------- src/libaura/test/hoom_tests.cpp | 55 +++++++++++++++++++++++++++++ src/libaura/test/protocol_tests.cpp | 2 +- 9 files changed, 112 insertions(+), 57 deletions(-) create mode 100644 src/libaura/test/hoom_tests.cpp diff --git a/.idea/workspace.xml b/.idea/workspace.xml index d60d2b9286..bd27b2bbce 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -10,13 +10,15 @@ + - + + + - - - + + - + - @@ -74,7 +76,8 @@ - + + diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 8f25458691..14a7bc69f9 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -98,6 +98,7 @@ BITCOIN_TESTS = \ sigma/test/serialize_test.cpp \ sigma/test/sigma_primitive_types_test.cpp \ libaura/test/protocol_tests.cpp \ + libaura/test/hoom_tests.cpp \ test/addrman_tests.cpp \ test/allocator_tests.cpp \ test/amount_tests.cpp \ diff --git a/src/libaura/hoom_proof.h b/src/libaura/hoom_proof.h index 8558a117b7..f8c1eac550 100644 --- a/src/libaura/hoom_proof.h +++ b/src/libaura/hoom_proof.h @@ -19,28 +19,28 @@ class HOOMProof { public: HOOMProof(int t_n_, int t_m_, int m_n_, int m_m_): - t_n_(t_n_), t_m_(t_m_) m_n_(m_n_), m_m_(m_m_) {}; + t_n_(t_n_), t_m_(t_m_), m_n_(m_n_), m_m_(m_m_), d_Proof_(m_n_, m_m_), D_Proof_(t_n_, t_m_) {}; public: - bool operator==(const SigmaPlusProof& other) const { + bool operator==(const HOOMProof& other) const { return t_n_ == other.t_n_ && t_m_ == other.t_m_ && m_n_ == other.t_n_ && m_m_ == other.t_m_ && d_ == other.d_ && d_Proof_ == other.d_Proof_ && - D_Proof_ == other.D_Proof_ && + D_Proof_ == other.D_Proof_; } - bool operator!=(const SigmaPlusProof& other) const { + bool operator!=(const HOOMProof& other) const { return !(*this == other); } public: inline int memoryRequired() const { return d_.memoryRequired() - + d_Proof_.memoryRequired(n, m) - + D_Proof_.memoryRequired(n, m); + + d_Proof_.memoryRequired(m_n_, m_m_) + + D_Proof_.memoryRequired(t_n_, t_m_); } /* inline unsigned char* serialize(unsigned char* buffer) const { diff --git a/src/libaura/hoom_prover.h b/src/libaura/hoom_prover.h index 4e3d8ad38b..1b11b8e7e0 100644 --- a/src/libaura/hoom_prover.h +++ b/src/libaura/hoom_prover.h @@ -8,14 +8,15 @@ namespace aura { template -class HierarchicOOMProver{ +class HOOMProver{ public: - HierarchicOOMProver(const GroupElement& g, + HOOMProver(const GroupElement& g, const std::vector& h_gens, int t_n, int t_m, int m_n, int m_m); void proof(const std::vector& commits, - const Exponent& l, + const int& l, + const Exponent& r, HOOMProof& proof_out); private: diff --git a/src/libaura/hoom_prover.hpp b/src/libaura/hoom_prover.hpp index 610141d232..231c7fe75e 100644 --- a/src/libaura/hoom_prover.hpp +++ b/src/libaura/hoom_prover.hpp @@ -2,7 +2,7 @@ namespace aura { template - HierarchicOOMProver(const GroupElement& g, + HOOMProver::HOOMProver(const GroupElement& g, const std::vector& h_gens, int t_n, int t_m, int m_n, int m_m) : g_(g) @@ -14,35 +14,35 @@ namespace aura { } template - void proof(const std::vector& commits, - const Exponent& l, + void HOOMProver::proof(const std::vector& commits, + const int& l, + const Exponent& r, HOOMProof& proof_out) { int t_ = pow(t_n_, t_m_); int m_ = pow(m_n_, m_m_); - std::vector r; - r.resize(m_); + std::vector r_; + r_.resize(m_); for (int k = 0; k < m_; ++k) { - r[k].randomize(); + r_[k].randomize(); } proof_out.d_.resize(m_); int ptr = l / m_ * m_; for (int k = 0; k < m_; ++k) { - d_[k] = commits[ptr + k] + h_[0] * r[k]; + proof_out.d_[k] = commits[ptr + k] + h_[0] * r_[k]; } + secp_primitives::GroupElement c; + secp_primitives::Scalar zero(uint64_t(0)); aura::SigmaPlusProver d_prover(g_, h_, m_n_, m_m_); - aura::SigmaPlusProof d_proof(m_n_, m_m_); - d_prover.proof(d, l - ptr, false, d_proof); - proof_out.d_Proof_ = d_proof; + d_prover.proof(proof_out.d_, l - ptr, r, true, proof_out.d_Proof_); std::vector x; x.resize(m_); - std::vector group_elements = {g, h_[0] * t_n_, h_[0] * t_m_, h_[0] * m_n_, h_[0] * m_m_}; + std::vector group_elements = {g_, h_[0] * t_n_, h_[0] * t_m_, h_[0] * m_n_, h_[0] * m_m_}; group_elements.insert(group_elements.end(), proof_out.d_.begin(), proof_out.d_.end()); - proof_out.D_Proof_.resize(t_); for (int k = 0; k < m_; ++k) { SigmaPrimitives::generate_challenge(group_elements, x[k]); - group_elements.pushback(h_[0] * x[k]); + group_elements.push_back(h_[0] * x[k]); } std::vector C_; C_.resize(m_); @@ -51,13 +51,13 @@ namespace aura { GroupElement D; D = SigmaPrimitives::HelperFunction(proof_out.d_, x); for (int k = 0; k < t_; ++k) { - std::copy(commits.begin() + k * m_, commits.begin() + (k + 1) * m_ - 1, C_.begin()) + std::copy(commits.begin() + k * m_, commits.begin() + (k + 1) * m_ - 1, C_.begin()); D_[k] = SigmaPrimitives::HelperFunction(C_, x) + D * -1; } aura::SigmaPlusProver D_prover(g_, h_, t_n_, t_m_); aura::SigmaPlusProof D_proof(t_n_, t_m_); - D_prover.proof(D_, l / m_, false, D_proof); + D_prover.proof(D_, l / m_, r, true, D_proof); proof_out.D_Proof_ = D_proof; } diff --git a/src/libaura/hoom_verifier.h b/src/libaura/hoom_verifier.h index 2e686d5fac..5112be7a56 100644 --- a/src/libaura/hoom_verifier.h +++ b/src/libaura/hoom_verifier.h @@ -9,7 +9,7 @@ template class HOOMVerifier{ public: - SigmaPlusVerifier(const GroupElement& g, + HOOMVerifier(const GroupElement& g, const std::vector& h_gens, int t_n, int t_m, int m_n, int m_m); @@ -18,7 +18,7 @@ class HOOMVerifier{ bool batch_verify(const std::vector& commits, const std::vector& serials, - const std::vector>& proofs) const; + const std::vector>& proofs) const; private: diff --git a/src/libaura/hoom_verifier.hpp b/src/libaura/hoom_verifier.hpp index 4b1e2d6075..1ac2983cd0 100644 --- a/src/libaura/hoom_verifier.hpp +++ b/src/libaura/hoom_verifier.hpp @@ -1,47 +1,42 @@ #include namespace aura { -template -class HOOMVerifier{ template - HOOMVerifier(const GroupElement& g, - const std::vector& h_gens, - int t_n, int t_m, int m_n, int m_m) - : g_(g) - , h_(h_gens) - , t_n_(t_n) - , t_m_(t_m) - , m_n_(m_n) - , m_m_(m_m) { + HOOMVerifier::HOOMVerifier(const GroupElement &g, + const std::vector &h_gens, + int t_n, int t_m, int m_n, int m_m) + : g_(g), h_(h_gens), t_n_(t_n), t_m_(t_m), m_n_(m_n), m_m_(m_m) { } template - bool verify(const std::vector& commits - const std::vector>& proof){ + bool HOOMVerifier::verify(const std::vector &commits, + const HOOMProof &proof) const { int t_ = pow(t_n_, t_m_); int m_ = pow(m_n_, m_m_); - aura::SigmaPlusVerifier d_verifier(g, h_gens, m_n_, m_m_); - aura::SigmaPlusVerifier D_verifier(g, h_gens, t_n_, t_m_); + aura::SigmaPlusVerifier d_verifier(g_, h_, m_n_, m_m_); + aura::SigmaPlusVerifier D_verifier(g_, h_, t_n_, t_m_); - std::vector group_elements = {g, h_[0] * t_n_, h_[0] * t_m_, h_[0] * m_n_, h_[0] * m_m_}; + std::vector group_elements = {g_, h_[0] * t_n_, h_[0] * t_m_, h_[0] * m_n_, h_[0] * m_m_}; group_elements.insert(group_elements.end(), proof.d_.begin(), proof.d_.end()); - proof_out.D_Proof_.resize(t_); + std::vector x; + x.resize(m_); for (int k = 0; k < m_; ++k) { SigmaPrimitives::generate_challenge(group_elements, x[k]); - group_elements.pushback(h_[0] * x[k]); + group_elements.push_back(h_[0] * x[k]); } - std::vector C_; + + std::vector C_; C_.resize(m_); - std::vector D_; + std::vector D_; D_.resize(t_); GroupElement D; - D = SigmaPrimitives::HelperFunction(proof_out.d_, x); + D = SigmaPrimitives::HelperFunction(proof.d_, x); + for (int k = 0; k < t_; ++k) { - std::copy(commits.begin() + k * m_, commits.begin() + (k + 1) * m_ - 1, C_.begin()) + std::copy(commits.begin() + k * m_, commits.begin() + (k + 1) * m_ - 1, C_.begin()); D_[k] = SigmaPrimitives::HelperFunction(C_, x) + D * -1; } return d_verifier.verify(proof.d_, proof.d_Proof_, true) && D_verifier.verify(D_, proof.D_Proof_, true); } -}; } // namespace aura diff --git a/src/libaura/test/hoom_tests.cpp b/src/libaura/test/hoom_tests.cpp new file mode 100644 index 0000000000..f1ae511e21 --- /dev/null +++ b/src/libaura/test/hoom_tests.cpp @@ -0,0 +1,55 @@ +#include "../params.h" +#include "../sigmaplus_prover.h" +#include "../sigmaplus_verifier.h" +#include "../hoom_prover.h" +#include "../hoom_verifier.h" + +#include + +#include "../../test/fixtures.h" + +BOOST_FIXTURE_TEST_SUITE(aura_hoom_protocol_tests, ZerocoinTestingSetup200) + +BOOST_AUTO_TEST_CASE(one_out_of_n) +{ + int N = 16384; + int t_n = 2; + int t_m = 3; + int m_n = 2; + int m_m = 3; + int index = 20; + + secp_primitives::GroupElement g; + g.randomize(); + std::vector h_gens; + h_gens.resize(1); + h_gens[0].randomize(); + aura::HOOMProver prover(g, h_gens, t_n, t_m, m_n, m_m); + std::vector commits; + secp_primitives::Scalar r; + r.randomize(); + for(int i = 0; i < N; ++i){ + if(i == index){ + secp_primitives::GroupElement c; + secp_primitives::Scalar zero(uint64_t(0)); + c = aura::SigmaPrimitives::commit(g, zero, h_gens[0], r); + commits.push_back(c); + } + else{ + secp_primitives::GroupElement c; + secp_primitives::Scalar value; + value.randomize(); + c = aura::SigmaPrimitives::commit(g, value, h_gens[0], r); + commits.push_back(c); + } + } + aura::HOOMProof proof(t_n, t_m, m_n, m_m); + + prover.proof(commits, index, r, proof); + + aura::HOOMVerifier verifier(g, h_gens, t_n, t_m, m_n, m_m); + + BOOST_CHECK(verifier.verify(commits, proof)); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/libaura/test/protocol_tests.cpp b/src/libaura/test/protocol_tests.cpp index 40a29e1be9..301043ab32 100644 --- a/src/libaura/test/protocol_tests.cpp +++ b/src/libaura/test/protocol_tests.cpp @@ -6,7 +6,7 @@ #include "../../test/fixtures.h" -BOOST_FIXTURE_TEST_SUITE(aura_protocol_tests, ZerocoinTestingSetup200) +BOOST_FIXTURE_TEST_SUITE(aura_sigma_protocol_tests, ZerocoinTestingSetup200) BOOST_AUTO_TEST_CASE(one_out_of_n) { From 0fae4049023284c7ae5c3d2ce40cdbff22ef65f7 Mon Sep 17 00:00:00 2001 From: aregvrtanesian Date: Sat, 26 Mar 2022 14:20:02 +0400 Subject: [PATCH 5/7] Fixes --- .idea/workspace.xml | 23 ++- output.txt | 41 +++++ src/libaura/aura_primitives.h | 0 src/libaura/aura_primitives.hpp | 0 src/libaura/hoom_proof.h | 0 src/libaura/hoom_prover.h | 1 + src/libaura/hoom_prover.hpp | 18 +-- src/libaura/hoom_verifier.h | 0 src/libaura/hoom_verifier.hpp | 14 +- src/libaura/params.cpp | 28 +++- src/libaura/params.h | 10 +- src/libaura/r1_proof.h | 0 src/libaura/r1_proof_generator.h | 0 src/libaura/r1_proof_generator.hpp | 0 src/libaura/r1_proof_verifier.h | 0 src/libaura/r1_proof_verifier.hpp | 0 src/libaura/sigmaplus_proof.h | 0 src/libaura/sigmaplus_prover.h | 0 src/libaura/sigmaplus_prover.hpp | 0 src/libaura/sigmaplus_verifier.h | 0 src/libaura/sigmaplus_verifier.hpp | 0 src/libaura/test/hoom_tests.cpp | 6 +- src/libaura/test/protocol_tests.cpp | 237 +++++++--------------------- 23 files changed, 176 insertions(+), 202 deletions(-) create mode 100644 output.txt mode change 100644 => 100755 src/libaura/aura_primitives.h mode change 100644 => 100755 src/libaura/aura_primitives.hpp mode change 100644 => 100755 src/libaura/hoom_proof.h mode change 100644 => 100755 src/libaura/hoom_prover.h mode change 100644 => 100755 src/libaura/hoom_prover.hpp mode change 100644 => 100755 src/libaura/hoom_verifier.h mode change 100644 => 100755 src/libaura/hoom_verifier.hpp mode change 100644 => 100755 src/libaura/params.cpp mode change 100644 => 100755 src/libaura/params.h mode change 100644 => 100755 src/libaura/r1_proof.h mode change 100644 => 100755 src/libaura/r1_proof_generator.h mode change 100644 => 100755 src/libaura/r1_proof_generator.hpp mode change 100644 => 100755 src/libaura/r1_proof_verifier.h mode change 100644 => 100755 src/libaura/r1_proof_verifier.hpp mode change 100644 => 100755 src/libaura/sigmaplus_proof.h mode change 100644 => 100755 src/libaura/sigmaplus_prover.h mode change 100644 => 100755 src/libaura/sigmaplus_prover.hpp mode change 100644 => 100755 src/libaura/sigmaplus_verifier.h mode change 100644 => 100755 src/libaura/sigmaplus_verifier.hpp mode change 100644 => 100755 src/libaura/test/hoom_tests.cpp mode change 100644 => 100755 src/libaura/test/protocol_tests.cpp diff --git a/.idea/workspace.xml b/.idea/workspace.xml index bd27b2bbce..c933703f49 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -10,14 +10,27 @@ - - + + + + + + + + + + + + + + + + + @@ -78,6 +94,9 @@ + + + diff --git a/output.txt b/output.txt new file mode 100644 index 0000000000..774f05f807 --- /dev/null +++ b/output.txt @@ -0,0 +1,41 @@ +Running 1 test case... +HOOM PROOF GENERATED + t_n = 2 t_m = 6 m_n = 4 m_m = 6 Proof time 2782 ms +PASSED + t_n = 2 t_m = 6 m_n = 4 m_m = 6 Verify time 2272 ms +SIGMA PROOF GENERATED + N = 262144 n = 8 m = 6 Proof time 17613 ms +PASSED + N = 262144 n = 8 m = 6 Verify time 4328 ms +HOOM PROOF GENERATED + t_n = 2 t_m = 6 m_n = 5 m_m = 6 Proof time 10325 ms +PASSED + t_n = 2 t_m = 6 m_n = 5 m_m = 6 Verify time 8679 ms +SIGMA PROOF GENERATED + N = 1000000 n = 10 m = 6 Proof time 67777 ms +PASSED + N = 1000000 n = 10 m = 6 Verify time 16314 ms +HOOM PROOF GENERATED + t_n = 2 t_m = 7 m_n = 4 m_m = 7 Proof time 20343 ms +PASSED + t_n = 2 t_m = 7 m_n = 4 m_m = 7 Verify time 19087 ms +SIGMA PROOF GENERATED + N = 2097152 n = 8 m = 7 Proof time 169001 ms +PASSED + N = 2097152 n = 8 m = 7 Verify time 34939 ms +HOOM PROOF GENERATED + t_n = 2 t_m = 8 m_n = 3 m_m = 8 Proof time 16039 ms +PASSED + t_n = 2 t_m = 8 m_n = 3 m_m = 8 Verify time 14293 ms +SIGMA PROOF GENERATED + N = 1679616 n = 6 m = 8 Proof time 162508 ms +PASSED + N = 1679616 n = 6 m = 8 Verify time 27215 ms +HOOM PROOF GENERATED + t_n = 2 t_m = 8 m_n = 3 m_m = 8 Proof time 16049 ms +PASSED + t_n = 2 t_m = 8 m_n = 3 m_m = 8 Verify time 15193 ms +SIGMA PROOF GENERATED + N = 1679616 n = 6 m = 8 Proof time 154506 ms +PASSED + N = 1679616 n = 6 m = 8 Verify time 27583 ms diff --git a/src/libaura/aura_primitives.h b/src/libaura/aura_primitives.h old mode 100644 new mode 100755 diff --git a/src/libaura/aura_primitives.hpp b/src/libaura/aura_primitives.hpp old mode 100644 new mode 100755 diff --git a/src/libaura/hoom_proof.h b/src/libaura/hoom_proof.h old mode 100644 new mode 100755 diff --git a/src/libaura/hoom_prover.h b/src/libaura/hoom_prover.h old mode 100644 new mode 100755 index 1b11b8e7e0..72f6065780 --- a/src/libaura/hoom_prover.h +++ b/src/libaura/hoom_prover.h @@ -1,6 +1,7 @@ #ifndef FIRO_AURA_HOOM_PROVER_H #define FIRO_AURA_HOOM_PROVER_H +#include "sigmaplus_prover.h" #include "hoom_proof.h" #include diff --git a/src/libaura/hoom_prover.hpp b/src/libaura/hoom_prover.hpp old mode 100644 new mode 100755 index 231c7fe75e..3c2ac23cf7 --- a/src/libaura/hoom_prover.hpp +++ b/src/libaura/hoom_prover.hpp @@ -34,31 +34,27 @@ namespace aura { secp_primitives::GroupElement c; secp_primitives::Scalar zero(uint64_t(0)); aura::SigmaPlusProver d_prover(g_, h_, m_n_, m_m_); - d_prover.proof(proof_out.d_, l - ptr, r, true, proof_out.d_Proof_); + d_prover.proof(proof_out.d_, l % m_, r_[l % m_] + r, true, proof_out.d_Proof_); std::vector x; x.resize(m_); - + std::Scalar xsum = uint64_t(0); std::vector group_elements = {g_, h_[0] * t_n_, h_[0] * t_m_, h_[0] * m_n_, h_[0] * m_m_}; group_elements.insert(group_elements.end(), proof_out.d_.begin(), proof_out.d_.end()); for (int k = 0; k < m_; ++k) { - SigmaPrimitives::generate_challenge(group_elements, x[k]); +// SigmaPrimitives::generate_challenge(group_elements, x[k]); + x[k] = uint64_t(124); group_elements.push_back(h_[0] * x[k]); + xsum += x[k] * r_[k]; } - std::vector C_; - C_.resize(m_); std::vector D_; D_.resize(t_); GroupElement D; D = SigmaPrimitives::HelperFunction(proof_out.d_, x); for (int k = 0; k < t_; ++k) { - std::copy(commits.begin() + k * m_, commits.begin() + (k + 1) * m_ - 1, C_.begin()); - D_[k] = SigmaPrimitives::HelperFunction(C_, x) + D * -1; + D_[k] = D + SigmaPrimitives::HelperFunction({commits.begin() + k * m_, commits.begin() + (k + 1) * m_}, x).inverse(); } - aura::SigmaPlusProver D_prover(g_, h_, t_n_, t_m_); - aura::SigmaPlusProof D_proof(t_n_, t_m_); - D_prover.proof(D_, l / m_, r, true, D_proof); - proof_out.D_Proof_ = D_proof; + D_prover.proof(D_, l / m_, xsum, true, proof_out.D_Proof_); } diff --git a/src/libaura/hoom_verifier.h b/src/libaura/hoom_verifier.h old mode 100644 new mode 100755 diff --git a/src/libaura/hoom_verifier.hpp b/src/libaura/hoom_verifier.hpp old mode 100644 new mode 100755 index 1ac2983cd0..d4460a43a7 --- a/src/libaura/hoom_verifier.hpp +++ b/src/libaura/hoom_verifier.hpp @@ -21,10 +21,10 @@ namespace aura { std::vector x; x.resize(m_); for (int k = 0; k < m_; ++k) { - SigmaPrimitives::generate_challenge(group_elements, x[k]); +// SigmaPrimitives::generate_challenge(group_elements, x[k]); + x[k] = uint64_t(124); group_elements.push_back(h_[0] * x[k]); } - std::vector C_; C_.resize(m_); std::vector D_; @@ -33,10 +33,14 @@ namespace aura { D = SigmaPrimitives::HelperFunction(proof.d_, x); for (int k = 0; k < t_; ++k) { - std::copy(commits.begin() + k * m_, commits.begin() + (k + 1) * m_ - 1, C_.begin()); - D_[k] = SigmaPrimitives::HelperFunction(C_, x) + D * -1; + std::copy(commits.begin() + k * m_, commits.begin() + (k + 1) * m_, C_.begin()); + D_[k] = D + SigmaPrimitives::HelperFunction(C_, x).inverse(); } - return d_verifier.verify(proof.d_, proof.d_Proof_, true) && D_verifier.verify(D_, proof.D_Proof_, true); + if(!d_verifier.verify(proof.d_, proof.d_Proof_, true) && D_verifier.verify(D_, proof.D_Proof_, true)) { + LogPrintf("Hierarchic one out of many proof failed due to final check failed."); + return false; + } + return true; } } // namespace aura diff --git a/src/libaura/params.cpp b/src/libaura/params.cpp old mode 100644 new mode 100755 index a1f4cbabec..fc0ec780f6 --- a/src/libaura/params.cpp +++ b/src/libaura/params.cpp @@ -25,15 +25,24 @@ Params* Params::get_default() { //fixing n and m; N = n^m = 16,384 int n = 4; int m = 7; - instance = new Params(g, n, m); + int t_n = 4; + int t_m = 7; + int m_n = 4; + int m_m = 7; + instance = new Params(g, n, m, t_m, t_n, m_m, m_n); return instance; } } -Params::Params(const GroupElement& g, int n, int m) : +Params::Params(const GroupElement& g, int n, int m, int t_n, int t_m, int m_n, int m_m) : g_(g), m_(m), - n_(n) + n_(n), + t_m_(t_m), + t_n_(t_n), + m_m_(m_m), + m_n_(m_n) + { unsigned char buff0[32] = {0}; g.sha256(buff0); @@ -70,5 +79,16 @@ uint64_t Params::get_n() const{ uint64_t Params::get_m() const{ return m_; } - + uint64_t Params::get_t_n() const{ + return t_n_; + } + uint64_t Params::get_t_m() const{ + return t_m_; + } + uint64_t Params::get_m_n() const{ + return m_n_; + } + uint64_t Params::get_m_m() const{ + return m_m_; + } } //namespace aura diff --git a/src/libaura/params.h b/src/libaura/params.h old mode 100644 new mode 100755 index 3d034a5a64..37eca7f489 --- a/src/libaura/params.h +++ b/src/libaura/params.h @@ -16,9 +16,13 @@ class Params { const std::vector& get_h() const; uint64_t get_n() const; uint64_t get_m() const; + uint64_t get_t_n() const; + uint64_t get_t_m() const; + uint64_t get_m_n() const; + uint64_t get_m_m() const; private: - Params(const GroupElement& g, int n, int m); + Params(const GroupElement& g, int n, int m, int t_n, int t_m, int m_n, int m_m); ~Params(); private: @@ -27,6 +31,10 @@ class Params { std::vector h_; int m_; int n_; + int t_m_; + int t_n_; + int m_m_; + int m_n_; }; }//namespace aura diff --git a/src/libaura/r1_proof.h b/src/libaura/r1_proof.h old mode 100644 new mode 100755 diff --git a/src/libaura/r1_proof_generator.h b/src/libaura/r1_proof_generator.h old mode 100644 new mode 100755 diff --git a/src/libaura/r1_proof_generator.hpp b/src/libaura/r1_proof_generator.hpp old mode 100644 new mode 100755 diff --git a/src/libaura/r1_proof_verifier.h b/src/libaura/r1_proof_verifier.h old mode 100644 new mode 100755 diff --git a/src/libaura/r1_proof_verifier.hpp b/src/libaura/r1_proof_verifier.hpp old mode 100644 new mode 100755 diff --git a/src/libaura/sigmaplus_proof.h b/src/libaura/sigmaplus_proof.h old mode 100644 new mode 100755 diff --git a/src/libaura/sigmaplus_prover.h b/src/libaura/sigmaplus_prover.h old mode 100644 new mode 100755 diff --git a/src/libaura/sigmaplus_prover.hpp b/src/libaura/sigmaplus_prover.hpp old mode 100644 new mode 100755 diff --git a/src/libaura/sigmaplus_verifier.h b/src/libaura/sigmaplus_verifier.h old mode 100644 new mode 100755 diff --git a/src/libaura/sigmaplus_verifier.hpp b/src/libaura/sigmaplus_verifier.hpp old mode 100644 new mode 100755 diff --git a/src/libaura/test/hoom_tests.cpp b/src/libaura/test/hoom_tests.cpp old mode 100644 new mode 100755 index f1ae511e21..b04af2daa2 --- a/src/libaura/test/hoom_tests.cpp +++ b/src/libaura/test/hoom_tests.cpp @@ -12,11 +12,11 @@ BOOST_FIXTURE_TEST_SUITE(aura_hoom_protocol_tests, ZerocoinTestingSetup200) BOOST_AUTO_TEST_CASE(one_out_of_n) { - int N = 16384; + int N = 65536; int t_n = 2; int t_m = 3; - int m_n = 2; - int m_m = 3; + int m_n = 3; + int m_m = 4; int index = 20; secp_primitives::GroupElement g; diff --git a/src/libaura/test/protocol_tests.cpp b/src/libaura/test/protocol_tests.cpp old mode 100644 new mode 100755 index 301043ab32..9fa8eab81e --- a/src/libaura/test/protocol_tests.cpp +++ b/src/libaura/test/protocol_tests.cpp @@ -1,212 +1,97 @@ #include "../params.h" -#include "../sigmaplus_prover.h" -#include "../sigmaplus_verifier.h" +#include "../hoom_prover.h" +#include "../hoom_verifier.h" +#include "../hoom_proof.h" #include #include "../../test/fixtures.h" -BOOST_FIXTURE_TEST_SUITE(aura_sigma_protocol_tests, ZerocoinTestingSetup200) - -BOOST_AUTO_TEST_CASE(one_out_of_n) +void test(int t_n, int t_m, int m_n, int m_m, int n, int m, int index) { - auto params = aura::Params::get_default(); - int N = 16384; - int n = params->get_n(); - int m = params->get_m(); - int index = 0; + int N = std::pow(t_n, t_m) * std::pow(m_n, m_m); secp_primitives::GroupElement g; g.randomize(); std::vector h_gens; - h_gens.resize(n * m); - for(int i = 0; i < n * m; ++i ){ - h_gens[i].randomize(); - } - secp_primitives::Scalar r; - r.randomize(); - aura::SigmaPlusProver prover(g,h_gens, n, m); + h_gens.resize(1); + h_gens[0].randomize(); + aura::SigmaPlusProver sigmaprover(g, h_gens, n, m); + aura::HOOMProver prover(g, h_gens, t_n, t_m, m_n, m_m); std::vector commits; - for(int i = 0; i < N; ++i){ - if(i == index){ - secp_primitives::GroupElement c; - secp_primitives::Scalar zero(uint64_t(0)); - c = aura::SigmaPrimitives::commit(g, zero, h_gens[0], r); - commits.push_back(c); - - } - else{ - commits.push_back(secp_primitives::GroupElement()); - commits[i].randomize(); - } - } - aura::SigmaPlusProof proof(n, m); - - prover.proof(commits, index, r, true, proof); - - aura::SigmaPlusVerifier verifier(g, h_gens, n, m); - - BOOST_CHECK(verifier.verify(commits, proof, true)); -} - -BOOST_AUTO_TEST_CASE(one_out_of_n_padding) -{ - auto params = aura::Params::get_default(); - int N = 10000; - int n = params->get_n(); - int m = params->get_m(); - int index = 9999; - - secp_primitives::GroupElement g; - g.randomize(); - std::vector h_gens; - h_gens.resize(n * m); - for(int i = 0; i < n * m; ++i ){ - h_gens[i].randomize(); - } secp_primitives::Scalar r; r.randomize(); - aura::SigmaPlusProver prover(g,h_gens, n, m); - - std::vector commits; - for(int i = 0; i < N; ++i){ - if(i == index){ + for (int i = 0; i < N; ++i){ + if (i == index) { secp_primitives::GroupElement c; secp_primitives::Scalar zero(uint64_t(0)); - c = aura::SigmaPrimitives::commit(g, zero, h_gens[0], r); + c = aura::SigmaPrimitives::commit(g, zero, + h_gens[0], r); commits.push_back(c); - - } - else{ - commits.push_back(secp_primitives::GroupElement()); - commits[i].randomize(); - } - } - aura::SigmaPlusProof proof(n, m); - - prover.proof(commits, index, r, true, proof); - - aura::SigmaPlusVerifier verifier(g, h_gens, n, m); - - BOOST_CHECK(verifier.verify(commits, proof, true)); - - aura::SigmaPlusProof proofNew(n, m); - prover.proof(commits, 11111, r, true, proofNew); - BOOST_CHECK(verifier.verify(commits, proofNew, true)); -} - -BOOST_AUTO_TEST_CASE(prove_and_verify_in_different_set) -{ - auto params = aura::Params::get_default(); - int N = 16384; - int n = params->get_n(); - int m = params->get_m(); - int index = 0; - - secp_primitives::GroupElement g; - g.randomize(); - std::vector h_gens; - h_gens.resize(n * m); - for(int i = 0; i < n * m; ++i ){ - h_gens[i].randomize(); - } - secp_primitives::Scalar r; - r.randomize(); - aura::SigmaPlusProver prover(g,h_gens, n, m); - - std::vector commits; - for(int i = 0; i < N; ++i){ - if(i == index){ + } else { secp_primitives::GroupElement c; - secp_primitives::Scalar zero(uint64_t(0)); - c = aura::SigmaPrimitives::commit(g, zero, h_gens[0], r); + secp_primitives::Scalar value; + value.randomize(); + c = aura::SigmaPrimitives::commit(g, value, + h_gens[0], r); commits.push_back(c); - - } - else{ - commits.push_back(secp_primitives::GroupElement()); - commits[i].randomize(); } } - aura::SigmaPlusProof proof(n, m); - - prover.proof(commits, index, r, true, proof); + aura::HOOMProof proof(t_n, t_m, m_n, m_m); + + std::clock_t verify_start = std::clock(); + prover.proof(commits, index, r, proof); + std::cout<< "HOOM PROOF GENERATED" << std::endl; + std::cout <<" t_n = " << t_n <<" t_m = " << t_m <<" m_n = " << m_n <<" m_m = " << m_m; + auto duration_clock = ( std::clock() - verify_start ) / (CLOCKS_PER_SEC / 1000); + std::cout << " Proof time " << duration_clock << " ms \n"; + + aura::HOOMVerifier verifier(g, h_gens, t_n, t_m, m_n, m_m); + + verify_start = std::clock(); + if(verifier.verify(commits, proof)) + std::cout<< "PASSED" << std::endl; + std::cout <<" t_n = " << t_n <<" t_m = " << t_m <<" m_n = " << m_n <<" m_m = " << m_m; + duration_clock = ( std::clock() - verify_start ) / (CLOCKS_PER_SEC / 1000); + std::cout << " Verify time " << duration_clock << " ms \n"; + + aura::SigmaPlusProof sigmaproof(n, m); + + verify_start = std::clock(); + sigmaprover.proof(commits, index, r, true, sigmaproof); + std::cout<< "SIGMA PROOF GENERATED" << std::endl; + std::cout <<" N = " << N << " n = " << n << " m = " < sigmaverifier(g, h_gens, n, m); + verify_start = std::clock(); + if(sigmaverifier.verify(commits, sigmaproof, true)) + std::cout<< "PASSED" << std::endl; + std::cout <<" N = " << N << " n = " << n << " m = " < verifier(g, h_gens, n, m); - // Add more commit - secp_primitives::GroupElement c; - secp_primitives::Scalar zero(uint64_t(0)); - c = aura::SigmaPrimitives::commit(g, zero, h_gens[0], r); - commits.push_back(c); +BOOST_FIXTURE_TEST_SUITE(aura_protocol_tests, ZerocoinTestingSetup200 +) - BOOST_CHECK(!verifier.verify(commits, proof, true)); -} - -BOOST_AUTO_TEST_CASE(prove_coin_out_of_index) +BOOST_AUTO_TEST_CASE(one_out_of_n) { - auto params = aura::Params::get_default(); - int N = 16384; - int n = params->get_n(); - int m = params->get_m(); - secp_primitives::GroupElement g; - g.randomize(); - std::vector h_gens; - h_gens.resize(n * m); - for(int i = 0; i < n * m; ++i ){ - h_gens[i].randomize(); - } - secp_primitives::Scalar r; - r.randomize(); - aura::SigmaPlusProver prover(g,h_gens, n, m); - - std::vector commits; - for(int i = 0; i < N; ++i){ - commits.push_back(secp_primitives::GroupElement()); - commits[i].randomize(); - } - aura::SigmaPlusProof proof(n, m); + test(2,6,4,6,8,6,11); + test(2,6,5,6,10,6,11); + test(2,7,4,7,8,7,11); + test(2,8,3,8,6,8,11); + test(2,8,3,8,6,8,11); - prover.proof(commits, commits.size(), r, true, proof); - aura::SigmaPlusVerifier verifier(g, h_gens, n, m); - BOOST_CHECK(!verifier.verify(commits, proof, true)); } -BOOST_AUTO_TEST_CASE(prove_coin_not_in_set) -{ - auto params = aura::Params::get_default(); - int N = 16384; - int n = params->get_n(); - int m = params->get_m(); - int index = 0; - secp_primitives::GroupElement g; - g.randomize(); - std::vector h_gens; - h_gens.resize(n * m); - for(int i = 0; i < n * m; ++i ){ - h_gens[i].randomize(); - } - secp_primitives::Scalar r; - r.randomize(); - aura::SigmaPlusProver prover(g,h_gens, n, m); - - std::vector commits; - for(int i = 0; i < N; ++i){ - commits.push_back(secp_primitives::GroupElement()); - commits[i].randomize(); - } - - aura::SigmaPlusProof proof(n, m); - prover.proof(commits, index, r, true, proof); - - aura::SigmaPlusVerifier verifier(g, h_gens, n, m); - BOOST_CHECK(!verifier.verify(commits, proof, true)); -} BOOST_AUTO_TEST_SUITE_END() From fca72136aac0ee4b3fe823f10f23088f8f5b1f36 Mon Sep 17 00:00:00 2001 From: aregvrtanesian Date: Tue, 26 Apr 2022 15:55:56 +0400 Subject: [PATCH 6/7] Implemented batch verification for HOOM --- .idea/workspace.xml | 35 ++++++----- output.txt | 39 ------------- src/libaura/hoom_prover.hpp | 28 ++++----- src/libaura/hoom_verifier.hpp | 90 ++++++++++++++++++++++++----- src/libaura/sigmaplus_prover.h | 1 + src/libaura/sigmaplus_prover.hpp | 5 +- src/libaura/sigmaplus_verifier.h | 11 +++- src/libaura/sigmaplus_verifier.hpp | 83 ++++++++++++++++++++++++-- src/libaura/test/protocol_tests.cpp | 79 +++++++++++++++++++++++-- 9 files changed, 279 insertions(+), 92 deletions(-) diff --git a/.idea/workspace.xml b/.idea/workspace.xml index c933703f49..0e1428fd51 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -11,26 +11,13 @@ - - - - + - - - - - - - - - - diff --git a/output.txt b/output.txt index 774f05f807..48cff60075 100644 --- a/output.txt +++ b/output.txt @@ -1,41 +1,2 @@ Running 1 test case... -HOOM PROOF GENERATED - t_n = 2 t_m = 6 m_n = 4 m_m = 6 Proof time 2782 ms PASSED - t_n = 2 t_m = 6 m_n = 4 m_m = 6 Verify time 2272 ms -SIGMA PROOF GENERATED - N = 262144 n = 8 m = 6 Proof time 17613 ms -PASSED - N = 262144 n = 8 m = 6 Verify time 4328 ms -HOOM PROOF GENERATED - t_n = 2 t_m = 6 m_n = 5 m_m = 6 Proof time 10325 ms -PASSED - t_n = 2 t_m = 6 m_n = 5 m_m = 6 Verify time 8679 ms -SIGMA PROOF GENERATED - N = 1000000 n = 10 m = 6 Proof time 67777 ms -PASSED - N = 1000000 n = 10 m = 6 Verify time 16314 ms -HOOM PROOF GENERATED - t_n = 2 t_m = 7 m_n = 4 m_m = 7 Proof time 20343 ms -PASSED - t_n = 2 t_m = 7 m_n = 4 m_m = 7 Verify time 19087 ms -SIGMA PROOF GENERATED - N = 2097152 n = 8 m = 7 Proof time 169001 ms -PASSED - N = 2097152 n = 8 m = 7 Verify time 34939 ms -HOOM PROOF GENERATED - t_n = 2 t_m = 8 m_n = 3 m_m = 8 Proof time 16039 ms -PASSED - t_n = 2 t_m = 8 m_n = 3 m_m = 8 Verify time 14293 ms -SIGMA PROOF GENERATED - N = 1679616 n = 6 m = 8 Proof time 162508 ms -PASSED - N = 1679616 n = 6 m = 8 Verify time 27215 ms -HOOM PROOF GENERATED - t_n = 2 t_m = 8 m_n = 3 m_m = 8 Proof time 16049 ms -PASSED - t_n = 2 t_m = 8 m_n = 3 m_m = 8 Verify time 15193 ms -SIGMA PROOF GENERATED - N = 1679616 n = 6 m = 8 Proof time 154506 ms -PASSED - N = 1679616 n = 6 m = 8 Verify time 27583 ms diff --git a/src/libaura/hoom_prover.hpp b/src/libaura/hoom_prover.hpp index 3c2ac23cf7..40c0ff1167 100755 --- a/src/libaura/hoom_prover.hpp +++ b/src/libaura/hoom_prover.hpp @@ -1,4 +1,6 @@ #include +#include + namespace aura { template @@ -18,9 +20,11 @@ namespace aura { const int& l, const Exponent& r, HOOMProof& proof_out) { + Exponent y; + SigmaPrimitives::generate_challenge(commits, y); int t_ = pow(t_n_, t_m_); int m_ = pow(m_n_, m_m_); - std::vector r_; + std::vector r_; r_.resize(m_); for (int k = 0; k < m_; ++k) { r_[k].randomize(); @@ -34,17 +38,14 @@ namespace aura { secp_primitives::GroupElement c; secp_primitives::Scalar zero(uint64_t(0)); aura::SigmaPlusProver d_prover(g_, h_, m_n_, m_m_); - d_prover.proof(proof_out.d_, l % m_, r_[l % m_] + r, true, proof_out.d_Proof_); - std::vector x; + d_prover.proof(proof_out.d_, l % m_, r_[l % m_] + r, true, y, proof_out.d_Proof_); + std::vector x; x.resize(m_); - std::Scalar xsum = uint64_t(0); - std::vector group_elements = {g_, h_[0] * t_n_, h_[0] * t_m_, h_[0] * m_n_, h_[0] * m_m_}; - group_elements.insert(group_elements.end(), proof_out.d_.begin(), proof_out.d_.end()); - for (int k = 0; k < m_; ++k) { -// SigmaPrimitives::generate_challenge(group_elements, x[k]); - x[k] = uint64_t(124); - group_elements.push_back(h_[0] * x[k]); - xsum += x[k] * r_[k]; + SigmaPrimitives::generate_challenge({h_[0] * y}, x[0]); + secp_primitives::Scalar xsum = r_[0] * x[0]; + for (int k = 1; k < m_; ++k) { + SigmaPrimitives::generate_challenge({h_[0] * x[k - 1]}, x[k]); + xsum += r_[k] * x[k]; } std::vector D_; D_.resize(t_); @@ -54,8 +55,9 @@ namespace aura { D_[k] = D + SigmaPrimitives::HelperFunction({commits.begin() + k * m_, commits.begin() + (k + 1) * m_}, x).inverse(); } aura::SigmaPlusProver D_prover(g_, h_, t_n_, t_m_); - D_prover.proof(D_, l / m_, xsum, true, proof_out.D_Proof_); - + D_prover.proof(D_, l / m_, xsum, true, x[m_ - 1], proof_out.D_Proof_); } + + } // namespace aura diff --git a/src/libaura/hoom_verifier.hpp b/src/libaura/hoom_verifier.hpp index d4460a43a7..d099c9e77b 100755 --- a/src/libaura/hoom_verifier.hpp +++ b/src/libaura/hoom_verifier.hpp @@ -1,4 +1,6 @@ #include +#include + namespace aura { template @@ -11,33 +13,95 @@ namespace aura { template bool HOOMVerifier::verify(const std::vector &commits, const HOOMProof &proof) const { + Exponent y; + SigmaPrimitives::generate_challenge(commits, y); int t_ = pow(t_n_, t_m_); int m_ = pow(m_n_, m_m_); aura::SigmaPlusVerifier d_verifier(g_, h_, m_n_, m_m_); aura::SigmaPlusVerifier D_verifier(g_, h_, t_n_, t_m_); - std::vector group_elements = {g_, h_[0] * t_n_, h_[0] * t_m_, h_[0] * m_n_, h_[0] * m_m_}; - group_elements.insert(group_elements.end(), proof.d_.begin(), proof.d_.end()); - std::vector x; + if(!d_verifier.verify(proof.d_, proof.d_Proof_, true, y)) { + LogPrintf("Hierarchic one out of many proof failed due to d_ check failed."); + return false; + } + std::vector x; x.resize(m_); - for (int k = 0; k < m_; ++k) { -// SigmaPrimitives::generate_challenge(group_elements, x[k]); - x[k] = uint64_t(124); - group_elements.push_back(h_[0] * x[k]); + SigmaPrimitives::generate_challenge({h_[0] * y}, x[0]); + for (int k = 1; k < m_; ++k) { + SigmaPrimitives::generate_challenge({h_[0] * x[k - 1]}, x[k]); } - std::vector C_; - C_.resize(m_); std::vector D_; D_.resize(t_); GroupElement D; D = SigmaPrimitives::HelperFunction(proof.d_, x); for (int k = 0; k < t_; ++k) { - std::copy(commits.begin() + k * m_, commits.begin() + (k + 1) * m_, C_.begin()); - D_[k] = D + SigmaPrimitives::HelperFunction(C_, x).inverse(); + D_[k] = D + SigmaPrimitives::HelperFunction({commits.begin() + k * m_, commits.begin() + (k + 1) * m_}, x).inverse(); + } + if(!D_verifier.verify(D_, proof.D_Proof_, true, x[m_ - 1])) { + LogPrintf("Hierarchic one out of many proof failed due to D_ check failed."); + return false; + } + return true; + } + + template + bool HOOMVerifier::batch_verify(const std::vector& commits, + const std::vector& serials, + const std::vector>& proofs) const { + Exponent commits_hash; + SigmaPrimitives::generate_challenge(commits, commits_hash); + int t_ = pow(t_n_, t_m_); + int m_ = pow(m_n_, m_m_); + int batchsize = serials.size(); + std::vector D_; + D_.resize(t_); + GroupElement D; + GroupElement left; + GroupElement right; + GroupElement t; + std::vector f_i_; + GroupElement zero_commit; + aura::SigmaPlusVerifier d_verifier(g_, h_, m_n_, m_m_); + aura::SigmaPlusVerifier D_verifier(g_, h_, t_n_, t_m_); + std::vector x; + x.resize(m_); + std::vector pows; + pows.resize(commits.size()); + + for(int i = 0; i < batchsize; ++i){ + Exponent y = commits_hash; + if(!d_verifier.verify(proofs[i].d_, proofs[i].d_Proof_, true, y)){ + LogPrintf("Hierarchic one out of many proof failed due to d_ check failed."); + return false; + } + SigmaPrimitives::generate_challenge({h_[0] * y}, x[0]); + for (int k = 1; k < m_; ++k) { + SigmaPrimitives::generate_challenge({h_[0] * x[k - 1]}, x[k]); + } + D = SigmaPrimitives::HelperFunction(proofs[i].d_, x); + for (int k = 0; k < t_; ++k) { + D_[k] = D + SigmaPrimitives::HelperFunction({commits.begin() + k * m_, commits.begin() + (k + 1) * m_}, x).inverse(); + } + Exponent xtemp = x[m_ - 1]; + if(!D_verifier.calculate_batch(D_, proofs[i].D_Proof_, t, f_i_, zero_commit, xtemp)){ + LogPrintf("Hierarchic one out of many proof failed due to one of D_ checks failed."); + return false; + } + Exponent f_i_sum; + for(int k = 0; k < t_; ++k){ + for(int j = 0; j < m_; ++j) { + pows[k * m_ + j] += x[j] * f_i_[k] * serials[i]; + } + f_i_sum += f_i_[k]; + } + left += t * serials[i] + D * f_i_sum * serials[i]; + right += zero_commit * serials[i]; } - if(!d_verifier.verify(proof.d_, proof.d_Proof_, true) && D_verifier.verify(D_, proof.D_Proof_, true)) { - LogPrintf("Hierarchic one out of many proof failed due to final check failed."); + secp_primitives::MultiExponent mult(commits, pows); + right += mult.get_multiple(); + if(left != right) { + LogPrintf("Hierarchic one out of many proof failed due to final batch check failed."); return false; } return true; diff --git a/src/libaura/sigmaplus_prover.h b/src/libaura/sigmaplus_prover.h index b3b65fe9b2..54516263f6 100755 --- a/src/libaura/sigmaplus_prover.h +++ b/src/libaura/sigmaplus_prover.h @@ -18,6 +18,7 @@ class SigmaPlusProver{ std::size_t l, const Exponent& r, bool fPadding, + Exponent challenge, SigmaPlusProof& proof_out); private: diff --git a/src/libaura/sigmaplus_prover.hpp b/src/libaura/sigmaplus_prover.hpp index da6da803f6..022a60f8f1 100755 --- a/src/libaura/sigmaplus_prover.hpp +++ b/src/libaura/sigmaplus_prover.hpp @@ -19,6 +19,7 @@ void SigmaPlusProver::proof( std::size_t l, const Exponent& r, bool fPadding, + Exponent challenge, SigmaPlusProof& proof_out) { std::size_t setSize = commits.size(); assert(setSize > 0); @@ -125,14 +126,14 @@ void SigmaPlusProver::proof( proof_out.Gk_ = Gk; // Compute value of challenge X, then continue R1 proof and sigma final response proof. - std::vector group_elements = { + std::vector group_elements = {h_[0] * challenge, proof_out.r1Proof_.A_, proof_out.B_, proof_out.r1Proof_.C_, proof_out.r1Proof_.D_}; group_elements.insert(group_elements.end(), Gk.begin(), Gk.end()); Exponent x; SigmaPrimitives::generate_challenge(group_elements, x); r1prover.generate_final_response(a, x, proof_out.r1Proof_); - + challenge = x; //computing z Exponent z; z = r * x.exponent(uint64_t(m_)); diff --git a/src/libaura/sigmaplus_verifier.h b/src/libaura/sigmaplus_verifier.h index 0a5e70c80d..c140aed139 100755 --- a/src/libaura/sigmaplus_verifier.h +++ b/src/libaura/sigmaplus_verifier.h @@ -15,7 +15,8 @@ class SigmaPlusVerifier{ bool verify(const std::vector& commits, const SigmaPlusProof& proof, - bool fPadding) const; + bool fPadding, + Exponent challenge) const; bool batch_verify(const std::vector& commits, const std::vector& serials, @@ -23,6 +24,14 @@ class SigmaPlusVerifier{ const std::vector& setSizes, const std::vector>& proofs) const; + + bool calculate_batch(const std::vector& commits, + const SigmaPlusProof& proof, + GroupElement& t, + std::vector& f_i_, + GroupElement& zero_commit, + Exponent challenge) const; + bool membership_checks(const SigmaPlusProof& proof) const; bool compute_fs(const SigmaPlusProof& proof, const Exponent& x, std::vector& f_) const; bool abcd_checks(const SigmaPlusProof& proof, const Exponent& x, const std::vector& f_) const; diff --git a/src/libaura/sigmaplus_verifier.hpp b/src/libaura/sigmaplus_verifier.hpp index 14a0061382..45389399bb 100755 --- a/src/libaura/sigmaplus_verifier.hpp +++ b/src/libaura/sigmaplus_verifier.hpp @@ -14,11 +14,85 @@ SigmaPlusVerifier::SigmaPlusVerifier( , m(m){ } +template +bool SigmaPlusVerifier::calculate_batch( + const std::vector& commits, + const SigmaPlusProof& proof, + GroupElement& t, + std::vector& f_i_, + GroupElement& zero_commit, + Exponent challenge) const { + + f_i_.clear(); + GroupElement t2; + t = t2; + + R1ProofVerifier r1ProofVerifier(g_, h_, proof.B_, n, m); + std::vector f; + const R1Proof& r1Proof = proof.r1Proof_; + if (!r1ProofVerifier.verify(r1Proof, f, true /* Skip verification of final response */)) { + LogPrintf("Sigma spend failed due to r1 proof incorrect."); + return false; + } + if (!proof.B_.isMember() || proof.B_.isInfinity()) { + LogPrintf("Sigma spend failed due to value of B outside of group."); + return false; + } + + const std::vector & Gk = proof.Gk_; + for (int k = 0; k < m; ++k) { + if (!Gk[k].isMember() || Gk[k].isInfinity()) { + LogPrintf("Sigma spend failed due to value of GK[i] outside of group."); + return false; + } + } + + // Compute value of challenge X, then continue R1 proof and sigma final response proof. + std::vector group_elements = {h_[0] * challenge, + r1Proof.A_, proof.B_, r1Proof.C_, r1Proof.D_}; + + group_elements.insert(group_elements.end(), Gk.begin(), Gk.end()); + Exponent challenge_x; + SigmaPrimitives::generate_challenge(group_elements, challenge_x); + challenge = challenge_x; + + // Now verify the final response of r1 proof. Values of "f" are finalized only after this call. + if (!r1ProofVerifier.verify_final_response(r1Proof, challenge_x, f)) { + LogPrintf("Sigma spend failed due to incorrect final response."); + return false; + } + + if(!proof.z_.isMember() || proof.z_.isZero()) { + LogPrintf("Sigma spend failed due to value of Z outside of group."); + return false; + } + + if (commits.empty()) { + LogPrintf("No mints in the anonymity set"); + return false; + } + + std::size_t N = commits.size(); + f_i_.resize(N); + + compute_fis(m, f, f_i_); + + Exponent x_k(uint64_t(1)); + for(int k = 0; k < m; ++k){ + t += (Gk[k] * (x_k.negate())); + x_k *= challenge_x; + } + + zero_commit = SigmaPrimitives::commit(g_, Exponent(uint64_t(0)), h_[0], proof.z_); + return true; +} + template bool SigmaPlusVerifier::verify( const std::vector& commits, const SigmaPlusProof& proof, - bool fPadding) const { + bool fPadding, + Exponent challenge) const { R1ProofVerifier r1ProofVerifier(g_, h_, proof.B_, n, m); std::vector f; @@ -42,12 +116,13 @@ bool SigmaPlusVerifier::verify( } // Compute value of challenge X, then continue R1 proof and sigma final response proof. - std::vector group_elements = { - r1Proof.A_, proof.B_, r1Proof.C_, r1Proof.D_}; + std::vector group_elements = {h_[0] * challenge, + r1Proof.A_, proof.B_, r1Proof.C_, r1Proof.D_}; group_elements.insert(group_elements.end(), Gk.begin(), Gk.end()); Exponent challenge_x; SigmaPrimitives::generate_challenge(group_elements, challenge_x); + challenge = challenge_x; // Now verify the final response of r1 proof. Values of "f" are finalized only after this call. if (!r1ProofVerifier.verify_final_response(r1Proof, challenge_x, f)) { @@ -115,13 +190,11 @@ bool SigmaPlusVerifier::verify( t2 += (Gk[k] * (x_k.negate())); x_k *= challenge_x; } - GroupElement left(t1 + t2); if (left != SigmaPrimitives::commit(g_, Exponent(uint64_t(0)), h_[0], proof.z_)) { LogPrintf("Sigma spend failed due to final proof verification failure."); return false; } - return true; } diff --git a/src/libaura/test/protocol_tests.cpp b/src/libaura/test/protocol_tests.cpp index 9fa8eab81e..6ea102b17d 100755 --- a/src/libaura/test/protocol_tests.cpp +++ b/src/libaura/test/protocol_tests.cpp @@ -16,7 +16,7 @@ void test(int t_n, int t_m, int m_n, int m_m, int n, int m, int index) std::vector h_gens; h_gens.resize(1); h_gens[0].randomize(); - + secp_primitives::Scalar y = u_int64_t(3241); aura::SigmaPlusProver sigmaprover(g, h_gens, n, m); aura::HOOMProver prover(g, h_gens, t_n, t_m, m_n, m_m); std::vector commits; @@ -60,7 +60,7 @@ void test(int t_n, int t_m, int m_n, int m_m, int n, int m, int index) aura::SigmaPlusProof sigmaproof(n, m); verify_start = std::clock(); - sigmaprover.proof(commits, index, r, true, sigmaproof); + sigmaprover.proof(commits, index, r, true, y, sigmaproof); std::cout<< "SIGMA PROOF GENERATED" << std::endl; std::cout <<" N = " << N << " n = " << n << " m = " < sigmaverifier(g, h_gens, n, m); verify_start = std::clock(); - if(sigmaverifier.verify(commits, sigmaproof, true)) + if(sigmaverifier.verify(commits, sigmaproof, true, y)) std::cout<< "PASSED" << std::endl; std::cout <<" N = " << N << " n = " << n << " m = " < index) +{ + int N = std::pow(t_n, t_m) * std::pow(m_n, m_m); + secp_primitives::GroupElement g; + int b = index.size(); + g.randomize(); + std::vector h_gens; + h_gens.resize(1); + h_gens[0].randomize(); + aura::HOOMProver prover(g, h_gens, t_n, t_m, m_n, m_m); + std::vector commits; + secp_primitives::Scalar r; + r.randomize(); + std::vector serials; + serials.resize(b); + for(int i = 0; i < b; ++i){ + serials[i].randomize(); + } + for (int i = 0; i < N; ++i){ + secp_primitives::GroupElement c; + secp_primitives::Scalar value; + value.randomize(); + c = aura::SigmaPrimitives::commit(g, value, + h_gens[0], r); + commits.push_back(c); + } + for (int i : index) { + commits[i] = aura::SigmaPrimitives::commit(g, uint64_t(0), + h_gens[0], + r); + } + + std::vector> proofs; + for(int i = 0; i < b; i++){ + aura::HOOMProof proof(t_n, t_m, m_n, m_m); + prover.proof(commits, index[i], r, proof); + proofs.push_back(proof); + } + + aura::HOOMVerifier verifier(g, h_gens, t_n, t_m, m_n, m_m); + if(verifier.batch_verify(commits, serials, proofs)) + std::cout<< "PASSED" << std::endl; + +/* std::clock_t verify_start = std::clock(); + prover.proof(commits, index, r, proof); + std::cout<< "HOOM PROOF GENERATED" << std::endl; + std::cout <<" t_n = " << t_n <<" t_m = " << t_m <<" m_n = " << m_n <<" m_m = " << m_m; + auto duration_clock = ( std::clock() - verify_start ) / (CLOCKS_PER_SEC / 1000); + std::cout << " Proof time " << duration_clock << " ms \n"; + + aura::HOOMVerifier verifier(g, h_gens, t_n, t_m, m_n, m_m); + + verify_start = std::clock(); + if(verifier.verify(commits, proof)) + std::cout<< "PASSED" << std::endl; + std::cout <<" t_n = " << t_n <<" t_m = " << t_m <<" m_n = " << m_n <<" m_m = " << m_m; + duration_clock = ( std::clock() - verify_start ) / (CLOCKS_PER_SEC / 1000); + std::cout << " Verify time " << duration_clock << " ms \n"; */ +} + BOOST_FIXTURE_TEST_SUITE(aura_protocol_tests, ZerocoinTestingSetup200 ) BOOST_AUTO_TEST_CASE(one_out_of_n) { +// test(2,4,4,4,8,4,11); +// test(2,5,4,5,8,5,11); + batch_test(2,4,4,4,8,4,{10,11,20}); + batch_test(2,2,3,2,6,2,{10,11,12}); + batch_test(2,4,4,4,8,4,{1,2,3,4,5,6}); + batch_test(2,2,3,2,6,2,{3,5,7,9}); + + - test(2,6,4,6,8,6,11); + + /* test(2,6,4,6,8,6,11); test(2,6,5,6,10,6,11); test(2,7,4,7,8,7,11); test(2,8,3,8,6,8,11); - test(2,8,3,8,6,8,11); + test(2,8,3,8,6,8,11); */ } From 444187c559714f720b7f3204932a304d0d25ee15 Mon Sep 17 00:00:00 2001 From: aregvrtanesian Date: Mon, 2 May 2022 15:30:05 +0400 Subject: [PATCH 7/7] cleaned up the code and added comments --- .idea/workspace.xml | 9 +++--- output.txt | 3 ++ src/libaura/hoom_prover.hpp | 18 ++++++++--- src/libaura/hoom_verifier.hpp | 50 +++++++++++++++++++++++------ src/libaura/sigmaplus_verifier.hpp | 4 --- src/libaura/test/protocol_tests.cpp | 4 --- 6 files changed, 63 insertions(+), 25 deletions(-) diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 0e1428fd51..7aeb59971c 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -14,9 +14,6 @@ - - - @@ -103,7 +100,11 @@ - + + + + + diff --git a/output.txt b/output.txt index 48cff60075..b38ad8b4d7 100644 --- a/output.txt +++ b/output.txt @@ -1,2 +1,5 @@ Running 1 test case... PASSED +PASSED +PASSED +PASSED diff --git a/src/libaura/hoom_prover.hpp b/src/libaura/hoom_prover.hpp index 40c0ff1167..3c34bc3c5f 100755 --- a/src/libaura/hoom_prover.hpp +++ b/src/libaura/hoom_prover.hpp @@ -20,10 +20,15 @@ namespace aura { const int& l, const Exponent& r, HOOMProof& proof_out) { - Exponent y; - SigmaPrimitives::generate_challenge(commits, y); + int t_ = pow(t_n_, t_m_); int m_ = pow(m_n_, m_m_); + + //binds the commitments to the y challenge + Exponent y; + SigmaPrimitives::generate_challenge(commits, y); + + //generates blinding keys and binds the correct subset std::vector r_; r_.resize(m_); for (int k = 0; k < m_; ++k) { @@ -35,10 +40,11 @@ namespace aura { proof_out.d_[k] = commits[ptr + k] + h_[0] * r_[k]; } - secp_primitives::GroupElement c; - secp_primitives::Scalar zero(uint64_t(0)); + //generates one out of many sigma proof for the blinded subset aura::SigmaPlusProver d_prover(g_, h_, m_n_, m_m_); d_prover.proof(proof_out.d_, l % m_, r_[l % m_] + r, true, y, proof_out.d_Proof_); + + //generates x challenge using the y challenge calculated in the sigma std::vector x; x.resize(m_); SigmaPrimitives::generate_challenge({h_[0] * y}, x[0]); @@ -47,6 +53,8 @@ namespace aura { SigmaPrimitives::generate_challenge({h_[0] * x[k - 1]}, x[k]); xsum += r_[k] * x[k]; } + + //creates digests of the subsets std::vector D_; D_.resize(t_); GroupElement D; @@ -54,6 +62,8 @@ namespace aura { for (int k = 0; k < t_; ++k) { D_[k] = D + SigmaPrimitives::HelperFunction({commits.begin() + k * m_, commits.begin() + (k + 1) * m_}, x).inverse(); } + + //generates proof that the digest of our blinded subset is a member of the digests of all subsets aura::SigmaPlusProver D_prover(g_, h_, t_n_, t_m_); D_prover.proof(D_, l / m_, xsum, true, x[m_ - 1], proof_out.D_Proof_); } diff --git a/src/libaura/hoom_verifier.hpp b/src/libaura/hoom_verifier.hpp index d099c9e77b..2b31487cc4 100755 --- a/src/libaura/hoom_verifier.hpp +++ b/src/libaura/hoom_verifier.hpp @@ -13,31 +13,41 @@ namespace aura { template bool HOOMVerifier::verify(const std::vector &commits, const HOOMProof &proof) const { - Exponent y; - SigmaPrimitives::generate_challenge(commits, y); + + int t_ = pow(t_n_, t_m_); int m_ = pow(m_n_, m_m_); aura::SigmaPlusVerifier d_verifier(g_, h_, m_n_, m_m_); aura::SigmaPlusVerifier D_verifier(g_, h_, t_n_, t_m_); + //binds the commitments to the y challenge + Exponent y; + SigmaPrimitives::generate_challenge(commits, y); + + //checks one out of many sigma proof for the blinded subset if(!d_verifier.verify(proof.d_, proof.d_Proof_, true, y)) { LogPrintf("Hierarchic one out of many proof failed due to d_ check failed."); return false; } + + //generates x challenge using the y challenge calculated in the sigma std::vector x; x.resize(m_); SigmaPrimitives::generate_challenge({h_[0] * y}, x[0]); for (int k = 1; k < m_; ++k) { SigmaPrimitives::generate_challenge({h_[0] * x[k - 1]}, x[k]); } + + //creates digests of the subsets std::vector D_; D_.resize(t_); GroupElement D; D = SigmaPrimitives::HelperFunction(proof.d_, x); - for (int k = 0; k < t_; ++k) { D_[k] = D + SigmaPrimitives::HelperFunction({commits.begin() + k * m_, commits.begin() + (k + 1) * m_}, x).inverse(); } + + //the proof that the digest of our blinded subset is a member of the digests of all subsets if(!D_verifier.verify(D_, proof.D_Proof_, true, x[m_ - 1])) { LogPrintf("Hierarchic one out of many proof failed due to D_ check failed."); return false; @@ -49,32 +59,46 @@ namespace aura { bool HOOMVerifier::batch_verify(const std::vector& commits, const std::vector& serials, const std::vector>& proofs) const { + + //Pre-hashing the commits for challenge generation Exponent commits_hash; SigmaPrimitives::generate_challenge(commits, commits_hash); + int t_ = pow(t_n_, t_m_); int m_ = pow(m_n_, m_m_); int batchsize = serials.size(); + std::vector D_; D_.resize(t_); GroupElement D; + GroupElement left; GroupElement right; - GroupElement t; - std::vector f_i_; - GroupElement zero_commit; + aura::SigmaPlusVerifier d_verifier(g_, h_, m_n_, m_m_); aura::SigmaPlusVerifier D_verifier(g_, h_, t_n_, t_m_); + std::vector x; x.resize(m_); + + //where we calculate the powers required for the exponentation std::vector pows; pows.resize(commits.size()); for(int i = 0; i < batchsize; ++i){ + //those values are used to store the results of SigmaPlusVerifier's calculate_batch() + GroupElement t; + std::vector f_i_; + GroupElement zero_commit; + + //checks the one out of many proof in the blinded subset Exponent y = commits_hash; if(!d_verifier.verify(proofs[i].d_, proofs[i].d_Proof_, true, y)){ LogPrintf("Hierarchic one out of many proof failed due to d_ check failed."); return false; } + + //generates the x challenge and the subset digests SigmaPrimitives::generate_challenge({h_[0] * y}, x[0]); for (int k = 1; k < m_; ++k) { SigmaPrimitives::generate_challenge({h_[0] * x[k - 1]}, x[k]); @@ -83,23 +107,31 @@ namespace aura { for (int k = 0; k < t_; ++k) { D_[k] = D + SigmaPrimitives::HelperFunction({commits.begin() + k * m_, commits.begin() + (k + 1) * m_}, x).inverse(); } + + //We use temporary variable to not alter the x[m_ - 1] value Exponent xtemp = x[m_ - 1]; if(!D_verifier.calculate_batch(D_, proofs[i].D_Proof_, t, f_i_, zero_commit, xtemp)){ LogPrintf("Hierarchic one out of many proof failed due to one of D_ checks failed."); return false; } + + //uses the f_i to add up the powers of commits in the final batch Exponent f_i_sum; for(int k = 0; k < t_; ++k){ for(int j = 0; j < m_; ++j) { pows[k * m_ + j] += x[j] * f_i_[k] * serials[i]; } + //used for the right side of the equation f_i_sum += f_i_[k]; } - left += t * serials[i] + D * f_i_sum * serials[i]; - right += zero_commit * serials[i]; + + left += t * serials[i]; + right += zero_commit * serials[i] + D.inverse() * f_i_sum * serials[i]; } + secp_primitives::MultiExponent mult(commits, pows); - right += mult.get_multiple(); + left += mult.get_multiple().inverse(); + if(left != right) { LogPrintf("Hierarchic one out of many proof failed due to final batch check failed."); return false; diff --git a/src/libaura/sigmaplus_verifier.hpp b/src/libaura/sigmaplus_verifier.hpp index 45389399bb..b2decf981c 100755 --- a/src/libaura/sigmaplus_verifier.hpp +++ b/src/libaura/sigmaplus_verifier.hpp @@ -23,10 +23,6 @@ bool SigmaPlusVerifier::calculate_batch( GroupElement& zero_commit, Exponent challenge) const { - f_i_.clear(); - GroupElement t2; - t = t2; - R1ProofVerifier r1ProofVerifier(g_, h_, proof.B_, n, m); std::vector f; const R1Proof& r1Proof = proof.r1Proof_; diff --git a/src/libaura/test/protocol_tests.cpp b/src/libaura/test/protocol_tests.cpp index 6ea102b17d..6bda330446 100755 --- a/src/libaura/test/protocol_tests.cpp +++ b/src/libaura/test/protocol_tests.cpp @@ -148,10 +148,6 @@ BOOST_AUTO_TEST_CASE(one_out_of_n) batch_test(2,4,4,4,8,4,{1,2,3,4,5,6}); batch_test(2,2,3,2,6,2,{3,5,7,9}); - - - - /* test(2,6,4,6,8,6,11); test(2,6,5,6,10,6,11); test(2,7,4,7,8,7,11);