From 45e1bbcafad24e4106221591a9aa9f95a81d7dbb Mon Sep 17 00:00:00 2001 From: sowle Date: Tue, 28 Jun 2022 22:17:29 +0200 Subject: [PATCH] zarcanum outputs detection/decoding --- src/currency_core/crypto_config.h | 10 ++++ src/currency_core/currency_format_utils.cpp | 60 ++++++++++++++++----- src/currency_core/currency_format_utils.h | 11 +++- 3 files changed, 65 insertions(+), 16 deletions(-) create mode 100644 src/currency_core/crypto_config.h diff --git a/src/currency_core/crypto_config.h b/src/currency_core/crypto_config.h new file mode 100644 index 00000000..24ae3d6a --- /dev/null +++ b/src/currency_core/crypto_config.h @@ -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_____" diff --git a/src/currency_core/currency_format_utils.cpp b/src/currency_core/currency_format_utils.cpp index df66336a..aa7a44fd 100644 --- a/src/currency_core/currency_format_utils.cpp +++ b/src/currency_core/currency_format_utils.cpp @@ -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& 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(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; } diff --git a/src/currency_core/currency_format_utils.h b/src/currency_core/currency_format_utils.h index 28353fdb..7e28632a 100644 --- a/src/currency_core/currency_format_utils.h +++ b/src/currency_core/currency_format_utils.h @@ -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& 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& outs, uint64_t& money_transfered, crypto::key_derivation& derivation, std::list& htlc_info_list); bool lookup_acc_outs(const account_keys& acc, const transaction& tx, std::vector& outs, uint64_t& money_transfered, crypto::key_derivation& derivation);