forked from lthn/blockchain
159 lines
5.1 KiB
C++
159 lines
5.1 KiB
C++
// Copyright (c) 2014-2018 Zano Project
|
||
// Copyright (c) 2014-2018 The Louisdor Project
|
||
// Copyright (c) 2012-2013 The Boolberry developers
|
||
// Copyright (c) 2017-2025 Lethean (https://lt.hn)
|
||
//
|
||
// Licensed under the European Union Public Licence (EUPL) version 1.2.
|
||
// You may obtain a copy of the licence at:
|
||
//
|
||
// https://joinup.ec.europa.eu/software/page/eupl/licence-eupl
|
||
//
|
||
// The EUPL is a copyleft licence that is compatible with the MIT/X11
|
||
// licence used by the original projects; the MIT terms are therefore
|
||
// considered “grandfathered” under the EUPL for this code.
|
||
//
|
||
// SPDX‑License‑Identifier: EUPL-1.2
|
||
//
|
||
#pragma once
|
||
|
||
#include "epee/include/misc_log_ex.h"
|
||
#include "crypto-sugar.h"
|
||
|
||
namespace crypto
|
||
{
|
||
|
||
// returns x + x^2 + x^3 + ... + x^(2^f)
|
||
// == x * (x + 1) * (x^2 + 1) * (x^4 + 1) * ...(x^(f+1) + 1)
|
||
inline scalar_t sum_of_powers(scalar_t x, size_t f)
|
||
{
|
||
scalar_t result = x;
|
||
for (size_t i = 0; i < f; ++i)
|
||
{
|
||
result.assign_muladd(result, x, result);
|
||
x *= x;
|
||
}
|
||
return result;
|
||
}
|
||
|
||
// returns least significant bit uing de Bruijn sequence
|
||
// http://graphics.stanford.edu/~seander/bithacks.html
|
||
inline uint8_t calc_lsb_32(uint32_t v)
|
||
{
|
||
static const uint8_t multiply_de_bruijn_bit_position[32] =
|
||
{
|
||
0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
|
||
31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
|
||
};
|
||
return multiply_de_bruijn_bit_position[((uint32_t)((v & -(int32_t)v) * 0x077CB531U)) >> 27];
|
||
}
|
||
|
||
|
||
////////////////////////////////////////
|
||
// crypto trait for Zano
|
||
////////////////////////////////////////
|
||
struct bpp_ct_generators_HGX
|
||
{
|
||
// NOTE! This notation follows the original BP+ whitepaper, see mapping to Zano's generators in range_proofs.cpp
|
||
static const point_t& bpp_G;
|
||
static const point_t& bpp_H;
|
||
static const point_t& bpp_H2;
|
||
};
|
||
|
||
struct bpp_ct_generators_UGX
|
||
{
|
||
// NOTE! This notation follows the original BP+ whitepaper, see mapping to Zano's generators in range_proofs.cpp
|
||
static const point_t& bpp_G;
|
||
static const point_t& bpp_H;
|
||
static const point_t& bpp_H2;
|
||
};
|
||
|
||
|
||
template<typename gen_trait_t, size_t N = 64, size_t values_max = 32>
|
||
struct bpp_crypto_trait_zano : gen_trait_t
|
||
{
|
||
static constexpr size_t c_bpp_n = N; // the upper bound for the witness's range
|
||
static constexpr size_t c_bpp_values_max = values_max; // maximum number of elements in BP+ proof, i.e. max allowed BP+ outputs
|
||
static constexpr size_t c_bpp_log2_n = constexpr_ceil_log2(c_bpp_n);
|
||
static constexpr size_t c_bpp_mn_max = c_bpp_n * c_bpp_values_max;
|
||
|
||
static void calc_pedersen_commitment(const scalar_t& value, const scalar_t& mask, point_t& commitment)
|
||
{
|
||
// commitment = value * bpp_G + mask * bpp_H
|
||
commitment = operator*(value, bpp_G) + mask * bpp_H;
|
||
}
|
||
|
||
static void calc_pedersen_commitment_2(const scalar_t& value, const scalar_t& mask1, const scalar_t& mask2, point_t& commitment)
|
||
{
|
||
// commitment = value * bpp_G + mask1 * bpp_H * mask2 * bpp_H2
|
||
commitment = operator*(value, bpp_G) + mask1 * bpp_H + mask2 * bpp_H2;
|
||
}
|
||
|
||
static const scalar_t& get_initial_transcript()
|
||
{
|
||
static scalar_t value = hash_helper_t::hs("Lethean BP+ initial transcript");
|
||
return value;
|
||
}
|
||
|
||
// assumes hsc is cleared
|
||
static void update_transcript(hash_helper_t::hs_t& hsc, scalar_t& e, const std::vector<point_t>& points)
|
||
{
|
||
hsc.add_scalar(e);
|
||
hsc.add_points_array(points);
|
||
e = hsc.calc_hash();
|
||
}
|
||
|
||
// assumes hsc is cleared
|
||
static void update_transcript(hash_helper_t::hs_t& hsc, scalar_t& e, const std::vector<const public_key*>& pub_keys)
|
||
{
|
||
hsc.add_scalar(e);
|
||
for(auto p : pub_keys)
|
||
hsc.add_pub_key(*p);
|
||
e = hsc.calc_hash();
|
||
}
|
||
|
||
// TODO: refactor with proper OOB handling
|
||
static const point_t& get_generator(bool select_H, size_t index)
|
||
{
|
||
if (index >= c_bpp_mn_max)
|
||
return c_point_0; // out of bound
|
||
|
||
static std::vector<point_t> generators(2 * c_bpp_mn_max);
|
||
static bool calculated = false;
|
||
if (!calculated)
|
||
{
|
||
scalar_t hash_buf[2] = { hash_helper_t::hs("Lethean BP+ generator"), 0 };
|
||
for (size_t i = 0; i < 2 * c_bpp_mn_max; ++i)
|
||
{
|
||
hash_buf[1].m_u64[0] = i;
|
||
ge_bytes_hash_to_ec(&generators[i].m_p3, &hash_buf, sizeof hash_buf);
|
||
}
|
||
calculated = true;
|
||
}
|
||
|
||
return generators[2 * index + (select_H ? 1 : 0)];
|
||
}
|
||
|
||
static const scalar_t& get_2_to_the_power_of_N_minus_1()
|
||
{
|
||
static scalar_t result = scalar_t::power_of_2(c_bpp_n) - 1;
|
||
return result;
|
||
}
|
||
|
||
using gen_trait_t::bpp_G;
|
||
using gen_trait_t::bpp_H;
|
||
using gen_trait_t::bpp_H2;
|
||
}; // struct bpp_crypto_trait_zano
|
||
|
||
|
||
typedef bpp_crypto_trait_zano<bpp_ct_generators_UGX, 64, 32> bpp_crypto_trait_ZC_out;
|
||
|
||
typedef bpp_crypto_trait_zano<bpp_ct_generators_HGX, 128, 16> bpp_crypto_trait_Zarcanum;
|
||
|
||
|
||
} // namespace crypto
|
||
|
||
#include "epee/include/profile_tools.h" // <- remove this, sowle
|
||
|
||
#include "msm.h"
|
||
#include "range_proof_bpp.h"
|
||
#include "range_proof_bppe.h"
|