1
0
Fork 0
forked from lthn/blockchain

Merge branch 'zarcanum' into zarcanum_wallet

This commit is contained in:
cryptozoidberg 2022-06-30 19:03:03 +02:00
commit e75c2e603c
No known key found for this signature in database
GPG key ID: 22DEB97A54C6FDEC
8 changed files with 110 additions and 34 deletions

View file

@ -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;

View file

@ -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];

View file

@ -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);

View 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_____"

View file

@ -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()
};

View file

@ -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>

View file

@ -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;
}

View file

@ -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);