1
0
Fork 0
forked from lthn/blockchain

verify_BGE_proof() first PoC implementation

This commit is contained in:
sowle 2023-03-27 22:31:55 +02:00
parent 5b0431daf9
commit 154e649f56
No known key found for this signature in database
GPG key ID: C07A24B2D89D49FC
4 changed files with 177 additions and 4 deletions

View file

@ -9,7 +9,7 @@
//DISABLE_GCC_AND_CLANG_WARNING(unused-function)
#if 0
#if 1
# define DBG_VAL_PRINT(x) std::cout << std::setw(30) << std::left << #x ": " << x << std::endl
# define DBG_PRINT(x) std::cout << x << std::endl
#else
@ -188,6 +188,7 @@ namespace crypto
hsc.add_pub_key(result.B);
hsc.add_pub_keys_array(result.Pk);
scalar_t x = hsc.calc_hash();
DBG_VAL_PRINT(x);
result.f.resize(m * (n - 1));
for(size_t j = 0; j < m; ++j)
@ -213,12 +214,105 @@ namespace crypto
return true;
}
#undef CHECK_AND_FAIL_WITH_ERROR_IF_FALSE
//---------------------------------------------------------------
bool verify_BGE_proof(const hash& context_hash, const std::vector<const public_key*>& ring, BGE_proof& result, uint8_t* p_err /* = nullptr */)
#define CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(cond, err_code) \
if (!(cond)) { LOG_PRINT_RED("generate_BGE_proof: \"" << #cond << "\" is false at " << LOCATION_SS << ENDL << "error code = " << (int)err_code, LOG_LEVEL_3); \
if (p_err) { *p_err = err_code; } return false; }
bool verify_BGE_proof(const hash& context_hash, const std::vector<const public_key*>& ring, const BGE_proof& sig, uint8_t* p_err /* = nullptr */)
{
return false;
static constexpr size_t n = 4; // TODO: @#@# move it out
DBG_PRINT(" - - - verify_BGE_proof - - -");
size_t ring_size = ring.size();
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(ring_size > 0, 0);
const size_t m = std::max(1ull, constexpr_ceil_log_n(ring_size, n));
const size_t N = constexpr_pow(m, n);
const size_t mn = m * n;
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(sig.Pk.size() == m, 1);
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(sig.f.size() == m * (n - 1), 2);
hash_helper_t::hs_t hsc(1 + ring_size + 2 + m);
hsc.add_hash(context_hash);
for(const public_key* ppk : ring)
hsc.add_pub_key(*ppk);
hsc.add_pub_key(sig.A);
hsc.add_pub_key(sig.B);
hsc.add_pub_keys_array(sig.Pk);
scalar_t x = hsc.calc_hash();
DBG_VAL_PRINT(x);
scalar_vec_t f0(m); // the first column f_{i,0} = x - sum{j=1}{n-1}( f_{i,j} )
for(size_t j = 0; j < m; ++j)
{
f0[j] = x;
for(size_t i = 1; i < n; ++i)
f0[j] -= sig.f[j * (n - 1) + i - 1];
}
//
// 1
//
point_t A = point_t(sig.A).modify_mul8();
point_t B = point_t(sig.B).modify_mul8();
point_t Z = A + x * B;
bool r = false, r2 = false;
for(size_t j = 0; j < m; ++j)
{
for(size_t i = 0; i < n; ++i)
{
const point_t& gen_1 = get_BGE_generator((j * n + i) * 2 + 0, r);
const point_t& gen_2 = get_BGE_generator((j * n + i) * 2 + 1, r2);
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(r && r2, 5);
const scalar_t& f_ji = (i == 0) ? f0[j] : sig.f[j * (n - 1) + i - 1];
Z -= f_ji * gen_1 + f_ji * (x - f_ji) * gen_2;
}
}
Z -= sig.y * c_point_X;
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(Z.is_zero(), 100);
//
// 2
//
scalar_vec_t p_vec(N);
for(size_t i = 0; i < N; ++i)
{
p_vec[i] = c_scalar_1;
for(size_t j = 0; j < m; ++j)
{
const scalar_t& f_ji = (i == 0) ? f0[j] : sig.f[j * (n - 1) + i - 1];
p_vec[i] *= f_ji;
}
}
for(size_t i = 0; i < ring_size; ++i)
Z += p_vec[i] * point_t(*ring[i]).modify_mul8();
for(size_t i = ring_size; i < N; ++i)
Z += p_vec[i] * point_t(*ring[ring_size - 1]).modify_mul8();
scalar_t x_power = c_scalar_1;
for(size_t k = 0; k < m; ++k)
{
Z -= x_power * point_t(sig.Pk[k]).modify_mul8();
x_power *= x;
}
Z -= sig.z * c_point_X;
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(Z.is_zero(), 101);
return true;
}
#undef CHECK_AND_FAIL_WITH_ERROR_IF_FALSE
} // namespace crypto

View file

@ -34,7 +34,7 @@ namespace crypto
bool generate_BGE_proof(const hash& context_hash, const std::vector<point_t>& ring, const scalar_t& secret, const size_t secret_index, BGE_proof& result, uint8_t* p_err = nullptr);
bool verify_BGE_proof(const hash& context_hash, const std::vector<const public_key*>& ring, BGE_proof& result, uint8_t* p_err = nullptr);
bool verify_BGE_proof(const hash& context_hash, const std::vector<const public_key*>& ring, const BGE_proof& sig, uint8_t* p_err = nullptr);
} // namespace crypto

View file

@ -494,6 +494,7 @@ struct test_keeper_t
#include "crypto_tests_ml2s.h"
#include "crypto_tests_range_proofs.h"
#include "crypto_tests_clsag.h"
#include "crypto_tests_one_out_of_many_proofs.h"
////////////////////////////////////////////////////////////////////////////////

View file

@ -0,0 +1,78 @@
// Copyright (c) 2023 Zano Project (https://zano.org/)
// Copyright (c) 2023 sowle (val@zano.org, crypto.sowle@gmail.com)
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#pragma once
#include <crypto/one_out_of_many_proofs.h>
struct BGE_proff_check_t
{
hash context_hash;
std::vector<public_key> ring; // 1/8
std::vector<point_t> ring_pt;
size_t secret_index;
scalar_t secret;
BGE_proof sig;
BGE_proff_check_t& operator=(const BGE_proff_check_t&) = default;
void prepare_random_data(size_t ring_size)
{
context_hash = *(hash*)scalar_t::random().data();
secret.make_random();
secret_index = random_in_range(0, ring_size - 1);
ring_pt.resize(ring_size);
ring.resize(ring_size);
for(size_t i = 0; i < ring_size; ++i)
{
ring_pt[i] = (i == secret_index) ? (secret * c_point_X) : hash_helper_t::hp(hash_helper_t::hs("0123456789012345678901234567890", scalar_t(i)));
ring[i] = (c_scalar_1div8 * ring_pt[i]).to_public_key();
}
}
bool generate() noexcept
{
try
{
uint8_t err = 0;
return generate_BGE_proof(context_hash, ring_pt, secret, secret_index, sig, &err) && err == 0;
}
catch(...)
{
return false;
}
}
bool verify() noexcept
{
try
{
uint8_t err = 0;
std::vector<const public_key*> ring_ptr;
for(auto& el : ring)
ring_ptr.emplace_back(&el);
return verify_BGE_proof(context_hash, ring_ptr, sig, &err) && err == 0;
}
catch(...)
{
return false;
}
}
};
TEST(BGE_proof, basics)
{
BGE_proff_check_t cc;
cc.prepare_random_data(1);
ASSERT_TRUE(cc.generate());
ASSERT_TRUE(cc.verify());
return true;
}