forked from lthn/blockchain
verify_BGE_proof() first PoC implementation
This commit is contained in:
parent
5b0431daf9
commit
154e649f56
4 changed files with 177 additions and 4 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
|
|
|||
78
tests/functional_tests/crypto_tests_one_out_of_many_proofs.h
Normal file
78
tests/functional_tests/crypto_tests_one_out_of_many_proofs.h
Normal 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;
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue