forked from lthn/blockchain
Merge branch 'zarcanum' into zarcanum_wallet
This commit is contained in:
commit
e75c2e603c
8 changed files with 110 additions and 34 deletions
|
|
@ -16,7 +16,9 @@ namespace crypto
|
|||
#include "crypto/crypto-ops.h"
|
||||
} // extern "C"
|
||||
|
||||
|
||||
#define CRYPTO_STR_(X) #X
|
||||
#define CRYPTO_STR(X) CRYPTO_STR_(X)
|
||||
#define CRYPTO_CHECK_AND_THROW_MES(cond, msg) if (!(cond)) { throw std::runtime_error(msg " @ " __FILE__ ":" CRYPTO_STR(__LINE__)); }
|
||||
|
||||
//
|
||||
// Helpers
|
||||
|
|
@ -480,27 +482,24 @@ namespace crypto
|
|||
{
|
||||
}
|
||||
|
||||
explicit point_t(const crypto::public_key& pk)
|
||||
explicit point_t(const crypto::public_key& pk) // can throw std::runtime_error
|
||||
{
|
||||
if (!from_public_key(pk))
|
||||
zero();
|
||||
CRYPTO_CHECK_AND_THROW_MES(from_public_key(pk), "invalid public key");
|
||||
}
|
||||
|
||||
point_t(const unsigned char(&v)[32])
|
||||
point_t(const unsigned char(&v)[32]) // can throw std::runtime_error
|
||||
{
|
||||
static_assert(sizeof(crypto::public_key) == sizeof v, "size missmatch");
|
||||
if (!from_public_key(*(const crypto::public_key*)v))
|
||||
zero();
|
||||
CRYPTO_CHECK_AND_THROW_MES(from_public_key(*(const crypto::public_key*)v), "invalid public key (char[32])");
|
||||
}
|
||||
|
||||
point_t(const uint64_t(&v)[4])
|
||||
point_t(const uint64_t(&v)[4]) // can throw std::runtime_error
|
||||
{
|
||||
static_assert(sizeof(crypto::public_key) == sizeof v, "size missmatch");
|
||||
if (!from_public_key(*(const crypto::public_key*)v))
|
||||
zero();
|
||||
CRYPTO_CHECK_AND_THROW_MES(from_public_key(*(const crypto::public_key*)v), "invalid public key (uint64_t[4])");
|
||||
}
|
||||
|
||||
point_t(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3)
|
||||
point_t(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3) // can throw std::runtime_error
|
||||
{
|
||||
crypto::public_key pk;
|
||||
((uint64_t*)&pk)[0] = a0;
|
||||
|
|
@ -508,8 +507,7 @@ namespace crypto
|
|||
((uint64_t*)&pk)[2] = a2;
|
||||
((uint64_t*)&pk)[3] = a3;
|
||||
|
||||
if (!from_public_key(pk))
|
||||
zero();
|
||||
CRYPTO_CHECK_AND_THROW_MES(from_public_key(pk), "invalid public key (four uint64_t)");
|
||||
}
|
||||
|
||||
explicit point_t(tag_zero&&)
|
||||
|
|
@ -935,9 +933,10 @@ namespace crypto
|
|||
|
||||
struct hs_t
|
||||
{
|
||||
hs_t()
|
||||
hs_t(size_t size_to_reserve = 0)
|
||||
{
|
||||
static_assert(sizeof(scalar_t) == sizeof(crypto::public_key), "unexpected size of data");
|
||||
m_elements.reserve(size_to_reserve);
|
||||
}
|
||||
|
||||
void reserve(size_t elements_count)
|
||||
|
|
@ -1007,6 +1006,11 @@ namespace crypto
|
|||
m_elements.emplace_back(key_image_array[i]);
|
||||
}
|
||||
|
||||
void add_32_chars(const char(&str32)[32])
|
||||
{
|
||||
m_elements.emplace_back(str32);
|
||||
}
|
||||
|
||||
scalar_t calc_hash(bool clear = true)
|
||||
{
|
||||
size_t data_size_bytes = m_elements.size() * sizeof(item_t);
|
||||
|
|
@ -1033,17 +1037,21 @@ namespace crypto
|
|||
item_t(const scalar_t& scalar) : scalar(scalar) {}
|
||||
item_t(const crypto::public_key& pk) : pk(pk) {}
|
||||
item_t(const crypto::key_image& ki) : ki(ki) {}
|
||||
item_t(const char(&str32)[32]) { memcpy(c, str32, sizeof c); }
|
||||
scalar_t scalar;
|
||||
crypto::public_key pk;
|
||||
crypto::key_image ki;
|
||||
char c[32];
|
||||
};
|
||||
|
||||
static_assert(sizeof(item_t::c) == sizeof(item_t::pk), "size missmatch");
|
||||
|
||||
std::vector<item_t> m_elements;
|
||||
};
|
||||
|
||||
static scalar_t hs(const scalar_t& s, const std::vector<point_t>& ps0, const std::vector<point_t>& ps1)
|
||||
{
|
||||
hs_t hs_calculator;
|
||||
hs_t hs_calculator(3);
|
||||
hs_calculator.add_scalar(s);
|
||||
hs_calculator.add_points_array(ps0);
|
||||
hs_calculator.add_points_array(ps1);
|
||||
|
|
@ -1053,7 +1061,7 @@ namespace crypto
|
|||
static scalar_t hs(const crypto::hash& s, const std::vector<crypto::public_key>& ps0, const std::vector<crypto::key_image>& ps1)
|
||||
{
|
||||
static_assert(sizeof(crypto::hash) == sizeof(scalar_t), "size missmatch");
|
||||
hs_t hs_calculator;
|
||||
hs_t hs_calculator(3);
|
||||
hs_calculator.add_scalar(*reinterpret_cast<const scalar_t*>(&s));
|
||||
hs_calculator.add_pub_keys_array(ps0);
|
||||
hs_calculator.add_key_images_array(ps1);
|
||||
|
|
@ -1062,12 +1070,20 @@ namespace crypto
|
|||
|
||||
static scalar_t hs(const std::vector<point_t>& ps0, const std::vector<point_t>& ps1)
|
||||
{
|
||||
hs_t hs_calculator;
|
||||
hs_t hs_calculator(2);
|
||||
hs_calculator.add_points_array(ps0);
|
||||
hs_calculator.add_points_array(ps1);
|
||||
return hs_calculator.calc_hash();
|
||||
}
|
||||
|
||||
static scalar_t hs(const char(&str32)[32], const scalar_t& s)
|
||||
{
|
||||
hs_t hs_calculator(2);
|
||||
hs_calculator.add_32_chars(str32);
|
||||
hs_calculator.add_scalar(s);
|
||||
return hs_calculator.calc_hash();
|
||||
}
|
||||
|
||||
static point_t hp(const point_t& p)
|
||||
{
|
||||
point_t result;
|
||||
|
|
|
|||
|
|
@ -187,7 +187,8 @@ namespace crypto {
|
|||
return true;
|
||||
}
|
||||
|
||||
static void derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res) {
|
||||
void crypto_ops::derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res)
|
||||
{
|
||||
struct {
|
||||
key_derivation derivation;
|
||||
char output_index[(sizeof(size_t) * 8 + 6) / 7];
|
||||
|
|
|
|||
|
|
@ -86,6 +86,8 @@ namespace crypto {
|
|||
friend bool secret_key_to_public_key(const secret_key &, public_key &);
|
||||
static bool generate_key_derivation(const public_key &, const secret_key &, key_derivation &);
|
||||
friend bool generate_key_derivation(const public_key &, const secret_key &, key_derivation &);
|
||||
static void derivation_to_scalar(const key_derivation &, size_t, ec_scalar &);
|
||||
friend void derivation_to_scalar(const key_derivation &, size_t, ec_scalar &);
|
||||
static bool derive_public_key(const key_derivation &, std::size_t, const public_key &, public_key &);
|
||||
friend bool derive_public_key(const key_derivation &, std::size_t, const public_key &, public_key &);
|
||||
static void derive_secret_key(const key_derivation &, std::size_t, const secret_key &, secret_key &);
|
||||
|
|
@ -174,6 +176,10 @@ namespace crypto {
|
|||
inline bool generate_key_derivation(const public_key &key1, const secret_key &key2, key_derivation &derivation) {
|
||||
return crypto_ops::generate_key_derivation(key1, key2, derivation);
|
||||
}
|
||||
inline void derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &result) {
|
||||
crypto::crypto_ops::derivation_to_scalar(derivation, output_index, result);
|
||||
}
|
||||
|
||||
inline bool derive_public_key(const key_derivation &derivation, std::size_t output_index,
|
||||
const public_key &base, public_key &derived_key) {
|
||||
return crypto_ops::derive_public_key(derivation, output_index, base, derived_key);
|
||||
|
|
|
|||
10
src/currency_core/crypto_config.h
Normal file
10
src/currency_core/crypto_config.h
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
// Copyright (c) 2022 Zano Project
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
//
|
||||
#pragma once
|
||||
|
||||
// hash domain separation strings, 32 bytes long (31 chars + \0)
|
||||
//
|
||||
#define CRYPTO_HDS_OUT_AMOUNT_MASK "ZANO_HDS_OUT_AMOUNT_MASK_______"
|
||||
#define CRYPTO_HDS_OUT_BLINDING_MASK "ZANO_HDS_OUT_BLINDING_MASK_____"
|
||||
|
|
@ -358,6 +358,7 @@ namespace currency
|
|||
crypto::public_key concealing_point; // group element Q, see also Zarcanum paper
|
||||
crypto::public_key amount_commitment;
|
||||
uint64_t encrypted_amount;
|
||||
uint8_t mix_attr;
|
||||
//crypto::public_key token_masked_generator;
|
||||
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
|
|
@ -365,6 +366,7 @@ namespace currency
|
|||
FIELD(concealing_point)
|
||||
FIELD(amount_commitment)
|
||||
FIELD(encrypted_amount)
|
||||
FIELD(mix_attr)
|
||||
END_SERIALIZE()
|
||||
|
||||
BEGIN_BOOST_SERIALIZATION()
|
||||
|
|
@ -372,6 +374,7 @@ namespace currency
|
|||
BOOST_SERIALIZE(concealing_point)
|
||||
BOOST_SERIALIZE(amount_commitment)
|
||||
BOOST_SERIALIZE(encrypted_amount)
|
||||
BOOST_SERIALIZE(mix_attr)
|
||||
END_BOOST_SERIALIZATION()
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -117,6 +117,7 @@ namespace boost
|
|||
a & x.concealing_point;
|
||||
a & x.amount_commitment;
|
||||
a & x.encrypted_amount;
|
||||
a & x.mix_attr;
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ using namespace epee;
|
|||
#include "genesis_acc.h"
|
||||
#include "common/mnemonic-encoding.h"
|
||||
#include "crypto/bitcoin/sha256_helper.h"
|
||||
#include "crypto_config.h"
|
||||
|
||||
namespace currency
|
||||
{
|
||||
|
|
@ -1960,6 +1961,33 @@ namespace currency
|
|||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool is_out_to_acc(const account_keys& acc, const tx_out_zarcanum& zo, const crypto::key_derivation& derivation, size_t output_index, uint64_t& decoded_amount)
|
||||
{
|
||||
crypto::scalar_t h = {};
|
||||
crypto::derivation_to_scalar(derivation, output_index, h.as_secret_key()); // h = Hs(r * V, i)
|
||||
|
||||
crypto::point_t P_prime = h * crypto::c_point_G + crypto::point_t(acc.account_address.spend_public_key); // P =? Hs(rV, i) * G + S
|
||||
if (P_prime.to_public_key() != zo.stealth_address)
|
||||
return false;
|
||||
|
||||
crypto::point_t Q_prime = h * crypto::point_t(acc.account_address.view_public_key); // Q =? v * Hs(rv, i) * G
|
||||
if (Q_prime.to_public_key() != zo.concealing_point)
|
||||
return false;
|
||||
|
||||
crypto::scalar_t amount_mask = crypto::hash_helper_t::hs(CRYPTO_HDS_OUT_AMOUNT_MASK, h);
|
||||
decoded_amount = zo.encrypted_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, h)
|
||||
|
||||
crypto::point_t A_prime;
|
||||
A_prime.assign_mul_plus_G(decoded_amount, crypto::c_point_H, blinding_mask); // A =? a * H + f * G
|
||||
if (A_prime.to_public_key() != zo.amount_commitment)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
bool lookup_acc_outs(const account_keys& acc, const transaction& tx, std::vector<wallet_out_info>& outs, uint64_t& money_transfered, crypto::key_derivation& derivation)
|
||||
{
|
||||
|
|
@ -2009,7 +2037,7 @@ namespace currency
|
|||
CHECK_AND_ASSERT_MES(o.target.type() == typeid(txout_to_key), false, "condition failed: o.target.type() == typeid(txout_to_key)");
|
||||
if (is_out_to_acc(acc, boost::get<txout_to_key>(o.target), derivation, offset))
|
||||
{
|
||||
outs.push_back(offset);
|
||||
outs.emplace_back(offset, o.amount);
|
||||
money_transfered += o.amount;
|
||||
}
|
||||
return true;
|
||||
|
|
@ -2036,7 +2064,7 @@ namespace currency
|
|||
if (!check_tx_derivation_hint(tx, derivation))
|
||||
return true;
|
||||
|
||||
size_t i = 0;
|
||||
size_t output_index = 0;
|
||||
for(const auto& ov : tx.vout)
|
||||
{
|
||||
VARIANT_SWITCH_BEGIN(ov);
|
||||
|
|
@ -2044,40 +2072,44 @@ namespace currency
|
|||
{
|
||||
VARIANT_SWITCH_BEGIN(o.target);
|
||||
VARIANT_CASE_CONST(txout_to_key, t)
|
||||
if (is_out_to_acc(acc, t, derivation, i))
|
||||
if (is_out_to_acc(acc, t, derivation, output_index))
|
||||
{
|
||||
outs.push_back(i);
|
||||
outs.emplace_back(output_index, o.amount);
|
||||
money_transfered += o.amount;
|
||||
}
|
||||
VARIANT_CASE_CONST(txout_multisig, t)
|
||||
if (is_out_to_acc(acc, t, derivation, i))
|
||||
if (is_out_to_acc(acc, t, derivation, output_index))
|
||||
{
|
||||
outs.push_back(i);
|
||||
//don't count this money
|
||||
outs.emplace_back(output_index, 0); // TODO: @#@# consider this
|
||||
//don't cout this money
|
||||
}
|
||||
VARIANT_CASE_CONST(txout_htlc, htlc)
|
||||
htlc_info hi = AUTO_VAL_INIT(hi);
|
||||
if (is_out_to_acc(acc, htlc.pkey_redeem, derivation, i))
|
||||
if (is_out_to_acc(acc, htlc.pkey_redeem, derivation, output_index))
|
||||
{
|
||||
hi.hltc_our_out_is_before_expiration = true;
|
||||
htlc_info_list.push_back(hi);
|
||||
outs.push_back(i);
|
||||
}
|
||||
else if (is_out_to_acc(acc, htlc.pkey_refund, derivation, i))
|
||||
else if (is_out_to_acc(acc, htlc.pkey_refund, derivation, output_index))
|
||||
{
|
||||
hi.hltc_our_out_is_before_expiration = false;
|
||||
htlc_info_list.push_back(hi);
|
||||
outs.push_back(i);
|
||||
}
|
||||
outs.emplace_back(output_index, o.amount);
|
||||
VARIANT_CASE_OTHER()
|
||||
LOG_ERROR("Wrong type at lookup_acc_outs, unexpected type is: " << o.target.type().name());
|
||||
return false;
|
||||
VARIANT_SWITCH_END();
|
||||
}
|
||||
VARIANT_CASE_CONST(tx_out_zarcanum, o)
|
||||
//@#@
|
||||
VARIANT_CASE_CONST(tx_out_zarcanum, zo)
|
||||
//@#@
|
||||
wallet_out_info woi(output_index, 0);
|
||||
if (is_out_to_acc(acc, zo, derivation, output_index, woi.amount))
|
||||
{
|
||||
outs.emplace_back(woi);
|
||||
}
|
||||
VARIANT_SWITCH_END();
|
||||
i++;
|
||||
output_index++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -197,8 +197,14 @@ namespace currency
|
|||
|
||||
struct wallet_out_info
|
||||
{
|
||||
size_t index;
|
||||
uint64_t amount;
|
||||
wallet_out_info() = default;
|
||||
wallet_out_info(size_t index, uint64_t amount)
|
||||
: index(index)
|
||||
, amount(amount)
|
||||
{}
|
||||
|
||||
size_t index = SIZE_MAX;
|
||||
uint64_t amount = 0;
|
||||
//todo: additional input info
|
||||
};
|
||||
|
||||
|
|
@ -289,6 +295,7 @@ namespace currency
|
|||
crypto::hash get_multisig_out_id(const transaction& tx, size_t n);
|
||||
bool is_out_to_acc(const account_keys& acc, const txout_to_key& out_key, const crypto::key_derivation& derivation, size_t output_index);
|
||||
bool is_out_to_acc(const account_keys& acc, const txout_multisig& out_multisig, const crypto::key_derivation& derivation, size_t output_index);
|
||||
bool is_out_to_acc(const account_keys& acc, const tx_out_zarcanum& zo, const crypto::key_derivation& derivation, size_t output_index, uint64_t& decoded_amount);
|
||||
bool lookup_acc_outs(const account_keys& acc, const transaction& tx, const crypto::public_key& tx_pub_key, std::vector<wallet_out_info>& outs, uint64_t& money_transfered, crypto::key_derivation& derivation);
|
||||
bool lookup_acc_outs(const account_keys& acc, const transaction& tx, const crypto::public_key& tx_pub_key, std::vector<wallet_out_info>& outs, uint64_t& money_transfered, crypto::key_derivation& derivation, std::list<htlc_info>& htlc_info_list);
|
||||
bool lookup_acc_outs(const account_keys& acc, const transaction& tx, std::vector<wallet_out_info>& outs, uint64_t& money_transfered, crypto::key_derivation& derivation);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue