forked from lthn/blockchain
Merge branch 'zarcanum' into zarcanum_wallet
This commit is contained in:
commit
87e7905be1
6 changed files with 112 additions and 40 deletions
|
|
@ -23,16 +23,18 @@ namespace crypto
|
|||
scalar_t delta;
|
||||
};
|
||||
|
||||
#define DBG_VAL_PRINT(x) std::cout << #x ": " << x << ENDL
|
||||
#define DBG_PRINT(x) std::cout << x << ENDL
|
||||
#define DBG_VAL_PRINT(x) (void(0)) // std::cout << #x ": " << x << ENDL
|
||||
#define DBG_PRINT(x) (void(0)) // std::cout << x << ENDL
|
||||
|
||||
template<typename CT>
|
||||
bool bpp_gen(const scalar_vec_t& values, const scalar_vec_t& masks, bpp_signature& sig, std::vector<point_t>& commitments, uint8_t* p_err = nullptr)
|
||||
{
|
||||
#define CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(cond, err_code) \
|
||||
if (!(cond)) { LOG_PRINT_RED("bpp_gen: \"" << #cond << "\" is false at " << LOCATION_SS << ENDL << "error code = " << err_code, LOG_LEVEL_3); \
|
||||
if (p_err) { *p_err = err_code; } return false; }
|
||||
if (!(cond)) { LOG_PRINT_RED("bpp_gen: \"" << #cond << "\" is false at " << LOCATION_SS << ENDL << "error code = " << err_code, LOG_LEVEL_3); \
|
||||
if (p_err) { *p_err = err_code; } return false; }
|
||||
|
||||
|
||||
template<typename CT = bpp_crypto_trait_zano<>>
|
||||
bool bpp_gen(const scalar_vec_t& values, const scalar_vec_t& masks, const std::vector<const crypto::public_key*>& commitments_1div8, bpp_signature& sig, uint8_t* p_err = nullptr)
|
||||
{
|
||||
// Note: commitments_1div8 are supposed to be already calculated
|
||||
static_assert(CT::c_bpp_n <= 255, "too big N");
|
||||
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(values.size() > 0 && values.size() <= CT::c_bpp_values_max && values.size() == masks.size(), 1);
|
||||
CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(masks.is_reduced(), 3);
|
||||
|
|
@ -42,15 +44,6 @@ namespace crypto
|
|||
const size_t c_bpp_mn = c_bpp_m * CT::c_bpp_n;
|
||||
const size_t c_bpp_log2_mn = c_bpp_log2_m + CT::c_bpp_log2_n;
|
||||
|
||||
// pre-multiply all output points by c_scalar_1div8
|
||||
// in order to enforce these points to be in the prime-order subgroup (after mul by 8 in bpp_verify())
|
||||
|
||||
// calc commitments vector as commitments[i] = 1/8 * values[i] * G + 1/8 * masks[i] * H
|
||||
commitments.resize(values.size());
|
||||
for (size_t i = 0; i < values.size(); ++i)
|
||||
CT::calc_pedersen_commitment(values[i] * c_scalar_1div8, masks[i] * c_scalar_1div8, commitments[i]);
|
||||
|
||||
|
||||
// s.a. BP+ paper, page 15, eq. 11
|
||||
// decompose v into aL and aR:
|
||||
// v = aL o (1, 2, 2^2, ..., 2^n-1), o - component-wise product aka Hadamard product
|
||||
|
|
@ -85,7 +78,7 @@ namespace crypto
|
|||
DBG_PRINT("initial transcript: " << e);
|
||||
|
||||
hash_helper_t::hs_t hsc;
|
||||
CT::update_transcript(hsc, e, commitments);
|
||||
CT::update_transcript(hsc, e, commitments_1div8);
|
||||
|
||||
// BP+ paper, page 15: The prover begins with sending A = g^aL h^aR h^alpha (group element)
|
||||
// so we calculate A0 = alpha * H + SUM(aL_i * G_i) + SUM(aR_i * H_i)
|
||||
|
|
@ -96,7 +89,8 @@ namespace crypto
|
|||
for (size_t i = 0; i < c_bpp_mn; ++i)
|
||||
A0 += aLs[i] * CT::get_generator(false, i) + aRs[i] * CT::get_generator(true, i);
|
||||
|
||||
// part of 1/8 defense scheme
|
||||
// pre-multiply all output points by c_scalar_1div8
|
||||
// in order to enforce these points to be in the prime-order subgroup (after mul by 8 in bpp_verify())
|
||||
A0 *= c_scalar_1div8;
|
||||
A0.to_public_key(sig.A0);
|
||||
|
||||
|
|
@ -147,7 +141,7 @@ namespace crypto
|
|||
|
||||
// aL_hat = aL - 1*z
|
||||
scalar_vec_t aLs_hat = aLs - z;
|
||||
// aL_hat = aR + d o y^leftarr + 1*z where y^leftarr = (y^n, y^(n-1), ..., y) (BP+ paper, page 18, Fig. 3)
|
||||
// aR_hat = aR + d o y^leftarr + 1*z where y^leftarr = (y^n, y^(n-1), ..., y) (BP+ paper, page 18, Fig. 3)
|
||||
scalar_vec_t aRs_hat = aRs + z;
|
||||
for (size_t i = 0; i < c_bpp_mn; ++i)
|
||||
aRs_hat[i] += d[i] * y_powers[c_bpp_mn - i];
|
||||
|
|
@ -339,7 +333,7 @@ namespace crypto
|
|||
};
|
||||
|
||||
|
||||
template<typename CT>
|
||||
template<typename CT = bpp_crypto_trait_zano<>>
|
||||
bool bpp_verify(const std::vector<bpp_sig_commit_ref_t>& sigs, uint8_t* p_err = nullptr)
|
||||
{
|
||||
#define CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(cond, err_code) \
|
||||
|
|
@ -696,4 +690,7 @@ namespace crypto
|
|||
#undef CHECK_AND_FAIL_WITH_ERROR_IF_FALSE
|
||||
}
|
||||
|
||||
#undef DBG_VAL_PRINT
|
||||
#undef DBG_PRINT
|
||||
|
||||
} // namespace crypto
|
||||
|
|
|
|||
|
|
@ -24,8 +24,8 @@ namespace crypto
|
|||
scalar_t delta_2;
|
||||
};
|
||||
|
||||
#define DBG_VAL_PRINT(x) std::cout << #x ": " << x << ENDL
|
||||
#define DBG_PRINT(x) std::cout << x << ENDL
|
||||
#define DBG_VAL_PRINT(x) (void(0)) // std::cout << #x ": " << x << ENDL
|
||||
#define DBG_PRINT(x) (void(0)) // std::cout << x << ENDL
|
||||
|
||||
template<typename CT>
|
||||
bool bppe_gen(const scalar_vec_t& values, const scalar_vec_t& masks, const scalar_vec_t& masks2, bppe_signature& sig, std::vector<point_t>& commitments, uint8_t* p_err = nullptr)
|
||||
|
|
@ -149,7 +149,7 @@ namespace crypto
|
|||
|
||||
// aL_hat = aL - 1*z
|
||||
scalar_vec_t aLs_hat = aLs - z;
|
||||
// aL_hat = aR + d o y^leftarr + 1*z where y^leftarr = (y^n, y^(n-1), ..., y) (BP+ paper, page 18, Fig. 3)
|
||||
// aR_hat = aR + d o y^leftarr + 1*z where y^leftarr = (y^n, y^(n-1), ..., y) (BP+ paper, page 18, Fig. 3)
|
||||
scalar_vec_t aRs_hat = aRs + z;
|
||||
for (size_t i = 0; i < c_bpp_mn; ++i)
|
||||
aRs_hat[i] += d[i] * y_powers[c_bpp_mn - i];
|
||||
|
|
@ -716,4 +716,7 @@ namespace crypto
|
|||
#undef CHECK_AND_FAIL_WITH_ERROR_IF_FALSE
|
||||
}
|
||||
|
||||
#undef DBG_VAL_PRINT
|
||||
#undef DBG_PRINT
|
||||
|
||||
} // namespace crypto
|
||||
|
|
|
|||
|
|
@ -88,6 +88,15 @@ namespace crypto
|
|||
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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1026,6 +1026,7 @@ SET_VARIANT_TAGS(crypto::bppe_signature_serialized, 41, "bppe_signature_serializ
|
|||
SET_VARIANT_TAGS(currency::NLSAG_sig, 42, "NLSAG_sig");
|
||||
SET_VARIANT_TAGS(currency::zarcanum_sig, 43, "zarcanum_sig");
|
||||
SET_VARIANT_TAGS(currency::void_sig, 44, "void_sig");
|
||||
SET_VARIANT_TAGS(currency::zarcanum_outs_range_proof, 45, "zarcanum_outs_range_proof");
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -609,10 +609,12 @@ namespace currency
|
|||
bool construct_tx_out(const tx_destination_entry& de, const crypto::secret_key& tx_sec_key, size_t output_index, transaction& tx, std::set<uint16_t>& deriv_cache, const account_keys& self, uint8_t tx_outs_attr)
|
||||
{
|
||||
finalized_tx result = AUTO_VAL_INIT(result);
|
||||
return construct_tx_out(de, tx_sec_key, output_index, tx, deriv_cache, self, result, tx_outs_attr);
|
||||
crypto::scalar_t out_blinding_mask = AUTO_VAL_INIT(out_blinding_mask);
|
||||
return construct_tx_out(de, tx_sec_key, output_index, tx, deriv_cache, self, out_blinding_mask, result, tx_outs_attr);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool construct_tx_out(const tx_destination_entry& de, const crypto::secret_key& tx_sec_key, size_t output_index, transaction& tx, std::set<uint16_t>& deriv_cache, const account_keys& self, finalized_tx& result, uint8_t tx_outs_attr)
|
||||
bool construct_tx_out(const tx_destination_entry& de, const crypto::secret_key& tx_sec_key, size_t output_index, transaction& tx, std::set<uint16_t>& deriv_cache,
|
||||
const account_keys& self, crypto::scalar_t& out_blinding_mask, finalized_tx& result, uint8_t tx_outs_attr)
|
||||
{
|
||||
if (tx.version > TRANSACTION_VERSION_PRE_HF4)
|
||||
{
|
||||
|
|
@ -634,8 +636,8 @@ namespace currency
|
|||
crypto::scalar_t amount_mask = crypto::hash_helper_t::hs(CRYPTO_HDS_OUT_AMOUNT_MASK, h);
|
||||
out.encrypted_amount = de.amount ^ amount_mask.m_u64[0];
|
||||
|
||||
crypto::scalar_t blinding_mask = crypto::hash_helper_t::hs(CRYPTO_HDS_OUT_BLINDING_MASK, h); // f = Hs(domain_sep, d, i)
|
||||
out.amount_commitment = (de.amount * crypto::c_point_H + blinding_mask * crypto::c_point_G).to_public_key();
|
||||
out_blinding_mask = crypto::hash_helper_t::hs(CRYPTO_HDS_OUT_BLINDING_MASK, h); // f = Hs(domain_sep, d, i)
|
||||
out.amount_commitment = (crypto::c_scalar_1div8 * de.amount * crypto::c_point_H + crypto::c_scalar_1div8 * out_blinding_mask * crypto::c_point_G).to_public_key();
|
||||
|
||||
out.mix_attr = tx_outs_attr; // TODO @#@# @CZ check this
|
||||
}
|
||||
|
|
@ -648,11 +650,11 @@ namespace currency
|
|||
out.stealth_address = (h * crypto::c_point_G + crypto::point_t(apa.spend_public_key)).to_public_key();
|
||||
out.concealing_point = (crypto::hash_helper_t::hs(CRYPTO_HDS_OUT_CONCEALING_POINT, h) * crypto::point_t(apa.view_public_key)).to_public_key(); // Q = Hs(domain_sep, h) * V
|
||||
|
||||
crypto::scalar_t amount_mask = crypto::hash_helper_t::hs(CRYPTO_HDS_OUT_AMOUNT_MASK, h);
|
||||
crypto::scalar_t amount_mask = crypto::hash_helper_t::hs(CRYPTO_HDS_OUT_AMOUNT_MASK, h);
|
||||
out.encrypted_amount = de.amount ^ amount_mask.m_u64[0];
|
||||
|
||||
crypto::scalar_t blinding_mask = crypto::hash_helper_t::hs(CRYPTO_HDS_OUT_BLINDING_MASK, h); // f = Hs(domain_sep, d, i)
|
||||
out.amount_commitment = (de.amount * crypto::c_point_H + blinding_mask * crypto::c_point_G).to_public_key();
|
||||
out_blinding_mask = crypto::hash_helper_t::hs(CRYPTO_HDS_OUT_BLINDING_MASK, h); // f = Hs(domain_sep, d, i)
|
||||
out.amount_commitment = (crypto::c_scalar_1div8 * de.amount * crypto::c_point_H + crypto::c_scalar_1div8 * out_blinding_mask * crypto::c_point_G).to_public_key();
|
||||
|
||||
if (de.addr.front().is_auditable())
|
||||
out.mix_attr = CURRENCY_TO_KEY_OUT_FORCED_NO_MIX; // override mix_attr to 1 for auditable target addresses
|
||||
|
|
@ -1524,11 +1526,14 @@ namespace currency
|
|||
//fill outputs
|
||||
size_t output_index = tx.vout.size(); // in case of append mode we need to start output indexing from the last one + 1
|
||||
std::set<uint16_t> deriv_cache;
|
||||
crypto::scalar_vec_t blinding_masks(destinations.size()); // vector of secret blinging masks for each output. For range proof generation
|
||||
crypto::scalar_vec_t amounts(destinations.size()); // vector of amounts, converted to scalars. For rnage proof generation
|
||||
for(const tx_destination_entry& dst_entr : shuffled_dsts)
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(dst_entr.amount > 0, false, "Destination with wrong amount: " << dst_entr.amount);
|
||||
bool r = construct_tx_out(dst_entr, txkey.sec, output_index, tx, deriv_cache, sender_account_keys, result, tx_outs_attr);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Failed to construc tx out");
|
||||
CHECK_AND_ASSERT_MES(dst_entr.amount > 0, false, "Destination with wrong amount: " << dst_entr.amount); // <<-- TODO @#@# consider removing this check
|
||||
bool r = construct_tx_out(dst_entr, txkey.sec, output_index, tx, deriv_cache, sender_account_keys, blinding_masks[output_index], result, tx_outs_attr);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Failed to construct tx out");
|
||||
amounts[output_index] = dst_entr.amount;
|
||||
output_index++;
|
||||
summary_outs_money += dst_entr.amount;
|
||||
}
|
||||
|
|
@ -2868,6 +2873,12 @@ namespace currency
|
|||
tv.details_view = tv.short_view;
|
||||
return true;
|
||||
}
|
||||
bool operator()(const zarcanum_outs_range_proof& rp)
|
||||
{
|
||||
tv.type = "zarcanum_outs_range_proof";
|
||||
tv.short_view = "outputs_count = " + std::to_string(rp.outputs_count);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
//------------------------------------------------------------------
|
||||
template<class t_container>
|
||||
|
|
@ -3446,6 +3457,57 @@ namespace currency
|
|||
return false;
|
||||
}
|
||||
//--------------------------------------------------------------------------------
|
||||
bool generate_zarcanum_outs_range_proof(size_t out_index_start, size_t outs_count, const crypto::scalar_vec_t& amounts, const crypto::scalar_vec_t& blinding_masks,
|
||||
const std::vector<tx_out_v>& vouts, zarcanum_outs_range_proof& result)
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(amounts.size() == outs_count, false, "");
|
||||
CHECK_AND_ASSERT_MES(blinding_masks.size() == outs_count, false, "");
|
||||
CHECK_AND_ASSERT_MES(out_index_start + outs_count == vouts.size(), false, "");
|
||||
|
||||
std::vector<const crypto::public_key*> commitments_1div8;
|
||||
for(size_t out_index = out_index_start, i = 0; i < outs_count; ++out_index, ++i)
|
||||
{
|
||||
const tx_out_zarcanum& toz = boost::get<tx_out_zarcanum>(vouts[out_index]); // may throw an exception, only zarcanum outputs are exprected
|
||||
const crypto::public_key* p = &toz.amount_commitment;
|
||||
commitments_1div8.push_back(p);
|
||||
}
|
||||
|
||||
uint8_t err = 0;
|
||||
bool r = crypto::bpp_gen<>(amounts, blinding_masks, commitments_1div8, result.bpp, &err);
|
||||
CHECK_AND_ASSERT_MES(r, false, "bpp_gen failed with error " << err);
|
||||
|
||||
return true;
|
||||
}
|
||||
//--------------------------------------------------------------------------------
|
||||
struct zarcanum_outs_range_proof_commit_ref_t
|
||||
{
|
||||
zarcanum_outs_range_proof_commit_ref_t(const zarcanum_outs_range_proof& range_proof, const std::vector<crypto::point_t>& amount_commitments)
|
||||
: range_proof(range_proof)
|
||||
, amount_commitments(amount_commitments)
|
||||
{}
|
||||
const zarcanum_outs_range_proof& range_proof;
|
||||
const std::vector<crypto::point_t>& amount_commitments;
|
||||
};
|
||||
|
||||
bool verify_multiple_zarcanum_outs_range_proofs(const std::vector<zarcanum_outs_range_proof_commit_ref_t>& range_proofs)
|
||||
{
|
||||
std::vector<crypto::bpp_sig_commit_ref_t> sigs;
|
||||
for(auto el : range_proofs)
|
||||
sigs.emplace_back(el.range_proof.bpp, el.amount_commitments);
|
||||
|
||||
uint8_t err = 0;
|
||||
bool r = crypto::bpp_verify<>(sigs, &err);
|
||||
CHECK_AND_ASSERT_MES(r, false, "bpp_vefiry failed with error " << err);
|
||||
|
||||
return true;
|
||||
}
|
||||
//--------------------------------------------------------------------------------
|
||||
bool generate_zarcanum_signature(const crypto::hash& prefix_hash, const std::vector<tx_source_entry>& sources, const txin_zarcanum_inputs& zins, zarcanum_sig& result)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
//--------------------------------------------------------------------------------
|
||||
|
||||
|
||||
boost::multiprecision::uint1024_t get_a_to_b_relative_cumulative_difficulty(const wide_difficulty_type& difficulty_pos_at_split_point,
|
||||
const wide_difficulty_type& difficulty_pow_at_split_point,
|
||||
|
|
|
|||
|
|
@ -235,7 +235,7 @@ namespace currency
|
|||
|
||||
//---------------------------------------------------------------
|
||||
uint64_t get_string_uint64_hash(const std::string& str);
|
||||
bool construct_tx_out(const tx_destination_entry& de, const crypto::secret_key& tx_sec_key, size_t output_index, transaction& tx, std::set<uint16_t>& deriv_cache, const account_keys& self, finalized_tx& result, uint8_t tx_outs_attr = CURRENCY_TO_KEY_OUT_RELAXED);
|
||||
bool construct_tx_out(const tx_destination_entry& de, const crypto::secret_key& tx_sec_key, size_t output_index, transaction& tx, std::set<uint16_t>& deriv_cache, const account_keys& self, crypto::scalar_t& out_blinding_mask, finalized_tx& result, uint8_t tx_outs_attr = CURRENCY_TO_KEY_OUT_RELAXED);
|
||||
bool construct_tx_out(const tx_destination_entry& de, const crypto::secret_key& tx_sec_key, size_t output_index, transaction& tx, std::set<uint16_t>& deriv_cache, const account_keys& self, uint8_t tx_outs_attr = CURRENCY_TO_KEY_OUT_RELAXED);
|
||||
bool validate_alias_name(const std::string& al);
|
||||
bool validate_password(const std::string& password);
|
||||
|
|
@ -406,20 +406,20 @@ namespace currency
|
|||
}
|
||||
|
||||
template<typename out_t>
|
||||
bool is_out_burned(const out_t& out) { CHECK_AND_ASSERT_THROW_MES(false, "incorrect out type: " << typeid(out).name()); }
|
||||
bool is_out_burned(const tx_out_bare& o) { return is_out_burned(o.target); }
|
||||
bool is_out_burned(const txout_to_key& o) { return o.key == null_pkey; }
|
||||
bool is_out_burned(const tx_out_zarcanum& o) { return o.stealth_address == null_pkey; }
|
||||
inline bool is_out_burned(const out_t& out) { CHECK_AND_ASSERT_THROW_MES(false, "incorrect out type: " << typeid(out).name()); }
|
||||
inline bool is_out_burned(const tx_out_bare& o) { return is_out_burned(o.target); }
|
||||
inline bool is_out_burned(const txout_to_key& o) { return o.key == null_pkey; }
|
||||
inline bool is_out_burned(const tx_out_zarcanum& o) { return o.stealth_address == null_pkey; }
|
||||
struct zz_is_out_burned_helper_visitor : boost::static_visitor<bool>
|
||||
{
|
||||
template<typename T>
|
||||
bool operator()(const T& v) const { return is_out_burned(v); }
|
||||
};
|
||||
bool is_out_burned(const tx_out_v& v)
|
||||
inline bool is_out_burned(const tx_out_v& v)
|
||||
{
|
||||
return boost::apply_visitor(zz_is_out_burned_helper_visitor(), v);
|
||||
}
|
||||
bool is_out_burned(const txout_target_v& v)
|
||||
inline bool is_out_burned(const txout_target_v& v)
|
||||
{
|
||||
return boost::apply_visitor(zz_is_out_burned_helper_visitor(), v);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue