From 0123e311c087f3ccaa2734c84d607288b19583dd Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Sat, 14 May 2022 00:00:34 +0200 Subject: [PATCH 01/10] Added get_mining_history API --- src/wallet/wallet2.cpp | 4 ++-- src/wallet/wallet2.h | 2 +- src/wallet/wallet_public_structs_defs.h | 6 ++++++ src/wallet/wallet_rpc_server.cpp | 5 +++++ src/wallet/wallet_rpc_server.h | 2 ++ 5 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 26778182..54f88e1e 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -3373,11 +3373,11 @@ bool wallet2::is_transfer_okay_for_pos(const transfer_details& tr, uint64_t& sta return true; } //---------------------------------------------------------------------------------------------------- -void wallet2::get_mining_history(wallet_public::mining_history& hist) +void wallet2::get_mining_history(wallet_public::mining_history& hist, uint64_t timestamp_from) { for (auto& tr : m_transfer_history) { - if (currency::is_coinbase(tr.tx) && tr.tx.vin.size() == 2) + if (currency::is_coinbase(tr.tx) && tr.tx.vin.size() == 2 && tr.timestamp > timestamp_from) { tools::wallet_public::mining_history_entry mhe = AUTO_VAL_INIT(mhe); mhe.a = tr.amount; diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index e57ff79a..d34cc4e0 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -819,7 +819,7 @@ namespace tools bool reset_history(); bool is_transfer_unlocked(const transfer_details& td) const; bool is_transfer_unlocked(const transfer_details& td, bool for_pos_mining, uint64_t& stake_lock_time) const; - void get_mining_history(wallet_public::mining_history& hist); + void get_mining_history(wallet_public::mining_history& hist, uint64_t timestamp_from = 0); void set_core_runtime_config(const currency::core_runtime_config& pc); currency::core_runtime_config& get_core_runtime_config(); bool backup_keys(const std::string& path); diff --git a/src/wallet/wallet_public_structs_defs.h b/src/wallet/wallet_public_structs_defs.h index 960516db..ce318bf5 100644 --- a/src/wallet/wallet_public_structs_defs.h +++ b/src/wallet/wallet_public_structs_defs.h @@ -318,6 +318,12 @@ namespace wallet_public END_KV_SERIALIZE_MAP() }; + struct COMMAND_RPC_GET_MINING_HISTORY + { + typedef currency::struct_with_one_t_type request; + typedef wallet_public::mining_history response; + }; + #define ORDER_FROM_BEGIN_TO_END "FROM_BEGIN_TO_END" #define ORDER_FROM_FROM_END_TO_BEGIN "FROM_END_TO_BEGIN" diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index 43d9625b..dc809096 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -741,6 +741,11 @@ namespace tools return true; } + bool wallet_rpc_server::on_get_mining_history(const wallet_public::COMMAND_RPC_GET_MINING_HISTORY::request& req, wallet_public::COMMAND_RPC_GET_MINING_HISTORY::response& res, epee::json_rpc::error& er, connection_context& cntx) + { + m_wallet.get_mining_history(res, req.v); + return true; + } //------------------------------------------------------------------------------------------------------------------------------ bool wallet_rpc_server::on_contracts_send_proposal(const wallet_public::COMMAND_CONTRACTS_SEND_PROPOSAL::request& req, wallet_public::COMMAND_CONTRACTS_SEND_PROPOSAL::response& res, epee::json_rpc::error& er, connection_context& cntx) { diff --git a/src/wallet/wallet_rpc_server.h b/src/wallet/wallet_rpc_server.h index b99420d4..8d1aa084 100644 --- a/src/wallet/wallet_rpc_server.h +++ b/src/wallet/wallet_rpc_server.h @@ -53,6 +53,7 @@ namespace tools MAP_JON_RPC_WE("search_for_transactions", on_search_for_transactions, wallet_public::COMMAND_RPC_SEARCH_FOR_TRANSACTIONS) MAP_JON_RPC_WE("get_restore_info", on_getwallet_restore_info, wallet_public::COMMAND_RPC_GET_WALLET_RESTORE_INFO) MAP_JON_RPC_WE("get_seed_phrase_info", on_get_seed_phrase_info, wallet_public::COMMAND_RPC_GET_SEED_PHRASE_INFO) + MAP_JON_RPC_WE("get_mining_history", on_get_mining_history, wallet_public::COMMAND_RPC_GET_MINING_HISTORY) //contracts API MAP_JON_RPC_WE("contracts_send_proposal", on_contracts_send_proposal, wallet_public::COMMAND_CONTRACTS_SEND_PROPOSAL) MAP_JON_RPC_WE("contracts_accept_proposal", on_contracts_accept_proposal, wallet_public::COMMAND_CONTRACTS_ACCEPT_PROPOSAL) @@ -91,6 +92,7 @@ namespace tools bool on_sign_transfer(const wallet_public::COMMAND_SIGN_TRANSFER::request& req, wallet_public::COMMAND_SIGN_TRANSFER::response& res, epee::json_rpc::error& er, connection_context& cntx); bool on_submit_transfer(const wallet_public::COMMAND_SUBMIT_TRANSFER::request& req, wallet_public::COMMAND_SUBMIT_TRANSFER::response& res, epee::json_rpc::error& er, connection_context& cntx); bool on_search_for_transactions(const wallet_public::COMMAND_RPC_SEARCH_FOR_TRANSACTIONS::request& req, wallet_public::COMMAND_RPC_SEARCH_FOR_TRANSACTIONS::response& res, epee::json_rpc::error& er, connection_context& cntx); + bool on_get_mining_history(const wallet_public::COMMAND_RPC_GET_MINING_HISTORY::request& req, wallet_public::COMMAND_RPC_GET_MINING_HISTORY::response& res, epee::json_rpc::error& er, connection_context& cntx); bool on_contracts_send_proposal(const wallet_public::COMMAND_CONTRACTS_SEND_PROPOSAL::request& req, wallet_public::COMMAND_CONTRACTS_SEND_PROPOSAL::response& res, epee::json_rpc::error& er, connection_context& cntx); bool on_contracts_accept_proposal(const wallet_public::COMMAND_CONTRACTS_ACCEPT_PROPOSAL::request& req, wallet_public::COMMAND_CONTRACTS_ACCEPT_PROPOSAL::response& res, epee::json_rpc::error& er, connection_context& cntx); From 60f6c76ad60bb4b02537bc4cf5c06a46193b7d25 Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Wed, 18 May 2022 16:34:19 +0200 Subject: [PATCH 02/10] fixes over signatures structure --- src/currency_core/currency_basic.h | 34 ++++++++++-- .../currency_basic_backward_comp.inl | 52 +++++++++++++++++-- .../currency_format_utils_transactions.cpp | 9 ++++ 3 files changed, 87 insertions(+), 8 deletions(-) diff --git a/src/currency_core/currency_basic.h b/src/currency_core/currency_basic.h index 8ff69bff..8c24ac27 100644 --- a/src/currency_core/currency_basic.h +++ b/src/currency_core/currency_basic.h @@ -541,8 +541,7 @@ namespace currency extra_alias_entry(const extra_alias_entry_old& old) : extra_alias_entry_base(old) , m_alias(old.m_alias) - { - } + {} std::string m_alias; @@ -656,6 +655,26 @@ namespace currency END_BOOST_SERIALIZATION() }; + //classic CryptoNote signature by Nicolas Van Saberhagen + struct NLSAG_sig + { + std::vector > s; + }; + + struct zarcanum_sig + { + //TODO: + }; + + struct void_sig + { + //TODO: + }; + + typedef boost::variant signature_v; + + + //include backward compatibility defintions #include "currency_basic_backward_comp.inl" @@ -668,7 +687,7 @@ namespace currency //extra std::vector extra; std::vector vin; - std::vector vout;//std::vector vout; + std::vector vout; BEGIN_SERIALIZE() VARINT_FIELD(version) @@ -697,14 +716,16 @@ namespace currency class transaction: public transaction_prefix { public: - std::vector > signatures; //count signatures always the same as inputs count + signature_v signature; std::vector attachment; transaction(); BEGIN_SERIALIZE_OBJECT() FIELDS(*static_cast(this)) - FIELD(signatures) + CHAIN_TRANSITION_VER(TRANSACTION_VERSION_INITAL, transaction_v1) + CHAIN_TRANSITION_VER(TRANSACTION_VERSION_PRE_HF4, transaction_v1) + FIELD(signature) FIELD(attachment) END_SERIALIZE() }; @@ -913,6 +934,9 @@ SET_VARIANT_TAGS(currency::tx_out_zarcanum, 38, "tx_out_zarcanum"); SET_VARIANT_TAGS(currency::zarcanum_tx_data_v1, 39, "zarcanum_tx_data_v1"); SET_VARIANT_TAGS(crypto::bpp_signature_serialized, 40, "bpp_signature_serialized"); SET_VARIANT_TAGS(crypto::bppe_signature_serialized, 41, "bppe_signature_serialized"); +SET_VARIANT_TAGS(currency::NLSAG_sig, 42, "NLSAG_sig"); +SET_VARIANT_TAGS(currency::zarcanum_sig, 43, "zarcanum_sig"); +SET_VARIANT_TAGS(currency::void_sig, 43, "void_sig"); diff --git a/src/currency_core/currency_basic_backward_comp.inl b/src/currency_core/currency_basic_backward_comp.inl index 4a8ff1fe..fbd47181 100644 --- a/src/currency_core/currency_basic_backward_comp.inl +++ b/src/currency_core/currency_basic_backward_comp.inl @@ -49,7 +49,16 @@ bool transition_convert(const transaction_prefix_current_t& from, transaction_pr to.version = from.version; to.extra = from.extra; to.vin = from.vin; - to.vout = from.vout; + for (const auto& v : from.vout) + { + if (v.type() == typeid(tx_out_bare)) + { + to.vout.push_back(boost::get(v)); + } + else { + throw std::runtime_error("Unexpected type in tx_out_v"); + } + } return true; } template @@ -58,8 +67,45 @@ bool transition_convert(const transaction_prefix_v1& from, transaction_prefix_cu to.version = from.version; to.extra = from.extra; to.vin = from.vin; - to.vout = from.vout; + for (const auto& v : from.vout) + { + to.vout.push_back(v); + } return true; } - \ No newline at end of file + +class transaction_v1: +{ +public: + std::vector > signatures; //count signatures always the same as inputs count + std::vector attachment; + + BEGIN_SERIALIZE_OBJECT() + FIELD(signatures) + FIELD(attachment) + END_SERIALIZE() +}; + +template +bool transition_convert(const transaction_current_t& from, transaction_v1& to) +{ + to.attachment = from.attachment; + if (from.signature.type() == typeid(NLSAG_sig)) + { + to.signatures = boost::get(from.signature).s; + } + else + { + throw std::runtime_error("Unexpected type in signature_v"); + } + return true; +} +template +bool transition_convert(const transaction_v1& from, transaction_current_t& to) +{ + to.attachment = from.attachment; + to.signature = NLSAG_sig(); + boost::get(to.signature).s = from.signatures; + return true; +} \ No newline at end of file diff --git a/src/currency_core/currency_format_utils_transactions.cpp b/src/currency_core/currency_format_utils_transactions.cpp index 264f604e..14e25e68 100644 --- a/src/currency_core/currency_format_utils_transactions.cpp +++ b/src/currency_core/currency_format_utils_transactions.cpp @@ -32,6 +32,15 @@ namespace currency return expiration_time <= expiration_ts_median + TX_EXPIRATION_MEDIAN_SHIFT; } //--------------------------------------------------------------- + + +#define VARIANT_SWITCH_BEGIN(v_type_obj) {decltype(v_type_obj)& local_reference_eokcmeokmeokcm = v_type_obj; if(false) {; +#define VARIANT_CASE(v_type) } else if(local_reference_eokcmeokmeokcm.type() == typeid(v_type)) { v_type& v_type_obj##_typed = boost::get(local_reference_eokcmeokmeokcm); +#define VARIANT_CASE_OTHER(v_type) } else { +#define VARIANT_SWITCH_END() } } + + + uint64_t get_burned_amount(const transaction& tx) { uint64_t res = 0; From c46f46e4e36743e35b688937114dab9b78e9cd1f Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Wed, 18 May 2022 16:35:26 +0200 Subject: [PATCH 03/10] updated UI to latest commit --- src/gui/qt-daemon/layout | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/qt-daemon/layout b/src/gui/qt-daemon/layout index b091d45a..32b34f8e 160000 --- a/src/gui/qt-daemon/layout +++ b/src/gui/qt-daemon/layout @@ -1 +1 @@ -Subproject commit b091d45ad697db2d35e94de41be3f175bad0f71d +Subproject commit 32b34f8ea235b91360d4bc5eb5eefde293680759 From 0833566d96244b86b934adc079ddd3bf99e8fa33 Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Wed, 18 May 2022 23:39:08 +0200 Subject: [PATCH 04/10] transition to multi-types vout(in progress) --- src/common/variant_helper.h | 41 ++ src/currency_core/blockchain_storage.cpp | 478 +++++++++++------- src/currency_core/blockchain_storage.h | 98 ++-- src/currency_core/currency_format_utils.cpp | 206 ++++---- .../currency_format_utils_transactions.cpp | 21 +- src/currency_core/tx_pool.cpp | 20 +- 6 files changed, 524 insertions(+), 340 deletions(-) create mode 100644 src/common/variant_helper.h diff --git a/src/common/variant_helper.h b/src/common/variant_helper.h new file mode 100644 index 00000000..ae4f8d02 --- /dev/null +++ b/src/common/variant_helper.h @@ -0,0 +1,41 @@ +// Copyright (c) 2014-2018 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 + +#define VARIANT_SWITCH_BEGIN(v_type_obj) {decltype(v_type_obj)& local_reference_eokcmeokmeokcm = v_type_obj; if(false) {; +#define VARIANT_CASE(v_type, typed_name) } else if(local_reference_eokcmeokmeokcm.type() == typeid(v_type)) { v_type& typed_name = boost::get(local_reference_eokcmeokmeokcm); +#define VARIANT_CASE_TV(v_type) VARIANT_CASE(v_type, tv) +#define VARIANT_CASE_OTHER() } else { +#define VARIANT_CASE_THROW_ON_OTHER() } else { ASSERT_MES_AND_THROW("Unknown type in switch statemet: " << local_reference_eokcmeokmeokcm.type().name()); + +#define VARIANT_SWITCH_END() } } + + +/* + +usage: + + + VARIANT_SWITCH_BEGIN(o); + VARIANT_CASE(tx_out_bare, o) + + VARIANT_CASE_TV(tx_out_zarcanum) + //@#@ + VARIANT_SWITCH_END(); + + + + + VARIANT_SWITCH_BEGIN(o); + VARIANT_CASE(tx_out_bare, o) + + VARIANT_CASE_TV(tx_out_zarcanum) + //@#@ + VARIANT_CASE_THROW_ON_OTHER(); + VARIANT_SWITCH_END(); + + +*/ + diff --git a/src/currency_core/blockchain_storage.cpp b/src/currency_core/blockchain_storage.cpp index 81c3a0e2..72d9df16 100644 --- a/src/currency_core/blockchain_storage.cpp +++ b/src/currency_core/blockchain_storage.cpp @@ -2478,42 +2478,50 @@ bool blockchain_storage::add_out_to_get_random_outs(COMMAND_RPC_GET_RANDOM_OUTPU << out_ptr->out_no << " more than transaction outputs = " << tx_ptr->tx.vout.size() << ", for tx id = " << out_ptr->tx_id); const transaction& tx = tx_ptr->tx; - if (tx.vout[out_ptr->out_no].target.type() == typeid(txout_htlc)) + VARIANT_SWITCH_BEGIN(tx.vout[out_ptr->out_no]); + VARIANT_CASE(tx_out_bare, o) { - //silently return false, it's ok - return false; + if (o.target.type() == typeid(txout_htlc)) + { + //silently return false, it's ok + return false; + } + CHECK_AND_ASSERT_MES(o.target.type() == typeid(txout_to_key), false, "unknown tx out type"); + const txout_to_key& otk = boost::get(o.target); + + CHECK_AND_ASSERT_MES(tx_ptr->m_spent_flags.size() == tx.vout.size(), false, "internal error"); + + //do not use outputs that obviously spent for mixins + if (tx_ptr->m_spent_flags[out_ptr->out_no]) + return false; + + // do not use burned coins + if (otk.key == null_pkey) + return false; + + //check if transaction is unlocked + if (!is_tx_spendtime_unlocked(get_tx_unlock_time(tx, out_ptr->out_no))) + return false; + + //use appropriate mix_attr out + uint8_t mix_attr = otk.mix_attr; + + if (mix_attr == CURRENCY_TO_KEY_OUT_FORCED_NO_MIX) + return false; //COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS call means that ring signature will have more than one entry. + else if (use_only_forced_to_mix && mix_attr == CURRENCY_TO_KEY_OUT_RELAXED) + return false; //relaxed not allowed + else if (mix_attr != CURRENCY_TO_KEY_OUT_RELAXED && mix_attr > mix_count) + return false;//mix_attr set to specific minimum, and mix_count is less then desired count + + + COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::out_entry& oen = *result_outs.outs.insert(result_outs.outs.end(), COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::out_entry()); + oen.global_amount_index = i; + oen.out_key = otk.key; } - CHECK_AND_ASSERT_MES(tx.vout[out_ptr->out_no].target.type() == typeid(txout_to_key), false, "unknown tx out type"); - const txout_to_key& otk = boost::get(tx.vout[out_ptr->out_no].target); + VARIANT_CASE_TV(tx_out_zarcanum) + //@#@ + VARIANT_SWITCH_END(); - CHECK_AND_ASSERT_MES(tx_ptr->m_spent_flags.size() == tx.vout.size(), false, "internal error"); - - //do not use outputs that obviously spent for mixins - if (tx_ptr->m_spent_flags[out_ptr->out_no]) - return false; - - // do not use burned coins - if (otk.key == null_pkey) - return false; - - //check if transaction is unlocked - if (!is_tx_spendtime_unlocked(get_tx_unlock_time(tx, out_ptr->out_no))) - return false; - - //use appropriate mix_attr out - uint8_t mix_attr = otk.mix_attr; - - if(mix_attr == CURRENCY_TO_KEY_OUT_FORCED_NO_MIX) - return false; //COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS call means that ring signature will have more than one entry. - else if(use_only_forced_to_mix && mix_attr == CURRENCY_TO_KEY_OUT_RELAXED) - return false; //relaxed not allowed - else if(mix_attr != CURRENCY_TO_KEY_OUT_RELAXED && mix_attr > mix_count) - return false;//mix_attr set to specific minimum, and mix_count is less then desired count - - - COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::out_entry& oen = *result_outs.outs.insert(result_outs.outs.end(), COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::out_entry()); - oen.global_amount_index = i; - oen.out_key = otk.key; return true; } //------------------------------------------------------------------ @@ -3014,10 +3022,15 @@ void blockchain_storage::print_blockchain_outs_stats() const if (!spent) ++stat.unspent; - if (!spent && p_tx->tx.vout[output_entry.out_no].target.type() == typeid(txout_to_key)) + if (!spent)// && p_tx->tx.vout[output_entry.out_no].target.type() == typeid(txout_to_key)) { - if (boost::get(p_tx->tx.vout[output_entry.out_no].target).mix_attr != CURRENCY_TO_KEY_OUT_FORCED_NO_MIX) - ++stat.mixable; + VARIANT_SWITCH_BEGIN(p_tx->tx.vout[output_entry.out_no]); + VARIANT_CASE(tx_out_bare, o) + if (boost::get(o.target).mix_attr != CURRENCY_TO_KEY_OUT_FORCED_NO_MIX) + ++stat.mixable; + VARIANT_CASE_TV(tx_out_zarcanum) + //@#@ + VARIANT_SWITCH_END(); } return true; }; @@ -3329,28 +3342,33 @@ bool blockchain_storage::push_transaction_to_global_outs_index(const transaction { CRITICAL_REGION_LOCAL(m_read_lock); size_t i = 0; - BOOST_FOREACH(const auto& ot, tx.vout) + BOOST_FOREACH(const auto& otv, tx.vout) { - if (ot.target.type() == typeid(txout_to_key) || ot.target.type() == typeid(txout_htlc)) - { - m_db_outputs.push_back_item(ot.amount, global_output_entry::construct(tx_id, i)); - global_indexes.push_back(m_db_outputs.get_item_size(ot.amount) - 1); - if (ot.target.type() == typeid(txout_htlc) && !is_after_hardfork_3_zone()) + VARIANT_SWITCH_BEGIN(otv); + VARIANT_CASE(tx_out_bare, ot) + if (ot.target.type() == typeid(txout_to_key) || ot.target.type() == typeid(txout_htlc)) { - LOG_ERROR("Error: Transaction with txout_htlc before is_after_hardfork_3_zone(before height " << m_core_runtime_config.hard_forks.hard_fork_03_starts_after_height <<")"); - return false; + m_db_outputs.push_back_item(ot.amount, global_output_entry::construct(tx_id, i)); + global_indexes.push_back(m_db_outputs.get_item_size(ot.amount) - 1); + if (ot.target.type() == typeid(txout_htlc) && !is_after_hardfork_3_zone()) + { + LOG_ERROR("Error: Transaction with txout_htlc before is_after_hardfork_3_zone(before height " << m_core_runtime_config.hard_forks.hard_fork_03_starts_after_height << ")"); + return false; + } } - } - else if (ot.target.type() == typeid(txout_multisig)) - { - - crypto::hash multisig_out_id = get_multisig_out_id(tx, i); - CHECK_AND_ASSERT_MES(multisig_out_id != null_hash, false, "internal error during handling get_multisig_out_id() with tx id " << tx_id); - CHECK_AND_ASSERT_MES(!m_db_multisig_outs.find(multisig_out_id), false, "Internal error: already have multisig_out_id " << multisig_out_id << "in multisig outs index"); - m_db_multisig_outs.set(multisig_out_id, ms_output_entry::construct(tx_id, i)); - global_indexes.push_back(0); // just stub to make other code easier - } + else if (ot.target.type() == typeid(txout_multisig)) + { + crypto::hash multisig_out_id = get_multisig_out_id(tx, i); + CHECK_AND_ASSERT_MES(multisig_out_id != null_hash, false, "internal error during handling get_multisig_out_id() with tx id " << tx_id); + CHECK_AND_ASSERT_MES(!m_db_multisig_outs.find(multisig_out_id), false, "Internal error: already have multisig_out_id " << multisig_out_id << "in multisig outs index"); + m_db_multisig_outs.set(multisig_out_id, ms_output_entry::construct(tx_id, i)); + global_indexes.push_back(0); // just stub to make other code easier + } + VARIANT_CASE_TV(tx_out_zarcanum) + //@#@ + VARIANT_CASE_THROW_ON_OTHER(); + VARIANT_SWITCH_END(); ++i; } return true; @@ -3378,13 +3396,20 @@ bool blockchain_storage::get_outs(uint64_t amount, std::list CHECK_AND_ASSERT_MES(tx_ptr, false, "transactions outs global index consistency broken: can't find tx " << out_entry_ptr->tx_id << " in DB, for amount: " << amount << ", gindex: " << i); CHECK_AND_ASSERT_MES(tx_ptr->tx.vout.size() > out_entry_ptr->out_no, false, "transactions outs global index consistency broken: index in tx_outx == " << out_entry_ptr->out_no << " is greather than tx.vout size == " << tx_ptr->tx.vout.size() << ", for amount: " << amount << ", gindex: " << i); //CHECK_AND_ASSERT_MES(tx_ptr->tx.vout[out_entry_ptr->out_no].target.type() == typeid(txout_to_key), false, "transactions outs global index consistency broken: out #" << out_entry_ptr->out_no << " in tx " << out_entry_ptr->tx_id << " has wrong type, for amount: " << amount << ", gindex: " << i); - if (tx_ptr->tx.vout[out_entry_ptr->out_no].target.type() == typeid(txout_to_key)) - { - pkeys.push_back(boost::get(tx_ptr->tx.vout[out_entry_ptr->out_no].target).key); - }else if(tx_ptr->tx.vout[out_entry_ptr->out_no].target.type() == typeid(txout_htlc)) - { - pkeys.push_back(boost::get(tx_ptr->tx.vout[out_entry_ptr->out_no].target).pkey_redeem); - } + VARIANT_SWITCH_BEGIN(tx_ptr->tx.vout[out_entry_ptr->out_no]); + VARIANT_CASE(tx_out_bare, o) + if (o.target.type() == typeid(txout_to_key)) + { + pkeys.push_back(boost::get(o.target).key); + } + else if (o.target.type() == typeid(txout_htlc)) + { + pkeys.push_back(boost::get(o.target).pkey_redeem); + } + VARIANT_CASE_TV(tx_out_zarcanum) + //@#@ + VARIANT_CASE_THROW_ON_OTHER(); + VARIANT_SWITCH_END(); } return true; @@ -3394,26 +3419,32 @@ bool blockchain_storage::pop_transaction_from_global_index(const transaction& tx { CRITICAL_REGION_LOCAL(m_read_lock); size_t i = tx.vout.size()-1; - BOOST_REVERSE_FOREACH(const auto& ot, tx.vout) + BOOST_REVERSE_FOREACH(const auto& otv, tx.vout) { - if (ot.target.type() == typeid(txout_to_key) || ot.target.type() == typeid(txout_htlc)) - { - uint64_t sz= m_db_outputs.get_item_size(ot.amount); - CHECK_AND_ASSERT_MES(sz, false, "transactions outs global index: empty index for amount: " << ot.amount); - auto back_item = m_db_outputs.get_subitem(ot.amount, sz - 1); - CHECK_AND_ASSERT_MES(back_item->tx_id == tx_id, false, "transactions outs global index consistency broken: tx id missmatch"); - CHECK_AND_ASSERT_MES(back_item->out_no == i, false, "transactions outs global index consistency broken: in transaction index missmatch"); - m_db_outputs.pop_back_item(ot.amount); - //if (!it->second.size()) - // m_db_outputs.erase(it); - } - else if (ot.target.type() == typeid(txout_multisig)) - { - crypto::hash multisig_out_id = get_multisig_out_id(tx, i); - CHECK_AND_ASSERT_MES(multisig_out_id != null_hash, false, "internal error during handling get_multisig_out_id() with tx id " << tx_id); - bool res = m_db_multisig_outs.erase_validate(multisig_out_id); - CHECK_AND_ASSERT_MES(res, false, "Internal error: multisig out not found, multisig_out_id " << multisig_out_id << "in multisig outs index"); - } + VARIANT_SWITCH_BEGIN(otv); + VARIANT_CASE(tx_out_bare, ot) + if (ot.target.type() == typeid(txout_to_key) || ot.target.type() == typeid(txout_htlc)) + { + uint64_t sz = m_db_outputs.get_item_size(ot.amount); + CHECK_AND_ASSERT_MES(sz, false, "transactions outs global index: empty index for amount: " << ot.amount); + auto back_item = m_db_outputs.get_subitem(ot.amount, sz - 1); + CHECK_AND_ASSERT_MES(back_item->tx_id == tx_id, false, "transactions outs global index consistency broken: tx id missmatch"); + CHECK_AND_ASSERT_MES(back_item->out_no == i, false, "transactions outs global index consistency broken: in transaction index missmatch"); + m_db_outputs.pop_back_item(ot.amount); + //if (!it->second.size()) + // m_db_outputs.erase(it); + } + else if (ot.target.type() == typeid(txout_multisig)) + { + crypto::hash multisig_out_id = get_multisig_out_id(tx, i); + CHECK_AND_ASSERT_MES(multisig_out_id != null_hash, false, "internal error during handling get_multisig_out_id() with tx id " << tx_id); + bool res = m_db_multisig_outs.erase_validate(multisig_out_id); + CHECK_AND_ASSERT_MES(res, false, "Internal error: multisig out not found, multisig_out_id " << multisig_out_id << "in multisig outs index"); + } + VARIANT_CASE_TV(tx_out_zarcanum) + //@#@ + VARIANT_CASE_THROW_ON_OTHER(); + VARIANT_SWITCH_END(); --i; } return true; @@ -4147,12 +4178,15 @@ bool blockchain_storage::print_tx_outputs_lookup(const crypto::hash& tx_id)const CHECK_AND_ASSERT_MES(tx_ptr->tx.vout.size() == tx_ptr->m_global_output_indexes.size(), false, "Internal error: output size missmatch"); for (uint64_t i = 0; i!= tx_ptr->tx.vout.size();i++) { - strm_tx << "[" << i << "]: " << print_money(tx_ptr->tx.vout[i].amount) << ENDL; - if (tx_ptr->tx.vout[i].target.type() != typeid(currency::txout_to_key)) - continue; - - usage_stat[tx_ptr->tx.vout[i].amount][tx_ptr->m_global_output_indexes[i]]; - + VARIANT_SWITCH_BEGIN(tx_ptr->tx.vout[i]); + VARIANT_CASE(tx_out_bare, o) + strm_tx << "[" << i << "]: " << print_money(o.amount) << ENDL; + if (o.target.type() != typeid(currency::txout_to_key)) + continue; + usage_stat[o.amount][tx_ptr->m_global_output_indexes[i]]; + VARIANT_CASE_TV(tx_out_zarcanum) + //@#@ + VARIANT_SWITCH_END(); } LOG_PRINT_L0("Lookup in all transactions...."); @@ -4521,7 +4555,9 @@ bool blockchain_storage::check_ms_input(const transaction& tx, size_t in_index, LOC_CHK(is_tx_spendtime_unlocked(unlock_time), "Source transaction is LOCKED! unlock_time: " << unlock_time << ", now is " << m_core_runtime_config.get_core_time() << ", blockchain size is " << get_current_blockchain_size()); LOC_CHK(source_tx.vout.size() > out_n, "internal error: out_n==" << out_n << " is out-of-bounds of source_tx.vout, size=" << source_tx.vout.size()); - const tx_out_bare& source_tx_out = source_tx.vout[out_n]; + LOC_CHK(source_tx.vout[out_n].type() !== typeid(tx_out_bare), "internal error: out_n==" << out_n << " has unexpected type: " << source_tx.vout[out_n].type().name()); + + const tx_out_bare& source_tx_out = boost::get(source_tx.vout[out_n]); const txout_multisig& source_ms_out_target = boost::get(source_tx_out.target); LOC_CHK(txin.sigs_count == source_ms_out_target.minimum_sigs, @@ -4614,7 +4650,8 @@ bool blockchain_storage::check_tx_input(const transaction& tx, size_t in_index, auto source_tx_ptr = m_db_transactions.find(source_tx_id); LOC_CHK(source_tx_ptr, "Can't find source transaction"); LOC_CHK(source_tx_ptr->tx.vout.size() > n, "ms output index is incorrect, source tx's vout size is " << source_tx_ptr->tx.vout.size()); - LOC_CHK(source_tx_ptr->tx.vout[n].target.type() == typeid(txout_multisig), "ms output has wrong type, txout_multisig expected"); + LOC_CHK(source_tx_ptr->tx.vout[n].type() != = typeid(tx_out_bare), "internal error: out_n==" << n << " has unexpected type: " << source_tx_ptr->tx.vout[n].type().name()); + LOC_CHK(boost::get(source_tx_ptr->tx.vout[n]).target.type() == typeid(txout_multisig), "ms output has wrong type, txout_multisig expected"); LOC_CHK(source_tx_ptr->m_spent_flags.size() > n, "Internal error, m_spent_flags size (" << source_tx_ptr->m_spent_flags.size() << ") less then expected, n: " << n); LOC_CHK(source_tx_ptr->m_spent_flags[n] == false, "Internal error, ms output is already spent"); // should never happen as multisig_ptr->spent_height is checked above @@ -4958,6 +4995,7 @@ bool blockchain_storage::validate_tx_for_hardfork_specific_terms(const transacti bool var_is_after_hardfork_1_zone = is_after_hardfork_1_zone(block_height); bool var_is_after_hardfork_2_zone = is_after_hardfork_2_zone(block_height); bool var_is_after_hardfork_3_zone = is_after_hardfork_3_zone(block_height); + bool var_is_after_hardfork_4_zone = is_after_hardfork_4_zone(block_height); //inputs for (const auto in : tx.vin) @@ -4971,11 +5009,17 @@ bool blockchain_storage::validate_tx_for_hardfork_specific_terms(const transacti //outputs for (const auto out : tx.vout) { - if (out.target.type() == typeid(txout_htlc)) - { - if (!var_is_after_hardfork_3_zone) + VARIANT_SWITCH_BEGIN(out); + VARIANT_CASE(tx_out_bare, o) + if (o.target.type() == typeid(txout_htlc)) + { + if (!var_is_after_hardfork_3_zone) + return false; + } + VARIANT_CASE_TV(tx_out_zarcanum) + if (!var_is_after_hardfork_4_zone) return false; - } + VARIANT_SWITCH_END(); } //extra @@ -5025,7 +5069,14 @@ bool blockchain_storage::validate_pos_coinbase_outs_unlock_time(const transactio uint64_t unlock_value = ut2.unlock_time_array[i]; CHECK_AND_ASSERT_MES(should_unlock_value_be_treated_as_block_height(unlock_value), false, "output #" << i << " is locked by time, not buy height, which is not allowed for PoS coinbase"); if (unlock_value >= source_max_unlock_time) - amount_of_coins_in_unlock_in_range += miner_tx.vout[i].amount; + { + VARIANT_SWITCH_BEGIN(miner_tx.vout[i]); + VARIANT_CASE(tx_out_bare, o) + amount_of_coins_in_unlock_in_range += o.amount; + VARIANT_CASE_TV(tx_out_zarcanum) + //@#@ + VARIANT_SWITCH_END(); + } } if (amount_of_coins_in_unlock_in_range >= staked_amount) @@ -5780,6 +5831,18 @@ bool blockchain_storage::is_after_hardfork_3_zone(uint64_t height)const return false; } //------------------------------------------------------------------ +bool blockchain_storage::is_after_hardfork_4_zone()const +{ + return is_after_hardfork_4_zone(m_db_blocks.size()); +} +//------------------------------------------------------------------ +bool blockchain_storage::is_after_hardfork_4_zone(uint64_t height)const +{ + if (height > m_core_runtime_config.hard_forks.hard_fork_04_starts_after_height) + return true; + return false; +} +//------------------------------------------------------------------ bool blockchain_storage::prevalidate_block(const block& bl) { //before hard_fork1 @@ -6439,97 +6502,110 @@ bool blockchain_storage::validate_alt_block_input(const transaction& input_tx, uint64_t height_of_source_block = it->second.second; CHECK_AND_ASSERT_MES(height_of_current_alt_block > height_of_source_block, false, "Intenral error: height_of_current_alt_block > height_of_source_block failed"); - /* - here we do validation against compatibility of input and output type - - TxOutput | TxInput | Allowed - ---------------------------- - HTLC | HTLC | ONLY IF HTLC NOT EXPIRED - HTLC | TO_KEY | ONLY IF HTLC IS EXPIRED - TO_KEY | HTLC | NOT - TO_KEY | TO_KEY | YES - */ - //source tx found in altchain CHECK_AND_ASSERT_MES(it->second.first.vout.size() > out_n, false, "Internal error: out_n(" << out_n << ") >= it->second.vout.size()(" << it->second.first.vout.size() << ")"); - txout_target_v out_target_v = it->second.first.vout[out_n].target; - bool r = is_output_allowed_for_input(out_target_v, input_v, height_of_current_alt_block - height_of_source_block); - CHECK_AND_ASSERT_MES(r, false, "Input and output incompatible type"); + VARIANT_SWITCH_BEGIN(it->second.first.vout[out_n]); + VARIANT_CASE(tx_out_bare, o) + { + /* + here we do validation against compatibility of input and output type + TxOutput | TxInput | Allowed + ---------------------------- + HTLC | HTLC | ONLY IF HTLC NOT EXPIRED + HTLC | TO_KEY | ONLY IF HTLC IS EXPIRED + TO_KEY | HTLC | NOT + TO_KEY | TO_KEY | YES + */ + txout_target_v out_target_v = o.target; - if (out_target_v.type() == typeid(txout_htlc)) - { - //source is hltc out - const txout_htlc& htlc = boost::get(out_target_v); - bool htlc_expired = htlc.expiration > (height_of_current_alt_block - height_of_source_block) ? false : true; - pk = htlc_expired ? htlc.pkey_refund : htlc.pkey_redeem; - pub_key_pointers.push_back(&pk); - continue; - } - else if (out_target_v.type() == typeid(txout_to_key)) - { - //source is to_key out - pk = boost::get(out_target_v).key; - pub_key_pointers.push_back(&pk); - continue; - } - else - { - ASSERT_MES_AND_THROW("Unexpected out type for tx_in in altblock: " << out_target_v.type().name()); + bool r = is_output_allowed_for_input(out_target_v, input_v, height_of_current_alt_block - height_of_source_block); + CHECK_AND_ASSERT_MES(r, false, "Input and output incompatible type"); + if (out_target_v.type() == typeid(txout_htlc)) + { + //source is hltc out + const txout_htlc& htlc = boost::get(out_target_v); + bool htlc_expired = htlc.expiration > (height_of_current_alt_block - height_of_source_block) ? false : true; + pk = htlc_expired ? htlc.pkey_refund : htlc.pkey_redeem; + pub_key_pointers.push_back(&pk); + continue; + } + else if (out_target_v.type() == typeid(txout_to_key)) + { + //source is to_key out + pk = boost::get(out_target_v).key; + pub_key_pointers.push_back(&pk); + continue; + } + else + { + ASSERT_MES_AND_THROW("Unexpected out type for tx_in in altblock: " << out_target_v.type().name()); + } } + VARIANT_CASE_TV(tx_out_zarcanum) + //@#@ + VARIANT_SWITCH_END(); } } auto p = m_db_transactions.get(tx_id); CHECK_AND_ASSERT_MES(p != nullptr && out_n < p->tx.vout.size(), false, "can't find output #" << out_n << " for tx " << tx_id << " referred by offset #" << pk_n); - auto &t = p->tx.vout[out_n].target; - - /* - here we do validation against compatibility of input and output type - TxOutput | TxInput | Allowed - ---------------------------- - HTLC | HTLC | ONLY IF HTLC NOT EXPIRED - HTLC | TO_KEY | ONLY IF HTLC IS EXPIRED - TO_KEY | HTLC | NOT - TO_KEY | TO_KEY | YES - */ - uint64_t height_of_source_block = p->m_keeper_block_height; - CHECK_AND_ASSERT_MES(height_of_current_alt_block > height_of_source_block, false, "Intenral error: height_of_current_alt_block > height_of_source_block failed"); - bool r = is_output_allowed_for_input(t, input_v, height_of_current_alt_block - height_of_source_block); - CHECK_AND_ASSERT_MES(r, false, "Input and output incompatible type"); - - if (t.type() == typeid(txout_to_key)) + VARIANT_SWITCH_BEGIN(p->tx.vout[out_n]); + VARIANT_CASE(tx_out_bare, o) { - const txout_to_key& out_tk = boost::get(t); - pk = out_tk.key; + auto &t = o.target; - bool mixattr_ok = is_mixattr_applicable_for_fake_outs_counter(out_tk.mix_attr, abs_key_offsets.size() - 1); - CHECK_AND_ASSERT_MES(mixattr_ok, false, "input offset #" << pk_n << " violates mixin restrictions: mix_attr = " << static_cast(out_tk.mix_attr) << ", input's key_offsets.size = " << abs_key_offsets.size()); + /* + here we do validation against compatibility of input and output type + TxOutput | TxInput | Allowed + ---------------------------- + HTLC | HTLC | ONLY IF HTLC NOT EXPIRED + HTLC | TO_KEY | ONLY IF HTLC IS EXPIRED + TO_KEY | HTLC | NOT + TO_KEY | TO_KEY | YES + */ + uint64_t height_of_source_block = p->m_keeper_block_height; + CHECK_AND_ASSERT_MES(height_of_current_alt_block > height_of_source_block, false, "Intenral error: height_of_current_alt_block > height_of_source_block failed"); + bool r = is_output_allowed_for_input(t, input_v, height_of_current_alt_block - height_of_source_block); + CHECK_AND_ASSERT_MES(r, false, "Input and output incompatible type"); + + if (t.type() == typeid(txout_to_key)) + { + const txout_to_key& out_tk = boost::get(t); + pk = out_tk.key; + + bool mixattr_ok = is_mixattr_applicable_for_fake_outs_counter(out_tk.mix_attr, abs_key_offsets.size() - 1); + CHECK_AND_ASSERT_MES(mixattr_ok, false, "input offset #" << pk_n << " violates mixin restrictions: mix_attr = " << static_cast(out_tk.mix_attr) << ", input's key_offsets.size = " << abs_key_offsets.size()); + + } + else if (t.type() == typeid(txout_htlc)) + { + const txout_htlc& htlc = boost::get(t); + bool htlc_expired = htlc.expiration > (height_of_current_alt_block - height_of_source_block) ? false : true; + pk = htlc_expired ? htlc.pkey_refund : htlc.pkey_redeem; + } + + // case b4 (make sure source tx in the main chain is preceding split point, otherwise this referece is invalid) + CHECK_AND_ASSERT_MES(p->m_keeper_block_height < split_height, false, "input offset #" << pk_n << " refers to main chain tx " << tx_id << " at height " << p->m_keeper_block_height << " while split height is " << split_height); + + if (p_max_related_block_height != nullptr && *p_max_related_block_height < p->m_keeper_block_height) + *p_max_related_block_height = p->m_keeper_block_height; + + // TODO: consider checking p->tx for unlock time validity as it's checked in get_output_keys_for_input_with_checks() + // make sure it was actually found + + // let's disable this check due to missing equal check in main chain validation code + //TODO: implement more strict validation with next hard fork + //CHECK_AND_ASSERT_MES(pk != null_pkey, false, "Can't determine output public key for offset " << pk_n << " in related tx: " << tx_id << ", out_n = " << out_n); + pub_key_pointers.push_back(&pk); } - else if (t.type() == typeid(txout_htlc)) - { - const txout_htlc& htlc = boost::get(t); - bool htlc_expired = htlc.expiration > (height_of_current_alt_block - height_of_source_block) ? false : true; - pk = htlc_expired ? htlc.pkey_refund : htlc.pkey_redeem; - } - - // case b4 (make sure source tx in the main chain is preceding split point, otherwise this referece is invalid) - CHECK_AND_ASSERT_MES(p->m_keeper_block_height < split_height, false, "input offset #" << pk_n << " refers to main chain tx " << tx_id << " at height " << p->m_keeper_block_height << " while split height is " << split_height); - - if (p_max_related_block_height != nullptr && *p_max_related_block_height < p->m_keeper_block_height) - *p_max_related_block_height = p->m_keeper_block_height; - - // TODO: consider checking p->tx for unlock time validity as it's checked in get_output_keys_for_input_with_checks() - // make sure it was actually found - - // let's disable this check due to missing equal check in main chain validation code - //TODO: implement more strict validation with next hard fork - //CHECK_AND_ASSERT_MES(pk != null_pkey, false, "Can't determine output public key for offset " << pk_n << " in related tx: " << tx_id << ", out_n = " << out_n); - pub_key_pointers.push_back(&pk); + VARIANT_CASE_TV(tx_out_zarcanum) + //@#@ + VARIANT_SWITCH_END(); } // do input checks (attachment_info, ring signature and extra signature, etc.) @@ -6689,17 +6765,22 @@ bool blockchain_storage::validate_alt_block_ms_input(const transaction& input_tx for (size_t out_n = 0; out_n < tx.vout.size(); ++out_n) { - const tx_out_bare& out = tx.vout[out_n]; - if (out.target.type() == typeid(txout_multisig)) - { - const crypto::hash& ms_out_id = get_multisig_out_id(tx, out_n); - if (ms_out_id == input.multisig_out_id) + VARIANT_SWITCH_BEGIN(tx.vout[out_n]); + VARIANT_CASE(tx_out_bare, o) + const tx_out_bare& out = o; + if (out.target.type() == typeid(txout_multisig)) { - // cases g3, g4, g5 - output_found = true; - return check_ms_input(input_tx, input_index, input, input_tx_hash, input_sigs, tx, out_n); + const crypto::hash& ms_out_id = get_multisig_out_id(tx, out_n); + if (ms_out_id == input.multisig_out_id) + { + // cases g3, g4, g5 + output_found = true; + return check_ms_input(input_tx, input_index, input, input_tx_hash, input_sigs, tx, out_n); + } } - } + VARIANT_CASE_TV(tx_out_zarcanum) + //@#@ + VARIANT_SWITCH_END(); } return true; }; @@ -6747,29 +6828,34 @@ bool blockchain_storage::get_transaction_from_pool_or_db(const crypto::hash& tx_ bool blockchain_storage::update_alt_out_indexes_for_tx_in_block(const transaction& tx, alt_block_extended_info& abei) const { //add tx outputs to gindex_lookup_table - for (auto o : tx.vout) + for (auto ov : tx.vout) { - if (o.target.type() == typeid(txout_to_key) || o.target.type() == typeid(txout_htlc)) - { - //LOG_PRINT_MAGENTA("ALT_OUT KEY ON H[" << abei.height << "] AMOUNT: " << o.amount, LOG_LEVEL_0); - // first, look at local gindexes tables - if (abei.gindex_lookup_table.find(o.amount) == abei.gindex_lookup_table.end()) + VARIANT_SWITCH_BEGIN(ov); + VARIANT_CASE(tx_out_bare, o) + if (o.target.type() == typeid(txout_to_key) || o.target.type() == typeid(txout_htlc)) { - // amount was not found in altchain gindexes container, start indexing from current main chain gindex - abei.gindex_lookup_table[o.amount] = m_db_outputs.get_item_size(o.amount); - //LOG_PRINT_MAGENTA("FIRST TOUCH: size=" << abei.gindex_lookup_table[o.amount], LOG_LEVEL_0); + //LOG_PRINT_MAGENTA("ALT_OUT KEY ON H[" << abei.height << "] AMOUNT: " << o.amount, LOG_LEVEL_0); + // first, look at local gindexes tables + if (abei.gindex_lookup_table.find(o.amount) == abei.gindex_lookup_table.end()) + { + // amount was not found in altchain gindexes container, start indexing from current main chain gindex + abei.gindex_lookup_table[o.amount] = m_db_outputs.get_item_size(o.amount); + //LOG_PRINT_MAGENTA("FIRST TOUCH: size=" << abei.gindex_lookup_table[o.amount], LOG_LEVEL_0); + } + if (o.target.type() == typeid(txout_to_key)) + { + abei.outputs_pub_keys[o.amount].push_back(boost::get(o.target).key); + } + else + { + abei.outputs_pub_keys[o.amount].push_back(boost::get(o.target)); + } + + //TODO: At the moment we ignore check of mix_attr again mixing to simplify alt chain check, but in future consider it for stronger validation } - if (o.target.type() == typeid(txout_to_key)) - { - abei.outputs_pub_keys[o.amount].push_back(boost::get(o.target).key); - } - else - { - abei.outputs_pub_keys[o.amount].push_back(boost::get(o.target)); - } - - //TODO: At the moment we ignore check of mix_attr again mixing to simplify alt chain check, but in future consider it for stronger validation - } + VARIANT_CASE_TV(tx_out_zarcanum) + //@#@ + VARIANT_SWITCH_END(); } return true; } diff --git a/src/currency_core/blockchain_storage.h b/src/currency_core/blockchain_storage.h index 67a649a0..2a182323 100644 --- a/src/currency_core/blockchain_storage.h +++ b/src/currency_core/blockchain_storage.h @@ -667,8 +667,8 @@ namespace currency bool is_after_hardfork_2_zone(uint64_t height)const; bool is_after_hardfork_3_zone()const; bool is_after_hardfork_3_zone(uint64_t height)const; -// bool is_after_hardfork_4_zone()const; -// bool is_after_hardfork_4_zone(uint64_t height)const; + bool is_after_hardfork_4_zone()const; + bool is_after_hardfork_4_zone(uint64_t height)const; @@ -776,55 +776,65 @@ namespace currency TO_KEY | TO_KEY | YES */ - bool r = is_output_allowed_for_input(tx_ptr->tx.vout[n].target, verified_input, get_current_blockchain_size() - tx_ptr->m_keeper_block_height); - CHECK_AND_ASSERT_MES(r, false, "Input and output incompatible type"); - - if (tx_ptr->tx.vout[n].target.type() == typeid(txout_to_key)) + VARIANT_SWITCH_BEGIN(tx_ptr->tx.vout[n]); + VARIANT_CASE(tx_out_bare, o) { - CHECKED_GET_SPECIFIC_VARIANT(tx_ptr->tx.vout[n].target, const txout_to_key, outtk, false); - //fix for burned money - patch_out_if_needed(const_cast(outtk), tx_id, n); + bool r = is_output_allowed_for_input(o.target, verified_input, get_current_blockchain_size() - tx_ptr->m_keeper_block_height); + CHECK_AND_ASSERT_MES(r, false, "Input and output incompatible type"); - bool mixattr_ok = is_mixattr_applicable_for_fake_outs_counter(outtk.mix_attr, key_offsets.size() - 1); - CHECK_AND_ASSERT_MES(mixattr_ok, false, "tx output #" << output_index << " violates mixin restrictions: mix_attr = " << static_cast(outtk.mix_attr) << ", key_offsets.size = " << key_offsets.size()); - } - else if (tx_ptr->tx.vout[n].target.type() == typeid(txout_htlc)) - { - //check for spend flags - CHECK_AND_ASSERT_MES(tx_ptr->m_spent_flags.size() > n, false, - "Internal error: tx_ptr->m_spent_flags.size(){" << tx_ptr->m_spent_flags.size() << "} > n{" << n << "}"); - CHECK_AND_ASSERT_MES(tx_ptr->m_spent_flags[n] == false, false, "HTLC out already spent, double spent attempt detected"); - - const txout_htlc& htlc_out = boost::get(tx_ptr->tx.vout[n].target); - if (htlc_out.expiration > get_current_blockchain_size() - tx_ptr->m_keeper_block_height) + if (o.target.type() == typeid(txout_to_key)) { - //HTLC IS NOT expired, can be used ONLY by pkey_before_expiration and ONLY by HTLC input - scan_context.htlc_is_expired = false; - } - else - { - //HTLC IS expired, can be used ONLY by pkey_after_expiration and ONLY by to_key input - scan_context.htlc_is_expired = true; - } - }else - { - LOG_ERROR("[scan_outputkeys_for_indexes]: Wrong output type in : " << tx_ptr->tx.vout[n].target.type().name()); - return false; - } + CHECKED_GET_SPECIFIC_VARIANT(o.target, const txout_to_key, outtk, false); + //fix for burned money + patch_out_if_needed(const_cast(outtk), tx_id, n); - - TIME_MEASURE_START_PD(tx_check_inputs_loop_scan_outputkeys_loop_handle_output); - if (!vis.handle_output(tx_ptr->tx, validated_tx, tx_ptr->tx.vout[n], n)) - { - LOG_PRINT_L0("Failed to handle_output for output id = " << tx_id << ", no " << n); - return false; + bool mixattr_ok = is_mixattr_applicable_for_fake_outs_counter(outtk.mix_attr, key_offsets.size() - 1); + CHECK_AND_ASSERT_MES(mixattr_ok, false, "tx output #" << output_index << " violates mixin restrictions: mix_attr = " << static_cast(outtk.mix_attr) << ", key_offsets.size = " << key_offsets.size()); + } + else if (o.target.type() == typeid(txout_htlc)) + { + //check for spend flags + CHECK_AND_ASSERT_MES(tx_ptr->m_spent_flags.size() > n, false, + "Internal error: tx_ptr->m_spent_flags.size(){" << tx_ptr->m_spent_flags.size() << "} > n{" << n << "}"); + CHECK_AND_ASSERT_MES(tx_ptr->m_spent_flags[n] == false, false, "HTLC out already spent, double spent attempt detected"); + + const txout_htlc& htlc_out = boost::get(o.target); + if (htlc_out.expiration > get_current_blockchain_size() - tx_ptr->m_keeper_block_height) + { + //HTLC IS NOT expired, can be used ONLY by pkey_before_expiration and ONLY by HTLC input + scan_context.htlc_is_expired = false; + } + else + { + //HTLC IS expired, can be used ONLY by pkey_after_expiration and ONLY by to_key input + scan_context.htlc_is_expired = true; + } + } + else + { + LOG_ERROR("[scan_outputkeys_for_indexes]: Wrong output type in : " << o.target.type().name()); + return false; + } + + + TIME_MEASURE_START_PD(tx_check_inputs_loop_scan_outputkeys_loop_handle_output); + if (!vis.handle_output(tx_ptr->tx, validated_tx, tx_ptr->tx.vout[n], n)) + { + LOG_PRINT_L0("Failed to handle_output for output id = " << tx_id << ", no " << n); + return false; + } } + VARIANT_CASE_TV(tx_out_zarcanum) + //@#@ + VARIANT_CASE_THROW_ON_OTHER(); + VARIANT_SWITCH_END(); + + TIME_MEASURE_FINISH_PD(tx_check_inputs_loop_scan_outputkeys_loop_handle_output); - if (max_related_block_height < tx_ptr->m_keeper_block_height) - max_related_block_height = tx_ptr->m_keeper_block_height; - - + if (max_related_block_height < tx_ptr->m_keeper_block_height) + max_related_block_height = tx_ptr->m_keeper_block_height; + ++output_index; } TIME_MEASURE_FINISH_PD(tx_check_inputs_loop_scan_outputkeys_loop); diff --git a/src/currency_core/currency_format_utils.cpp b/src/currency_core/currency_format_utils.cpp index fabca75d..a1ffe112 100644 --- a/src/currency_core/currency_format_utils.cpp +++ b/src/currency_core/currency_format_utils.cpp @@ -525,8 +525,9 @@ namespace currency //msg.vin = tx.vin; msg.onetime_key = get_tx_pub_key_from_extra(tx); CHECK_AND_ASSERT_MES(tx.vout.size() > n, null_hash, "tx.vout.size() > n condition failed "); - CHECK_AND_ASSERT_MES(tx.vout[n].target.type() == typeid(txout_multisig), null_hash, "tx.vout[n].target.type() == typeid(txout_multisig) condition failed"); - msg.vout.push_back(tx.vout[n]); + CHECK_AND_ASSERT_MES(tx.vout[n].type() == typeid(tx_out_bare), null_hash, "Unexpected type of out:" << tx.vout[n].type().name()); + CHECK_AND_ASSERT_MES(boost::get(tx.vout[n]).target.type() == typeid(txout_multisig), null_hash, "tx.vout[n].target.type() == typeid(txout_multisig) condition failed"); + msg.vout.push_back(boost::get(tx.vout[n])); return get_object_hash(msg); } //--------------------------------------------------------------- @@ -1127,13 +1128,17 @@ namespace currency if (bc_services::get_first_service_attachment_by_id(tx, BC_ESCROW_SERVICE_ID, BC_ESCROW_SERVICE_INSTRUCTION_CANCEL_PROPOSAL, tsa)) return GUI_TX_TYPE_ESCROW_CANCEL_PROPOSAL; - for (auto o : tx.vout) + for (auto ov : tx.vout) { - if (o.target.type() == typeid(txout_htlc)) - { - htlc_out = o; - return GUI_TX_TYPE_HTLC_DEPOSIT; - } + VARIANT_SWITCH_BEGIN(ov); + VARIANT_CASE(tx_out_bare, o) + if (o.target.type() == typeid(txout_htlc)) + { + htlc_out = o; + return GUI_TX_TYPE_HTLC_DEPOSIT; + } + VARIANT_SWITCH_END(); + } if (get_type_in_variant_container(tx.vin, htlc_in)) @@ -1272,7 +1277,7 @@ namespace currency { tx.vin.clear(); tx.vout.clear(); - tx.signatures.clear(); + tx.signature.clear(); tx.extra = extra; tx.version = ftp.tx_version; @@ -1597,7 +1602,12 @@ namespace currency uint64_t reward = 0; for (auto& out : tx.vout) { - reward += out.amount; + VARIANT_SWITCH_BEGIN(out); + VARIANT_CASE(tx_out_bare, o) + reward += o.amount; + VARIANT_CASE_TV(tx_out_zarcanum) + //@#@ + VARIANT_SWITCH_END(); } reward -= income; return reward; @@ -1648,14 +1658,20 @@ namespace currency size_t ms_out_index = SIZE_MAX; for (size_t i = 0; i < source_tx.vout.size(); ++i) { - if (source_tx.vout[i].target.type() == typeid(txout_multisig) && ms_in.multisig_out_id == get_multisig_out_id(source_tx, i)) - { - ms_out_index = i; - break; - } + + VARIANT_SWITCH_BEGIN(source_tx.vout[i]); + VARIANT_CASE(tx_out_bare, o) + if (o.target.type() == typeid(txout_multisig) && ms_in.multisig_out_id == get_multisig_out_id(source_tx, i)) + { + ms_out_index = i; + break; + } + VARIANT_CASE_TV(tx_out_zarcanum) + //@#@ + VARIANT_SWITCH_END(); } LOC_CHK(ms_out_index != SIZE_MAX, "failed to find ms output in source tx " << get_transaction_hash(source_tx) << " by ms id " << ms_in.multisig_out_id); - const txout_multisig& out_ms = boost::get(source_tx.vout[ms_out_index].target); + const txout_multisig& out_ms = boost::get( boost::get(source_tx.vout[ms_out_index]).target); crypto::public_key source_tx_pub_key = get_tx_pub_key_from_extra(source_tx); @@ -1667,7 +1683,7 @@ namespace currency LOC_CHK(participant_index < out_ms.keys.size(), "Can't find given participant's ms key in ms output keys list"); LOC_CHK(ms_input_index < tx.signatures.size(), "transaction does not have signatures vectory entry for ms input #" << ms_input_index); - auto& sigs = tx.signatures[ms_input_index]; + auto& sigs = tx.signature[ms_input_index]; LOC_CHK(!sigs.empty(), "empty signatures container"); bool extra_signature_expected = (get_tx_flags(tx) & TX_FLAG_SIGNATURE_MODE_SEPARATE) && ms_input_index == tx.vin.size() - 1; @@ -1801,36 +1817,37 @@ namespace currency //----------------------------------------------------------------------------------------------- bool check_outs_valid(const transaction& tx) { - for(const tx_out_bare& out : tx.vout) + for(const auto& vo : tx.vout) { - CHECK_AND_NO_ASSERT_MES(0 < out.amount, false, "zero amount output in transaction id=" << get_transaction_hash(tx)); - if (out.target.type() == typeid(txout_to_key)) + + VARIANT_SWITCH_BEGIN(vo); + VARIANT_CASE(tx_out_bare, out) { - if (!check_key(boost::get(out.target).key)) - return false; - } - else if (out.target.type() == typeid(txout_htlc)) - { - const txout_htlc& htlc = boost::get(out.target); - if (!check_key(htlc.pkey_redeem)) - return false; - if (!check_key(htlc.pkey_refund)) - return false; - } - else if (out.target.type() == typeid(txout_multisig)) - { - const txout_multisig& ms = boost::get(out.target); - if (!(ms.keys.size() > 0 && ms.minimum_sigs > 0 && ms.minimum_sigs <= ms.keys.size())) - { - LOG_ERROR("wrong multisig in transaction id=" << get_transaction_hash(tx)); - return false; - } - } - else - { - LOG_ERROR("wrong variant type: " << out.target.type().name() << ", expected " << typeid(txout_to_key).name() - << ", in transaction id=" << get_transaction_hash(tx)); + CHECK_AND_NO_ASSERT_MES(0 < out.amount, false, "zero amount output in transaction id=" << get_transaction_hash(tx)); + + VARIANT_SWITCH_BEGIN(out.target); + VARIANT_CASE(txout_to_key, tk) + if (!check_key(tk.key)) + return false; + VARIANT_CASE(txout_htlc, htlc) + if (!check_key(htlc.pkey_redeem)) + return false; + if (!check_key(htlc.pkey_refund)) + return false; + VARIANT_CASE(txout_multisig, ms) + if (!(ms.keys.size() > 0 && ms.minimum_sigs > 0 && ms.minimum_sigs <= ms.keys.size())) + { + LOG_ERROR("wrong multisig in transaction id=" << get_transaction_hash(tx)); + return false; + } + VARIANT_CASE_OTHER() + LOG_ERROR("wrong variant type: " << out.target.type().name() << ", expected " << typeid(txout_to_key).name() + << ", in transaction id=" << get_transaction_hash(tx)); + VARIANT_SWITCH_END(); } + VARIANT_CASE_TV(tx_out_zarcanum) + //@#@ + VARIANT_SWITCH_END(); } return true; } @@ -1878,9 +1895,14 @@ namespace currency uint64_t money = 0; BOOST_FOREACH(const auto& o, tx.vout) { - if (money > o.amount + money) - return false; - money += o.amount; + VARIANT_SWITCH_BEGIN(o); + VARIANT_CASE(tx_out_bare, o) + if (money > o.amount + money) + return false; + money += o.amount; + VARIANT_CASE_TV(tx_out_zarcanum) + //@#@ + VARIANT_SWITCH_END(); } return true; } @@ -1888,8 +1910,15 @@ namespace currency uint64_t get_outs_money_amount(const transaction& tx) { uint64_t outputs_amount = 0; - for(const auto& o : tx.vout) - outputs_amount += o.amount; + for (const auto& o : tx.vout) + { + VARIANT_SWITCH_BEGIN(o); + VARIANT_CASE(tx_out_bare, o) + outputs_amount += o.amount; + VARIANT_CASE_TV(tx_out_zarcanum) + //@#@ + VARIANT_SWITCH_END(); + } return outputs_amount; } //--------------------------------------------------------------- @@ -1962,7 +1991,10 @@ namespace currency return true; CHECK_AND_ASSERT_MES(offset < tx.vout.size(), false, "condition failed: offset(" << offset << ") < tx.vout.size() (" << tx.vout.size() << ")"); - auto& o = tx.vout[offset]; + auto& ov = tx.vout[offset]; + CHECK_AND_ASSERT_MES(ov.type() == typeid(tx_out_bare), false, "unexpected type id in lookup_acc_outs_genesis:" << ov.type().name()); + const tx_out_bare& o = boost::get(ov); + 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)) { @@ -1994,46 +2026,46 @@ namespace currency return true; size_t i = 0; - for(const tx_out_bare& o : tx.vout) + for(const auto& ov : tx.vout) { - if (o.target.type() == typeid(txout_to_key)) + VARIANT_SWITCH_BEGIN(ov); + VARIANT_CASE(tx_out_bare, o) { - if (is_out_to_acc(acc, boost::get(o.target), derivation, i)) - { - outs.push_back(i); - money_transfered += o.amount; - } - } - else if (o.target.type() == typeid(txout_multisig)) - { - if (is_out_to_acc(acc, boost::get(o.target), derivation, i)) - { - outs.push_back(i); - //don't count this money - } - } - else if (o.target.type() == typeid(txout_htlc)) - { - htlc_info hi = AUTO_VAL_INIT(hi); - const txout_htlc& htlc = boost::get(o.target); - if (is_out_to_acc(acc, htlc.pkey_redeem, derivation, i)) - { - 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)) - { - hi.hltc_our_out_is_before_expiration = false; - htlc_info_list.push_back(hi); - outs.push_back(i); - } - } - else - { - LOG_ERROR("Wrong type at lookup_acc_outs, unexpected type is: " << o.target.type().name()); - return false; + VARIANT_SWITCH_BEGIN(o.target); + VARIANT_CASE(txout_to_key, t) + if (is_out_to_acc(acc, t, derivation, i)) + { + outs.push_back(i); + money_transfered += o.amount; + } + VARIANT_CASE(txout_multisig, t) + if (is_out_to_acc(acc, t, derivation, i)) + { + outs.push_back(i); + //don't count this money + } + VARIANT_CASE(txout_htlc, htlc) + htlc_info hi = AUTO_VAL_INIT(hi); + if (is_out_to_acc(acc, htlc.pkey_redeem, derivation, i)) + { + 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)) + { + hi.hltc_our_out_is_before_expiration = false; + htlc_info_list.push_back(hi); + outs.push_back(i); + } + 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_TV(tx_out_zarcanum) + //@#@ + VARIANT_SWITCH_END(); i++; } return true; diff --git a/src/currency_core/currency_format_utils_transactions.cpp b/src/currency_core/currency_format_utils_transactions.cpp index 14e25e68..78744d9a 100644 --- a/src/currency_core/currency_format_utils_transactions.cpp +++ b/src/currency_core/currency_format_utils_transactions.cpp @@ -8,6 +8,7 @@ #include "serialization/serialization.h" #include "currency_format_utils.h" #include "currency_format_utils_abstract.h" +#include "variant_helper.h" namespace currency { @@ -34,10 +35,6 @@ namespace currency //--------------------------------------------------------------- -#define VARIANT_SWITCH_BEGIN(v_type_obj) {decltype(v_type_obj)& local_reference_eokcmeokmeokcm = v_type_obj; if(false) {; -#define VARIANT_CASE(v_type) } else if(local_reference_eokcmeokmeokcm.type() == typeid(v_type)) { v_type& v_type_obj##_typed = boost::get(local_reference_eokcmeokmeokcm); -#define VARIANT_CASE_OTHER(v_type) } else { -#define VARIANT_SWITCH_END() } } @@ -46,11 +43,17 @@ namespace currency uint64_t res = 0; for (auto& o : tx.vout) { - if (o.target.type() == typeid(txout_to_key)) - { - if (boost::get(o.target).key == null_pkey) - res += o.amount; - } + VARIANT_SWITCH_BEGIN(o); + VARIANT_CASE(tx_out_bare, o) + if (o.target.type() == typeid(txout_to_key)) + { + if (boost::get(o.target).key == null_pkey) + res += o.amount; + } + VARIANT_CASE_TV(tx_out_zarcanum) + //@#@ + VARIANT_CASE_THROW_ON_OTHER(); + VARIANT_SWITCH_END(); } return res; } diff --git a/src/currency_core/tx_pool.cpp b/src/currency_core/tx_pool.cpp index 7f4d4495..266f2e4b 100644 --- a/src/currency_core/tx_pool.cpp +++ b/src/currency_core/tx_pool.cpp @@ -1330,8 +1330,15 @@ namespace currency idx = 0; for (const auto& out : tx.vout) { - if (out.target.type() == typeid(txout_multisig)) - result.push_back(ms_out_info({ get_multisig_out_id(tx, idx), idx, false })); + VARIANT_SWITCH_BEGIN(out); + VARIANT_CASE(tx_out_bare, o) + if (o.target.type() == typeid(txout_multisig)) + result.push_back(ms_out_info({ get_multisig_out_id(tx, idx), idx, false })); + + VARIANT_CASE_TV(tx_out_zarcanum) + //@#@ + VARIANT_CASE_THROW_ON_OTHER(); + VARIANT_SWITCH_END(); ++idx; } } @@ -1347,8 +1354,13 @@ namespace currency size_t idx = 0; for (const auto& out : tx.vout) { - if (out.target.type() == typeid(txout_multisig) && get_multisig_out_id(tx, idx) == multisig_id) - return true; + VARIANT_SWITCH_BEGIN(out); + VARIANT_CASE(tx_out_bare, o) + if (o.target.type() == typeid(txout_multisig) && get_multisig_out_id(tx, idx) == multisig_id) + return true; + VARIANT_CASE_TV(tx_out_zarcanum) + //@#@ + VARIANT_SWITCH_END(); ++idx; } From 6b6511b73f4158bac7f2cdcf87f514953c546597 Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Thu, 19 May 2022 21:22:44 +0200 Subject: [PATCH 05/10] tx stracture changes: in progress --- src/common/variant_helper.h | 9 +- src/currency_core/currency_format_utils.cpp | 80 +++++++++-------- src/currency_core/currency_format_utils.h | 8 +- src/rpc/core_rpc_server.cpp | 9 +- src/wallet/wallet2.h | 6 +- src/wallet/wallet2_escrow.cpp | 95 +++++++++++++-------- 6 files changed, 128 insertions(+), 79 deletions(-) diff --git a/src/common/variant_helper.h b/src/common/variant_helper.h index ae4f8d02..c730bf3c 100644 --- a/src/common/variant_helper.h +++ b/src/common/variant_helper.h @@ -19,13 +19,18 @@ usage: VARIANT_SWITCH_BEGIN(o); - VARIANT_CASE(tx_out_bare, o) + VARIANT_CASE(tx_out_bare, o); - VARIANT_CASE_TV(tx_out_zarcanum) + VARIANT_CASE_TV(tx_out_zarcanum); //@#@ VARIANT_SWITCH_END(); + VARIANT_SWITCH_BEGIN(o); + VARIANT_CASE(txout_to_key, o) + VARIANT_CASE_TV(txout_multisig) + VARIANT_CASE_TV(txout_htlc) + VARIANT_SWITCH_END(); VARIANT_SWITCH_BEGIN(o); diff --git a/src/currency_core/currency_format_utils.cpp b/src/currency_core/currency_format_utils.cpp index a1ffe112..ebe8db6f 100644 --- a/src/currency_core/currency_format_utils.cpp +++ b/src/currency_core/currency_format_utils.cpp @@ -2536,12 +2536,18 @@ namespace currency uint64_t found_alias_reward = 0; for (const auto& out : tx.vout) { - if (out.target.type() != typeid(txout_to_key)) - continue; + VARIANT_SWITCH_BEGIN(out); + VARIANT_CASE(tx_out_bare, out) + if (out.target.type() != typeid(txout_to_key)) + continue; + + const txout_to_key& o = boost::get(out.target); + if (o.key == null_pkey) + found_alias_reward += out.amount; + VARIANT_CASE_TV(tx_out_zarcanum) + //@#@ + VARIANT_SWITCH_END(); - const txout_to_key& o = boost::get(out.target); - if (o.key == null_pkey) - found_alias_reward += out.amount; } return found_alias_reward; } @@ -2776,35 +2782,34 @@ namespace currency for (auto& out : tx.vout) { tei.outs.push_back(tx_out_rpc_entry()); - tei.outs.back().amount = out.amount; tei.outs.back().is_spent = ptce ? ptce->m_spent_flags[i] : false; tei.outs.back().global_index = ptce ? ptce->m_global_output_indexes[i] : 0; + VARIANT_SWITCH_BEGIN(out); + VARIANT_CASE(tx_out_bare, out) + { + tei.outs.back().amount = out.amount; - if (out.target.type() == typeid(txout_to_key)) - { - const txout_to_key& otk = boost::get(out.target); - tei.outs.back().pub_keys.push_back(epee::string_tools::pod_to_hex(otk.key)); - if (otk.mix_attr == CURRENCY_TO_KEY_OUT_FORCED_NO_MIX) - tei.outs.back().pub_keys.back() += "(FORCED_NO_MIX)"; - if (otk.mix_attr >= CURRENCY_TO_KEY_OUT_FORCED_MIX_LOWER_BOUND) - tei.outs.back().pub_keys.back() += std::string("(FORCED_MIX_LOWER_BOUND: ") + std::to_string(otk.mix_attr) + ")"; + VARIANT_SWITCH_BEGIN(out.target); + VARIANT_CASE(txout_to_key, otk) + tei.outs.back().pub_keys.push_back(epee::string_tools::pod_to_hex(otk.key)); + if (otk.mix_attr == CURRENCY_TO_KEY_OUT_FORCED_NO_MIX) + tei.outs.back().pub_keys.back() += "(FORCED_NO_MIX)"; + if (otk.mix_attr >= CURRENCY_TO_KEY_OUT_FORCED_MIX_LOWER_BOUND) + tei.outs.back().pub_keys.back() += std::string("(FORCED_MIX_LOWER_BOUND: ") + std::to_string(otk.mix_attr) + ")"; + VARIANT_CASE(txout_multisig, otm) + for (auto& k : otm.keys) + { + tei.outs.back().pub_keys.push_back(epee::string_tools::pod_to_hex(k)); + } + tei.outs.back().minimum_sigs = otm.minimum_sigs; + VARIANT_CASE(txout_htlc, otk) + tei.outs.back().pub_keys.push_back(epee::string_tools::pod_to_hex(otk.pkey_redeem) + "(htlc_pkey_redeem)"); + tei.outs.back().pub_keys.push_back(epee::string_tools::pod_to_hex(otk.pkey_refund) + "(htlc_pkey_refund)"); + VARIANT_SWITCH_END(); } - else if (out.target.type() == typeid(txout_multisig)) - { - const txout_multisig& otm = boost::get(out.target); - for (auto& k : otm.keys) - { - tei.outs.back().pub_keys.push_back(epee::string_tools::pod_to_hex(k)); - } - tei.outs.back().minimum_sigs = otm.minimum_sigs; - } - else if (out.target.type() == typeid(txout_htlc)) - { - const txout_htlc& otk = boost::get(out.target); - tei.outs.back().pub_keys.push_back(epee::string_tools::pod_to_hex(otk.pkey_redeem) + "(htlc_pkey_redeem)"); - tei.outs.back().pub_keys.push_back(epee::string_tools::pod_to_hex(otk.pkey_refund) + "(htlc_pkey_refund)"); - } - + VARIANT_CASE_TV(tx_out_zarcanum) + //@#@ + VARIANT_SWITCH_END(); ++i; } return true; @@ -2912,11 +2917,16 @@ namespace currency { for (size_t n = 0; n < tx.vout.size(); ++n) { - if (tx.vout[n].target.type() == typeid(txout_to_key) || tx.vout[n].target.type() == typeid(txout_htlc)) - { - uint64_t amount = tx.vout[n].amount; - gindices[amount] += 1; - } + VARIANT_SWITCH_BEGIN(tx.vout[n]); + VARIANT_CASE(tx_out_bare, o) + if (o.target.type() == typeid(txout_to_key) || o.target.type() == typeid(txout_htlc)) + { + uint64_t amount = o.amount; + gindices[amount] += 1; + } + VARIANT_CASE_TV(tx_out_zarcanum) + //@#@ + VARIANT_SWITCH_END(); } } //--------------------------------------------------------------- diff --git a/src/currency_core/currency_format_utils.h b/src/currency_core/currency_format_utils.h index ee86735d..eb94538d 100644 --- a/src/currency_core/currency_format_utils.h +++ b/src/currency_core/currency_format_utils.h @@ -698,7 +698,13 @@ namespace currency uint64_t operator()(const t_input& i) const{return i.amount;} uint64_t operator()(const txin_gen& i) const {return 0;} }; - + //--------------------------------------------------------------- + const tx_out_bare& get_tx_out_bare_from_out_v(const tx_out_v& o) + { + //this function will throw if type is not matching + return boost::get(o); + } + //--------------------------------------------------------------- inline uint64_t get_amount_from_variant(const txin_v& v) { return boost::apply_visitor(input_amount_getter(), v); diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index 375e14de..159349b4 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -970,9 +970,14 @@ namespace currency uint64_t core_rpc_server::get_block_reward(const block& blk) { uint64_t reward = 0; - BOOST_FOREACH(const tx_out_bare& out, blk.miner_tx.vout) + BOOST_FOREACH(const auto& out, blk.miner_tx.vout) { - reward += out.amount; + VARIANT_SWITCH_BEGIN(out); + VARIANT_CASE(tx_out_bare, out) + reward += out.amount; + VARIANT_CASE_TV(tx_out_zarcanum) + //@#@ + VARIANT_SWITCH_END(); } return reward; } diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 57e8695a..0a1d7e70 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -379,8 +379,10 @@ namespace tools uint64_t m_spent_height; uint32_t m_flags; - uint64_t amount() const { return m_ptx_wallet_info->m_tx.vout[m_internal_output_index].amount; } - const currency::tx_out_bare& output() const { return m_ptx_wallet_info->m_tx.vout[m_internal_output_index]; } + // @#@ will throw if type is not tx_out_bare, TODO: change according to new model, + // need to replace all get_tx_out_bare_from_out_v() to proper code + uint64_t amount() const { return currency::get_tx_out_bare_from_out_v(m_ptx_wallet_info->m_tx.vout[m_internal_output_index]).amount; } + const currency::tx_out_bare& output() const { return currency::get_tx_out_bare_from_out_v(m_ptx_wallet_info->m_tx.vout[m_internal_output_index]); } uint8_t mix_attr() const { return output().target.type() == typeid(currency::txout_to_key) ? boost::get(output().target).mix_attr : UINT8_MAX; } crypto::hash tx_hash() const { return get_transaction_hash(m_ptx_wallet_info->m_tx); } bool is_spent() const { return m_flags & WALLET_TRANSFER_DETAIL_FLAG_SPENT; } diff --git a/src/wallet/wallet2_escrow.cpp b/src/wallet/wallet2_escrow.cpp index 4c5f1d65..bbf2b533 100644 --- a/src/wallet/wallet2_escrow.cpp +++ b/src/wallet/wallet2_escrow.cpp @@ -74,20 +74,28 @@ bool wallet2::validate_escrow_proposal(const wallet_public::wallet_transfer_info size_t ms_out_index = SIZE_MAX; for (size_t i = 0; i != prop.tx_template.vout.size(); ++i) { - if (prop.tx_template.vout[i].target.type() == typeid(txout_multisig)) + VARIANT_SWITCH_BEGIN(prop.tx_template.vout[i]); + VARIANT_CASE(tx_out_bare, o) { - LOC_CHK(ms_out_index == SIZE_MAX, "template has more than one multisig output"); - ms_out_index = i; + if (o.target.type() == typeid(txout_multisig)) + { + LOC_CHK(ms_out_index == SIZE_MAX, "template has more than one multisig output"); + ms_out_index = i; + } + else if (o.target.type() == typeid(txout_to_key)) + to_key_outputs_amount += o.amount; + else + LOC_CHK(false, "Invalid output type: " << o.target.type().name()); } - else if (prop.tx_template.vout[i].target.type() == typeid(txout_to_key)) - to_key_outputs_amount += prop.tx_template.vout[i].amount; - else - LOC_CHK(false, "Invalid output type: " << prop.tx_template.vout[i].target.type().name()); + VARIANT_CASE_TV(tx_out_zarcanum); + //@#@ + VARIANT_SWITCH_END(); } LOC_CHK(ms_out_index != SIZE_MAX, "template has no multisig outputs"); ms_id = currency::get_multisig_out_id(prop.tx_template, ms_out_index); - uint64_t ms_amount = prop.tx_template.vout[ms_out_index].amount; - const txout_multisig& ms = boost::get(prop.tx_template.vout[ms_out_index].target); + // @#@ using of get_tx_out_bare_from_out_v might be not safe, TODO: review this code + uint64_t ms_amount = currency::get_tx_out_bare_from_out_v(prop.tx_template.vout[ms_out_index]).amount; + const txout_multisig& ms = boost::get(currency::get_tx_out_bare_from_out_v(prop.tx_template.vout[ms_out_index]).target); LOC_CHK(ms.minimum_sigs == 2, "template has multisig output with wrong minimum_sigs==" << ms.minimum_sigs); LOC_CHK(ms.keys.size() == 2, "template has multisig output with wrong keys size: " << ms.keys.size()); @@ -138,7 +146,8 @@ bool wallet2::validate_escrow_release(const transaction& tx, bool release_type_n LOC_CHK(ms.multisig_out_id == ms_id, "multisig input references to wrong ms output: " << ms.multisig_out_id << ", expected: " << ms_id); LOC_CHK(source_ms_out.minimum_sigs == 2, "multisig output has wrong minimim_sigs: " <= min_ms_amount, "multisig input amount " << ms.amount << " is less than contract expected value: " << min_ms_amount << ", a_pledge=" << cpd.amount_a_pledge << ", b_pledge=" << cpd.amount_b_pledge << ", amount_to_pay=" << cpd.amount_to_pay); @@ -181,20 +190,27 @@ bool wallet2::validate_escrow_release(const transaction& tx, bool release_type_n uint64_t total_outputs_amount = 0, outputs_to_A_amount = 0, outputs_to_null_addr_amount = 0; for (size_t i = 0; i != tx.vout.size(); ++i) { - if (tx.vout[i].target.type() == typeid(txout_to_key)) + VARIANT_SWITCH_BEGIN(tx.vout[i]); + VARIANT_CASE(tx_out_bare, o); { - total_outputs_amount += tx.vout[i].amount; - const txout_to_key& otk = boost::get(tx.vout[i].target); - crypto::public_key ephemeral_pub_key = AUTO_VAL_INIT(ephemeral_pub_key); - r = crypto::derive_public_key(der, i, cpd.a_addr.spend_public_key, ephemeral_pub_key); - LOC_CHK(r, "derive_public_key failed for output #" << i); - if (otk.key == ephemeral_pub_key) - outputs_to_A_amount += tx.vout[i].amount; - else if (otk.key == null_pkey) - outputs_to_null_addr_amount += tx.vout[i].amount; + if (o.target.type() == typeid(txout_to_key)) + { + total_outputs_amount += o.amount; + const txout_to_key& otk = boost::get(o.target); + crypto::public_key ephemeral_pub_key = AUTO_VAL_INIT(ephemeral_pub_key); + r = crypto::derive_public_key(der, i, cpd.a_addr.spend_public_key, ephemeral_pub_key); + LOC_CHK(r, "derive_public_key failed for output #" << i); + if (otk.key == ephemeral_pub_key) + outputs_to_A_amount += o.amount; + else if (otk.key == null_pkey) + outputs_to_null_addr_amount += o.amount; + } + else + LOC_CHK(false, "Invalid output type: " << o.target.type().name()); } - else - LOC_CHK(false, "Invalid output type: " << tx.vout[i].target.type().name()); + VARIANT_CASE(tx_out_zarcanum, o) + LOC_CHK(false, "Invalid output type: " << o.type().name()); + VARIANT_SWITCH_END(); } if (release_type_normal) @@ -258,7 +274,7 @@ bool wallet2::validate_escrow_contract(const wallet_public::wallet_transfer_info LOC_CHK(n < wti.tx.vout.size(), "multisig output was not found"); ms_id = currency::get_multisig_out_id(wti.tx, n); LOC_CHK(ms_id != null_hash, "failed to obtain ms output id"); - const txout_multisig& ms = boost::get(wti.tx.vout[n].target); + const txout_multisig& ms = boost::get( boost::get(wti.tx.vout[n]).target); tx_service_attachment tsa = AUTO_VAL_INIT(tsa); r = bc_services::get_first_service_attachment_by_id(decrypted_items, BC_ESCROW_SERVICE_ID, BC_ESCROW_SERVICE_INSTRUCTION_RELEASE_TEMPLATES, tsa); @@ -318,11 +334,11 @@ bool wallet2::validate_escrow_cancel_release(const currency::transaction& tx, co LOC_CHK(tx.vin.back().type() == typeid(txin_multisig), "input 0 is not txin_multisig"); const txin_multisig& ms = boost::get(tx.vin.back()); LOC_CHK(source_ms_out_index < source_tx.vout.size(), "internal invariant failed: source_ms_out_index is out of bounds: " << source_ms_out_index); - const txout_multisig& source_ms_out = boost::get(source_tx.vout[source_ms_out_index].target); + const txout_multisig& source_ms_out = boost::get(currency::get_tx_out_bare_from_out_v(source_tx.vout[source_ms_out_index]).target); LOC_CHK(ms.multisig_out_id == ms_id, "multisig input references to wrong ms output: " << ms.multisig_out_id << ", expected: " << ms_id); LOC_CHK(source_ms_out.minimum_sigs == 2, "source multisig output has wrong minimim_sigs: " <(tx.vout[i].target); - crypto::public_key ephemeral_pub_key = AUTO_VAL_INIT(ephemeral_pub_key); - r = crypto::derive_public_key(der, i, cpd.b_addr.spend_public_key, ephemeral_pub_key); - LOC_CHK(r, "derive_public_key failed for output #" << i); - if (otk.key == ephemeral_pub_key) - outputs_to_B_amount += tx.vout[i].amount; - } - else - LOC_CHK(false, "Invalid output type: " << tx.vout[i].target.type().name()); + VARIANT_SWITCH_BEGIN(tx.vout[i]); + VARIANT_CASE(tx_out_bare, o) + if (o.target.type() == typeid(txout_to_key)) + { + total_outputs_amount += o.amount; + const txout_to_key& otk = boost::get(o.target); + crypto::public_key ephemeral_pub_key = AUTO_VAL_INIT(ephemeral_pub_key); + r = crypto::derive_public_key(der, i, cpd.b_addr.spend_public_key, ephemeral_pub_key); + LOC_CHK(r, "derive_public_key failed for output #" << i); + if (otk.key == ephemeral_pub_key) + outputs_to_B_amount += o.amount; + } + else + LOC_CHK(false, "Invalid output type: " << o.target.type().name()); + VARIANT_CASE_TV(tx_out_zarcanum) + LOC_CHK(false, "Invalid output type: " << tv.type().name()); + VARIANT_SWITCH_END(); } LOC_CHK(outputs_to_B_amount >= cpd.amount_b_pledge, "B-addressed outs total amount: " << print_money(outputs_to_B_amount) << " is less than b_pledge: " << print_money(cpd.amount_b_pledge)); From 7e5c50435727af564395fb4f6e2ce240485dad51 Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Thu, 19 May 2022 22:46:57 +0200 Subject: [PATCH 06/10] tx stracture changes: in progress 2 --- src/wallet/wallet2.cpp | 365 ++++++++++++++++++++++------------------- 1 file changed, 192 insertions(+), 173 deletions(-) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index eada75a7..45afefbe 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -86,12 +86,17 @@ namespace tools for (auto ri : td.receive_indices) { CHECK_AND_ASSERT_THROW_MES(ri < tx.vout.size(), "Internal error: wrong tx transfer details: reciev index=" << ri << " is greater than transaction outputs vector " << tx.vout.size()); - if (tx.vout[ri].target.type() == typeid(currency::txout_to_key)) - { - //update unlock_time if needed - if (ut2.unlock_time_array[ri] > max_unlock_time) - max_unlock_time = ut2.unlock_time_array[ri]; - } + VARIANT_SWITCH_BEGIN(tx.vout[ri]); + VARIANT_CASE(tx_out_bare, o) + if (o.target.type() == typeid(currency::txout_to_key)) + { + //update unlock_time if needed + if (ut2.unlock_time_array[ri] > max_unlock_time) + max_unlock_time = ut2.unlock_time_array[ri]; + } + VARIANT_CASE_TV(tx_out_zarcanum); + VARIANT_SWITCH_END(); + } return max_unlock_time; } @@ -109,10 +114,16 @@ void wallet2::fill_transfer_details(const currency::transaction& tx, const tools for (auto ri : td.receive_indices) { WLT_CHECK_AND_ASSERT_MES(ri < tx.vout.size(), void(), "Internal error: wrong tx transfer details: reciev index=" << ri << " is greater than transaction outputs vector " << tx.vout.size()); - if (tx.vout[ri].target.type() == typeid(currency::txout_to_key)) - { - res_td.rcv.push_back(tx.vout[ri].amount); - } + VARIANT_SWITCH_BEGIN(tx.vout[ri]); + VARIANT_CASE(tx_out_bare, o) + if (o.target.type() == typeid(currency::txout_to_key)) + { + res_td.rcv.push_back(o.amount); + } + VARIANT_CASE_TV(tx_out_zarcanum); + //@#@ + VARIANT_SWITCH_END(); + } } //---------------------------------------------------------------------------------------------------- @@ -405,7 +416,8 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t { transfer_details& td = m_transfers[it->second]; WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(td.m_ptx_wallet_info->m_tx.vout.size() > td.m_internal_output_index, "Internal error: wrong td.m_internal_output_index: " << td.m_internal_output_index); - const boost::typeindex::type_info& ti = td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index].target.type(); + WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index].type() == typeid(tx_out_bare), "Internal error: wrong output type: " << td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index].type().name()); + const boost::typeindex::type_info& ti = boost::get(td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index]).target.type(); WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(ti == typeid(txout_htlc), "Internal error: wrong type of output's target: " << ti.name()); //input spend active htlc m_transfers[it->second].m_spent_height = height; @@ -465,199 +477,206 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t { size_t o = outs[i_in_outs]; WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(o < tx.vout.size(), "wrong out in transaction: internal index=" << o << ", total_outs=" << tx.vout.size()); - if (tx.vout[o].target.type() == typeid(txout_to_key) || tx.vout[o].target.type() == typeid(txout_htlc)) + VARIANT_SWITCH_BEGIN(tx.vout[o]); + VARIANT_CASE(tx_out_bare, out) { - bool hltc_our_out_is_before_expiration = false; - crypto::public_key out_key = null_pkey; - if (tx.vout[o].target.type() == typeid(txout_to_key)) + if (out.target.type() == typeid(txout_to_key) || out.target.type() == typeid(txout_htlc)) { - out_key = boost::get(tx.vout[o].target).key; - } - else if (tx.vout[o].target.type() == typeid(txout_htlc)) - { - THROW_IF_FALSE_WALLET_INT_ERR_EX(htlc_info_list.size() > 0, "Found txout_htlc out but htlc_info_list is empty"); - if (htlc_info_list.front().hltc_our_out_is_before_expiration) + bool hltc_our_out_is_before_expiration = false; + crypto::public_key out_key = null_pkey; + if (out.target.type() == typeid(txout_to_key)) { - out_key = boost::get(tx.vout[o].target).pkey_redeem; + out_key = boost::get(out.target).key; } - else + else if (out.target.type() == typeid(txout_htlc)) { - out_key = boost::get(tx.vout[o].target).pkey_refund; - } - htlc_info_list.pop_front(); - } - else - { - THROW_IF_TRUE_WALLET_INT_ERR_EX(false, "Unexpected out type im wallet: " << tx.vout[o].target.type().name()); - } - //const currency::txout_to_key& otk = boost::get(tx.vout[o].target); - - // obtain key image for this output - crypto::key_image ki = currency::null_ki; - if (m_watch_only) - { - if (!is_auditable()) - { - // don't have spend secret key, so we unable to calculate key image for an output - // look it up in special container instead - auto it = m_pending_key_images.find(out_key); - if (it != m_pending_key_images.end()) + THROW_IF_FALSE_WALLET_INT_ERR_EX(htlc_info_list.size() > 0, "Found txout_htlc out but htlc_info_list is empty"); + if (htlc_info_list.front().hltc_our_out_is_before_expiration) { - ki = it->second; - WLT_LOG_L1("pending key image " << ki << " was found by out pub key " << out_key); + out_key = boost::get(out.target).pkey_redeem; } else { - ki = currency::null_ki; - WLT_LOG_L1("can't find pending key image by out pub key: " << out_key << ", key image temporarily set to null"); + out_key = boost::get(out.target).pkey_refund; + } + htlc_info_list.pop_front(); + } + else + { + THROW_IF_TRUE_WALLET_INT_ERR_EX(false, "Unexpected out type im wallet: " << out.target.type().name()); + } + //const currency::txout_to_key& otk = boost::get(out.target); + + // obtain key image for this output + crypto::key_image ki = currency::null_ki; + if (m_watch_only) + { + if (!is_auditable()) + { + // don't have spend secret key, so we unable to calculate key image for an output + // look it up in special container instead + auto it = m_pending_key_images.find(out_key); + if (it != m_pending_key_images.end()) + { + ki = it->second; + WLT_LOG_L1("pending key image " << ki << " was found by out pub key " << out_key); + } + else + { + ki = currency::null_ki; + WLT_LOG_L1("can't find pending key image by out pub key: " << out_key << ", key image temporarily set to null"); + } } } - } - else - { - // normal wallet, calculate and store key images for own outs - currency::keypair in_ephemeral = AUTO_VAL_INIT(in_ephemeral); - currency::generate_key_image_helper(m_account.get_keys(), tx_pub_key, o, in_ephemeral, ki); - WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(in_ephemeral.pub == out_key, "key_image generated ephemeral public key that does not match with output_key"); - } - - if (ki != currency::null_ki) - { - // make sure calculated key image for this own output has not been seen before - auto it = m_key_images.find(ki); - if (it != m_key_images.end()) + else + { + // normal wallet, calculate and store key images for own outs + currency::keypair in_ephemeral = AUTO_VAL_INIT(in_ephemeral); + currency::generate_key_image_helper(m_account.get_keys(), tx_pub_key, o, in_ephemeral, ki); + WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(in_ephemeral.pub == out_key, "key_image generated ephemeral public key that does not match with output_key"); + } + + if (ki != currency::null_ki) + { + // make sure calculated key image for this own output has not been seen before + auto it = m_key_images.find(ki); + if (it != m_key_images.end()) + { + WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(it->second < m_transfers.size(), "m_key_images entry has wrong m_transfers index, it->second: " << it->second << ", m_transfers.size(): " << m_transfers.size()); + const transfer_details& local_td = m_transfers[it->second]; + std::stringstream ss; + ss << "tx " << get_transaction_hash(tx) << " @ block " << height << " has output #" << o << " with key image " << ki << " that has already been seen in output #" << + local_td.m_internal_output_index << " in tx " << get_transaction_hash(local_td.m_ptx_wallet_info->m_tx) << " @ block " << local_td.m_spent_height << + ". This output can't ever be spent and will be skipped."; + WLT_LOG_YELLOW(ss.str(), LOG_LEVEL_0); + if (m_wcallback) + m_wcallback->on_message(i_wallet2_callback::ms_yellow, ss.str()); + WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(tx_money_got_in_outs >= out.amount, "tx_money_got_in_outs: " << tx_money_got_in_outs << ", out.amount:" << out.amount); + tx_money_got_in_outs -= out.amount; + continue; // skip the output + } + } + + if (is_auditable() && out.target.type() == typeid(txout_to_key) && + boost::get(out.target).mix_attr != CURRENCY_TO_KEY_OUT_FORCED_NO_MIX) { - WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(it->second < m_transfers.size(), "m_key_images entry has wrong m_transfers index, it->second: " << it->second << ", m_transfers.size(): " << m_transfers.size()); - const transfer_details& local_td = m_transfers[it->second]; std::stringstream ss; - ss << "tx " << get_transaction_hash(tx) << " @ block " << height << " has output #" << o << " with key image " << ki << " that has already been seen in output #" << - local_td.m_internal_output_index << " in tx " << get_transaction_hash(local_td.m_ptx_wallet_info->m_tx) << " @ block " << local_td.m_spent_height << - ". This output can't ever be spent and will be skipped."; - WLT_LOG_YELLOW(ss.str(), LOG_LEVEL_0); + ss << "output #" << o << " from tx " << get_transaction_hash(tx) << " with amount " << print_money_brief(out.amount) + << " is targeted to this auditable wallet and has INCORRECT mix_attr = " << (uint64_t)boost::get(out.target).mix_attr << ". Output IGNORED."; + WLT_LOG_RED(ss.str(), LOG_LEVEL_0); if (m_wcallback) - m_wcallback->on_message(i_wallet2_callback::ms_yellow, ss.str()); - WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(tx_money_got_in_outs >= tx.vout[o].amount, "tx_money_got_in_outs: " << tx_money_got_in_outs << ", tx.vout[o].amount:" << tx.vout[o].amount); - tx_money_got_in_outs -= tx.vout[o].amount; + m_wcallback->on_message(i_wallet2_callback::ms_red, ss.str()); + tx_money_got_in_outs -= out.amount; continue; // skip the output } - } - if (is_auditable() && tx.vout[o].target.type() == typeid(txout_to_key) && - boost::get(tx.vout[o].target).mix_attr != CURRENCY_TO_KEY_OUT_FORCED_NO_MIX) - { - std::stringstream ss; - ss << "output #" << o << " from tx " << get_transaction_hash(tx) << " with amount " << print_money_brief(tx.vout[o].amount) - << " is targeted to this auditable wallet and has INCORRECT mix_attr = " << (uint64_t)boost::get(tx.vout[o].target).mix_attr << ". Output IGNORED."; - WLT_LOG_RED(ss.str(), LOG_LEVEL_0); - if (m_wcallback) - m_wcallback->on_message(i_wallet2_callback::ms_red, ss.str()); - tx_money_got_in_outs -= tx.vout[o].amount; - continue; // skip the output - } + mtd.receive_indices.push_back(o); - mtd.receive_indices.push_back(o); - - m_transfers.push_back(boost::value_initialized()); - transfer_details& td = m_transfers.back(); - td.m_ptx_wallet_info = pwallet_info; - td.m_internal_output_index = o; - td.m_key_image = ki; - if (m_use_deffered_global_outputs) - { - if (pglobal_indexes && pglobal_indexes->size() > o) - td.m_global_output_index = (*pglobal_indexes)[o]; - else - td.m_global_output_index = WALLET_GLOBAL_OUTPUT_INDEX_UNDEFINED; - } - else - { - WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(pglobal_indexes, "pglobal_indexes IS NULL in non mobile wallet"); - WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(pglobal_indexes->size() > o, "pglobal_indexes size()(" << pglobal_indexes->size() << ") <= o " << o ); - td.m_global_output_index = (*pglobal_indexes)[o]; - } - if (coin_base_tx) - { - //last out in coinbase tx supposed to be change from coinstake - if (!(o == tx.vout.size() - 1 && !is_derived_from_coinbase)) + m_transfers.push_back(boost::value_initialized()); + transfer_details& td = m_transfers.back(); + td.m_ptx_wallet_info = pwallet_info; + td.m_internal_output_index = o; + td.m_key_image = ki; + if (m_use_deffered_global_outputs) { - td.m_flags |= WALLET_TRANSFER_DETAIL_FLAG_MINED_TRANSFER; + if (pglobal_indexes && pglobal_indexes->size() > o) + td.m_global_output_index = (*pglobal_indexes)[o]; + else + td.m_global_output_index = WALLET_GLOBAL_OUTPUT_INDEX_UNDEFINED; } - } - uint64_t amount = tx.vout[o].amount; - size_t transfer_index = m_transfers.size() - 1; - if (tx.vout[o].target.type() == typeid(txout_htlc)) - { - const txout_htlc& hltc = boost::get(tx.vout[o].target); - //mark this as spent - td.m_flags |= WALLET_TRANSFER_DETAIL_FLAG_SPENT; - //create entry for htlc input - htlc_expiration_trigger het = AUTO_VAL_INIT(het); - het.is_wallet_owns_redeem = (out_key == hltc.pkey_redeem) ? true:false; - het.transfer_index = transfer_index; - uint64_t expired_if_more_then = td.m_ptx_wallet_info->m_block_height + hltc.expiration; - m_htlcs.insert(std::make_pair(expired_if_more_then, het)); - - if (het.is_wallet_owns_redeem) + else { - td.m_flags |= WALLET_TRANSFER_DETAIL_FLAG_HTLC_REDEEM; - } - - //active htlc - auto amount_gindex_pair = std::make_pair(amount, td.m_global_output_index); - m_active_htlcs[amount_gindex_pair] = transfer_index; - m_active_htlcs_txid[get_transaction_hash(tx)] = transfer_index; - //add payer to extra options - currency::tx_payer payer = AUTO_VAL_INIT(payer); - if (het.is_wallet_owns_redeem) + WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(pglobal_indexes, "pglobal_indexes IS NULL in non mobile wallet"); + WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(pglobal_indexes->size() > o, "pglobal_indexes size()(" << pglobal_indexes->size() << ") <= o " << o); + td.m_global_output_index = (*pglobal_indexes)[o]; + } + if (coin_base_tx) { - if (currency::get_type_in_variant_container(tx.extra, payer)) + //last out in coinbase tx supposed to be change from coinstake + if (!(o == tx.vout.size() - 1 && !is_derived_from_coinbase)) { - crypto::chacha_crypt(payer.acc_addr, derivation); - td.varian_options.push_back(payer); + td.m_flags |= WALLET_TRANSFER_DETAIL_FLAG_MINED_TRANSFER; } } - else + uint64_t amount = out.amount; + size_t transfer_index = m_transfers.size() - 1; + if (out.target.type() == typeid(txout_htlc)) { - //since this is refund-mode htlc out, then sender is this wallet itself - payer.acc_addr = m_account.get_public_address(); - td.varian_options.push_back(payer); + const txout_htlc& hltc = boost::get(out.target); + //mark this as spent + td.m_flags |= WALLET_TRANSFER_DETAIL_FLAG_SPENT; + //create entry for htlc input + htlc_expiration_trigger het = AUTO_VAL_INIT(het); + het.is_wallet_owns_redeem = (out_key == hltc.pkey_redeem) ? true : false; + het.transfer_index = transfer_index; + uint64_t expired_if_more_then = td.m_ptx_wallet_info->m_block_height + hltc.expiration; + m_htlcs.insert(std::make_pair(expired_if_more_then, het)); + + if (het.is_wallet_owns_redeem) + { + td.m_flags |= WALLET_TRANSFER_DETAIL_FLAG_HTLC_REDEEM; + } + + //active htlc + auto amount_gindex_pair = std::make_pair(amount, td.m_global_output_index); + m_active_htlcs[amount_gindex_pair] = transfer_index; + m_active_htlcs_txid[get_transaction_hash(tx)] = transfer_index; + //add payer to extra options + currency::tx_payer payer = AUTO_VAL_INIT(payer); + if (het.is_wallet_owns_redeem) + { + if (currency::get_type_in_variant_container(tx.extra, payer)) + { + crypto::chacha_crypt(payer.acc_addr, derivation); + td.varian_options.push_back(payer); + } + } + else + { + //since this is refund-mode htlc out, then sender is this wallet itself + payer.acc_addr = m_account.get_public_address(); + td.varian_options.push_back(payer); + } + + } + if (td.m_key_image != currency::null_ki) + m_key_images[td.m_key_image] = transfer_index; + + add_transfer_to_transfers_cache(amount, transfer_index); + + if (is_watch_only() && is_auditable()) + { + WLT_CHECK_AND_ASSERT_MES_NO_RET(td.m_global_output_index != WALLET_GLOBAL_OUTPUT_INDEX_UNDEFINED, "td.m_global_output_index != WALLET_GLOBAL_OUTPUT_INDEX_UNDEFINED validation failed"); + auto amount_gindex_pair = std::make_pair(amount, td.m_global_output_index); + WLT_CHECK_AND_ASSERT_MES_NO_RET(m_amount_gindex_to_transfer_id.count(amount_gindex_pair) == 0, "update m_amount_gindex_to_transfer_id: amount " << amount << ", gindex " << td.m_global_output_index << " already exists"); + m_amount_gindex_to_transfer_id[amount_gindex_pair] = transfer_index; + } + + if (max_out_unlock_time < get_tx_unlock_time(tx, o)) + max_out_unlock_time = get_tx_unlock_time(tx, o); + + if (out.target.type() == typeid(txout_to_key)) + { + WLT_LOG_L0("Received money, transfer #" << transfer_index << ", amount: " << print_money(td.amount()) << ", with tx: " << get_transaction_hash(tx) << ", at height " << height); + } + else if (out.target.type() == typeid(txout_htlc)) + { + WLT_LOG_L0("Detected HTLC[" << (td.m_flags&WALLET_TRANSFER_DETAIL_FLAG_HTLC_REDEEM ? "REDEEM" : "REFUND") << "], transfer #" << transfer_index << ", amount: " << print_money(td.amount()) << ", with tx: " << get_transaction_hash(tx) << ", at height " << height); } - } - if (td.m_key_image != currency::null_ki) - m_key_images[td.m_key_image] = transfer_index; - - add_transfer_to_transfers_cache(amount, transfer_index); - - if (is_watch_only() && is_auditable()) + else if (out.target.type() == typeid(txout_multisig)) { - WLT_CHECK_AND_ASSERT_MES_NO_RET(td.m_global_output_index != WALLET_GLOBAL_OUTPUT_INDEX_UNDEFINED, "td.m_global_output_index != WALLET_GLOBAL_OUTPUT_INDEX_UNDEFINED validation failed"); - auto amount_gindex_pair = std::make_pair(amount, td.m_global_output_index); - WLT_CHECK_AND_ASSERT_MES_NO_RET(m_amount_gindex_to_transfer_id.count(amount_gindex_pair) == 0, "update m_amount_gindex_to_transfer_id: amount " << amount << ", gindex " << td.m_global_output_index << " already exists"); - m_amount_gindex_to_transfer_id[amount_gindex_pair] = transfer_index; - } - - if (max_out_unlock_time < get_tx_unlock_time(tx, o)) - max_out_unlock_time = get_tx_unlock_time(tx, o); - - if (tx.vout[o].target.type() == typeid(txout_to_key)) - { - WLT_LOG_L0("Received money, transfer #" << transfer_index << ", amount: " << print_money(td.amount()) << ", with tx: " << get_transaction_hash(tx) << ", at height " << height); - } - else if (tx.vout[o].target.type() == typeid(txout_htlc)) - { - WLT_LOG_L0("Detected HTLC[" << (td.m_flags&WALLET_TRANSFER_DETAIL_FLAG_HTLC_REDEEM ? "REDEEM":"REFUND") << "], transfer #" << transfer_index << ", amount: " << print_money(td.amount()) << ", with tx: " << get_transaction_hash(tx) << ", at height " << height); + crypto::hash multisig_id = currency::get_multisig_out_id(tx, o); + WLT_CHECK_AND_ASSERT_MES_NO_RET(m_multisig_transfers.count(multisig_id) == 0, "multisig_id = " << multisig_id << " already in multisig container"); + transfer_details_base& tdb = m_multisig_transfers[multisig_id]; + tdb.m_ptx_wallet_info = pwallet_info; + tdb.m_internal_output_index = o; + WLT_LOG_L0("Received multisig, multisig out id: " << multisig_id << ", amount: " << tdb.amount() << ", with tx: " << get_transaction_hash(tx)); } } - else if (tx.vout[o].target.type() == typeid(txout_multisig)) - { - crypto::hash multisig_id = currency::get_multisig_out_id(tx, o); - WLT_CHECK_AND_ASSERT_MES_NO_RET(m_multisig_transfers.count(multisig_id) == 0, "multisig_id = " << multisig_id << " already in multisig container"); - transfer_details_base& tdb = m_multisig_transfers[multisig_id]; - tdb.m_ptx_wallet_info = pwallet_info; - tdb.m_internal_output_index = o; - WLT_LOG_L0("Received multisig, multisig out id: " << multisig_id << ", amount: " << tdb.amount() << ", with tx: " << get_transaction_hash(tx)); - } + VARIANT_CASE_TV(tx_out_zarcanum); + //@#@ + VARIANT_SWITCH_END(); } } From 389209ff02623d863eeea09235142c5813ecc361 Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Fri, 20 May 2022 21:32:27 +0200 Subject: [PATCH 07/10] tx stracture changes: in progress 3 + signatures converting to varian signature: in progress --- src/common/variant_helper.h | 16 +- src/currency_core/blockchain_storage.cpp | 225 +++++++++++++------- src/currency_core/blockchain_storage.h | 17 +- src/currency_core/currency_format_utils.cpp | 21 +- src/wallet/wallet2.cpp | 183 ++++++++++------ tests/core_tests/alias_tests.cpp | 8 +- tests/core_tests/block_reward.cpp | 4 +- tests/core_tests/block_validation.cpp | 18 +- tests/core_tests/chain_switch_pow_pos.cpp | 2 +- tests/core_tests/chaingen.cpp | 28 +-- tests/core_tests/checkpoints_tests.cpp | 8 +- tests/core_tests/double_spend.inl | 2 +- tests/core_tests/emission_test.cpp | 4 +- tests/core_tests/escrow_wallet_common.h | 4 +- tests/core_tests/hard_fork_1.cpp | 28 +-- tests/core_tests/integer_overflow.cpp | 8 +- tests/core_tests/misc_tests.cpp | 6 +- tests/core_tests/multisig_wallet_tests.cpp | 44 ++-- tests/core_tests/pos_block_builder.cpp | 4 +- tests/core_tests/pos_validation.cpp | 22 +- tests/core_tests/transaction_tests.cpp | 24 +-- 21 files changed, 412 insertions(+), 264 deletions(-) diff --git a/src/common/variant_helper.h b/src/common/variant_helper.h index c730bf3c..c1282d00 100644 --- a/src/common/variant_helper.h +++ b/src/common/variant_helper.h @@ -25,11 +25,19 @@ usage: //@#@ VARIANT_SWITCH_END(); - VARIANT_SWITCH_BEGIN(o); - VARIANT_CASE(txout_to_key, o) - VARIANT_CASE_TV(txout_multisig) - VARIANT_CASE_TV(txout_htlc) + VARIANT_CASE(txout_to_key, o); + VARIANT_CASE_TV(txout_multisig); + VARIANT_CASE_TV(txout_htlc); + VARIANT_SWITCH_END(); + + + + VARIANT_SWITCH_BEGIN(s); + VARIANT_CASE(void_sig, v); + VARIANT_CASE(NLSAG_sig, signatures); + VARIANT_CASE(zarcanum_sig, s); + //@#@ VARIANT_SWITCH_END(); diff --git a/src/currency_core/blockchain_storage.cpp b/src/currency_core/blockchain_storage.cpp index 72d9df16..41b6e32f 100644 --- a/src/currency_core/blockchain_storage.cpp +++ b/src/currency_core/blockchain_storage.cpp @@ -609,9 +609,18 @@ bool blockchain_storage::prune_ring_signatures_and_attachments(uint64_t height, "is mot equal to height = " << height << " in blockchain index, for block on height = " << height); transaction_chain_entry lolcal_chain_entry = *it; - signatures_pruned += lolcal_chain_entry.tx.signatures.size(); + VARIANT_SWITCH_BEGIN(lolcal_chain_entry.tx.signature); + VARIANT_CASE(void_sig, v); + VARIANT_CASE(NLSAG_sig, signatures) + { + signatures_pruned += signatures.s.size(); + signatures.s.clear(); + } + VARIANT_CASE(zarcanum_sig, s); + //@#@ + VARIANT_SWITCH_END(); + attachments_pruned += lolcal_chain_entry.tx.attachment.size(); - lolcal_chain_entry.tx.signatures.clear(); lolcal_chain_entry.tx.attachment.clear(); //reassign to db @@ -4286,8 +4295,17 @@ bool blockchain_storage::check_tx_inputs(const transaction& tx, const crypto::ha { if (!m_is_in_checkpoint_zone) { - CHECK_AND_ASSERT_MES(sig_index < tx.signatures.size(), false, "Wrong transaction: missing signature entry for input #" << sig_index << " tx: " << tx_prefix_hash); - psig = &tx.signatures[sig_index]; + VARIANT_SWITCH_BEGIN(tx.signatures); + VARIANT_CASE(void_sig, v); + VARIANT_CASE(NLSAG_sig, signatures); + { + CHECK_AND_ASSERT_MES(sig_index < tx.signatures.s.size(), false, "Wrong transaction: missing signature entry for input #" << sig_index << " tx: " << tx_prefix_hash); + psig = &signatures.s[sig_index]; + } + VARIANT_CASE(zarcanum_sig, s); + //@#@ + VARIANT_SWITCH_END(); + } if (txin.type() == typeid(txin_to_key)) @@ -4585,47 +4603,65 @@ bool blockchain_storage::check_ms_input(const transaction& tx, size_t in_index, LOC_CHK(!have_type_in_variant_container(txin.etc_details), "Incorrect using of extra_attachment_info in etc_details in input #" << in_index << " for tx " << tx_prefix_hash); } - LOC_CHK(tx.signatures.size() > in_index, "ms input index is out of signatures container bounds, tx.signatures.size() = " << tx.signatures.size()); - const std::vector& input_signatures = tx.signatures[in_index]; - - size_t expected_signatures_count = txin.sigs_count; - bool need_to_check_extra_sign = false; - if (get_tx_flags(tx)&TX_FLAG_SIGNATURE_MODE_SEPARATE && in_index == tx.vin.size() - 1) // last input in TX_FLAG_SIGNATURE_MODE_SEPARATE must contain one more signature to ensure that tx was completed by an authorized subject + VARIANT_SWITCH_BEGIN(tx.signature); + VARIANT_CASE(void_sig, v); + VARIANT_CASE(NLSAG_sig, signatures) { - expected_signatures_count++; - need_to_check_extra_sign = true; - } + LOC_CHK(tx.signatures.size() > in_index, "ms input index is out of signatures container bounds, tx.signatures.size() = " << tx.signatures.size()); + const std::vector& input_signatures = signatures.s[in_index]; - LOC_CHK(expected_signatures_count == input_signatures.size(), "Invalid input's signatures count: " << input_signatures.size() << ", expected: " << expected_signatures_count); - - crypto::hash tx_hash_for_signature = prepare_prefix_hash_for_sign(tx, in_index, tx_prefix_hash); - LOC_CHK(tx_hash_for_signature != null_hash, "prepare_prefix_hash_for_sign failed"); - - LOC_CHK(txin.sigs_count <= source_ms_out_target.keys.size(), "source tx invariant failed: ms output's minimum sigs == ms input's sigs_count (" << txin.sigs_count << ") is GREATHER than keys.size() = " << source_ms_out_target.keys.size()); // NOTE: sig_count == minimum_sigs as checked above - size_t out_key_index = 0; // index in source_ms_out_target.keys - for (size_t i = 0; i != txin.sigs_count; /* nothing */) - { - // if we run out of keys for this signature, then it's invalid signature - LOC_CHK(out_key_index < source_ms_out_target.keys.size(), "invalid signature #" << i << ": " << input_signatures[i]); - - // check signature #i against ms output key #out_key_index - if (crypto::check_signature(tx_hash_for_signature, source_ms_out_target.keys[out_key_index], input_signatures[i])) + size_t expected_signatures_count = txin.sigs_count; + bool need_to_check_extra_sign = false; + if (get_tx_flags(tx)&TX_FLAG_SIGNATURE_MODE_SEPARATE && in_index == tx.vin.size() - 1) // last input in TX_FLAG_SIGNATURE_MODE_SEPARATE must contain one more signature to ensure that tx was completed by an authorized subject { - // match: go for the next signature and the next key - i++; - out_key_index++; + expected_signatures_count++; + need_to_check_extra_sign = true; } - else + + LOC_CHK(expected_signatures_count == input_signatures.size(), "Invalid input's signatures count: " << input_signatures.size() << ", expected: " << expected_signatures_count); + + crypto::hash tx_hash_for_signature = prepare_prefix_hash_for_sign(tx, in_index, tx_prefix_hash); + LOC_CHK(tx_hash_for_signature != null_hash, "prepare_prefix_hash_for_sign failed"); + + LOC_CHK(txin.sigs_count <= source_ms_out_target.keys.size(), "source tx invariant failed: ms output's minimum sigs == ms input's sigs_count (" << txin.sigs_count << ") is GREATHER than keys.size() = " << source_ms_out_target.keys.size()); // NOTE: sig_count == minimum_sigs as checked above + size_t out_key_index = 0; // index in source_ms_out_target.keys + for (size_t i = 0; i != txin.sigs_count; /* nothing */) { - // missmatch: go for the next key for this signature - out_key_index++; + // if we run out of keys for this signature, then it's invalid signature + LOC_CHK(out_key_index < source_ms_out_target.keys.size(), "invalid signature #" << i << ": " << input_signatures[i]); + + // check signature #i against ms output key #out_key_index + if (crypto::check_signature(tx_hash_for_signature, source_ms_out_target.keys[out_key_index], input_signatures[i])) + { + // match: go for the next signature and the next key + i++; + out_key_index++; + } + else + { + // missmatch: go for the next key for this signature + out_key_index++; + } } } + VARIANT_CASE(zarcanum_sig, s); + //@#@ + VARIANT_SWITCH_END(); + if (need_to_check_extra_sign) { - //here we check extra signature to validate that transaction was finilized by authorized subject - bool r = crypto::check_signature(tx_prefix_hash, get_tx_pub_key_from_extra(tx), tx.signatures[in_index].back()); - LOC_CHK(r, "failed to check extra signature for last out with TX_FLAG_SIGNATURE_MODE_SEPARATE"); + VARIANT_SWITCH_BEGIN(tx.signature); + VARIANT_CASE(void_sig, v); + VARIANT_CASE(NLSAG_sig, signatures) + { + //here we check extra signature to validate that transaction was finilized by authorized subject + bool r = crypto::check_signature(tx_prefix_hash, get_tx_pub_key_from_extra(tx), signatures.s[in_index].back()); + LOC_CHK(r, "failed to check extra signature for last out with TX_FLAG_SIGNATURE_MODE_SEPARATE"); + } + VARIANT_CASE(zarcanum_sig, s); + //@#@ + VARIANT_SWITCH_END(); + } return true; @@ -5155,32 +5191,43 @@ bool blockchain_storage::validate_pos_block(const block& b, return false; } + + //validate signature uint64_t max_related_block_height = 0; const txin_to_key& coinstake_in = boost::get(b.miner_tx.vin[1]); - CHECK_AND_ASSERT_MES(b.miner_tx.signatures.size() == 1, false, "PoS block's miner_tx has incorrect signatures size = " << b.miner_tx.signatures.size() << ", block_id = " << get_block_hash(b)); - if (!for_altchain) - { - // Do coinstake input validation for main chain only. - // Txs in alternative PoS blocks (including miner_tx) are validated by validate_alt_block_txs() - uint64_t source_max_unlock_time_for_pos_coinbase = 0; - r = check_tx_input(b.miner_tx, 1, coinstake_in, id, b.miner_tx.signatures[0], max_related_block_height, source_max_unlock_time_for_pos_coinbase); - CHECK_AND_ASSERT_MES(r, false, "Failed to validate coinstake input in miner tx, block_id = " << get_block_hash(b)); - if (get_block_height(b) > m_core_runtime_config.hard_forks.hard_fork_01_starts_after_height) + VARIANT_SWITCH_BEGIN(b.miner_tx.signature); + VARIANT_CASE(void_sig, v); + VARIANT_CASE(NLSAG_sig, signatures) + { + CHECK_AND_ASSERT_MES(signatures.s.size() == 1, false, "PoS block's miner_tx has incorrect signatures size = " << signatures.s.size() << ", block_id = " << get_block_hash(b)); + if (!for_altchain) { - uint64_t last_pow_h = get_last_x_block_height(false); - CHECK_AND_ASSERT_MES(max_related_block_height <= last_pow_h, false, "Failed to validate coinbase in PoS block, condition failed: max_related_block_height(" << max_related_block_height << ") <= last_pow_h(" << last_pow_h << ")"); - //let's check that coinbase amount and unlock time - r = validate_pos_coinbase_outs_unlock_time(b.miner_tx, coinstake_in.amount, source_max_unlock_time_for_pos_coinbase); - CHECK_AND_ASSERT_MES(r, false, "Failed to validate_pos_coinbase_outs_unlock_time() in miner tx, block_id = " << get_block_hash(b) - << "source_max_unlock_time_for_pos_coinbase=" << source_max_unlock_time_for_pos_coinbase); - } - else - { - CHECK_AND_ASSERT_MES(is_tx_spendtime_unlocked(source_max_unlock_time_for_pos_coinbase), false, "Failed to validate coinbase in PoS block, condition failed: is_tx_spendtime_unlocked(source_max_unlock_time_for_pos_coinbase)(" << source_max_unlock_time_for_pos_coinbase << ")"); + // Do coinstake input validation for main chain only. + // Txs in alternative PoS blocks (including miner_tx) are validated by validate_alt_block_txs() + uint64_t source_max_unlock_time_for_pos_coinbase = 0; + r = check_tx_input(b.miner_tx, 1, coinstake_in, id, signatures.s[0], max_related_block_height, source_max_unlock_time_for_pos_coinbase); + CHECK_AND_ASSERT_MES(r, false, "Failed to validate coinstake input in miner tx, block_id = " << get_block_hash(b)); + + if (get_block_height(b) > m_core_runtime_config.hard_forks.hard_fork_01_starts_after_height) + { + uint64_t last_pow_h = get_last_x_block_height(false); + CHECK_AND_ASSERT_MES(max_related_block_height <= last_pow_h, false, "Failed to validate coinbase in PoS block, condition failed: max_related_block_height(" << max_related_block_height << ") <= last_pow_h(" << last_pow_h << ")"); + //let's check that coinbase amount and unlock time + r = validate_pos_coinbase_outs_unlock_time(b.miner_tx, coinstake_in.amount, source_max_unlock_time_for_pos_coinbase); + CHECK_AND_ASSERT_MES(r, false, "Failed to validate_pos_coinbase_outs_unlock_time() in miner tx, block_id = " << get_block_hash(b) + << "source_max_unlock_time_for_pos_coinbase=" << source_max_unlock_time_for_pos_coinbase); + } + else + { + CHECK_AND_ASSERT_MES(is_tx_spendtime_unlocked(source_max_unlock_time_for_pos_coinbase), false, "Failed to validate coinbase in PoS block, condition failed: is_tx_spendtime_unlocked(source_max_unlock_time_for_pos_coinbase)(" << source_max_unlock_time_for_pos_coinbase << ")"); + } } } + VARIANT_CASE(zarcanum_sig, s); + //@#@ + VARIANT_SWITCH_END(); uint64_t block_height = for_altchain ? split_height + alt_chain.size() : m_db_blocks.size(); uint64_t coinstake_age = block_height - max_related_block_height - 1; @@ -5482,7 +5529,13 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt //If we under checkpoints, ring signatures should be pruned if(m_is_in_checkpoint_zone) { - tx.signatures.clear(); + VARIANT_SWITCH_BEGIN(tx.signature); + VARIANT_CASE(NLSAG_sig, signatures) + signatures.s.clear(); + VARIANT_CASE(zarcanum_sig, s); + //@#@ + VARIANT_SWITCH_END(); + tx.attachment.clear(); } TIME_MEASURE_START_PD(tx_add_one_tx_time); @@ -6294,12 +6347,12 @@ void blockchain_storage::calculate_local_gindex_lookup_table_for_height(uint64_t } //------------------------------------------------------------------ bool blockchain_storage::validate_alt_block_input(const transaction& input_tx, - std::unordered_set& collected_keyimages, + std::unordered_set& collected_keyimages, const txs_by_id_and_height_altchain& alt_chain_tx_ids, - const crypto::hash& bl_id, - const crypto::hash& input_tx_hash, + const crypto::hash& bl_id, + const crypto::hash& input_tx_hash, size_t input_index, - const std::vector& input_sigs, + const signature_v& input_sigs, uint64_t split_height, const alt_chain_type& alt_chain, const std::unordered_set& alt_chain_block_ids, @@ -6338,6 +6391,8 @@ bool blockchain_storage::validate_alt_block_input(const transaction& input_tx, *p_max_related_block_height = 0; CHECK_AND_ASSERT_MES(input_index < input_tx.vin.size(), false, "invalid input index: " << input_index); + + const txin_v& input_v = input_tx.vin[input_index]; const txin_to_key& input_to_key = get_to_key_input_from_txin_v(input_v); @@ -6608,12 +6663,19 @@ bool blockchain_storage::validate_alt_block_input(const transaction& input_tx, VARIANT_SWITCH_END(); } - // do input checks (attachment_info, ring signature and extra signature, etc.) - r = check_input_signature(input_tx, input_index, input_to_key, input_tx_hash, input_sigs, pub_key_pointers); - CHECK_AND_ASSERT_MES(r, false, "to_key input validation failed"); + VARIANT_SWITCH_BEGIN(input_sigs); + VARIANT_CASE(void_sig, v); + VARIANT_CASE(NLSAG_sig, signatures) + { + // do input checks (attachment_info, ring signature and extra signature, etc.) + r = check_input_signature(input_tx, input_index, input_to_key, input_tx_hash, signatures.s[input_index], pub_key_pointers); + CHECK_AND_ASSERT_MES(r, false, "to_key input validation failed"); + } + VARIANT_CASE(zarcanum_sig, s); + //@#@ + VARIANT_SWITCH_END(); // TODO: consider checking input_tx for valid extra attachment info as it's checked in check_tx_inputs() - return true; } //------------------------------------------------------------------ @@ -6684,7 +6746,7 @@ bool blockchain_storage::is_output_allowed_for_input(const output_key_or_htlc_v& } } //------------------------------------------------------------------ -bool blockchain_storage::validate_alt_block_ms_input(const transaction& input_tx, const crypto::hash& input_tx_hash, size_t input_index, const std::vector& input_sigs, uint64_t split_height, const alt_chain_type& alt_chain) const +bool blockchain_storage::validate_alt_block_ms_input(const transaction& input_tx, const crypto::hash& input_tx_hash, size_t input_index, const signature_v& input_sigs_v, uint64_t split_height, const alt_chain_type& alt_chain) const { // Main and alt chain outline: // @@ -6713,10 +6775,12 @@ bool blockchain_storage::validate_alt_block_ms_input(const transaction& input_tx CRITICAL_REGION_LOCAL(m_read_lock); bool r = false; - - CHECK_AND_ASSERT_MES(input_index < input_tx.vin.size() && input_tx.vin[input_index].type() == typeid(txin_multisig), false, "invalid ms input index: " << input_index << " or type"); + CHECK_AND_ASSERT_MES(input_index < input_tx.vin.size() + && input_tx.vin[input_index].type() == typeid(txin_multisig) + && input_tx.signature.type() == typeid(NLSAG_sig), false, "invalid ms input index: " << input_index << " or type"); const txin_multisig& input = boost::get(input_tx.vin[input_index]); + const std::vector& input_sigs = boost::get(input_tx.signature).s[input_index]; // check corresponding ms out in the main chain auto p = m_db_multisig_outs.get(input.multisig_out_id); if (p != nullptr) @@ -6904,12 +6968,22 @@ bool blockchain_storage::validate_alt_block_txs(const block& b, const crypto::ha if (is_pos_block(b)) { - // check PoS block miner tx in a special way - CHECK_AND_ASSERT_MES(b.miner_tx.signatures.size() == 1 && b.miner_tx.vin.size() == 2, false, "invalid PoS block's miner_tx, signatures size = " << b.miner_tx.signatures.size() << ", miner_tx.vin.size() = " << b.miner_tx.vin.size()); uint64_t max_related_block_height = 0; uint64_t ki_lookup = 0; - r = validate_alt_block_input(b.miner_tx, collected_keyimages, alt_chain_tx_ids, id, get_block_hash(b), 1, b.miner_tx.signatures[0], split_height, alt_chain, alt_chain_block_ids, ki_lookup, &max_related_block_height); - CHECK_AND_ASSERT_MES(r, false, "miner tx " << get_transaction_hash(b.miner_tx) << ": validation failed"); + + // check PoS block miner tx in a special way + VARIANT_SWITCH_BEGIN(b.miner_tx.signature); + VARIANT_CASE(void_sig, v); + VARIANT_CASE(NLSAG_sig, signatures); + { + CHECK_AND_ASSERT_MES(signatures.s.size() == 1 && b.miner_tx.vin.size() == 2, false, "invalid PoS block's miner_tx, signatures size = " << signatures.s.size() << ", miner_tx.vin.size() = " << b.miner_tx.vin.size()); + r = validate_alt_block_input(b.miner_tx, collected_keyimages, alt_chain_tx_ids, id, get_block_hash(b), 1, signatures.s[0], split_height, alt_chain, alt_chain_block_ids, ki_lookup, &max_related_block_height); + CHECK_AND_ASSERT_MES(r, false, "miner tx " << get_transaction_hash(b.miner_tx) << ": validation failed"); + } + VARIANT_CASE(zarcanum_sig, s); + //@#@ + VARIANT_SWITCH_END(); + ki_lookup_time_total += ki_lookup; // check stake age uint64_t coinstake_age = height - max_related_block_height - 1; @@ -6929,19 +7003,22 @@ bool blockchain_storage::validate_alt_block_txs(const block& b, const crypto::ha CHECK_AND_ASSERT_MES(get_transaction_from_pool_or_db(tx_id, tx_ptr, split_height), false, "failed to get alt block tx " << tx_id << " with split_height == " << split_height); } const transaction& tx = it == abei.onboard_transactions.end() ? *tx_ptr : it->second; - CHECK_AND_ASSERT_MES(tx.signatures.size() == tx.vin.size(), false, "invalid tx: tx.signatures.size() == " << tx.signatures.size() << ", tx.vin.size() == " << tx.vin.size()); + if (tx.signature.type() == typeid(NLSAG_sig)) + { + CHECK_AND_ASSERT_MES(boost::get(tx.signature).s.size() == tx.vin.size(), false, "invalid tx: tx.signatures.size() == " << boost::get(tx.signature).s.size() << ", tx.vin.size() == " << tx.vin.size()); + } for (size_t n = 0; n < tx.vin.size(); ++n) { if (tx.vin[n].type() == typeid(txin_to_key) || tx.vin[n].type() == typeid(txin_htlc)) { uint64_t ki_lookup = 0; - r = validate_alt_block_input(tx, collected_keyimages, alt_chain_tx_ids, id, tx_id, n, tx.signatures[n], split_height, alt_chain, alt_chain_block_ids, ki_lookup); + r = validate_alt_block_input(tx, collected_keyimages, alt_chain_tx_ids, id, tx_id, n, tx.signature, split_height, alt_chain, alt_chain_block_ids, ki_lookup); CHECK_AND_ASSERT_MES(r, false, "tx " << tx_id << ", input #" << n << ": validation failed"); ki_lookup_time_total += ki_lookup; } else if (tx.vin[n].type() == typeid(txin_multisig)) { - r = validate_alt_block_ms_input(tx, tx_id, n, tx.signatures[n], split_height, alt_chain); + r = validate_alt_block_ms_input(tx, tx_id, n, tx.signature, split_height, alt_chain); CHECK_AND_ASSERT_MES(r, false, "tx " << tx_id << ", input #" << n << " (multisig): validation failed"); } else if (tx.vin[n].type() == typeid(txin_gen)) diff --git a/src/currency_core/blockchain_storage.h b/src/currency_core/blockchain_storage.h index 2a182323..ef864b8a 100644 --- a/src/currency_core/blockchain_storage.h +++ b/src/currency_core/blockchain_storage.h @@ -286,13 +286,13 @@ namespace currency uint64_t get_aliases_count()const; uint64_t get_block_h_older_then(uint64_t timestamp) const; bool validate_tx_service_attachmens_in_services(const tx_service_attachment& a, size_t i, const transaction& tx)const; - bool check_tx_input(const transaction& tx, size_t in_index, const txin_to_key& txin, const crypto::hash& tx_prefix_hash, const std::vector& sig, uint64_t& max_related_block_height, uint64_t& source_max_unlock_time_for_pos_coinbase)const; - bool check_tx_input(const transaction& tx, size_t in_index, const txin_multisig& txin, const crypto::hash& tx_prefix_hash, const std::vector& sig, uint64_t& max_related_block_height)const; - bool check_tx_input(const transaction& tx, size_t in_index, const txin_htlc& txin, const crypto::hash& tx_prefix_hash, const std::vector& sig, uint64_t& max_related_block_height)const; + bool check_tx_input(const transaction& tx, size_t in_index, const txin_to_key& txin, const crypto::hash& tx_prefix_hash, const signature_v& sig, uint64_t& max_related_block_height, uint64_t& source_max_unlock_time_for_pos_coinbase)const; + bool check_tx_input(const transaction& tx, size_t in_index, const txin_multisig& txin, const crypto::hash& tx_prefix_hash, const signature_v& sig, uint64_t& max_related_block_height)const; + bool check_tx_input(const transaction& tx, size_t in_index, const txin_htlc& txin, const crypto::hash& tx_prefix_hash, const signature_v& sig, uint64_t& max_related_block_height)const; bool check_tx_inputs(const transaction& tx, const crypto::hash& tx_prefix_hash, uint64_t& max_used_block_height)const; bool check_tx_inputs(const transaction& tx, const crypto::hash& tx_prefix_hash) const; bool check_tx_inputs(const transaction& tx, const crypto::hash& tx_prefix_hash, uint64_t& max_used_block_height, crypto::hash& max_used_block_id)const; - bool check_ms_input(const transaction& tx, size_t in_index, const txin_multisig& txin, const crypto::hash& tx_prefix_hash, const std::vector& sig, const transaction& source_tx, size_t out_n) const; + bool check_ms_input(const transaction& tx, size_t in_index, const txin_multisig& txin, const crypto::hash& tx_prefix_hash, const signature_v& sig, const transaction& source_tx, size_t out_n) const; bool validate_tx_for_hardfork_specific_terms(const transaction& tx, const crypto::hash& tx_id, uint64_t block_height) const; bool validate_tx_for_hardfork_specific_terms(const transaction& tx, const crypto::hash& tx_id) const; bool get_output_keys_for_input_with_checks(const transaction& tx, const txin_v& verified_input, std::vector& output_keys, uint64_t& max_related_block_height, uint64_t& source_max_unlock_time_for_pos_coinbase, scan_for_keys_context& scan_context) const; @@ -597,13 +597,18 @@ namespace currency const crypto::hash& bl_id, const crypto::hash& input_tx_hash, size_t input_index, - const std::vector& input_sigs, + const signature_v& input_sigs, //const std::vector& input_sigs, uint64_t split_height, const alt_chain_type& alt_chain, const std::unordered_set& alt_chain_block_ids, uint64_t& ki_lookuptime, uint64_t* p_max_related_block_height = nullptr) const; - bool validate_alt_block_ms_input(const transaction& input_tx, const crypto::hash& input_tx_hash, size_t input_index, const std::vector& input_sigs, uint64_t split_height, const alt_chain_type& alt_chain) const; + bool validate_alt_block_ms_input(const transaction& input_tx, + const crypto::hash& input_tx_hash, + size_t input_index, + const signature_v& input_sigs,//const std::vector& input_sigs, + uint64_t split_height, + const alt_chain_type& alt_chain) const; bool validate_alt_block_txs(const block& b, const crypto::hash& id, std::unordered_set& collected_keyimages, alt_block_extended_info& abei, const alt_chain_type& alt_chain, uint64_t split_height, uint64_t& ki_lookup_time_total) const; bool update_alt_out_indexes_for_tx_in_block(const transaction& tx, alt_block_extended_info& abei)const; bool get_transaction_from_pool_or_db(const crypto::hash& tx_id, std::shared_ptr& tx_ptr, uint64_t min_allowed_block_height = 0) const; diff --git a/src/currency_core/currency_format_utils.cpp b/src/currency_core/currency_format_utils.cpp index ebe8db6f..d02623d2 100644 --- a/src/currency_core/currency_format_utils.cpp +++ b/src/currency_core/currency_format_utils.cpp @@ -196,8 +196,9 @@ namespace currency posin.k_image = pe.keyimage; tx.vin.push_back(posin); //reserve place for ring signature - tx.signatures.resize(1); - tx.signatures[0].resize(posin.key_offsets.size()); + tx.signature = NLSAG_sig(); + boost::get(tx.signature).s.resize(1); + boost::get(tx.signature).s[0].resize(posin.key_offsets.size()); } uint64_t no = 0; @@ -1530,8 +1531,8 @@ namespace currency crypto::hash tx_hash_for_signature = prepare_prefix_hash_for_sign(tx, input_index, tx_prefix_hash); CHECK_AND_ASSERT_MES(tx_hash_for_signature != null_hash, false, "failed to prepare_prefix_hash_for_sign"); - tx.signatures.push_back(std::vector()); - std::vector& sigs = tx.signatures.back(); + boost::get(tx.signature).s.push_back(std::vector()); + std::vector& sigs = boost::get(tx.signature).s.back(); if(src_entr.is_multisig()) { @@ -1681,9 +1682,13 @@ namespace currency size_t participant_index = std::find(out_ms.keys.begin(), out_ms.keys.end(), ms_in_ephemeral_key.pub) - out_ms.keys.begin(); LOC_CHK(participant_index < out_ms.keys.size(), "Can't find given participant's ms key in ms output keys list"); - LOC_CHK(ms_input_index < tx.signatures.size(), "transaction does not have signatures vectory entry for ms input #" << ms_input_index); + + //@#@ + LOC_CHK(tx.signature.type() == typeid(NLSAG_sig), "Wrong type of signature"); - auto& sigs = tx.signature[ms_input_index]; + LOC_CHK(ms_input_index < boost::get(tx.signature).s.size(), "transaction does not have signatures vector entry for ms input #" << ms_input_index); + + auto& sigs = boost::get(tx.signature).s[ms_input_index]; LOC_CHK(!sigs.empty(), "empty signatures container"); bool extra_signature_expected = (get_tx_flags(tx) & TX_FLAG_SIGNATURE_MODE_SEPARATE) && ms_input_index == tx.vin.size() - 1; @@ -2856,8 +2861,8 @@ namespace currency txin_multisig& tms = boost::get(in); tei.ins.back().amount = tms.amount; tei.ins.back().kimage_or_ms_id = epee::string_tools::pod_to_hex(tms.multisig_out_id); - if (tx.signatures.size() >= tei.ins.size()) - tei.ins.back().multisig_count = tx.signatures[tei.ins.size() - 1].size(); + if (tx.signature.type() == typeid(NLSAG_sig) && boost::get(tx.signature).s.size() >= tei.ins.size()) + tei.ins.back().multisig_count = boost::get(tx.signature).s[tei.ins.size() - 1].size(); } } return true; diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 45afefbe..b69178fe 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -832,10 +832,11 @@ void wallet2::accept_proposal(const crypto::hash& contract_id, uint64_t b_accept tdb.m_flags &= ~(WALLET_TRANSFER_DETAIL_FLAG_SPENT); //--------------------------------- //figure out fee that was left for release contract - THROW_IF_FALSE_WALLET_INT_ERR_EX(tx.vout[n].amount > (contr_it->second.private_detailes.amount_to_pay + + THROW_IF_FALSE_WALLET_INT_ERR_EX(tx.vout[n].type() == typeid(tx_out_bare), "Unexpected output type in accept proposal"); + THROW_IF_FALSE_WALLET_INT_ERR_EX(boost::get(tx.vout[n]).amount > (contr_it->second.private_detailes.amount_to_pay + contr_it->second.private_detailes.amount_b_pledge + contr_it->second.private_detailes.amount_a_pledge), "THere is no left money for fee, contract_id: " << contract_id); - uint64_t left_for_fee_in_multisig = tx.vout[n].amount - (contr_it->second.private_detailes.amount_to_pay + + uint64_t left_for_fee_in_multisig = boost::get(tx.vout[n]).amount - (contr_it->second.private_detailes.amount_to_pay + contr_it->second.private_detailes.amount_b_pledge + contr_it->second.private_detailes.amount_a_pledge); @@ -1400,7 +1401,8 @@ void wallet2::unprocess_htlc_triggers_on_block_removed(uint64_t height) tr.m_spent_height = 0; } //re-add to active contracts - auto pair_key = std::make_pair(tr.m_ptx_wallet_info->m_tx.vout[tr.m_internal_output_index].amount, tr.m_global_output_index); + THROW_IF_FALSE_WALLET_EX(tr.m_ptx_wallet_info->m_tx.vout[tr.m_internal_output_index].type() == typeid(tx_out_bare), "Unexprected type of out in unprocess_htlc_triggers_on_block_removed : " << tr.m_ptx_wallet_info->m_tx.vout[tr.m_internal_output_index].type().name()); + auto pair_key = std::make_pair(boost::get(tr.m_ptx_wallet_info->m_tx.vout[tr.m_internal_output_index]).amount, tr.m_global_output_index); auto it_active_htlc = m_active_htlcs.find(pair_key); if (it_active_htlc != m_active_htlcs.end()) { @@ -1462,7 +1464,10 @@ void wallet2::process_htlc_triggers_on_block_added(uint64_t height) m_found_free_amounts.clear(); //remove it from active contracts - auto it_active_htlc = m_active_htlcs.find(std::make_pair(tr.m_ptx_wallet_info->m_tx.vout[tr.m_internal_output_index].amount, tr.m_global_output_index)); + CHECK_AND_ASSERT_MES(tr.m_ptx_wallet_info->m_tx.vout[tr.m_internal_output_index].type() == typeid(tx_out_bare), void(), "Unexpected type out in process_htlc_triggers_on_block_added: " << tr.m_ptx_wallet_info->m_tx.vout[tr.m_internal_output_index].type().name()); + uint64_t amount = boost::get(tr.m_ptx_wallet_info->m_tx.vout[tr.m_internal_output_index]).amount; + + auto it_active_htlc = m_active_htlcs.find(std::make_pair(, tr.m_global_output_index)); if (it_active_htlc == m_active_htlcs.end()) { LOG_ERROR("Erasing active htlc(m_active_htlcs), but it seems to be already erased"); @@ -2158,7 +2163,8 @@ bool wallet2::scan_unconfirmed_outdate_tx() if (t.m_flags&WALLET_TRANSFER_DETAIL_FLAG_SPENT && !t.m_spent_height && !static_cast(t.m_flags&WALLET_TRANSFER_DETAIL_FLAG_ESCROW_PROPOSAL_RESERVATION) - && t.m_ptx_wallet_info->m_tx.vout[t.m_internal_output_index].target.type() != typeid(txout_htlc) + && t.m_ptx_wallet_info->m_tx.vout[t.m_internal_output_index].type() == typeid(tx_out_bare) + && boost::get(t.m_ptx_wallet_info->m_tx.vout[t.m_internal_output_index]).target.type() != typeid(txout_htlc) ) { //check if there is unconfirmed for this transfer is no longer exist? @@ -2331,10 +2337,11 @@ void wallet2::detach_blockchain(uint64_t including_height) for (size_t i = i_start; i != m_transfers.size(); i++) { //check for htlc - if (m_transfers[i].m_ptx_wallet_info->m_tx.vout[m_transfers[i].m_internal_output_index].target.type() == typeid(txout_htlc)) + if (m_transfers[i].m_ptx_wallet_info->m_tx.vout[m_transfers[i].m_internal_output_index].type() == typeid(tx_out_bare) && + boost::get(m_transfers[i].m_ptx_wallet_info->m_tx.vout[m_transfers[i].m_internal_output_index]).target.type() == typeid(txout_htlc)) { //need to find an entry in m_htlc and remove it - const txout_htlc& hltc = boost::get(m_transfers[i].m_ptx_wallet_info->m_tx.vout[m_transfers[i].m_internal_output_index].target); + const txout_htlc& hltc = boost::get(boost::get(m_transfers[i].m_ptx_wallet_info->m_tx.vout[m_transfers[i].m_internal_output_index]).target); uint64_t expiration_height = m_transfers[i].m_ptx_wallet_info->m_block_height + hltc.expiration; auto pair_of_it = m_htlcs.equal_range(expiration_height); bool found = false; @@ -2900,7 +2907,9 @@ void wallet2::store_watch_only(const std::wstring& path_to_save, const std::stri if (!td.is_spent()) continue; // only spent transfers really need to be stored, because watch-only wallet will not be able to figure out they were spent otherwise WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(td.m_internal_output_index < td.m_ptx_wallet_info->m_tx.vout.size(), "invalid transfer #" << ti); - const currency::txout_target_v& out_t = td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index].target; + if(td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index].type() != typeid(tx_out_bare)) + continue; + const currency::txout_target_v& out_t = boost::get(td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index]).target; if (out_t.type() != typeid(currency::txout_to_key)) continue; const crypto::public_key& out_key = boost::get(out_t).key; @@ -3083,28 +3092,34 @@ void wallet2::sign_transfer(const std::string& tx_sources_blob, std::string& sig for (size_t i = 0; i < ft.tx.vout.size(); ++i) { - const auto& out = ft.tx.vout[i]; - if (out.target.type() != typeid(txout_to_key)) - continue; - const txout_to_key& otk = boost::get(out.target); - - crypto::public_key ephemeral_pub = AUTO_VAL_INIT(ephemeral_pub); - if (!crypto::derive_public_key(derivation, i, m_account.get_keys().account_address.spend_public_key, ephemeral_pub)) + VARIANT_SWITCH_BEGIN(ft.tx.vout[i]); + VARIANT_CASE(tx_out_bare, out) { - WLT_LOG_ERROR("derive_public_key failed for tx " << get_transaction_hash(ft.tx) << ", out # " << i); - } + if (out.target.type() != typeid(txout_to_key)) + continue; + const txout_to_key& otk = boost::get(out.target); - if (otk.key == ephemeral_pub) - { - // this is the output to the given keys - // derive secret key and calculate key image - crypto::secret_key ephemeral_sec = AUTO_VAL_INIT(ephemeral_sec); - crypto::derive_secret_key(derivation, i, m_account.get_keys().spend_secret_key, ephemeral_sec); - crypto::key_image ki = AUTO_VAL_INIT(ki); - crypto::generate_key_image(ephemeral_pub, ephemeral_sec, ki); + crypto::public_key ephemeral_pub = AUTO_VAL_INIT(ephemeral_pub); + if (!crypto::derive_public_key(derivation, i, m_account.get_keys().account_address.spend_public_key, ephemeral_pub)) + { + WLT_LOG_ERROR("derive_public_key failed for tx " << get_transaction_hash(ft.tx) << ", out # " << i); + } - ft.outs_key_images.push_back(make_serializable_pair(static_cast(i), ki)); + if (otk.key == ephemeral_pub) + { + // this is the output to the given keys + // derive secret key and calculate key image + crypto::secret_key ephemeral_sec = AUTO_VAL_INIT(ephemeral_sec); + crypto::derive_secret_key(derivation, i, m_account.get_keys().spend_secret_key, ephemeral_sec); + crypto::key_image ki = AUTO_VAL_INIT(ki); + crypto::generate_key_image(ephemeral_pub, ephemeral_sec, ki); + + ft.outs_key_images.push_back(make_serializable_pair(static_cast(i), ki)); + } } + VARIANT_CASE_TV(tx_out_zarcanum); + //@#@ + VARIANT_SWITCH_END(); } // serialize and encrypt the result @@ -3175,7 +3190,8 @@ void wallet2::submit_transfer(const std::string& signed_tx_blob, currency::trans for (auto& p : ft.outs_key_images) { THROW_IF_FALSE_WALLET_INT_ERR_EX(p.first < tx.vout.size(), "outs_key_images has invalid out index: " << p.first << ", tx.vout.size() = " << tx.vout.size()); - auto& out = tx.vout[p.first]; + THROW_IF_FALSE_WALLET_INT_ERR_EX(tx.vout[p.first].type() == typeid(tx_out_bare), "Unexpected type in submit_transfer: " << tx.vout[p.first].type().name()); + auto& out = boost::get(tx.vout[p.first]); THROW_IF_FALSE_WALLET_INT_ERR_EX(out.target.type() == typeid(txout_to_key), "outs_key_images has invalid out type, index: " << p.first); const txout_to_key& otk = boost::get(out.target); pk_ki_to_be_added.push_back(std::make_pair(otk.key, p.second)); @@ -3643,7 +3659,12 @@ bool wallet2::build_minted_block(const currency::COMMAND_RPC_SCAN_POS::request& WLT_CHECK_AND_ASSERT_MES(req.pos_entries[rsp.index].wallet_index < m_transfers.size(), false, "Wrong wallet_index at generating coinbase transacton"); - const auto& target = m_transfers[req.pos_entries[rsp.index].wallet_index].m_ptx_wallet_info->m_tx.vout[m_transfers[req.pos_entries[rsp.index].wallet_index].m_internal_output_index].target; + if (m_transfers[req.pos_entries[rsp.index].wallet_index].m_ptx_wallet_info->m_tx.vout[m_transfers[req.pos_entries[rsp.index].wallet_index].m_internal_output_index].type() != typeid(tx_out_bare)) + { + //@#@ review zarcanum here + return false; + } + const auto& target = boost::get(m_transfers[req.pos_entries[rsp.index].wallet_index].m_ptx_wallet_info->m_tx.vout[m_transfers[req.pos_entries[rsp.index].wallet_index].m_internal_output_index]).target; WLT_CHECK_AND_ASSERT_MES(target.type() == typeid(currency::txout_to_key), false, "wrong type_id in source transaction in coinbase tx"); const currency::txout_to_key& txtokey = boost::get(target); @@ -4312,10 +4333,17 @@ void wallet2::get_list_of_active_htlc(std::list& } wallet_public::htlc_entry_info entry = AUTO_VAL_INIT(entry); entry.tx_id = htlc_entry.first; - entry.amount = td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index].amount; - WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index].target.type() == typeid(txout_htlc), + if (td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index].type() != typeid(tx_out_bare)) + { + //@#@ + LOG_ERROR("Unexpected output type in get_list_of_active_htlc:" << td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index].type().name()); + continue; + } + const tx_out_bare out_b = boost::get(td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index]); + entry.amount = out_b.amount; + WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(out_b.target.type() == typeid(txout_htlc), "[get_list_of_active_htlc]Internal error: unexpected type of out"); - const txout_htlc& htlc = boost::get(td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index].target); + const txout_htlc& htlc = boost::get(out_b.target); entry.sha256_hash = htlc.htlc_hash; currency::tx_payer payer = AUTO_VAL_INIT(payer); @@ -4510,26 +4538,33 @@ bool wallet2::prepare_tx_sources(size_t fake_outputs_count, std::vectorm_tx.vout[td.m_internal_output_index].target.type() == typeid(txout_to_key)) + //@#@ + VARIANT_SWITCH_BEGIN(td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index]); + VARIANT_CASE(tx_out_bare, o) { - real_oe.second = boost::get(td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index].target).key; - } - else if (td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index].target.type() == typeid(txout_htlc)) - { - real_oe.second = boost::get(td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index].target).pkey_refund; - } - else - { - WLT_THROW_IF_FALSE_WITH_CODE(false, - "Internal error: unexpected type of target: " << td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index].target.type().name(), - API_RETURN_CODE_INTERNAL_ERROR); - } + VARIANT_SWITCH_BEGIN(o); + VARIANT_CASE(txout_to_key, o) + real_oe.second = o.key; + VARIANT_CASE(txout_htlc, htlc) + real_oe.second = htlc.pkey_refund; + VARIANT_CASE_OTHER() + { + WLT_THROW_IF_FALSE_WITH_CODE(false, + "Internal error: unexpected type of target: " << o.target.type().name(), + API_RETURN_CODE_INTERNAL_ERROR); + } + VARIANT_SWITCH_END(); - auto interted_it = src.outputs.insert(it_to_insert, real_oe); - src.real_out_tx_key = get_tx_pub_key_from_extra(td.m_ptx_wallet_info->m_tx); - src.real_output = interted_it - src.outputs.begin(); - src.real_output_in_tx_index = td.m_internal_output_index; - print_source_entry(src); + auto interted_it = src.outputs.insert(it_to_insert, real_oe); + src.real_out_tx_key = get_tx_pub_key_from_extra(td.m_ptx_wallet_info->m_tx); + src.real_output = interted_it - src.outputs.begin(); + src.real_output_in_tx_index = td.m_internal_output_index; + print_source_entry(src); + } + VARIANT_CASE_TV(tx_out_zarcanum); + //@#@ + VARIANT_SWITCH_END(); + ++i; } return true; @@ -4542,7 +4577,9 @@ bool wallet2::prepare_tx_sources(crypto::hash multisig_id, std::vectorsecond.is_spent(), "output with multisig_id: " + epee::string_tools::pod_to_hex(multisig_id) + " has already been spent by other party at height " + epee::string_tools::num_to_string_fast(it->second.m_spent_height)); THROW_IF_FALSE_WALLET_INT_ERR_EX(it->second.m_internal_output_index < it->second.m_ptx_wallet_info->m_tx.vout.size(), "it->second.m_internal_output_index < it->second.m_tx.vout.size()"); - const tx_out_bare& out = it->second.m_ptx_wallet_info->m_tx.vout[it->second.m_internal_output_index]; + //@#@ + THROW_IF_FALSE_WALLET_INT_ERR_EX(it->second.m_ptx_wallet_info->m_tx.vout[it->second.m_internal_output_index].type() == typeid(tx_out_bare), "Unknown type id in prepare_tx_sources: " << it->second.m_ptx_wallet_info->m_tx.vout[it->second.m_internal_output_index].type().name()); + const tx_out_bare& out = boost::get(it->second.m_ptx_wallet_info->m_tx.vout[it->second.m_internal_output_index]); THROW_IF_FALSE_WALLET_INT_ERR_EX(out.target.type() == typeid(txout_multisig), "ms out target type is " << out.target.type().name() << ", expected: txout_multisig"); const txout_multisig& ms_out = boost::get(out.target); @@ -4571,11 +4608,16 @@ bool wallet2::prepare_tx_sources_htlc(crypto::hash htlc_tx_id, const std::string WLT_THROW_IF_FALSE_WITH_CODE(m_transfers.size() > it->second, "Internal error: index in m_active_htlcs_txid <" << it->second << "> is bigger then size of m_transfers <" << m_transfers.size() << ">", API_RETURN_CODE_INTERNAL_ERROR); + //@#@ + WLT_THROW_IF_FALSE_WITH_CODE(td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index].type() == typeid(tx_out_bare), + "Unexpected out type in prepare_tx_sources_htlc:" << td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index].type().name()); + + const tx_out_bare& out_bare = boost::get(td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index]); const transfer_details& td = m_transfers[it->second]; - WLT_THROW_IF_FALSE_WITH_CODE(td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index].target.type() == typeid(txout_htlc), + WLT_THROW_IF_FALSE_WITH_CODE(out_bare.target.type() == typeid(txout_htlc), "Unexpected type in active htlc", API_RETURN_CODE_INTERNAL_ERROR); - const txout_htlc& htlc_out = boost::get(td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index].target); + const txout_htlc& htlc_out = boost::get(out_bare.target); bool use_sha256 = !(htlc_out.flags&CURRENCY_TXOUT_HTLC_FLAGS_HASH_TYPE_MASK); //check origin @@ -4958,18 +5000,23 @@ bool wallet2::is_transfer_able_to_go(const transfer_details& td, uint64_t fake_o { if (!td.is_spendable()) return false; - - if (td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index].target.type() == typeid(txout_htlc)) + VARIANT_SWITCH_BEGIN(td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index]); + VARIANT_CASE(tx_out_bare, o); { - if (fake_outputs_count != 0) - return false; + if (o.target.type() == typeid(txout_htlc)) + { + if (fake_outputs_count != 0) + return false; + } + else + { + if (!currency::is_mixattr_applicable_for_fake_outs_counter(boost::get(o.target).mix_attr, fake_outputs_count)) + return false; + } } - else - { - if (!currency::is_mixattr_applicable_for_fake_outs_counter(boost::get(td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index].target).mix_attr, fake_outputs_count)) - return false; - } - + VARIANT_CASE_TV(tx_out_zarcanum); + //@#@ + VARIANT_SWITCH_END(); return true; } //---------------------------------------------------------------------------------------------------- @@ -4985,7 +5032,8 @@ bool wallet2::prepare_free_transfers_cache(uint64_t fake_outputs_count) const transfer_details& td = m_transfers[i]; if (is_transfer_able_to_go(td, fake_outputs_count)) { - m_found_free_amounts[td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index].amount].insert(i); + //@#@ + boost::get(m_found_free_amounts[td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index].amount]).insert(i); count++; } } @@ -4998,8 +5046,9 @@ bool wallet2::prepare_free_transfers_cache(uint64_t fake_outputs_count) //---------------------------------------------------------------------------------------------------- void wallet2::add_transfers_to_transfers_cache(const std::vector& indexs) { + //@#@ for (auto i : indexs) - add_transfer_to_transfers_cache(m_transfers[i].m_ptx_wallet_info->m_tx.vout[m_transfers[i].m_internal_output_index].amount , i); + add_transfer_to_transfers_cache(boost::get(m_transfers[i].m_ptx_wallet_info->m_tx.vout[m_transfers[i].m_internal_output_index]).amount , i); } //---------------------------------------------------------------------------------------------------- void wallet2::add_transfer_to_transfers_cache(uint64_t amount, uint64_t index) @@ -5668,7 +5717,11 @@ void wallet2::sweep_below(size_t fake_outs_count, const currency::account_public }); tx_output_entry real_oe; real_oe.first = td.m_global_output_index; - real_oe.second = boost::get(td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index].target).key; + //@#@ + if(td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index].type() != typeid(tx_out_bare)) + continue; + const tx_out_bare& out_b = boost::get(td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index]); + real_oe.second = boost::get(out_b.target).key; auto inserted_it = src.outputs.insert(it_to_insert, real_oe); src.real_out_tx_key = get_tx_pub_key_from_extra(td.m_ptx_wallet_info->m_tx); src.real_output = inserted_it - src.outputs.begin(); diff --git a/tests/core_tests/alias_tests.cpp b/tests/core_tests/alias_tests.cpp index a3d79bc8..761caea9 100644 --- a/tests/core_tests/alias_tests.cpp +++ b/tests/core_tests/alias_tests.cpp @@ -884,8 +884,8 @@ bool gen_alias_reg_with_locked_money::generate(std::vector& ev ai.m_address = miner_acc.get_public_address(); currency::tx_source_entry se = AUTO_VAL_INIT(se); - se.amount = blk_0.miner_tx.vout[0].amount; - se.outputs.push_back(make_serializable_pair(0, boost::get(blk_0.miner_tx.vout[0].target).key)); + se.amount = blk_0.boost::get(miner_tx.vout[0]).amount; + se.outputs.push_back(make_serializable_pair(0, boost::get(blk_0.boost::get(miner_tx.vout[0]).target).key)); se.real_output = 0; se.real_output_in_tx_index = 0; se.real_out_tx_key = currency::get_tx_pub_key_from_extra(blk_0.miner_tx); @@ -1159,8 +1159,8 @@ bool gen_alias_tx_no_outs::generate(std::vector& events) const ai.m_address = miner_acc.get_public_address(); currency::tx_source_entry se = AUTO_VAL_INIT(se); - se.amount = blk_0.miner_tx.vout[0].amount; - se.outputs.push_back(make_serializable_pair(0, boost::get(blk_0.miner_tx.vout[0].target).key)); + se.amount = blk_0.boost::get(miner_tx.vout[0]).amount; + se.outputs.push_back(make_serializable_pair(0, boost::get(blk_0.boost::get(miner_tx.vout[0]).target).key)); se.real_output = 0; se.real_output_in_tx_index = 0; se.real_out_tx_key = currency::get_tx_pub_key_from_extra(blk_0.miner_tx); diff --git a/tests/core_tests/block_reward.cpp b/tests/core_tests/block_reward.cpp index 8f59fc93..1550175a 100644 --- a/tests/core_tests/block_reward.cpp +++ b/tests/core_tests/block_reward.cpp @@ -59,9 +59,9 @@ bool block_template_against_txs_size::c1(currency::core& c, size_t ev_index, con keypair ephemeral = AUTO_VAL_INIT(ephemeral); r = generate_key_image_helper(miner_acc.get_keys(), get_tx_pub_key_from_extra(blk_0.miner_tx), 0, ephemeral, ki); CHECK_AND_ASSERT_MES(r, false, "generate_key_image_helper failed"); - CHECK_AND_ASSERT_MES(boost::get(blk_0.miner_tx.vout[0].target).key == ephemeral.pub, false, "ephemeral.pub doesn't match with output key"); + CHECK_AND_ASSERT_MES(boost::get(blk_0.boost::get(miner_tx.vout[0]).target).key == ephemeral.pub, false, "ephemeral.pub doesn't match with output key"); pos_entry pe = AUTO_VAL_INIT(pe); - pe.amount = blk_0.miner_tx.vout[0].amount; + pe.amount = blk_0.boost::get(miner_tx.vout[0]).amount; pe.block_timestamp = UINT64_MAX; // doesn't matter pe.index = 0; // global index pe.keyimage = ki; diff --git a/tests/core_tests/block_validation.cpp b/tests/core_tests/block_validation.cpp index 2653e67a..9b7915b7 100644 --- a/tests/core_tests/block_validation.cpp +++ b/tests/core_tests/block_validation.cpp @@ -311,8 +311,8 @@ bool gen_block_miner_tx_has_2_in::generate(std::vector& events GENERATE_ACCOUNT(alice); tx_source_entry se = AUTO_VAL_INIT(se); - se.amount = blk_0.miner_tx.vout[0].amount; - se.outputs.push_back(make_serializable_pair(0, boost::get(blk_0.miner_tx.vout[0].target).key)); + se.amount = blk_0.boost::get(miner_tx.vout[0]).amount; + se.outputs.push_back(make_serializable_pair(0, boost::get(blk_0.boost::get(miner_tx.vout[0]).target).key)); se.real_output = 0; se.real_out_tx_key = get_tx_pub_key_from_extra(blk_0.miner_tx); se.real_output_in_tx_index = 0; @@ -356,8 +356,8 @@ bool gen_block_miner_tx_with_txin_to_key::generate(std::vector REWIND_BLOCKS(events, blk_1r, blk_1, miner_account); tx_source_entry se = AUTO_VAL_INIT(se); - se.amount = blk_1.miner_tx.vout[0].amount; - se.outputs.push_back(make_serializable_pair(0, boost::get(blk_1.miner_tx.vout[0].target).key)); + se.amount = blk_1.boost::get(miner_tx.vout[0]).amount; + se.outputs.push_back(make_serializable_pair(0, boost::get(blk_1.boost::get(miner_tx.vout[0]).target).key)); se.real_output = 0; se.real_out_tx_key = get_tx_pub_key_from_extra(blk_1.miner_tx); se.real_output_in_tx_index = 0; @@ -393,7 +393,7 @@ bool gen_block_miner_tx_out_is_small::generate(std::vector& ev BLOCK_VALIDATION_INIT_GENERATE(); MAKE_MINER_TX_MANUALLY(miner_tx, blk_0); - miner_tx.vout[0].amount /= 2; +boost::get( miner_tx.vout[0]).amount /= 2; block blk_1; generator.construct_block_manually(blk_1, blk_0, miner_account, test_generator::bf_miner_tx, 0, 0, 0, crypto::hash(), 0, miner_tx); @@ -409,7 +409,7 @@ bool gen_block_miner_tx_out_is_big::generate(std::vector& even BLOCK_VALIDATION_INIT_GENERATE(); MAKE_MINER_TX_MANUALLY(miner_tx, blk_0); - miner_tx.vout[0].amount *= 2; +boost::get( miner_tx.vout[0]).amount *= 2; block blk_1; generator.construct_block_manually(blk_1, blk_0, miner_account, test_generator::bf_miner_tx, 0, 0, 0, crypto::hash(), 0, miner_tx); @@ -451,8 +451,8 @@ bool gen_block_miner_tx_has_out_to_alice::generate(std::vector crypto::derive_public_key(derivation, 1, alice.get_keys().account_address.spend_public_key, out_eph_public_key); tx_out_bare out_to_alice; - out_to_alice.amount = miner_tx.vout[0].amount / 2; - miner_tx.vout[0].amount -= out_to_alice.amount; + out_to_alice.amount =boost::get( miner_tx.vout[0]).amount / 2; +boost::get( miner_tx.vout[0]).amount -= out_to_alice.amount; out_to_alice.target = txout_to_key(out_eph_public_key); miner_tx.vout.push_back(out_to_alice); @@ -491,7 +491,7 @@ bool gen_block_is_too_big::generate(std::vector& events) const uint64_t amount = get_outs_money_amount(miner_tx); uint64_t portion = amount / tx_out_count; uint64_t remainder = amount % tx_out_count; - txout_target_v target = miner_tx.vout[0].target; + txout_target_v target =boost::get( miner_tx.vout[0]).target; miner_tx.vout.clear(); for (size_t i = 0; i < tx_out_count; ++i) { diff --git a/tests/core_tests/chain_switch_pow_pos.cpp b/tests/core_tests/chain_switch_pow_pos.cpp index 2ebe47eb..f936db7c 100644 --- a/tests/core_tests/chain_switch_pow_pos.cpp +++ b/tests/core_tests/chain_switch_pow_pos.cpp @@ -124,7 +124,7 @@ bool gen_chain_switch_pow_pos::generate(std::vector& events) c crypto::key_image stake_output_key_image; keypair kp; generate_key_image_helper(alice.get_keys(), stake_tx_pub_key, stake_output_idx, kp, stake_output_key_image); - crypto::public_key stake_output_pubkey = boost::get(stake.vout[stake_output_idx].target).key; + crypto::public_key stake_output_pubkey = boost::get(boost::get(stake.vout[stake_output_idx]).target).key; pos_block_builder pb; pb.step1_init_header(height, prev_id); diff --git a/tests/core_tests/chaingen.cpp b/tests/core_tests/chaingen.cpp index 31bc4f25..3ce1d381 100644 --- a/tests/core_tests/chaingen.cpp +++ b/tests/core_tests/chaingen.cpp @@ -620,8 +620,8 @@ bool test_generator::build_outputs_indext_for_chain(const blockchain_vector& blo std::vector& coinbase_outs = txs_outs[currency::get_transaction_hash(blocks[h]->b.miner_tx)]; for (size_t out_i = 0; out_i != blocks[h]->b.miner_tx.vout.size(); out_i++) { - coinbase_outs.push_back(index[blocks[h]->b.miner_tx.vout[out_i].amount].size()); - index[blocks[h]->b.miner_tx.vout[out_i].amount].push_back(std::tuple(h, 0, out_i)); + coinbase_outs.push_back(index[blocks[h]->b.boost::get(miner_tx.vout[out_i]).amount].size()); + index[blocks[h]->b.boost::get(miner_tx.vout[out_i]).amount].push_back(std::tuple(h, 0, out_i)); } for (size_t tx_index = 0; tx_index != blocks[h]->m_transactions.size(); tx_index++) @@ -629,8 +629,8 @@ bool test_generator::build_outputs_indext_for_chain(const blockchain_vector& blo std::vector& tx_outs_indx = txs_outs[currency::get_transaction_hash(blocks[h]->m_transactions[tx_index])]; for (size_t out_i = 0; out_i != blocks[h]->m_transactions[tx_index].vout.size(); out_i++) { - tx_outs_indx.push_back(index[blocks[h]->m_transactions[tx_index].vout[out_i].amount].size()); - index[blocks[h]->m_transactions[tx_index].vout[out_i].amount].push_back(std::tuple(h, tx_index + 1, out_i)); + tx_outs_indx.push_back(index[blocks[h]->m_transactions[tx_index]boost::get(.vout[out_i]).amount].size()); + index[blocks[h]->m_transactions[tx_index]boost::get(.vout[out_i]).amount].push_back(std::tuple(h, tx_index + 1, out_i)); } } } @@ -664,10 +664,10 @@ bool test_generator::get_output_details_by_global_index(const test_generator::bl tx_pub_key = get_tx_pub_key_from_extra(*tx); CHECK_AND_ASSERT_THROW_MES(tx->vout[tx_out_index].target.type() == typeid(currency::txout_to_key), - "blck_chain[h]->m_transactions[tx_index].vout[tx_out_index].target.type() == typeid(currency::txout_to_key)"); + "blck_chain[h]->m_transactions[tx_index]boost::get(.vout[tx_out_index]).target.type() == typeid(currency::txout_to_key)"); CHECK_AND_ASSERT_THROW_MES(tx->vout[tx_out_index].amount == amount, - "blck_chain[h]->m_transactions[tx_index].vout[tx_out_index].amount == amount"); + "blck_chain[h]->m_transactions[tx_index]boost::get(.vout[tx_out_index]).amount == amount"); output_key = boost::get(tx->vout[tx_out_index].target).key; return true; @@ -1806,7 +1806,7 @@ bool find_global_index_for_output(const std::vector& events, c size_t get_tx_out_index_by_amount(const currency::transaction& tx, const uint64_t amount) { for (size_t i = 0; i < tx.vout.size(); ++i) - if (tx.vout[i].amount == amount) + if (boost::get(tx.vout[i]).amount == amount) return i; return SIZE_MAX; @@ -1827,14 +1827,14 @@ bool sign_multisig_input_in_tx_custom(currency::transaction& tx, size_t ms_input size_t ms_out_index = SIZE_MAX; for (size_t i = 0; i < source_tx.vout.size(); ++i) { - if (source_tx.vout[i].target.type() == typeid(txout_multisig) && ms_in.multisig_out_id == get_multisig_out_id(source_tx, i)) + if (boost::get(source_tx.vout[i]).target.type() == typeid(txout_multisig) && ms_in.multisig_out_id == get_multisig_out_id(source_tx, i)) { ms_out_index = i; break; } } LOC_CHK(ms_out_index != SIZE_MAX, "failed to find ms output in source tx " << get_transaction_hash(source_tx) << " by ms id " << ms_in.multisig_out_id); - const txout_multisig& out_ms = boost::get(source_tx.vout[ms_out_index].target); + const txout_multisig& out_ms = boost::get(boost::get(source_tx.vout[ms_out_index]).target); crypto::public_key source_tx_pub_key = get_tx_pub_key_from_extra(source_tx); @@ -1904,11 +1904,11 @@ bool make_tx_multisig_to_key(const currency::transaction& source_tx, CHECK_AND_ASSERT_MES(source_tx_out_idx < source_tx.vout.size(), false, "tx " << se.real_output << " has " << source_tx.vout.size() << " outputs, #" << source_tx_out_idx << " specified"); se.real_output_in_tx_index = source_tx_out_idx; se.multisig_id = get_multisig_out_id(source_tx, se.real_output_in_tx_index); - CHECK_AND_ASSERT_MES(source_tx.vout[se.real_output_in_tx_index].target.type() == typeid(txout_multisig), false, "tx " << se.real_output << " output #" << source_tx_out_idx << " is not a txout_multisig"); - const txout_multisig& ms_out = boost::get(source_tx.vout[se.real_output_in_tx_index].target); + CHECK_AND_ASSERT_MES(boost::get(source_tx.vout[se.real_output_in_tx_index]).target.type() == typeid(txout_multisig), false, "tx " << se.real_output << " output #" << source_tx_out_idx << " is not a txout_multisig"); + const txout_multisig& ms_out = boost::get(boost::get(source_tx.vout[se.real_output_in_tx_index]).target); se.ms_keys_count = ms_out.keys.size(); se.ms_sigs_count = ms_out.minimum_sigs; - se.amount = source_tx.vout[se.real_output_in_tx_index].amount; + se.amount =boost::get( source_tx.vout[se.real_output_in_tx_index]).amount; tx_destination_entry de(se.amount - fee, target_address); @@ -2002,11 +2002,11 @@ bool generate_pos_block_with_given_coinstake(test_generator& generator, const st bool r = find_global_index_for_output(events, prev_id, stake_tx, stake_output_idx, stake_output_gidx); CHECK_AND_ASSERT_MES(r, false, "find_global_index_for_output failed"); } - uint64_t stake_output_amount = stake_tx.vout[stake_output_idx].amount; + uint64_t stake_output_amount =boost::get( stake_tx.vout[stake_output_idx]).amount; crypto::key_image stake_output_key_image; keypair kp; generate_key_image_helper(miner.get_keys(), stake_tx_pub_key, stake_output_idx, kp, stake_output_key_image); - crypto::public_key stake_output_pubkey = boost::get(stake_tx.vout[stake_output_idx].target).key; + crypto::public_key stake_output_pubkey = boost::get(boost::get(stake_tx.vout[stake_output_idx]).target).key; pos_block_builder pb; pb.step1_init_header(height, prev_id); diff --git a/tests/core_tests/checkpoints_tests.cpp b/tests/core_tests/checkpoints_tests.cpp index 1e50d5c0..76e262da 100644 --- a/tests/core_tests/checkpoints_tests.cpp +++ b/tests/core_tests/checkpoints_tests.cpp @@ -552,11 +552,11 @@ bool gen_checkpoints_pos_validation_on_altchain::generate(std::vector( stake.vout[stake_output_idx]).amount; crypto::key_image stake_output_key_image; keypair kp; generate_key_image_helper(miner_acc.get_keys(), stake_tx_pub_key, stake_output_idx, kp, stake_output_key_image); - crypto::public_key stake_output_pubkey = boost::get(stake.vout[stake_output_idx].target).key; + crypto::public_key stake_output_pubkey = boost::get(boost::get(stake.vout[stake_output_idx]).target).key; pos_block_builder pb; pb.step1_init_header(height, prev_id); @@ -581,11 +581,11 @@ bool gen_checkpoints_pos_validation_on_altchain::generate(std::vector( stake.vout[stake_output_idx]).amount; crypto::key_image stake_output_key_image; keypair kp; generate_key_image_helper(miner_acc.get_keys(), stake_tx_pub_key, stake_output_idx, kp, stake_output_key_image); - //crypto::public_key stake_output_pubkey = boost::get(stake.vout[stake_output_idx].target).key; + //crypto::public_key stake_output_pubkey = boost::get(boost::get(stake.vout[stake_output_idx]).target).key; pos_block_builder pb; pb.step1_init_header(height, prev_id); diff --git a/tests/core_tests/double_spend.inl b/tests/core_tests/double_spend.inl index 7f58f237..28da7a36 100644 --- a/tests/core_tests/double_spend.inl +++ b/tests/core_tests/double_spend.inl @@ -80,7 +80,7 @@ bool gen_double_spend_in_tx::generate(std::vector(global_out_index, boost::get(tx_0.vout[se.real_output_in_tx_index].target).key)); + se.outputs.push_back(make_serializable_pair(global_out_index, boost::get(boost::get(tx_0.vout[se.real_output_in_tx_index]).target).key)); se.real_output = 0; se.real_out_tx_key = get_tx_pub_key_from_extra(tx_0); sources.push_back(se); diff --git a/tests/core_tests/emission_test.cpp b/tests/core_tests/emission_test.cpp index d117175a..734844a4 100644 --- a/tests/core_tests/emission_test.cpp +++ b/tests/core_tests/emission_test.cpp @@ -98,11 +98,11 @@ bool emission_test::c1(currency::core& c, size_t ev_index, const std::vectortx; crypto::public_key stake_tx_pub_key = get_tx_pub_key_from_extra(stake); size_t stake_output_gidx = tce_ptr->m_global_output_indexes[stake_output_idx]; - uint64_t stake_output_amount = stake.vout[stake_output_idx].amount; + uint64_t stake_output_amount =boost::get( stake.vout[stake_output_idx]).amount; crypto::key_image stake_output_key_image; keypair kp; generate_key_image_helper(m_miner_acc.get_keys(), stake_tx_pub_key, stake_output_idx, kp, stake_output_key_image); - crypto::public_key stake_output_pubkey = boost::get(stake.vout[stake_output_idx].target).key; + crypto::public_key stake_output_pubkey = boost::get(boost::get(stake.vout[stake_output_idx]).target).key; difficulty = c.get_blockchain_storage().get_next_diff_conditional(true); //size_t median_size = 0; // little hack: we're using small blocks (only coinbase tx), so we're in CURRENCY_BLOCK_GRANTED_FULL_REWARD_ZONE - don't need to calc median size diff --git a/tests/core_tests/escrow_wallet_common.h b/tests/core_tests/escrow_wallet_common.h index 57f204fd..4e9ddf90 100644 --- a/tests/core_tests/escrow_wallet_common.h +++ b/tests/core_tests/escrow_wallet_common.h @@ -338,11 +338,11 @@ inline bool build_custom_escrow_release_template( // inputs // create multisig (A-B) source, add keys from B tx_source_entry se = AUTO_VAL_INIT(se); - se.amount = (~custom_config_mask & eccf_rel_template_inv_ms_amount) ? escrow_template_tx.vout[ms_idx].amount : escrow_template_tx.vout[ms_idx].amount + 10 * TESTS_DEFAULT_FEE; + se.amount = (~custom_config_mask & eccf_rel_template_inv_ms_amount) ?boost::get( escrow_template_tx.vout[ms_idx]).amount :boost::get( escrow_template_tx.vout[ms_idx]).amount + 10 * TESTS_DEFAULT_FEE; se.multisig_id = ms_id; se.real_output_in_tx_index = ms_idx; se.real_out_tx_key = get_tx_pub_key_from_extra(escrow_template_tx); - se.ms_keys_count = boost::get(escrow_template_tx.vout[ms_idx].target).keys.size(); + se.ms_keys_count = boost::get(boost::get(escrow_template_tx.vout[ms_idx]).target).keys.size(); se.ms_sigs_count = (~custom_config_mask & eccf_rel_template_inv_sigs_count) ? 2 : 1; std::vector sources({ se }); diff --git a/tests/core_tests/hard_fork_1.cpp b/tests/core_tests/hard_fork_1.cpp index 688e20a5..bf38636f 100644 --- a/tests/core_tests/hard_fork_1.cpp +++ b/tests/core_tests/hard_fork_1.cpp @@ -390,11 +390,11 @@ bool hard_fork_1_checkpoint_basic_test::generate(std::vector& crypto::public_key stake_tx_pub_key = get_tx_pub_key_from_extra(stake); size_t stake_output_idx = 0; size_t stake_output_gidx = 0; - uint64_t stake_output_amount = stake.vout[stake_output_idx].amount; + uint64_t stake_output_amount =boost::get( stake.vout[stake_output_idx]).amount; crypto::key_image stake_output_key_image; keypair kp; generate_key_image_helper(stakeholder.get_keys(), stake_tx_pub_key, stake_output_idx, kp, stake_output_key_image); - crypto::public_key stake_output_pubkey = boost::get(stake.vout[stake_output_idx].target).key; + crypto::public_key stake_output_pubkey = boost::get(boost::get(stake.vout[stake_output_idx]).target).key; pos_block_builder pb; pb.step1_init_header(height, prev_id); @@ -566,11 +566,11 @@ bool hard_fork_1_pos_and_locked_coins::generate(std::vector& e crypto::public_key stake_tx_pub_key = get_tx_pub_key_from_extra(stake); size_t stake_output_idx = 0; size_t stake_output_gidx = 0; - uint64_t stake_output_amount = stake.vout[stake_output_idx].amount; + uint64_t stake_output_amount =boost::get( stake.vout[stake_output_idx]).amount; crypto::key_image stake_output_key_image; keypair kp; generate_key_image_helper(alice_acc.get_keys(), stake_tx_pub_key, stake_output_idx, kp, stake_output_key_image); - crypto::public_key stake_output_pubkey = boost::get(stake.vout[stake_output_idx].target).key; + crypto::public_key stake_output_pubkey = boost::get(boost::get(stake.vout[stake_output_idx]).target).key; pos_block_builder pb; pb.step1_init_header(height, prev_id); @@ -605,11 +605,11 @@ bool hard_fork_1_pos_and_locked_coins::generate(std::vector& e crypto::public_key stake_tx_pub_key = get_tx_pub_key_from_extra(stake); size_t stake_output_idx = 0; size_t stake_output_gidx = 0; - uint64_t stake_output_amount = stake.vout[stake_output_idx].amount; + uint64_t stake_output_amount =boost::get( stake.vout[stake_output_idx]).amount; crypto::key_image stake_output_key_image; keypair kp; generate_key_image_helper(alice_acc.get_keys(), stake_tx_pub_key, stake_output_idx, kp, stake_output_key_image); - crypto::public_key stake_output_pubkey = boost::get(stake.vout[stake_output_idx].target).key; + crypto::public_key stake_output_pubkey = boost::get(boost::get(stake.vout[stake_output_idx]).target).key; pos_block_builder pb; pb.step1_init_header(height, prev_id); @@ -653,11 +653,11 @@ bool hard_fork_1_pos_and_locked_coins::generate(std::vector& e crypto::public_key stake_tx_pub_key = get_tx_pub_key_from_extra(stake); size_t stake_output_idx = 0; size_t stake_output_gidx = 0; - uint64_t stake_output_amount = stake.vout[stake_output_idx].amount; + uint64_t stake_output_amount =boost::get( stake.vout[stake_output_idx]).amount; crypto::key_image stake_output_key_image; keypair kp; generate_key_image_helper(bob_acc.get_keys(), stake_tx_pub_key, stake_output_idx, kp, stake_output_key_image); - crypto::public_key stake_output_pubkey = boost::get(stake.vout[stake_output_idx].target).key; + crypto::public_key stake_output_pubkey = boost::get(boost::get(stake.vout[stake_output_idx]).target).key; pos_block_builder pb; pb.step1_init_header(height, prev_id); @@ -750,11 +750,11 @@ bool hard_fork_1_pos_locked_height_vs_time::generate(std::vector( stake.vout[stake_output_idx]).amount; crypto::key_image stake_output_key_image; keypair kp; generate_key_image_helper(stakeholder.get_keys(), stake_tx_pub_key, stake_output_idx, kp, stake_output_key_image); - crypto::public_key stake_output_pubkey = boost::get(stake.vout[stake_output_idx].target).key; + crypto::public_key stake_output_pubkey = boost::get(boost::get(stake.vout[stake_output_idx]).target).key; pos_block_builder pb; pb.step1_init_header(height, prev_id); @@ -795,11 +795,11 @@ bool hard_fork_1_pos_locked_height_vs_time::generate(std::vector( stake.vout[stake_output_idx]).amount; crypto::key_image stake_output_key_image; keypair kp; generate_key_image_helper(stakeholder.get_keys(), stake_tx_pub_key, stake_output_idx, kp, stake_output_key_image); - crypto::public_key stake_output_pubkey = boost::get(stake.vout[stake_output_idx].target).key; + crypto::public_key stake_output_pubkey = boost::get(boost::get(stake.vout[stake_output_idx]).target).key; pos_block_builder pb; pb.step1_init_header(height, prev_id); @@ -839,11 +839,11 @@ bool hard_fork_1_pos_locked_height_vs_time::generate(std::vector( stake.vout[stake_output_idx]).amount; crypto::key_image stake_output_key_image; keypair kp; generate_key_image_helper(stakeholder.get_keys(), stake_tx_pub_key, stake_output_idx, kp, stake_output_key_image); - crypto::public_key stake_output_pubkey = boost::get(stake.vout[stake_output_idx].target).key; + crypto::public_key stake_output_pubkey = boost::get(boost::get(stake.vout[stake_output_idx]).target).key; pos_block_builder pb; pb.step1_init_header(height, prev_id); diff --git a/tests/core_tests/integer_overflow.cpp b/tests/core_tests/integer_overflow.cpp index 7ed40482..b12b098e 100644 --- a/tests/core_tests/integer_overflow.cpp +++ b/tests/core_tests/integer_overflow.cpp @@ -21,7 +21,7 @@ namespace { uint64_t total_amount = get_outs_money_amount(miner_tx); uint64_t amount_2 = total_amount - amount_1; - txout_target_v target = miner_tx.vout[0].target; + txout_target_v target =boost::get( miner_tx.vout[0]).target; miner_tx.vout.clear(); @@ -39,8 +39,8 @@ namespace void append_tx_source_entry(std::vector& sources, const transaction& tx, size_t out_idx) { currency::tx_source_entry se = AUTO_VAL_INIT(se); - se.amount = tx.vout[out_idx].amount; - se.outputs.push_back(make_serializable_pair(0, boost::get(tx.vout[out_idx].target).key)); + se.amount =boost::get( tx.vout[out_idx]).amount; + se.outputs.push_back(make_serializable_pair(0, boost::get(boost::get(tx.vout[out_idx]).target).key)); se.real_output = 0; se.real_out_tx_key = get_tx_pub_key_from_extra(tx); se.real_output_in_tx_index = out_idx; @@ -134,7 +134,7 @@ bool gen_uint_overflow_2::generate(std::vector& events) const std::vector sources; for (size_t i = 0; i < blk_0.miner_tx.vout.size(); ++i) { - if (TESTS_DEFAULT_FEE < blk_0.miner_tx.vout[i].amount) + if (TESTS_DEFAULT_FEE < blk_0.boost::get(miner_tx.vout[i]).amount) { append_tx_source_entry(sources, blk_0.miner_tx, i); break; diff --git a/tests/core_tests/misc_tests.cpp b/tests/core_tests/misc_tests.cpp index 795c97d0..b9ccab13 100644 --- a/tests/core_tests/misc_tests.cpp +++ b/tests/core_tests/misc_tests.cpp @@ -267,7 +267,7 @@ bool block_template_vs_invalid_txs_from_pool::generate(std::vector(tx_1m.vout[se.real_output_in_tx_index].target).keys.size(); + se.ms_keys_count = boost::get(boost::get(tx_1m.vout[se.real_output_in_tx_index]).target).keys.size(); se.ms_sigs_count = 1; transaction tx_2m = AUTO_VAL_INIT(tx_2m); r = construct_tx(bob_acc.get_keys(), std::vector({ se }), std::vector({ tx_destination_entry(se.amount - TESTS_DEFAULT_FEE, miner_acc.get_public_address()) }), @@ -447,8 +447,8 @@ bool test_blockchain_vs_spent_multisig_outs::generate(std::vector txout_to_key size_t ms_out_idx = 0; tx_source_entry se = AUTO_VAL_INIT(se); - se.amount = tx_0.vout[ms_out_idx].amount; - se.ms_keys_count = boost::get(tx_0.vout[ms_out_idx].target).keys.size(); + se.amount =boost::get( tx_0.vout[ms_out_idx]).amount; + se.ms_keys_count = boost::get(boost::get(tx_0.vout[ms_out_idx]).target).keys.size(); se.ms_sigs_count = 1; se.multisig_id = get_multisig_out_id(tx_0, ms_out_idx); se.real_output_in_tx_index = ms_out_idx; diff --git a/tests/core_tests/multisig_wallet_tests.cpp b/tests/core_tests/multisig_wallet_tests.cpp index 54802559..4af7576f 100644 --- a/tests/core_tests/multisig_wallet_tests.cpp +++ b/tests/core_tests/multisig_wallet_tests.cpp @@ -168,7 +168,7 @@ bool multisig_wallet_test::c1(currency::core& c, size_t ev_index, const std::vec size_t i = 0; for (; i != result_tx.vout.size(); i++) { - if (result_tx.vout[i].target.type() == typeid(txout_multisig)) + if (boost::get(result_tx.vout[i]).target.type() == typeid(txout_multisig)) break; } CHECK_AND_ASSERT_MES(i != result_tx.vout.size(), false, "Incorrect txs outs"); @@ -906,7 +906,7 @@ bool multisig_minimum_sigs::generate(std::vector& events) cons se.multisig_id = ms_id; se.real_output_in_tx_index = ms_out_idx; se.real_out_tx_key = get_tx_pub_key_from_extra(tx_1); - se.ms_keys_count = boost::get(tx_1.vout[se.real_output_in_tx_index].target).keys.size(); + se.ms_keys_count = boost::get(boost::get(tx_1.vout[se.real_output_in_tx_index]).target).keys.size(); se.ms_sigs_count = 2; tx_destination_entry de(se.amount - TESTS_DEFAULT_FEE, bob_acc.get_public_address()); @@ -939,7 +939,7 @@ bool multisig_minimum_sigs::generate(std::vector& events) cons se.multisig_id = ms_id; se.real_output_in_tx_index = ms_out_idx; se.real_out_tx_key = get_tx_pub_key_from_extra(tx_1); - se.ms_keys_count = boost::get(tx_1.vout[se.real_output_in_tx_index].target).keys.size(); + se.ms_keys_count = boost::get(boost::get(tx_1.vout[se.real_output_in_tx_index]).target).keys.size(); se.ms_sigs_count = 2; transaction tx_3 = AUTO_VAL_INIT(tx_3); @@ -976,7 +976,7 @@ bool multisig_minimum_sigs::generate(std::vector& events) cons se.multisig_id = ms_4_id; se.real_output_in_tx_index = ms_4_out_idx; se.real_out_tx_key = get_tx_pub_key_from_extra(tx_4); - se.ms_keys_count = boost::get(tx_4.vout[se.real_output_in_tx_index].target).keys.size(); + se.ms_keys_count = boost::get(boost::get(tx_4.vout[se.real_output_in_tx_index]).target).keys.size(); se.ms_sigs_count = 3; transaction tx_5 = AUTO_VAL_INIT(tx_5); @@ -1020,7 +1020,7 @@ bool multisig_minimum_sigs::generate(std::vector& events) cons se.multisig_id = ms_6_id; se.real_output_in_tx_index = ms_6_out_idx; se.real_out_tx_key = get_tx_pub_key_from_extra(tx_6); - se.ms_keys_count = boost::get(tx_6.vout[se.real_output_in_tx_index].target).keys.size(); + se.ms_keys_count = boost::get(boost::get(tx_6.vout[se.real_output_in_tx_index]).target).keys.size(); se.ms_sigs_count = 4; transaction tx_7 = AUTO_VAL_INIT(tx_7); @@ -1062,7 +1062,7 @@ bool multisig_minimum_sigs::generate(std::vector& events) cons se.multisig_id = ms_8_id; se.real_output_in_tx_index = ms_8_out_idx; se.real_out_tx_key = get_tx_pub_key_from_extra(tx_8); - se.ms_keys_count = boost::get(tx_8.vout[se.real_output_in_tx_index].target).keys.size(); + se.ms_keys_count = boost::get(boost::get(tx_8.vout[se.real_output_in_tx_index]).target).keys.size(); static const size_t redundant_keys_count = 7000; se.ms_sigs_count = redundant_keys_count; @@ -1138,7 +1138,7 @@ bool multisig_and_fake_outputs::generate(std::vector& events) // Second, correctly set up multisig part tx_source_entry& se = sources.back(); se.multisig_id = tx_1_ms_out_id; - se.ms_keys_count = boost::get(tx_1.vout[tx_1_ms_out_idx].target).keys.size(); + se.ms_keys_count = boost::get(boost::get(tx_1.vout[tx_1_ms_out_idx]).target).keys.size(); se.ms_sigs_count = 1; se.real_output_in_tx_index = tx_1_ms_out_idx; se.real_out_tx_key = get_tx_pub_key_from_extra(tx_1); @@ -1217,7 +1217,7 @@ bool multisig_and_unlock_time::generate(std::vector& events) c se.multisig_id = tx_1_ms_out_id; se.real_output_in_tx_index = tx_1_ms_out_idx; se.real_out_tx_key = get_tx_pub_key_from_extra(tx_1); - se.ms_keys_count = boost::get(tx_1.vout[tx_1_ms_out_idx].target).keys.size(); + se.ms_keys_count = boost::get(boost::get(tx_1.vout[tx_1_ms_out_idx]).target).keys.size(); se.ms_sigs_count = 1; sources.assign({ se }); @@ -1295,7 +1295,7 @@ bool multisig_and_unlock_time::generate(std::vector& events) c se.multisig_id = tx_5_ms_out_id; se.real_output_in_tx_index = tx_5_ms_out_idx; se.real_out_tx_key = get_tx_pub_key_from_extra(tx_5); - se.ms_keys_count = boost::get(tx_5.vout[tx_5_ms_out_idx].target).keys.size(); + se.ms_keys_count = boost::get(boost::get(tx_5.vout[tx_5_ms_out_idx]).target).keys.size(); se.ms_sigs_count = 1; sources.assign({ se }); @@ -1351,11 +1351,11 @@ bool multisig_and_coinbase::generate(std::vector& events) cons crypto::public_key stake_tx_pub_key = get_tx_pub_key_from_extra(stake); size_t stake_output_idx = 0; size_t stake_output_gidx = 0; - uint64_t stake_output_amount = stake.vout[stake_output_idx].amount; + uint64_t stake_output_amount =boost::get( stake.vout[stake_output_idx]).amount; crypto::key_image stake_output_key_image; keypair kp; generate_key_image_helper(miner_acc.get_keys(), stake_tx_pub_key, stake_output_idx, kp, stake_output_key_image); - crypto::public_key stake_output_pubkey = boost::get(stake.vout[stake_output_idx].target).key; + crypto::public_key stake_output_pubkey = boost::get(boost::get(stake.vout[stake_output_idx]).target).key; keypair tx_key = keypair::generate(); pos_block_builder pb; @@ -1411,7 +1411,7 @@ bool multisig_and_coinbase::generate(std::vector& events) cons se.multisig_id = get_multisig_out_id(blk_1.miner_tx, se.real_output_in_tx_index); //se.participants.push_back(alice_acc.get_keys()); se.real_out_tx_key = get_tx_pub_key_from_extra(blk_1.miner_tx); - se.ms_keys_count = boost::get(blk_1.miner_tx.vout[se.real_output_in_tx_index].target).keys.size(); + se.ms_keys_count = boost::get(blk_1.boost::get(miner_tx.vout[se.real_output_in_tx_index]).target).keys.size(); se.ms_sigs_count = 1; sources.assign({ se }); @@ -1477,7 +1477,7 @@ bool multisig_and_coinbase::generate(std::vector& events) cons se.multisig_id = get_multisig_out_id(blk_3.miner_tx, 0); se.real_output_in_tx_index = 0; se.real_out_tx_key = get_tx_pub_key_from_extra(blk_3.miner_tx); - se.ms_keys_count= boost::get(blk_3.miner_tx.vout[se.real_output_in_tx_index].target).keys.size(); + se.ms_keys_count= boost::get(blk_3.boost::get(miner_tx.vout[se.real_output_in_tx_index]).target).keys.size(); se.ms_sigs_count = 1; transaction tx_2 = AUTO_VAL_INIT(tx_2); @@ -1582,7 +1582,7 @@ bool multisig_with_same_id_in_pool::generate(std::vector& even se.multisig_id = tx_1_ms_id; se.real_output_in_tx_index = get_tx_out_index_by_amount(tx_1, amount); se.real_out_tx_key = get_tx_pub_key_from_extra(tx_1); - se.ms_keys_count = boost::get(tx_1.vout[se.real_output_in_tx_index].target).keys.size(); + se.ms_keys_count = boost::get(boost::get(tx_1.vout[se.real_output_in_tx_index]).target).keys.size(); se.ms_sigs_count = 1; tx_destination_entry de(amount - TESTS_DEFAULT_FEE, bob_acc.get_public_address()); @@ -1693,7 +1693,7 @@ bool multisig_and_checkpoints::generate(std::vector& events) c se.real_output_in_tx_index = get_tx_out_index_by_amount(tx_1, amount); se.multisig_id = get_multisig_out_id(tx_1, se.real_output_in_tx_index); se.real_out_tx_key = get_tx_pub_key_from_extra(tx_1); - se.ms_keys_count = boost::get(tx_1.vout[se.real_output_in_tx_index].target).keys.size(); + se.ms_keys_count = boost::get(boost::get(tx_1.vout[se.real_output_in_tx_index]).target).keys.size(); se.ms_sigs_count = 1; tx_destination_entry de(amount - TESTS_DEFAULT_FEE, bob_acc.get_public_address()); @@ -1736,7 +1736,7 @@ bool multisig_and_checkpoints::generate(std::vector& events) c se.real_output_in_tx_index = get_tx_out_index_by_amount(tx_3, amount); se.multisig_id = get_multisig_out_id(tx_3, se.real_output_in_tx_index); se.real_out_tx_key = get_tx_pub_key_from_extra(tx_3); - se.ms_keys_count = boost::get(tx_3.vout[se.real_output_in_tx_index].target).keys.size(); + se.ms_keys_count = boost::get(boost::get(tx_3.vout[se.real_output_in_tx_index]).target).keys.size(); se.ms_sigs_count = 1; de = tx_destination_entry(amount - TESTS_DEFAULT_FEE, bob_acc.get_public_address()); @@ -1767,7 +1767,7 @@ bool multisig_and_checkpoints::generate(std::vector& events) c se.real_output_in_tx_index = get_tx_out_index_by_amount(tx_5, amount); se.multisig_id = get_multisig_out_id(tx_5, se.real_output_in_tx_index); se.real_out_tx_key = get_tx_pub_key_from_extra(tx_5); - se.ms_keys_count = boost::get(tx_5.vout[se.real_output_in_tx_index].target).keys.size(); + se.ms_keys_count = boost::get(boost::get(tx_5.vout[se.real_output_in_tx_index]).target).keys.size(); se.ms_sigs_count = 1; de = tx_destination_entry(amount - TESTS_DEFAULT_FEE, bob_acc.get_public_address()); @@ -1874,7 +1874,7 @@ bool multisig_and_checkpoints_bad_txs::generate(std::vector& e txb.step1_init(); txb.step2_fill_inputs(miner_acc.get_keys(), sources); txb.step3_fill_outputs(destinations, 0, 1); - boost::get(txb.m_tx.vout[0].target).keys.clear(); // zero keys + boost::get(txb.boost::get(m_tx.vout[0]).target).keys.clear(); // zero keys txb.step4_calc_hash(); txb.step5_sign(sources); transaction tx_4 = txb.m_tx; @@ -1888,8 +1888,8 @@ bool multisig_and_checkpoints_bad_txs::generate(std::vector& e txb.step1_init(); txb.step2_fill_inputs(miner_acc.get_keys(), sources); txb.step3_fill_outputs(destinations, 0, 1); - crypto::public_key k = boost::get(txb.m_tx.vout[0].target).keys[0]; - boost::get(txb.m_tx.vout[0].target).keys.resize(1500, k); + crypto::public_key k = boost::get(txb.boost::get(m_tx.vout[0]).target).keys[0]; + boost::get(txb.boost::get(m_tx.vout[0]).target).keys.resize(1500, k); txb.step4_calc_hash(); txb.step5_sign(sources); txb.m_tx.signatures.clear(); @@ -2262,7 +2262,7 @@ bool multisig_n_participants_seq_signing::generate(std::vector size_t ms_out_index = get_multisig_out_index(tx_1.vout); CHECK_AND_ASSERT_MES(ms_out_index != tx_1.vout.size(), false, "Can't find ms out index in tx_1"); tx_source_entry se = AUTO_VAL_INIT(se); - se.amount = tx_1.vout[ms_out_index].amount; + se.amount =boost::get( tx_1.vout[ms_out_index]).amount; se.multisig_id = get_multisig_out_id(tx_1, ms_out_index); se.ms_sigs_count = m_minimum_signs_to_spend; // se.outputs -- not used for ms-outs @@ -2270,7 +2270,7 @@ bool multisig_n_participants_seq_signing::generate(std::vector se.real_output_in_tx_index = ms_out_index; se.real_out_tx_key = get_tx_pub_key_from_extra(tx_1); // se.separately_signed_tx_complete -- not a separately-signed tx - se.ms_keys_count = boost::get(tx_1.vout[ms_out_index].target).keys.size(); + se.ms_keys_count = boost::get(boost::get(tx_1.vout[ms_out_index]).target).keys.size(); sources.push_back(se); tx_destination_entry de(ms_amount - TESTS_DEFAULT_FEE, alice_acc.get_public_address()); diff --git a/tests/core_tests/pos_block_builder.cpp b/tests/core_tests/pos_block_builder.cpp index 896eb483..811563fb 100644 --- a/tests/core_tests/pos_block_builder.cpp +++ b/tests/core_tests/pos_block_builder.cpp @@ -298,11 +298,11 @@ bool mine_next_pos_block_in_playtime_sign_cb(currency::core& c, const currency:: crypto::public_key stake_tx_pub_key = get_tx_pub_key_from_extra(stake); size_t stake_output_idx = 0; size_t stake_output_gidx = 0; - uint64_t stake_output_amount = stake.vout[stake_output_idx].amount; + uint64_t stake_output_amount =boost::get( stake.vout[stake_output_idx]).amount; crypto::key_image stake_output_key_image; keypair kp; generate_key_image_helper(acc.get_keys(), stake_tx_pub_key, stake_output_idx, kp, stake_output_key_image); - crypto::public_key stake_output_pubkey = boost::get(stake.vout[stake_output_idx].target).key; + crypto::public_key stake_output_pubkey = boost::get(boost::get(stake.vout[stake_output_idx]).target).key; pos_block_builder pb; pb.step1_init_header(height, prev_id); diff --git a/tests/core_tests/pos_validation.cpp b/tests/core_tests/pos_validation.cpp index 94fa4730..0cfb69ff 100644 --- a/tests/core_tests/pos_validation.cpp +++ b/tests/core_tests/pos_validation.cpp @@ -71,11 +71,11 @@ bool gen_pos_coinstake_already_spent::generate(std::vector& ev uint64_t stake_output_gidx = 0; bool r = find_global_index_for_output(events, prev_id, stake, stake_output_idx, stake_output_gidx); CHECK_AND_ASSERT_MES(r, false, "find_global_index_for_output failed"); - uint64_t stake_output_amount = stake.vout[stake_output_idx].amount; + uint64_t stake_output_amount =boost::get( stake.vout[stake_output_idx]).amount; crypto::key_image stake_output_key_image; keypair kp; generate_key_image_helper(miner.get_keys(), stake_tx_pub_key, stake_output_idx, kp, stake_output_key_image); - crypto::public_key stake_output_pubkey = boost::get(stake.vout[stake_output_idx].target).key; + crypto::public_key stake_output_pubkey = boost::get(boost::get(stake.vout[stake_output_idx]).target).key; pos_block_builder pb; pb.step1_init_header(height, prev_id); @@ -122,11 +122,11 @@ bool gen_pos_incorrect_timestamp::generate(std::vector& events crypto::public_key stake_tx_pub_key = get_tx_pub_key_from_extra(stake); size_t stake_output_idx = 0; size_t stake_output_gidx = 0; - uint64_t stake_output_amount = stake.vout[stake_output_idx].amount; + uint64_t stake_output_amount =boost::get( stake.vout[stake_output_idx]).amount; crypto::key_image stake_output_key_image; keypair kp; generate_key_image_helper(miner.get_keys(), stake_tx_pub_key, stake_output_idx, kp, stake_output_key_image); - crypto::public_key stake_output_pubkey = boost::get(stake.vout[stake_output_idx].target).key; + crypto::public_key stake_output_pubkey = boost::get(boost::get(stake.vout[stake_output_idx]).target).key; pos_block_builder pb; pb.step1_init_header(height, prev_id); @@ -239,11 +239,11 @@ bool gen_pos_extra_nonce::generate(std::vector& events) const crypto::public_key stake_tx_pub_key = get_tx_pub_key_from_extra(stake); size_t stake_output_idx = 0; size_t stake_output_gidx = 0; - uint64_t stake_output_amount = stake.vout[stake_output_idx].amount; + uint64_t stake_output_amount =boost::get( stake.vout[stake_output_idx]).amount; crypto::key_image stake_output_key_image; keypair kp; generate_key_image_helper(miner.get_keys(), stake_tx_pub_key, stake_output_idx, kp, stake_output_key_image); - crypto::public_key stake_output_pubkey = boost::get(stake.vout[stake_output_idx].target).key; + crypto::public_key stake_output_pubkey = boost::get(boost::get(stake.vout[stake_output_idx]).target).key; pos_block_builder pb; pb.step1_init_header(height, prev_id); @@ -293,11 +293,11 @@ bool gen_pos_min_allowed_height::generate(std::vector& events) crypto::public_key stake_tx_pub_key = get_tx_pub_key_from_extra(stake); size_t stake_output_idx = 0; size_t stake_output_gidx = 0; - uint64_t stake_output_amount = stake.vout[stake_output_idx].amount; + uint64_t stake_output_amount =boost::get( stake.vout[stake_output_idx]).amount; crypto::key_image stake_output_key_image; keypair kp; generate_key_image_helper(miner.get_keys(), stake_tx_pub_key, stake_output_idx, kp, stake_output_key_image); - crypto::public_key stake_output_pubkey = boost::get(stake.vout[stake_output_idx].target).key; + crypto::public_key stake_output_pubkey = boost::get(boost::get(stake.vout[stake_output_idx]).target).key; pos_block_builder pb; pb.step1_init_header(height, prev_id); @@ -345,11 +345,11 @@ bool gen_pos_invalid_coinbase::generate(std::vector& events) c crypto::public_key stake_tx_pub_key = get_tx_pub_key_from_extra(stake); size_t stake_output_idx = 0; size_t stake_output_gidx = 0; - uint64_t stake_output_amount = stake.vout[stake_output_idx].amount; + uint64_t stake_output_amount =boost::get( stake.vout[stake_output_idx]).amount; crypto::key_image stake_output_key_image; keypair kp; generate_key_image_helper(miner_acc.get_keys(), stake_tx_pub_key, stake_output_idx, kp, stake_output_key_image); - crypto::public_key stake_output_pubkey = boost::get(stake.vout[stake_output_idx].target).key; + crypto::public_key stake_output_pubkey = boost::get(boost::get(stake.vout[stake_output_idx]).target).key; pos_block_builder pb; pb.step1_init_header(height, prev_id); @@ -881,7 +881,7 @@ bool pos_altblocks_validation::generate(std::vector& events) c // select stake_tx_out_id as an output with the biggest amount for (size_t i = 1; i < stake_tx.vout.size(); ++i) { - if (stake_tx.vout[i].amount > stake_tx.vout[stake_tx_out_id].amount) + if (boost::get(stake_tx.vout[i]).amount >boost::get( stake_tx.vout[stake_tx_out_id]).amount) stake_tx_out_id = i; } diff --git a/tests/core_tests/transaction_tests.cpp b/tests/core_tests/transaction_tests.cpp index 310a4750..6607e262 100644 --- a/tests/core_tests/transaction_tests.cpp +++ b/tests/core_tests/transaction_tests.cpp @@ -61,27 +61,27 @@ bool test_transaction_generation_and_ring_signature() { tx_output_entry oe; oe.first = 0; - oe.second = boost::get(tx_mine_1.vout[0].target).key; + oe.second = boost::get(boost::get(tx_mine_1.vout[0]).target).key; src.outputs.push_back(oe); oe.first = 1; - oe.second = boost::get(tx_mine_2.vout[0].target).key; + oe.second = boost::get(boost::get(tx_mine_2.vout[0]).target).key; src.outputs.push_back(oe); oe.first = 2; - oe.second = boost::get(tx_mine_3.vout[0].target).key; + oe.second = boost::get(boost::get(tx_mine_3.vout[0]).target).key; src.outputs.push_back(oe); oe.first = 3; - oe.second = boost::get(tx_mine_4.vout[0].target).key; + oe.second = boost::get(boost::get(tx_mine_4.vout[0]).target).key; src.outputs.push_back(oe); oe.first = 4; - oe.second = boost::get(tx_mine_5.vout[0].target).key; + oe.second = boost::get(boost::get(tx_mine_5.vout[0]).target).key; src.outputs.push_back(oe); oe.first = 5; - oe.second = boost::get(tx_mine_6.vout[0].target).key; + oe.second = boost::get(boost::get(tx_mine_6.vout[0]).target).key; src.outputs.push_back(oe); crypto::public_key tx_pub_key = null_pkey; @@ -104,12 +104,12 @@ bool test_transaction_generation_and_ring_signature() crypto::hash pref_hash = get_transaction_prefix_hash(tx_rc1); std::vector output_keys; - output_keys.push_back(&boost::get(tx_mine_1.vout[0].target).key); - output_keys.push_back(&boost::get(tx_mine_2.vout[0].target).key); - output_keys.push_back(&boost::get(tx_mine_3.vout[0].target).key); - output_keys.push_back(&boost::get(tx_mine_4.vout[0].target).key); - output_keys.push_back(&boost::get(tx_mine_5.vout[0].target).key); - output_keys.push_back(&boost::get(tx_mine_6.vout[0].target).key); + output_keys.push_back(&boost::get(boost::get(tx_mine_1.vout[0]).target).key); + output_keys.push_back(&boost::get(boost::get(tx_mine_2.vout[0]).target).key); + output_keys.push_back(&boost::get(boost::get(tx_mine_3.vout[0]).target).key); + output_keys.push_back(&boost::get(boost::get(tx_mine_4.vout[0]).target).key); + output_keys.push_back(&boost::get(boost::get(tx_mine_5.vout[0]).target).key); + output_keys.push_back(&boost::get(boost::get(tx_mine_6.vout[0]).target).key); r = crypto::check_ring_signature(pref_hash, boost::get(tx_rc1.vin[0]).k_image, output_keys, &tx_rc1.signatures[0][0]); CHECK_AND_ASSERT_MES(r, false, "failed to check ring signature"); From 7070cecaf29fe85cd7a4364afcce9b98f312fd8c Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Mon, 23 May 2022 21:03:13 +0200 Subject: [PATCH 08/10] tx strcture and signature varian refactoring(compilation is still broken) --- src/common/variant_helper.h | 1 + src/currency_core/blockchain_storage.cpp | 20 +++-- src/currency_core/core_runtime_config.h | 10 +-- .../currency_boost_serialization.h | 2 +- src/currency_core/currency_config.h | 7 ++ src/wallet/wallet2.cpp | 72 +++++++++------ src/wallet/wallet2.h | 1 + src/wallet/wallet2_escrow.cpp | 69 +++++++++------ tests/core_tests/chaingen.cpp | 4 +- tests/core_tests/chaingen.h | 6 +- tests/core_tests/chaingen_helpers.h | 6 +- tests/core_tests/chaingen_main.cpp | 4 +- tests/core_tests/checkpoints_tests.cpp | 10 +-- tests/core_tests/escrow_wallet_common.h | 4 +- tests/core_tests/multisig_wallet_tests.cpp | 12 +-- tests/core_tests/pos_block_builder.cpp | 6 +- tests/core_tests/pos_validation.cpp | 2 +- tests/core_tests/pruning_ring_signatures.cpp | 4 +- tests/core_tests/transaction_tests.cpp | 2 +- tests/core_tests/tx_builder.h | 6 +- tests/core_tests/tx_validation.cpp | 38 ++++---- .../performance_tests/check_ring_signature.h | 2 +- tests/unit_tests/serialization.cpp | 88 +++++++++---------- 23 files changed, 212 insertions(+), 164 deletions(-) diff --git a/src/common/variant_helper.h b/src/common/variant_helper.h index c1282d00..03d8746a 100644 --- a/src/common/variant_helper.h +++ b/src/common/variant_helper.h @@ -38,6 +38,7 @@ usage: VARIANT_CASE(NLSAG_sig, signatures); VARIANT_CASE(zarcanum_sig, s); //@#@ + VARIANT_CASE_THROW_ON_OTHER(); VARIANT_SWITCH_END(); diff --git a/src/currency_core/blockchain_storage.cpp b/src/currency_core/blockchain_storage.cpp index 41b6e32f..20bc4f0e 100644 --- a/src/currency_core/blockchain_storage.cpp +++ b/src/currency_core/blockchain_storage.cpp @@ -1528,7 +1528,7 @@ bool blockchain_storage::print_transactions_statistics() const // { // total_full_blob += get_object_blobsize(tx_entry.second.tx); // transaction tx = tx_entry.second.tx; -// tx.signatures.clear(); +// signatures.clear(); // total_cropped_blob += get_object_blobsize(tx); // } // } @@ -4295,11 +4295,11 @@ bool blockchain_storage::check_tx_inputs(const transaction& tx, const crypto::ha { if (!m_is_in_checkpoint_zone) { - VARIANT_SWITCH_BEGIN(tx.signatures); + VARIANT_SWITCH_BEGIN(tx.signature); VARIANT_CASE(void_sig, v); VARIANT_CASE(NLSAG_sig, signatures); { - CHECK_AND_ASSERT_MES(sig_index < tx.signatures.s.size(), false, "Wrong transaction: missing signature entry for input #" << sig_index << " tx: " << tx_prefix_hash); + CHECK_AND_ASSERT_MES(sig_index < signatures.s.size(), false, "Wrong transaction: missing signature entry for input #" << sig_index << " tx: " << tx_prefix_hash); psig = &signatures.s[sig_index]; } VARIANT_CASE(zarcanum_sig, s); @@ -4366,7 +4366,15 @@ bool blockchain_storage::check_tx_inputs(const transaction& tx, const crypto::ha TIME_MEASURE_START_PD(tx_check_inputs_attachment_check); if (!m_is_in_checkpoint_zone) { - CHECK_AND_ASSERT_MES(tx.signatures.size() == sig_index, false, "tx signatures count differs from inputs"); + VARIANT_SWITCH_BEGIN(tx.signature); + VARIANT_CASE(NLSAG_sig, signatures) + { + CHECK_AND_ASSERT_MES(signatures.size() == sig_index, false, "tx signatures count differs from inputs"); + } + VARIANT_CASE(zarcanum_sig, s); + //@#@ + VARIANT_CASE_THROW_ON_OTHER(); + VARIANT_SWITCH_END(); if (!(get_tx_flags(tx) & TX_FLAG_SIGNATURE_MODE_SEPARATE)) { bool r = validate_attachment_info(tx.extra, tx.attachment, false); @@ -4607,7 +4615,7 @@ bool blockchain_storage::check_ms_input(const transaction& tx, size_t in_index, VARIANT_CASE(void_sig, v); VARIANT_CASE(NLSAG_sig, signatures) { - LOC_CHK(tx.signatures.size() > in_index, "ms input index is out of signatures container bounds, tx.signatures.size() = " << tx.signatures.size()); + LOC_CHK(signatures.size() > in_index, "ms input index is out of signatures container bounds, signatures.size() = " << signatures.size()); const std::vector& input_signatures = signatures.s[in_index]; size_t expected_signatures_count = txin.sigs_count; @@ -7005,7 +7013,7 @@ bool blockchain_storage::validate_alt_block_txs(const block& b, const crypto::ha const transaction& tx = it == abei.onboard_transactions.end() ? *tx_ptr : it->second; if (tx.signature.type() == typeid(NLSAG_sig)) { - CHECK_AND_ASSERT_MES(boost::get(tx.signature).s.size() == tx.vin.size(), false, "invalid tx: tx.signatures.size() == " << boost::get(tx.signature).s.size() << ", tx.vin.size() == " << tx.vin.size()); + CHECK_AND_ASSERT_MES(boost::get(tx.signature).s.size() == tx.vin.size(), false, "invalid tx: signatures.size() == " << boost::get(tx.signature).s.size() << ", tx.vin.size() == " << tx.vin.size()); } for (size_t n = 0; n < tx.vin.size(); ++n) { diff --git a/src/currency_core/core_runtime_config.h b/src/currency_core/core_runtime_config.h index 214a1590..1f8aa1e6 100644 --- a/src/currency_core/core_runtime_config.h +++ b/src/currency_core/core_runtime_config.h @@ -36,11 +36,11 @@ namespace currency { switch (hardfork_id) { - case 0: return true; - case 1: return height > hard_forks.hard_fork_01_starts_after_height; - case 2: return height > hard_forks.hard_fork_02_starts_after_height; - case 3: return height > hard_forks.hard_fork_03_starts_after_height; - case 4: return height > hard_forks.hard_fork_04_starts_after_height; + case ZANO_HARDFORK_00_INITAL: return true; + case ZANO_HARDFORK_01: return height > hard_forks.hard_fork_01_starts_after_height; + case ZANO_HARDFORK_02: return height > hard_forks.hard_fork_02_starts_after_height; + case ZANO_HARDFORK_03: return height > hard_forks.hard_fork_03_starts_after_height; + case ZANO_HARDFORK_04_ZARCANUM: return height > hard_forks.hard_fork_04_starts_after_height; default: return false; } } diff --git a/src/currency_core/currency_boost_serialization.h b/src/currency_core/currency_boost_serialization.h index b25b1b10..76cefc06 100644 --- a/src/currency_core/currency_boost_serialization.h +++ b/src/currency_core/currency_boost_serialization.h @@ -227,7 +227,7 @@ namespace boost a & x.vin; a & x.vout; a & x.extra; - a & x.signatures; + a & x.signature; a & x.attachment; } diff --git a/src/currency_core/currency_config.h b/src/currency_core/currency_config.h index 8275d11a..37d40601 100644 --- a/src/currency_core/currency_config.h +++ b/src/currency_core/currency_config.h @@ -253,6 +253,13 @@ #endif +#define ZANO_HARDFORK_00_INITAL 0 +#define ZANO_HARDFORK_01 1 +#define ZANO_HARDFORK_02 2 +#define ZANO_HARDFORK_03 3 +#define ZANO_HARDFORK_04_ZARCANUM 4 + + static_assert(CURRENCY_MINER_TX_MAX_OUTS <= CURRENCY_TX_MAX_ALLOWED_OUTS, "Miner tx must obey normal tx max outs limit"); diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index b69178fe..cce55f04 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -3462,6 +3462,12 @@ bool wallet2::get_pos_entries(currency::COMMAND_RPC_SCAN_POS::request& req) return true; } //---------------------------------------------------------------------------------------------------- +bool wallet2::is_in_hardfork_zone(uint64_t hardfork_index) +{ + const currency::core_runtime_config& rtc = get_core_runtime_config(); + return rtc.is_hardfork_active_for_height(hardfork_index, get_blockchain_current_size()); +} +//---------------------------------------------------------------------------------------------------- bool wallet2::prepare_and_sign_pos_block(currency::block& b, const currency::pos_entry& pos_info, const crypto::public_key& source_tx_pub_key, @@ -3473,43 +3479,51 @@ bool wallet2::prepare_and_sign_pos_block(currency::block& b, WLT_CHECK_AND_ASSERT_MES(b.miner_tx.vin[1].type() == typeid(currency::txin_to_key), false, "Wrong output input in transaction"); auto& txin = boost::get(b.miner_tx.vin[1]); txin.k_image = pos_info.keyimage; - WLT_CHECK_AND_ASSERT_MES(b.miner_tx.signatures.size() == 1 && b.miner_tx.signatures[0].size() == txin.key_offsets.size(), - false, "Wrong signatures amount in coinbase transacton"); + + if (is_in_hardfork_zone(ZANO_HARDFORK_04_ZARCANUM)) + { + //@#@ TODO: add proper support of Zarcanum + WLT_THROW_IF_FALSE_WALLET_CMN_ERR_EX(false, "ZRCANUM BLOCKS NOT IMPLEMENTED YET"); + }else + { + NLSAG_sig& signatures = boost::get(b.miner_tx.signature); + WLT_CHECK_AND_ASSERT_MES(signatures.size() == 1 && signatures[0].size() == txin.key_offsets.size(), + false, "Wrong signatures amount in coinbase transacton"); + //derive secret key + crypto::key_derivation pos_coin_derivation = AUTO_VAL_INIT(pos_coin_derivation); + bool r = crypto::generate_key_derivation(source_tx_pub_key, + m_account.get_keys().view_secret_key, + pos_coin_derivation); - //derive secret key - crypto::key_derivation pos_coin_derivation = AUTO_VAL_INIT(pos_coin_derivation); - bool r = crypto::generate_key_derivation(source_tx_pub_key, - m_account.get_keys().view_secret_key, - pos_coin_derivation); + WLT_CHECK_AND_ASSERT_MES(r, false, "internal error: pos coin base generator: failed to generate_key_derivation(" + << source_tx_pub_key + << ", view secret key: " << m_account.get_keys().view_secret_key << ")"); - WLT_CHECK_AND_ASSERT_MES(r, false, "internal error: pos coin base generator: failed to generate_key_derivation(" - << source_tx_pub_key - << ", view secret key: " << m_account.get_keys().view_secret_key << ")"); + crypto::secret_key derived_secret_ephemeral_key = AUTO_VAL_INIT(derived_secret_ephemeral_key); + crypto::derive_secret_key(pos_coin_derivation, + in_tx_output_index, + m_account.get_keys().spend_secret_key, + derived_secret_ephemeral_key); - crypto::secret_key derived_secret_ephemeral_key = AUTO_VAL_INIT(derived_secret_ephemeral_key); - crypto::derive_secret_key(pos_coin_derivation, - in_tx_output_index, - m_account.get_keys().spend_secret_key, - derived_secret_ephemeral_key); + // sign block actually in coinbase transaction + crypto::hash block_hash = currency::get_block_hash(b); - // sign block actually in coinbase transaction - crypto::hash block_hash = currency::get_block_hash(b); + crypto::generate_ring_signature(block_hash, + txin.k_image, + keys_ptrs, + derived_secret_ephemeral_key, + 0, + &signatures[0][0]); - crypto::generate_ring_signature(block_hash, - txin.k_image, - keys_ptrs, - derived_secret_ephemeral_key, - 0, - &b.miner_tx.signatures[0][0]); + WLT_LOG_L4("GENERATED RING SIGNATURE: block_id " << block_hash + << "txin.k_image" << txin.k_image + << "key_ptr:" << *keys_ptrs[0] + << "signature:" << signatures[0][0]); - WLT_LOG_L4("GENERATED RING SIGNATURE: block_id " << block_hash - << "txin.k_image" << txin.k_image - << "key_ptr:" << *keys_ptrs[0] - << "signature:" << b.miner_tx.signatures[0][0]); - - return true; + return true; + } } //------------------------------------------------------------------ bool wallet2::build_kernel(const pos_entry& pe, const stake_modifier_type& stake_modifier, const uint64_t timestamp, stake_kernel& kernel) diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 0a1d7e70..dae73d0b 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -1014,6 +1014,7 @@ private: uint64_t detach_from_block_ids(uint64_t height); uint64_t get_wallet_minimum_height(); uint64_t get_directly_spent_transfer_id_by_input_in_tracking_wallet(const currency::txin_to_key& intk); + bool is_in_hardfork_zone(uint64_t hardfork_index); void push_alias_info_to_extra_according_to_hf_status(const currency::extra_alias_entry& ai, std::vector& extra); void remove_transfer_from_amount_gindex_map(uint64_t tid); diff --git a/src/wallet/wallet2_escrow.cpp b/src/wallet/wallet2_escrow.cpp index bbf2b533..9c7e342c 100644 --- a/src/wallet/wallet2_escrow.cpp +++ b/src/wallet/wallet2_escrow.cpp @@ -233,28 +233,36 @@ bool wallet2::validate_escrow_release(const transaction& tx, bool release_type_n // (5/5) signatures - LOC_CHK(tx.signatures.size() == 1, "invalid singatures size: " << tx.signatures.size()); // only 1 input means only 1 signature vector + VARIANT_SWITCH_BEGIN(tx.signature); + VARIANT_CASE(NLSAG_sig, signatures) + { + LOC_CHK(signatures.size() == 1, "invalid singatures size: " << signatures.size()); // only 1 input means only 1 signature vector - // As we don't have b_keys we can't be sure which signature is B's and which is reserved for A (should be a null-placeholder, if present). - // Having a_keys, we determine index of A key in multisig output keys array. - // Thus it's possible to determine the order of signatures (A, B or B, A), and, eventually, validate B signature. - crypto::public_key source_tx_pub_key = get_tx_pub_key_from_extra(source_tx); - r = crypto::generate_key_derivation(source_tx_pub_key, a_keys.view_secret_key, der); - LOC_CHK(r, "generate_key_derivation failed"); - crypto::public_key ephemeral_pub_key = AUTO_VAL_INIT(ephemeral_pub_key); - r = crypto::derive_public_key(der, source_ms_out_index, a_keys.account_address.spend_public_key, ephemeral_pub_key); - LOC_CHK(r, "derive_public_key failed"); + // As we don't have b_keys we can't be sure which signature is B's and which is reserved for A (should be a null-placeholder, if present). + // Having a_keys, we determine index of A key in multisig output keys array. + // Thus it's possible to determine the order of signatures (A, B or B, A), and, eventually, validate B signature. + crypto::public_key source_tx_pub_key = get_tx_pub_key_from_extra(source_tx); + r = crypto::generate_key_derivation(source_tx_pub_key, a_keys.view_secret_key, der); + LOC_CHK(r, "generate_key_derivation failed"); + crypto::public_key ephemeral_pub_key = AUTO_VAL_INIT(ephemeral_pub_key); + r = crypto::derive_public_key(der, source_ms_out_index, a_keys.account_address.spend_public_key, ephemeral_pub_key); + LOC_CHK(r, "derive_public_key failed"); - LOC_CHK(source_ms_out.keys.size() == 2, "internal error: invalid ms output keys array, size: " << source_ms_out.keys.size()); - LOC_CHK(tx.signatures[0].size() == 2, "internal error: invalid signature size for input #0: " << tx.signatures[0].size()) - size_t ms_out_key_a_index = std::find(source_ms_out.keys.begin(), source_ms_out.keys.end(), ephemeral_pub_key) - source_ms_out.keys.begin(); - LOC_CHK(ms_out_key_a_index < source_ms_out.keys.size(), "internal error: can't find A ephemeral pub key within ms output keys"); - size_t ms_out_key_b_index = 1 - ms_out_key_a_index; + LOC_CHK(source_ms_out.keys.size() == 2, "internal error: invalid ms output keys array, size: " << source_ms_out.keys.size()); + LOC_CHK(signatures[0].size() == 2, "internal error: invalid signature size for input #0: " << signatures[0].size()) + size_t ms_out_key_a_index = std::find(source_ms_out.keys.begin(), source_ms_out.keys.end(), ephemeral_pub_key) - source_ms_out.keys.begin(); + LOC_CHK(ms_out_key_a_index < source_ms_out.keys.size(), "internal error: can't find A ephemeral pub key within ms output keys"); + size_t ms_out_key_b_index = 1 - ms_out_key_a_index; - // in this particular case (source_ms_out.minimum_sigs == source_ms_out.keys.size() == 2) index in 'keys' is the same as index in tx.signatures[0] - crypto::hash tx_hash_for_signature = prepare_prefix_hash_for_sign(tx, 0, get_transaction_hash(tx)); - r = crypto::check_signature(tx_hash_for_signature, source_ms_out.keys[ms_out_key_b_index], tx.signatures[0][ms_out_key_b_index]); - LOC_CHK(r, "B signature for multisig input is invalid"); + // in this particular case (source_ms_out.minimum_sigs == source_ms_out.keys.size() == 2) index in 'keys' is the same as index in signatures[0] + crypto::hash tx_hash_for_signature = prepare_prefix_hash_for_sign(tx, 0, get_transaction_hash(tx)); + r = crypto::check_signature(tx_hash_for_signature, source_ms_out.keys[ms_out_key_b_index], signatures[0][ms_out_key_b_index]); + LOC_CHK(r, "B signature for multisig input is invalid"); + } + VARIANT_CASE(zarcanum_sig, s); + //@#@ + VARIANT_CASE_THROW_ON_OTHER(); + VARIANT_SWITCH_END(); return true; #undef LOC_CHK @@ -409,15 +417,24 @@ bool wallet2::validate_escrow_cancel_release(const currency::transaction& tx, co // (5/5) signatures - LOC_CHK(tx.signatures.size() == 1, "invalid singatures size: " << tx.signatures.size()); // only 1 input means only 1 signature vector - LOC_CHK(tx.signatures[0].size() == 2, "invalid signature[0] size: " << tx.signatures[0].size()); // it's expected to contain A-party signature and null-sig placeholder - LOC_CHK(source_ms_out.keys.size() == 2, "internal error: invalid source ms output keys array, size: " << source_ms_out.keys.size()); + VARIANT_SWITCH_BEGIN(tx.signature); + VARIANT_CASE(NLSAG_sig, signatures) + { + LOC_CHK(signatures.size() == 1, "invalid singatures size: " << signatures.size()); // only 1 input means only 1 signature vector + LOC_CHK(signatures[0].size() == 2, "invalid signature[0] size: " << signatures[0].size()); // it's expected to contain A-party signature and null-sig placeholder + LOC_CHK(source_ms_out.keys.size() == 2, "internal error: invalid source ms output keys array, size: " << source_ms_out.keys.size()); - size_t a_sign_index = (tx.signatures[0][0] != null_sig) ? 0 : 1; + size_t a_sign_index = (signatures[0][0] != null_sig) ? 0 : 1; + + crypto::hash tx_hash_for_signature = prepare_prefix_hash_for_sign(tx, 0, get_transaction_hash(tx)); + r = crypto::check_signature(tx_hash_for_signature, source_ms_out.keys[a_sign_index], signatures[0][a_sign_index]); + LOC_CHK(r, "A signature for multisig input is invalid"); + } + VARIANT_CASE(zarcanum_sig, s); + //@#@ + VARIANT_CASE_THROW_ON_OTHER(); + VARIANT_SWITCH_END(); - crypto::hash tx_hash_for_signature = prepare_prefix_hash_for_sign(tx, 0, get_transaction_hash(tx)); - r = crypto::check_signature(tx_hash_for_signature, source_ms_out.keys[a_sign_index], tx.signatures[0][a_sign_index]); - LOC_CHK(r, "A signature for multisig input is invalid"); return true; #undef LOC_CHK diff --git a/tests/core_tests/chaingen.cpp b/tests/core_tests/chaingen.cpp index 3ce1d381..714efaee 100644 --- a/tests/core_tests/chaingen.cpp +++ b/tests/core_tests/chaingen.cpp @@ -1842,9 +1842,9 @@ bool sign_multisig_input_in_tx_custom(currency::transaction& tx, size_t ms_input bool r = currency::derive_ephemeral_key_helper(keys, source_tx_pub_key, ms_out_index, ms_in_ephemeral_key); LOC_CHK(r, "derive_ephemeral_key_helper failed"); - LOC_CHK(ms_input_index < tx.signatures.size(), "transaction does not have signatures vectory entry for ms input #" << ms_input_index); + LOC_CHK(ms_input_index < boost::get(tx.signature).s.size(), "transaction does not have signatures vectory entry for ms input #" << ms_input_index); - auto& sigs = tx.signatures[ms_input_index]; + auto& sigs = boost::get(tx.signature).s[ms_input_index]; LOC_CHK(!sigs.empty(), "empty signatures container"); bool extra_signature_expected = (get_tx_flags(tx) & TX_FLAG_SIGNATURE_MODE_SEPARATE) && ms_input_index == tx.vin.size() - 1; size_t allocated_sigs_for_participants = extra_signature_expected ? sigs.size() - 1 : sigs.size(); diff --git a/tests/core_tests/chaingen.h b/tests/core_tests/chaingen.h index 364d07e2..6a3d7f5d 100644 --- a/tests/core_tests/chaingen.h +++ b/tests/core_tests/chaingen.h @@ -743,7 +743,7 @@ bool construct_broken_tx(const currency::account_keys& sender_account_keys, cons { tx.vin.clear(); tx.vout.clear(); - tx.signatures.clear(); + boost::get(tx.signature).s.clear(); tx.extra = extra; tx.version = TRANSACTION_VERSION_PRE_HF4; @@ -845,8 +845,8 @@ bool construct_broken_tx(const currency::account_keys& sender_account_keys, cons ss_ring_s << o.second << ENDL; } - tx.signatures.push_back(std::vector()); - std::vector& sigs = tx.signatures.back(); + boost::get(tx.signature).s.push_back(std::vector()); + std::vector& sigs = boost::get(tx.signature).s.back(); sigs.resize(src_entr.outputs.size()); crypto::generate_ring_signature(tx_prefix_hash, boost::get(tx.vin[i]).k_image, keys_ptrs, in_contexts[i].in_ephemeral.sec, src_entr.real_output, sigs.data()); ss_ring_s << "signatures:" << ENDL; diff --git a/tests/core_tests/chaingen_helpers.h b/tests/core_tests/chaingen_helpers.h index 2f5921f9..823df8fc 100644 --- a/tests/core_tests/chaingen_helpers.h +++ b/tests/core_tests/chaingen_helpers.h @@ -218,7 +218,7 @@ inline bool resign_tx(const currency::account_keys& sender_keys, const std::vect if (sources.size() != tx.vin.size()) return false; - tx.signatures.clear(); + boost::get(tx.signature).s.clear(); crypto::hash tx_prefix_hash = get_transaction_hash(tx); size_t i = 0; @@ -234,8 +234,8 @@ inline bool resign_tx(const currency::account_keys& sender_keys, const std::vect return false; crypto::derive_secret_key(recv_derivation, se.real_output_in_tx_index, sender_keys.spend_secret_key, in_ephemeral_sec); - tx.signatures.push_back(std::vector()); - std::vector& sigs = tx.signatures.back(); + boost::get(tx.signature).s.push_back(std::vector()); + std::vector& sigs = boost::get(tx.signature).s.back(); if (se.is_multisig()) { diff --git a/tests/core_tests/chaingen_main.cpp b/tests/core_tests/chaingen_main.cpp index d09d1558..9339c9a3 100644 --- a/tests/core_tests/chaingen_main.cpp +++ b/tests/core_tests/chaingen_main.cpp @@ -308,7 +308,7 @@ public: return; // skip certainly invalid txs bool b_cp = c.get_blockchain_storage().is_in_checkpoint_zone(); - if (b_cp && tx.signatures.empty() && tx.attachment.empty()) + if (b_cp && boost::get(tx.signature).s.empty() && tx.attachment.empty()) return; // skip pruned txs in CP zone size_t tx_expected_blob_size = get_object_blobsize(tx); @@ -328,7 +328,7 @@ public: { // tx seems to be correct ( tx_expected_blob_size == blob.size() ) or BCS is in CP zone, prune sigs and attachments and check again currency::transaction pruned_tx = tx; - pruned_tx.signatures.clear(); + boost::get(pruned_tx.signature).s.clear(); pruned_tx.attachment.clear(); size_t pruned_tx_expected_blob_size = get_object_blobsize(pruned_tx); diff --git a/tests/core_tests/checkpoints_tests.cpp b/tests/core_tests/checkpoints_tests.cpp index 76e262da..f2dca325 100644 --- a/tests/core_tests/checkpoints_tests.cpp +++ b/tests/core_tests/checkpoints_tests.cpp @@ -121,7 +121,7 @@ bool gen_checkpoints_attachments_basic::check_tx(currency::core& c, size_t ev_in bool r = c.get_transaction(m_tx_hash, tx); CHECK_AND_ASSERT_MES(r, false, "can't get transaction"); - CHECK_AND_ASSERT_MES(tx.signatures.empty(), false, "tx has non-empty sig"); + CHECK_AND_ASSERT_MES(boost::get(tx.signature).s.empty(), false, "tx has non-empty sig"); CHECK_AND_ASSERT_MES(tx.attachment.empty(), false, "tx has non-empty attachments"); return true; } @@ -443,12 +443,12 @@ bool gen_checkpoints_prun_txs_after_blockchain_load::check_txs(currency::core& c transaction tx_0, tx_1; bool r = c.get_transaction(m_tx0_id, tx_0); CHECK_AND_ASSERT_MES(r, false, "can't get transaction tx_0"); - CHECK_AND_ASSERT_MES(tx_0.signatures.empty(), false, "tx_0 has non-empty sig"); + CHECK_AND_ASSERT_MES(boost::get(tx_0.signature).s.empty(), false, "tx_0 has non-empty sig"); CHECK_AND_ASSERT_MES(tx_0.attachment.empty(), false, "tx_0 has non-empty attachments"); r = c.get_transaction(m_tx1_id, tx_1); CHECK_AND_ASSERT_MES(r, false, "can't get transaction tx_1"); - CHECK_AND_ASSERT_MES(!tx_1.signatures.empty(), false, "tx_1 has empty sig"); + CHECK_AND_ASSERT_MES(!boost::get(tx_1.signature).s.empty(), false, "tx_1 has empty sig"); CHECK_AND_ASSERT_MES(!tx_1.attachment.empty(), false, "tx_1 has empty attachments"); return true; @@ -595,7 +595,7 @@ bool gen_checkpoints_pos_validation_on_altchain::generate(std::vector(pb.m_block.miner_tx.signature).s[0].clear(); // just to make sure blk_2 = pb.m_block; } @@ -877,7 +877,7 @@ bool gen_checkpoints_and_invalid_tx_to_pool::generate(std::vector(tx_0.signature).s.clear(); DO_CALLBACK(events, "mark_unverifiable_tx"); events.push_back(tx_0); diff --git a/tests/core_tests/escrow_wallet_common.h b/tests/core_tests/escrow_wallet_common.h index 4e9ddf90..813e2597 100644 --- a/tests/core_tests/escrow_wallet_common.h +++ b/tests/core_tests/escrow_wallet_common.h @@ -253,8 +253,8 @@ inline bool build_custom_escrow_template(const std::vector& ev if (custom_config_mask & eccf_template_no_a_sigs) { - escrow_template_tx.signatures.clear(); - escrow_template_tx.signatures.push_back(std::vector()); + boost::get(escrow_template_tx.signature).s.clear(); + boost::get(escrow_template_tx.signature).s.push_back(std::vector()); } append_vector_by_another_vector(used_sources, sources); diff --git a/tests/core_tests/multisig_wallet_tests.cpp b/tests/core_tests/multisig_wallet_tests.cpp index 4af7576f..717be7f0 100644 --- a/tests/core_tests/multisig_wallet_tests.cpp +++ b/tests/core_tests/multisig_wallet_tests.cpp @@ -1034,7 +1034,7 @@ bool multisig_minimum_sigs::generate(std::vector& events) cons CHECK_AND_ASSERT_MES(r && !tx_fully_signed, false, "sign_multisig_input_in_tx failed, tx_fully_signed : " << tx_fully_signed); r = sign_multisig_input_in_tx_custom(tx_7, ms_6_out_idx, miner_acc.get_keys(), tx_6, &tx_fully_signed, false); CHECK_AND_ASSERT_MES(r && !tx_fully_signed, false, "sign_multisig_input_in_tx failed, tx_fully_signed : " << tx_fully_signed); - tx_7.signatures[0].push_back(invalid_signature); // instead of 4th sig just add invalid sig + boost::get(tx_7.signature).s[0].push_back(invalid_signature); // instead of 4th sig just add invalid sig DO_CALLBACK(events, "mark_invalid_tx"); events.push_back(tx_7); @@ -1070,7 +1070,7 @@ bool multisig_minimum_sigs::generate(std::vector& events) cons r = construct_tx(miner_acc.get_keys(), std::vector({ se }), std::vector({ tx_destination_entry(se.amount - TESTS_DEFAULT_FEE, alice_acc.get_public_address()) }), empty_attachment, tx_9, get_tx_version_from_events(events), 0); CHECK_AND_ASSERT_MES(r, false, "construct_tx failed"); - tx_9.signatures[0].resize(redundant_keys_count, invalid_signature); + boost::get(tx_9.signature).s[0].resize(redundant_keys_count, invalid_signature); r = sign_multisig_input_in_tx_custom(tx_9, ms_8_out_idx, bob_acc.get_keys(), tx_8, &tx_fully_signed, false); CHECK_AND_ASSERT_MES(r && !tx_fully_signed, false, "sign_multisig_input_in_tx failed, tx_fully_signed : " << tx_fully_signed); @@ -1844,7 +1844,7 @@ bool multisig_and_checkpoints_bad_txs::generate(std::vector& e transaction tx_2 = AUTO_VAL_INIT(tx_2); r = make_tx_multisig_to_key(tx_1, get_tx_out_index_by_amount(tx_1, amount), std::list({ alice_acc.get_keys() }), bob_acc.get_public_address(), tx_2); CHECK_AND_ASSERT_MES(r, false, "make_tx_multisig_to_key failed"); - tx_2.signatures.resize(10); + boost::get(tx_2.signature).s.resize(10); boost::get(tx_2.vin[0]).sigs_count = 10; DO_CALLBACK(events, "mark_invalid_tx"); @@ -1860,7 +1860,7 @@ bool multisig_and_checkpoints_bad_txs::generate(std::vector& e transaction tx_3 = AUTO_VAL_INIT(tx_3); r = make_tx_multisig_to_key(tx_1, get_tx_out_index_by_amount(tx_1, amount), std::list({ alice_acc.get_keys() }), bob_acc.get_public_address(), tx_3); CHECK_AND_ASSERT_MES(r, false, "make_tx_multisig_to_key failed"); - tx_3.signatures.clear(); + boost::get(tx_3.signature).s.clear(); boost::get(tx_3.vin[0]).sigs_count = 0; events.push_back(event_visitor_settings(event_visitor_settings::set_txs_kept_by_block, true)); @@ -1892,7 +1892,7 @@ bool multisig_and_checkpoints_bad_txs::generate(std::vector& e boost::get(txb.boost::get(m_tx.vout[0]).target).keys.resize(1500, k); txb.step4_calc_hash(); txb.step5_sign(sources); - txb.m_tx.signatures.clear(); + boost::get(txb.m_tx.signature).s.clear(); transaction tx_6 = txb.m_tx; events.push_back(event_visitor_settings(event_visitor_settings::set_txs_kept_by_block, true)); events.push_back(tx_6); @@ -2113,7 +2113,7 @@ bool ref_by_id_basics::generate(std::vector& events) const r = construct_tx(miner_acc.get_keys(), sources, destinations, empty_attachment, tx_1, 0, CURRENCY_TO_KEY_OUT_RELAXED, true); CHECK_AND_ASSERT_MES(r, false, "construct_tx"); - r = check_ring_signature_at_gen_time(events, get_block_hash(blk_0r), boost::get(tx_1.vin[0]), get_transaction_hash(tx_1), tx_1.signatures[0]); + r = check_ring_signature_at_gen_time(events, get_block_hash(blk_0r), boost::get(tx_1.vin[0]), get_transaction_hash(tx_1), boost::get(tx_1.signature).s[0]); CHECK_AND_ASSERT_MES(r, false, "check_ring_signature_at_gen_time failed"); events.push_back(tx_1); diff --git a/tests/core_tests/pos_block_builder.cpp b/tests/core_tests/pos_block_builder.cpp index 811563fb..a7367922 100644 --- a/tests/core_tests/pos_block_builder.cpp +++ b/tests/core_tests/pos_block_builder.cpp @@ -173,7 +173,7 @@ void pos_block_builder::step5_sign(const crypto::public_key& stake_tx_pub_key, s // sign block actually in coinbase transaction crypto::hash block_hash = currency::get_block_hash(m_block); std::vector keys_ptrs(1, &stake_tx_out_pub_key); - crypto::generate_ring_signature(block_hash, m_stake_kernel.kimage, keys_ptrs, derived_secret_ephemeral_key, 0, &m_block.miner_tx.signatures[0][0]); + crypto::generate_ring_signature(block_hash, m_stake_kernel.kimage, keys_ptrs, derived_secret_ephemeral_key, 0, &boost::get(m_block.miner_tx.signature).s[0][0]); m_step = 5; } @@ -272,8 +272,8 @@ bool construct_homemade_pos_miner_tx(size_t height, size_t median_size, const bo posin.k_image = pos_stake_keyimage; tx.vin.push_back(posin); //reserve place for ring signature - tx.signatures.resize(1); - tx.signatures[0].resize(posin.key_offsets.size()); + boost::get(tx.signature).s.resize(1); + boost::get(tx.signature).s[0].resize(posin.key_offsets.size()); return true; } diff --git a/tests/core_tests/pos_validation.cpp b/tests/core_tests/pos_validation.cpp index 0cfb69ff..ce02e351 100644 --- a/tests/core_tests/pos_validation.cpp +++ b/tests/core_tests/pos_validation.cpp @@ -358,7 +358,7 @@ bool gen_pos_invalid_coinbase::generate(std::vector& events) c pb.step4_generate_coinbase_tx(generator.get_timestamps_median(prev_id), generator.get_already_generated_coins(prev_block), alice_acc.get_public_address()); pb.step5_sign(stake_tx_pub_key, stake_output_idx, stake_output_pubkey, miner_acc); - pb.m_block.miner_tx.signatures.clear(); // remove signatures + boost::get(pb.m_block.miner_tx.signature).s.clear(); // remove signatures block blk_1 = pb.m_block; diff --git a/tests/core_tests/pruning_ring_signatures.cpp b/tests/core_tests/pruning_ring_signatures.cpp index aedebf6f..5f2b3c46 100644 --- a/tests/core_tests/pruning_ring_signatures.cpp +++ b/tests/core_tests/pruning_ring_signatures.cpp @@ -25,8 +25,8 @@ struct ev_visitor : public boost::static_visitor { size_t real_bloc_size = t_serializable_object_to_blob(t).size(); - std::cout << "prunging sigs: " << t.signatures.size() << ENDL; - t.signatures.clear(); + std::cout << "prunging sigs: " << boost::get(t.signature).s.size() << ENDL; + boost::get(t.signature).s.clear(); //check tx pruning correctnes if (real_bloc_size != get_object_blobsize(t)) diff --git a/tests/core_tests/transaction_tests.cpp b/tests/core_tests/transaction_tests.cpp index 6607e262..b9a278d9 100644 --- a/tests/core_tests/transaction_tests.cpp +++ b/tests/core_tests/transaction_tests.cpp @@ -110,7 +110,7 @@ bool test_transaction_generation_and_ring_signature() output_keys.push_back(&boost::get(boost::get(tx_mine_4.vout[0]).target).key); output_keys.push_back(&boost::get(boost::get(tx_mine_5.vout[0]).target).key); output_keys.push_back(&boost::get(boost::get(tx_mine_6.vout[0]).target).key); - r = crypto::check_ring_signature(pref_hash, boost::get(tx_rc1.vin[0]).k_image, output_keys, &tx_rc1.signatures[0][0]); + r = crypto::check_ring_signature(pref_hash, boost::get(tx_rc1.vin[0]).k_image, output_keys, &boost::get(tx_rc1.signature).s[0][0]); CHECK_AND_ASSERT_MES(r, false, "failed to check ring signature"); std::vector outs; diff --git a/tests/core_tests/tx_builder.h b/tests/core_tests/tx_builder.h index 085f62ed..00aff6b0 100644 --- a/tests/core_tests/tx_builder.h +++ b/tests/core_tests/tx_builder.h @@ -98,7 +98,7 @@ struct tx_builder void step5_sign(const std::vector& sources) { - m_tx.signatures.clear(); + boost::get(m_tx.signature).s.clear(); size_t i = 0; for(const currency::tx_source_entry& src_entr : sources) @@ -109,8 +109,8 @@ struct tx_builder keys_ptrs.push_back(&o.second); } - m_tx.signatures.push_back(std::vector()); - std::vector& sigs = m_tx.signatures.back(); + boost::get(m_tx.signature).s.push_back(std::vector()); + std::vector& sigs = boost::get(m_tx.signature).s.back(); sigs.resize(src_entr.outputs.size()); generate_ring_signature(m_tx_prefix_hash, boost::get(m_tx.vin[i]).k_image, keys_ptrs, m_in_contexts[i].sec, src_entr.real_output, sigs.data()); i++; diff --git a/tests/core_tests/tx_validation.cpp b/tests/core_tests/tx_validation.cpp index a57426fd..f83ad53a 100644 --- a/tests/core_tests/tx_validation.cpp +++ b/tests/core_tests/tx_validation.cpp @@ -370,9 +370,9 @@ bool gen_tx_key_image_not_derive_from_tx_key::generate(std::vector(); + boost::get(builder.m_tx.signature).s.resize(1); + boost::get(builder.m_tx.signature).s[0].resize(1); + boost::get(builder.m_tx.signature).s[0][0] = boost::value_initialized(); DO_CALLBACK(events, "mark_invalid_tx"); events.push_back(builder.m_tx); @@ -404,9 +404,9 @@ bool gen_tx_key_image_is_invalid::generate(std::vector& events builder.step4_calc_hash(); // Tx with invalid key image can't be subscribed, so create empty signature - builder.m_tx.signatures.resize(1); - builder.m_tx.signatures[0].resize(1); - builder.m_tx.signatures[0][0] = boost::value_initialized(); + boost::get(builder.m_tx.signature).s.resize(1); + boost::get(builder.m_tx.signature).s[0].resize(1); + boost::get(builder.m_tx.signature).s[0][0] = boost::value_initialized(); DO_CALLBACK(events, "mark_invalid_tx"); events.push_back(builder.m_tx); @@ -633,62 +633,62 @@ bool gen_tx_signatures_are_invalid::generate(std::vector& even // create reference transaction tx_0, Carol->Alice, nmix=0 MAKE_TX(events, tx_0, carol_account, alice_account, amount, blk_1r_f); events.pop_back(); - CHECK_AND_ASSERT_MES(tx_0.vin.size() > 1 && tx_0.vout.size() > 1 && tx_0.signatures.size() > 1, false, "tx_0 is incorrect"); // need > 1 for this test + CHECK_AND_ASSERT_MES(tx_0.vin.size() > 1 && tx_0.vout.size() > 1 && boost::get(tx_0.signature).s.size() > 1, false, "tx_0 is incorrect"); // need > 1 for this test // create reference transaction tx_1, Dan->Alice, nmix=1 MAKE_TX_MIX(events, tx_1, dan_account, alice_account, amount, 1, blk_1r_f); events.pop_back(); - CHECK_AND_ASSERT_MES(tx_1.vin.size() > 1 && tx_1.vout.size() > 1 && tx_1.signatures.size() > 1, false, "tx_1 is incorrect"); // need > 1 for this test + CHECK_AND_ASSERT_MES(tx_1.vin.size() > 1 && tx_1.vout.size() > 1 && boost::get(tx_1.signature).s.size() > 1, false, "tx_1 is incorrect"); // need > 1 for this test const block& prev_block = blk_1r_f; transaction broken_tx; // Tx with nmix = 0 without signatures broken_tx = tx_0; - broken_tx.signatures.clear(); + boost::get(broken_tx.signature).s.clear(); check_broken_tx(events, broken_tx, prev_block, miner_account, generator); // Tx with nmix = 0 have a few inputs, and not enough signatures broken_tx = tx_0; - broken_tx.signatures.resize(broken_tx.signatures.size() - 1); + boost::get(broken_tx.signature).s.resize(boost::get(broken_tx.signature).s.size() - 1); check_broken_tx(events, broken_tx, prev_block, miner_account, generator); // Tx with nmix = 0 have a few inputs, and too many signatures (1/2) broken_tx = tx_0; - broken_tx.signatures.back().push_back(invalid_signature); + boost::get(broken_tx.signature).s.back().push_back(invalid_signature); check_broken_tx(events, broken_tx, prev_block, miner_account, generator); // Tx with nmix = 0 have a few inputs, and too many signatures (2/2) broken_tx = tx_0; - broken_tx.signatures.push_back(std::vector()); - broken_tx.signatures.back().push_back(invalid_signature); + boost::get(broken_tx.signature).s.push_back(std::vector()); + boost::get(broken_tx.signature).s.back().push_back(invalid_signature); check_broken_tx(events, broken_tx, prev_block, miner_account, generator); // Tx with nmix = 1 without signatures broken_tx = tx_1; - broken_tx.signatures.clear(); + boost::get(broken_tx.signature).s.clear(); check_broken_tx(events, broken_tx, prev_block, miner_account, generator); // Tx with nmix = 1 have not enough signatures (1/2) broken_tx = tx_1; - broken_tx.signatures.resize(broken_tx.signatures.size() - 1); + boost::get(broken_tx.signature).s.resize(boost::get(broken_tx.signature).s.size() - 1); check_broken_tx(events, broken_tx, prev_block, miner_account, generator); // Tx with nmix = 1 have not enough signatures (2/2) broken_tx = tx_1; - broken_tx.signatures.back().resize(broken_tx.signatures.back().size() - 1); + boost::get(broken_tx.signature).s.back().resize(boost::get(broken_tx.signature).s.back().size() - 1); check_broken_tx(events, broken_tx, prev_block, miner_account, generator); // Tx with nmix = 1 have too many signatures (1/2) broken_tx = tx_1; - broken_tx.signatures.back().push_back(invalid_signature); + boost::get(broken_tx.signature).s.back().push_back(invalid_signature); check_broken_tx(events, broken_tx, prev_block, miner_account, generator); // Tx with nmix = 1 have too many signatures (2/2) broken_tx = tx_1; - broken_tx.signatures.push_back(std::vector()); - broken_tx.signatures.back().push_back(invalid_signature); + boost::get(broken_tx.signature).s.push_back(std::vector()); + boost::get(broken_tx.signature).s.back().push_back(invalid_signature); check_broken_tx(events, broken_tx, prev_block, miner_account, generator); diff --git a/tests/performance_tests/check_ring_signature.h b/tests/performance_tests/check_ring_signature.h index 5a56a783..d63ec01f 100644 --- a/tests/performance_tests/check_ring_signature.h +++ b/tests/performance_tests/check_ring_signature.h @@ -47,7 +47,7 @@ public: bool test() { const currency::txin_to_key& txin = boost::get(m_tx.vin[0]); - return crypto::check_ring_signature(m_tx_prefix_hash, txin.k_image, this->m_public_key_ptrs, ring_size, m_tx.signatures[0].data()); + return crypto::check_ring_signature(m_tx_prefix_hash, txin.k_image, this->m_public_key_ptrs, ring_size, boost::get(m_tx.signature)[0].data()); } private: diff --git a/tests/unit_tests/serialization.cpp b/tests/unit_tests/serialization.cpp index 5ebc3dd6..5091a20e 100644 --- a/tests/unit_tests/serialization.cpp +++ b/tests/unit_tests/serialization.cpp @@ -330,7 +330,7 @@ TEST(Serialization, serializes_transacion_signatures_correctly) ASSERT_TRUE(false); } - ASSERT_EQ(linearize_vector2(tx.signatures), linearize_vector2(tx1.signatures)); + ASSERT_EQ(linearize_vector2(boost::get(tx.signature).s), linearize_vector2(boost::get(tx1.signature).s)); // Miner tx without signatures txin_gen txin_gen1; @@ -344,10 +344,10 @@ TEST(Serialization, serializes_transacion_signatures_correctly) { ASSERT_TRUE(false); } - ASSERT_EQ(linearize_vector2(tx.signatures), linearize_vector2(tx1.signatures)); + ASSERT_EQ(linearize_vector2(boost::get(tx.signature).s), linearize_vector2(boost::get(tx1.signature).s)); // Miner tx with empty signatures 2nd vector - tx.signatures.resize(1); + boost::get(tx.signature).s.resize(1); ASSERT_TRUE(serialization::dump_binary(tx, blob)); ASSERT_EQ(9, blob.size()); // 5 bytes + 2 bytes vin[0] + 0 bytes extra + 0 bytes signatures + counter ASSERT_TRUE(serialization::parse_binary(blob, tx1)); @@ -355,29 +355,29 @@ TEST(Serialization, serializes_transacion_signatures_correctly) { ASSERT_TRUE(false); } - ASSERT_EQ(linearize_vector2(tx.signatures), linearize_vector2(tx1.signatures)); + ASSERT_EQ(linearize_vector2(boost::get(tx.signature).s), linearize_vector2(boost::get(tx1.signature).s)); //TX VALIDATION REMOVED FROM SERIALIZATION /* // Miner tx with one signature - tx.signatures[0].resize(1); + boost::get(tx.signature).s[0].resize(1); ASSERT_FALSE(serialization::dump_binary(tx, blob)); // Miner tx with 2 empty vectors - tx.signatures.resize(2); - tx.signatures[0].resize(0); - tx.signatures[1].resize(0); + boost::get(tx.signature).s.resize(2); + boost::get(tx.signature).s[0].resize(0); + boost::get(tx.signature).s[1].resize(0); ASSERT_FALSE(serialization::dump_binary(tx, blob)); // Miner tx with 2 signatures - tx.signatures[0].resize(1); - tx.signatures[1].resize(1); + boost::get(tx.signature).s[0].resize(1); + boost::get(tx.signature).s[1].resize(1); ASSERT_FALSE(serialization::dump_binary(tx, blob)); */ // Two txin_gen, no signatures tx.vin.push_back(txin_gen1); - tx.signatures.resize(0); + boost::get(tx.signature).s.resize(0); ASSERT_TRUE(serialization::dump_binary(tx, blob)); ASSERT_EQ(10, blob.size()); // 5 bytes + 2 * 2 bytes vins + 0 bytes extra + 0 bytes signatures ASSERT_TRUE(serialization::parse_binary(blob, tx1)); @@ -385,14 +385,14 @@ TEST(Serialization, serializes_transacion_signatures_correctly) { ASSERT_TRUE(false); } - ASSERT_EQ(linearize_vector2(tx.signatures), linearize_vector2(tx1.signatures)); + ASSERT_EQ(linearize_vector2(boost::get(tx.signature).s), linearize_vector2(boost::get(tx1.signature).s)); // Two txin_gen, signatures vector contains only one empty element - //tx.signatures.resize(1); + //signatures.resize(1); //ASSERT_FALSE(serialization::dump_binary(tx, blob)); // Two txin_gen, signatures vector contains two empty elements - tx.signatures.resize(2); + boost::get(tx.signature).s.resize(2); ASSERT_TRUE(serialization::dump_binary(tx, blob)); ASSERT_EQ(12, blob.size()); // 5 bytes + 2 * 2 bytes vins + 0 bytes extra + 0 bytes signatures ASSERT_TRUE(serialization::parse_binary(blob, tx1)); @@ -400,22 +400,22 @@ TEST(Serialization, serializes_transacion_signatures_correctly) { ASSERT_TRUE(false); } - ASSERT_EQ(linearize_vector2(tx.signatures), linearize_vector2(tx1.signatures)); + ASSERT_EQ(linearize_vector2(boost::get(tx.signature).s), linearize_vector2(boost::get(tx1.signature).s)); // Two txin_gen, signatures vector contains three empty elements - //tx.signatures.resize(3); + //signatures.resize(3); //ASSERT_FALSE(serialization::dump_binary(tx, blob)); // Two txin_gen, signatures vector contains two non empty elements - //tx.signatures.resize(2); - //tx.signatures[0].resize(1); - //tx.signatures[1].resize(1); + //signatures.resize(2); + //signatures[0].resize(1); + //signatures[1].resize(1); //ASSERT_FALSE(serialization::dump_binary(tx, blob)); // A few bytes instead of signature tx.vin.clear(); tx.vin.push_back(txin_gen1); - tx.signatures.clear(); + boost::get(tx.signature).s.clear(); ASSERT_TRUE(serialization::dump_binary(tx, blob)); blob.append(std::string(sizeof(crypto::signature) / 2, 'x')); ASSERT_FALSE(serialization::parse_binary(blob, tx1)); @@ -430,40 +430,40 @@ TEST(Serialization, serializes_transacion_signatures_correctly) //tx.vin.clear(); //tx.vin.push_back(txin_to_key1); //tx.vin.push_back(txin_to_key1); - //tx.signatures.resize(1); - //tx.signatures[0].resize(2); + //signatures.resize(1); + //signatures[0].resize(2); //ASSERT_FALSE(serialization::dump_binary(tx, blob)); /* // Too much signatures for two inputs - tx.signatures.resize(3); - tx.signatures[0].resize(2); - tx.signatures[1].resize(2); - tx.signatures[2].resize(2); + boost::get(tx.signature).s.resize(3); + boost::get(tx.signature).s[0].resize(2); + boost::get(tx.signature).s[1].resize(2); + boost::get(tx.signature).s[2].resize(2); ASSERT_FALSE(serialization::dump_binary(tx, blob)); // First signatures vector contains too little elements - tx.signatures.resize(2); - tx.signatures[0].resize(1); - tx.signatures[1].resize(2); + boost::get(tx.signature).s.resize(2); + boost::get(tx.signature).s[0].resize(1); + boost::get(tx.signature).s[1].resize(2); ASSERT_FALSE(serialization::dump_binary(tx, blob)); // First signatures vector contains too much elements - tx.signatures.resize(2); - tx.signatures[0].resize(3); - tx.signatures[1].resize(2); + boost::get(tx.signature).s.resize(2); + boost::get(tx.signature).s[0].resize(3); + boost::get(tx.signature).s[1].resize(2); ASSERT_FALSE(serialization::dump_binary(tx, blob)); // There are signatures for each input - tx.signatures.resize(2); - tx.signatures[0].resize(2); - tx.signatures[1].resize(2); + boost::get(tx.signature).s.resize(2); + boost::get(tx.signature).s[0].resize(2); + boost::get(tx.signature).s[1].resize(2); ASSERT_TRUE(serialization::dump_binary(tx, blob)); ASSERT_TRUE(serialization::parse_binary(blob, tx1)); ASSERT_EQ(tx, tx1); - ASSERT_EQ(linearize_vector2(tx.signatures), linearize_vector2(tx1.signatures)); + ASSERT_EQ(linearize_vector2(boost::get(tx.signature).s), linearize_vector2(boost::get(tx1.signature).s)); // Blob doesn't contain enough data blob.resize(blob.size() - sizeof(crypto::signature) / 2); @@ -622,7 +622,7 @@ bool operator ==(const transaction_new_tests& a, const transaction_new_tests& b) a.extra.size() == b.extra.size() && a.vin.size() == b.vin.size() && a.vout.size() == b.vout.size() && - a.signatures.size() == b.signatures.size(); + boost::get(a.signature).s.size() == boost::get(b.signature).s.size(); } bool operator ==(const transaction_new_tests& a, const transaction_old_tests& b) { @@ -630,7 +630,7 @@ bool operator ==(const transaction_new_tests& a, const transaction_old_tests& b) a.extra.size() == b.extra.size() && a.vin.size() == b.vin.size() && a.vout.size() == b.vout.size() && - a.signatures.size() == b.signatures.size(); + boost::get(a.signature).s.size() == boost::get(b.signature).s.size(); } void validate_tx_serialisation(transaction_new_tests& tx) @@ -670,7 +670,7 @@ TEST(Serialization, serializes_transacion_versions) { ASSERT_TRUE(false); } - ASSERT_EQ(linearize_vector2(tx.signatures), linearize_vector2(tx1.signatures)); + ASSERT_EQ(linearize_vector2(boost::get(tx.signature).s), linearize_vector2(boost::get(tx1.signature).s)); */ txin_gen txin_gen1; @@ -705,12 +705,12 @@ TEST(Serialization, serializes_transacion_versions) eae.m_alias = "eokcmeockme"; eae.m_text_comment = "sdssccsc"; tx.extra.push_back(eae); - tx.signatures.resize(2); + boost::get(tx.signature).s.resize(2); crypto::signature sig = epee::string_tools::parse_tpod_from_hex_string("22608f59f8080e2fbfe3c8c80eb6e6a953d47cf2d6aebd345bada3a1cab9985222608f59f8080e2fbfe3c8c80eb6e6a953d47cf2d6aebd345bada3a1cab99852"); - tx.signatures[0].push_back(sig); - tx.signatures[0].push_back(sig); - tx.signatures[1].push_back(sig); - tx.signatures[1].push_back(sig); + boost::get(tx.signature).s[0].push_back(sig); + boost::get(tx.signature).s[0].push_back(sig); + boost::get(tx.signature).s[1].push_back(sig); + boost::get(tx.signature).s[1].push_back(sig); tx.version = TRANSACTION_VERSION_INITAL; From 7162a23dd37ecec597121dcc012ce732b54e864f Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Tue, 24 May 2022 00:46:44 +0200 Subject: [PATCH 09/10] blockchain_storage.cpp compilation fixed --- src/common/variant_helper.h | 10 +- src/currency_core/blockchain_storage.cpp | 224 +++++++++--------- src/currency_core/blockchain_storage.h | 25 +- src/currency_core/currency_basic.h | 10 +- .../currency_basic_backward_comp.inl | 3 +- 5 files changed, 141 insertions(+), 131 deletions(-) diff --git a/src/common/variant_helper.h b/src/common/variant_helper.h index 03d8746a..ecbca5a4 100644 --- a/src/common/variant_helper.h +++ b/src/common/variant_helper.h @@ -4,7 +4,8 @@ #pragma once -#define VARIANT_SWITCH_BEGIN(v_type_obj) {decltype(v_type_obj)& local_reference_eokcmeokmeokcm = v_type_obj; if(false) {; +#define VARIANT_SWITCH_BEGIN(v_type_obj) {auto & local_reference_eokcmeokmeokcm = v_type_obj; if(false) {; +#define VARIANT_CASE_CONST(v_type, typed_name) } else if(local_reference_eokcmeokmeokcm.type() == typeid(v_type)) { const v_type& typed_name = boost::get(local_reference_eokcmeokmeokcm); #define VARIANT_CASE(v_type, typed_name) } else if(local_reference_eokcmeokmeokcm.type() == typeid(v_type)) { v_type& typed_name = boost::get(local_reference_eokcmeokmeokcm); #define VARIANT_CASE_TV(v_type) VARIANT_CASE(v_type, tv) #define VARIANT_CASE_OTHER() } else { @@ -26,9 +27,10 @@ usage: VARIANT_SWITCH_END(); VARIANT_SWITCH_BEGIN(o); - VARIANT_CASE(txout_to_key, o); - VARIANT_CASE_TV(txout_multisig); - VARIANT_CASE_TV(txout_htlc); + VARIANT_CASE_CONST(txout_to_key, o); + VARIANT_CASE_CONST(txout_multisig, ms); + VARIANT_CASE_CONST(txout_htlc, htlc); + VARIANT_CASE_THROW_ON_OTHER(); VARIANT_SWITCH_END(); diff --git a/src/currency_core/blockchain_storage.cpp b/src/currency_core/blockchain_storage.cpp index 20bc4f0e..667fa2fc 100644 --- a/src/currency_core/blockchain_storage.cpp +++ b/src/currency_core/blockchain_storage.cpp @@ -38,6 +38,7 @@ #include "crypto/RIPEMD160_helper.h" #include "crypto/bitcoin/sha256_helper.h" + #undef LOG_DEFAULT_CHANNEL #define LOG_DEFAULT_CHANNEL "core" ENABLE_CHANNEL_BY_DEFAULT("core"); @@ -610,13 +611,13 @@ bool blockchain_storage::prune_ring_signatures_and_attachments(uint64_t height, transaction_chain_entry lolcal_chain_entry = *it; VARIANT_SWITCH_BEGIN(lolcal_chain_entry.tx.signature); - VARIANT_CASE(void_sig, v); + VARIANT_CASE_CONST(void_sig, v); VARIANT_CASE(NLSAG_sig, signatures) { signatures_pruned += signatures.s.size(); signatures.s.clear(); } - VARIANT_CASE(zarcanum_sig, s); + VARIANT_CASE_CONST(zarcanum_sig, s); //@#@ VARIANT_SWITCH_END(); @@ -2488,7 +2489,7 @@ bool blockchain_storage::add_out_to_get_random_outs(COMMAND_RPC_GET_RANDOM_OUTPU const transaction& tx = tx_ptr->tx; VARIANT_SWITCH_BEGIN(tx.vout[out_ptr->out_no]); - VARIANT_CASE(tx_out_bare, o) + VARIANT_CASE_CONST(tx_out_bare, o) { if (o.target.type() == typeid(txout_htlc)) { @@ -2527,7 +2528,7 @@ bool blockchain_storage::add_out_to_get_random_outs(COMMAND_RPC_GET_RANDOM_OUTPU oen.global_amount_index = i; oen.out_key = otk.key; } - VARIANT_CASE_TV(tx_out_zarcanum) + VARIANT_CASE_CONST(tx_out_zarcanum, toz) //@#@ VARIANT_SWITCH_END(); @@ -3034,10 +3035,10 @@ void blockchain_storage::print_blockchain_outs_stats() const if (!spent)// && p_tx->tx.vout[output_entry.out_no].target.type() == typeid(txout_to_key)) { VARIANT_SWITCH_BEGIN(p_tx->tx.vout[output_entry.out_no]); - VARIANT_CASE(tx_out_bare, o) + VARIANT_CASE_CONST(tx_out_bare, o) if (boost::get(o.target).mix_attr != CURRENCY_TO_KEY_OUT_FORCED_NO_MIX) ++stat.mixable; - VARIANT_CASE_TV(tx_out_zarcanum) + VARIANT_CASE_CONST(tx_out_zarcanum, toz) //@#@ VARIANT_SWITCH_END(); } @@ -3354,7 +3355,7 @@ bool blockchain_storage::push_transaction_to_global_outs_index(const transaction BOOST_FOREACH(const auto& otv, tx.vout) { VARIANT_SWITCH_BEGIN(otv); - VARIANT_CASE(tx_out_bare, ot) + VARIANT_CASE_CONST(tx_out_bare, ot) if (ot.target.type() == typeid(txout_to_key) || ot.target.type() == typeid(txout_htlc)) { m_db_outputs.push_back_item(ot.amount, global_output_entry::construct(tx_id, i)); @@ -3374,7 +3375,7 @@ bool blockchain_storage::push_transaction_to_global_outs_index(const transaction m_db_multisig_outs.set(multisig_out_id, ms_output_entry::construct(tx_id, i)); global_indexes.push_back(0); // just stub to make other code easier } - VARIANT_CASE_TV(tx_out_zarcanum) + VARIANT_CASE_CONST(tx_out_zarcanum, toz) //@#@ VARIANT_CASE_THROW_ON_OTHER(); VARIANT_SWITCH_END(); @@ -3406,7 +3407,7 @@ bool blockchain_storage::get_outs(uint64_t amount, std::list CHECK_AND_ASSERT_MES(tx_ptr->tx.vout.size() > out_entry_ptr->out_no, false, "transactions outs global index consistency broken: index in tx_outx == " << out_entry_ptr->out_no << " is greather than tx.vout size == " << tx_ptr->tx.vout.size() << ", for amount: " << amount << ", gindex: " << i); //CHECK_AND_ASSERT_MES(tx_ptr->tx.vout[out_entry_ptr->out_no].target.type() == typeid(txout_to_key), false, "transactions outs global index consistency broken: out #" << out_entry_ptr->out_no << " in tx " << out_entry_ptr->tx_id << " has wrong type, for amount: " << amount << ", gindex: " << i); VARIANT_SWITCH_BEGIN(tx_ptr->tx.vout[out_entry_ptr->out_no]); - VARIANT_CASE(tx_out_bare, o) + VARIANT_CASE_CONST(tx_out_bare, o) if (o.target.type() == typeid(txout_to_key)) { pkeys.push_back(boost::get(o.target).key); @@ -3415,7 +3416,7 @@ bool blockchain_storage::get_outs(uint64_t amount, std::list { pkeys.push_back(boost::get(o.target).pkey_redeem); } - VARIANT_CASE_TV(tx_out_zarcanum) + VARIANT_CASE_CONST(tx_out_zarcanum, toz) //@#@ VARIANT_CASE_THROW_ON_OTHER(); VARIANT_SWITCH_END(); @@ -3431,7 +3432,7 @@ bool blockchain_storage::pop_transaction_from_global_index(const transaction& tx BOOST_REVERSE_FOREACH(const auto& otv, tx.vout) { VARIANT_SWITCH_BEGIN(otv); - VARIANT_CASE(tx_out_bare, ot) + VARIANT_CASE_CONST(tx_out_bare, ot) if (ot.target.type() == typeid(txout_to_key) || ot.target.type() == typeid(txout_htlc)) { uint64_t sz = m_db_outputs.get_item_size(ot.amount); @@ -3450,7 +3451,7 @@ bool blockchain_storage::pop_transaction_from_global_index(const transaction& tx bool res = m_db_multisig_outs.erase_validate(multisig_out_id); CHECK_AND_ASSERT_MES(res, false, "Internal error: multisig out not found, multisig_out_id " << multisig_out_id << "in multisig outs index"); } - VARIANT_CASE_TV(tx_out_zarcanum) + VARIANT_CASE_CONST(tx_out_zarcanum, toz) //@#@ VARIANT_CASE_THROW_ON_OTHER(); VARIANT_SWITCH_END(); @@ -4188,12 +4189,12 @@ bool blockchain_storage::print_tx_outputs_lookup(const crypto::hash& tx_id)const for (uint64_t i = 0; i!= tx_ptr->tx.vout.size();i++) { VARIANT_SWITCH_BEGIN(tx_ptr->tx.vout[i]); - VARIANT_CASE(tx_out_bare, o) + VARIANT_CASE_CONST(tx_out_bare, o) strm_tx << "[" << i << "]: " << print_money(o.amount) << ENDL; if (o.target.type() != typeid(currency::txout_to_key)) continue; usage_stat[o.amount][tx_ptr->m_global_output_indexes[i]]; - VARIANT_CASE_TV(tx_out_zarcanum) + VARIANT_CASE_CONST(tx_out_zarcanum, toz) //@#@ VARIANT_SWITCH_END(); } @@ -4296,22 +4297,21 @@ bool blockchain_storage::check_tx_inputs(const transaction& tx, const crypto::ha if (!m_is_in_checkpoint_zone) { VARIANT_SWITCH_BEGIN(tx.signature); - VARIANT_CASE(void_sig, v); - VARIANT_CASE(NLSAG_sig, signatures); + VARIANT_CASE_CONST(void_sig, v); + VARIANT_CASE_CONST(NLSAG_sig, signatures); { CHECK_AND_ASSERT_MES(sig_index < signatures.s.size(), false, "Wrong transaction: missing signature entry for input #" << sig_index << " tx: " << tx_prefix_hash); psig = &signatures.s[sig_index]; } - VARIANT_CASE(zarcanum_sig, s); + VARIANT_CASE_CONST(zarcanum_sig, s); //@#@ VARIANT_SWITCH_END(); } - if (txin.type() == typeid(txin_to_key)) + VARIANT_SWITCH_BEGIN(txin); + VARIANT_CASE_CONST(txin_to_key, in_to_key) { - const txin_to_key& in_to_key = boost::get(txin); - CHECK_AND_ASSERT_MES(in_to_key.key_offsets.size(), false, "Empty in_to_key.key_offsets for input #" << sig_index << " tx: " << tx_prefix_hash); TIME_MEASURE_START_PD(tx_check_inputs_loop_kimage_check); if (have_tx_keyimg_as_spent(in_to_key.k_image)) @@ -4321,22 +4321,21 @@ bool blockchain_storage::check_tx_inputs(const transaction& tx, const crypto::ha } TIME_MEASURE_FINISH_PD(tx_check_inputs_loop_kimage_check); uint64_t max_unlock_time = 0; - if (!check_tx_input(tx, sig_index, in_to_key, tx_prefix_hash, *psig, max_used_block_height, max_unlock_time)) + if (!check_tx_input(tx, sig_index, in_to_key, tx_prefix_hash, max_used_block_height, max_unlock_time)) { LOG_ERROR("Failed to validate input #" << sig_index << " tx: " << tx_prefix_hash); return false; } } - else if (txin.type() == typeid(txin_multisig)) + VARIANT_CASE_CONST(txin_multisig, in_ms) { - const txin_multisig& in_ms = boost::get(txin); - if (!check_tx_input(tx, sig_index, in_ms, tx_prefix_hash, *psig, max_used_block_height)) + if (!check_tx_input(tx, sig_index, in_ms, tx_prefix_hash, max_used_block_height)) { LOG_ERROR("Failed to validate multisig input #" << sig_index << " (ms out id: " << in_ms.multisig_out_id << ") in tx: " << tx_prefix_hash); return false; } } - else if (txin.type() == typeid(txin_htlc)) + VARIANT_CASE_CONST(txin_htlc, in_htlc) { if (!is_after_hardfork_3_zone()) { @@ -4344,7 +4343,6 @@ bool blockchain_storage::check_tx_inputs(const transaction& tx, const crypto::ha return false; } - const txin_htlc& in_htlc = boost::get(txin); CHECK_AND_ASSERT_MES(in_htlc.key_offsets.size(), false, "Empty in_to_key.key_offsets for input #" << sig_index << " tx: " << tx_prefix_hash); TIME_MEASURE_START_PD(tx_check_inputs_loop_kimage_check); if (have_tx_keyimg_as_spent(in_htlc.k_image)) @@ -4353,12 +4351,15 @@ bool blockchain_storage::check_tx_inputs(const transaction& tx, const crypto::ha return false; } TIME_MEASURE_FINISH_PD(tx_check_inputs_loop_kimage_check); - if (!check_tx_input(tx, sig_index, in_htlc, tx_prefix_hash, *psig, max_used_block_height)) + if (!check_tx_input(tx, sig_index, in_htlc, tx_prefix_hash, max_used_block_height)) { LOG_ERROR("Failed to validate multisig input #" << sig_index << " (ms out id: " << obj_to_json_str(in_htlc) << ") in tx: " << tx_prefix_hash); return false; } } + VARIANT_CASE_THROW_ON_OTHER(); + VARIANT_SWITCH_END(); + sig_index++; } TIME_MEASURE_FINISH_PD(tx_check_inputs_loop); @@ -4367,11 +4368,11 @@ bool blockchain_storage::check_tx_inputs(const transaction& tx, const crypto::ha if (!m_is_in_checkpoint_zone) { VARIANT_SWITCH_BEGIN(tx.signature); - VARIANT_CASE(NLSAG_sig, signatures) + VARIANT_CASE_CONST(NLSAG_sig, signatures) { - CHECK_AND_ASSERT_MES(signatures.size() == sig_index, false, "tx signatures count differs from inputs"); + CHECK_AND_ASSERT_MES(signatures.s.size() == sig_index, false, "tx signatures count differs from inputs"); } - VARIANT_CASE(zarcanum_sig, s); + VARIANT_CASE_CONST(zarcanum_sig, s); //@#@ VARIANT_CASE_THROW_ON_OTHER(); VARIANT_SWITCH_END(); @@ -4390,7 +4391,7 @@ bool blockchain_storage::is_tx_spendtime_unlocked(uint64_t unlock_time) const return currency::is_tx_spendtime_unlocked(unlock_time, get_current_blockchain_size(), m_core_runtime_config.get_core_time()); } //------------------------------------------------------------------ -bool blockchain_storage::check_tx_input(const transaction& tx, size_t in_index, const txin_to_key& txin, const crypto::hash& tx_prefix_hash, const std::vector& sig, uint64_t& max_related_block_height, uint64_t& source_max_unlock_time_for_pos_coinbase) const +bool blockchain_storage::check_tx_input(const transaction& tx, size_t in_index, const txin_to_key& txin, const crypto::hash& tx_prefix_hash, uint64_t& max_related_block_height, uint64_t& source_max_unlock_time_for_pos_coinbase) const { CRITICAL_REGION_LOCAL(m_read_lock); @@ -4410,7 +4411,7 @@ bool blockchain_storage::check_tx_input(const transaction& tx, size_t in_index, for (auto& ptr : output_keys) output_keys_ptrs.push_back(&ptr); - return check_input_signature(tx, in_index, txin, tx_prefix_hash, sig, output_keys_ptrs); + return check_input_signature(tx, in_index, txin, tx_prefix_hash, output_keys_ptrs); } //---------------------------------------------------------------- struct outputs_visitor @@ -4497,7 +4498,7 @@ bool blockchain_storage::get_output_keys_for_input_with_checks(const transaction //------------------------------------------------------------------ // Note: this function can be used for checking to_key inputs against either main chain or alt chain, that's why it has output_keys_ptrs parameter // Doesn't check spent flags, the caller must check it. -bool blockchain_storage::check_input_signature(const transaction& tx, size_t in_index, const txin_to_key& txin, const crypto::hash& tx_prefix_hash, const std::vector& sig, const std::vector& output_keys_ptrs) const +bool blockchain_storage::check_input_signature(const transaction& tx, size_t in_index, const txin_to_key& txin, const crypto::hash& tx_prefix_hash, const std::vector& output_keys_ptrs) const { if (txin.key_offsets.size() != output_keys_ptrs.size()) { @@ -4505,7 +4506,7 @@ bool blockchain_storage::check_input_signature(const transaction& tx, size_t in_ return false; } - return check_input_signature(tx, in_index, /*txin.key_offsets,*/ txin.amount, txin.k_image, txin.etc_details, tx_prefix_hash, sig, output_keys_ptrs); + return check_input_signature(tx, in_index, /*txin.key_offsets,*/ txin.amount, txin.k_image, txin.etc_details, tx_prefix_hash, output_keys_ptrs); } //------------------------------------------------------------------ bool blockchain_storage::check_input_signature(const transaction& tx, @@ -4514,7 +4515,6 @@ bool blockchain_storage::check_input_signature(const transaction& tx, const crypto::key_image& in_k_image, const std::vector& in_etc_details, const crypto::hash& tx_prefix_hash, - const std::vector& sig, const std::vector& output_keys_ptrs) const { CRITICAL_REGION_LOCAL(m_read_lock); @@ -4524,6 +4524,10 @@ bool blockchain_storage::check_input_signature(const transaction& tx, if(m_is_in_checkpoint_zone) return true; + CHECK_AND_ASSERT_MES(tx.signature.type() == typeid(NLSAG_sig), false, "Unexpected type of sig in check_input_signature: " << tx.signature.type().name()); + auto s = boost::get(tx.signature).s; + CHECK_AND_ASSERT_MES(s.size() > in_index, false, "Failed to check s.size(){" << s.size() << "} > in_index {" << in_index << "}" ); + const std::vector& sig = s[in_index]; if (get_tx_flags(tx) & TX_FLAG_SIGNATURE_MODE_SEPARATE) { // check attachments, mentioned directly in this input @@ -4572,7 +4576,7 @@ bool blockchain_storage::check_input_signature(const transaction& tx, //------------------------------------------------------------------ // Note: this function doesn't check spent flags by design (to be able to use either for main chain and alt chains). // The caller MUST check spent flags. -bool blockchain_storage::check_ms_input(const transaction& tx, size_t in_index, const txin_multisig& txin, const crypto::hash& tx_prefix_hash, const std::vector& sig, const transaction& source_tx, size_t out_n) const +bool blockchain_storage::check_ms_input(const transaction& tx, size_t in_index, const txin_multisig& txin, const crypto::hash& tx_prefix_hash, const transaction& source_tx, size_t out_n) const { #define LOC_CHK(cond, msg) CHECK_AND_ASSERT_MES(cond, false, "ms input check failed: ms_id: " << txin.multisig_out_id << ", input #" << in_index << " in tx " << tx_prefix_hash << ", refers to ms output #" << out_n << " in source tx " << get_transaction_hash(source_tx) << ENDL << msg) CRITICAL_REGION_LOCAL(m_read_lock); @@ -4581,7 +4585,7 @@ bool blockchain_storage::check_ms_input(const transaction& tx, size_t in_index, LOC_CHK(is_tx_spendtime_unlocked(unlock_time), "Source transaction is LOCKED! unlock_time: " << unlock_time << ", now is " << m_core_runtime_config.get_core_time() << ", blockchain size is " << get_current_blockchain_size()); LOC_CHK(source_tx.vout.size() > out_n, "internal error: out_n==" << out_n << " is out-of-bounds of source_tx.vout, size=" << source_tx.vout.size()); - LOC_CHK(source_tx.vout[out_n].type() !== typeid(tx_out_bare), "internal error: out_n==" << out_n << " has unexpected type: " << source_tx.vout[out_n].type().name()); + LOC_CHK(source_tx.vout[out_n].type() != typeid(tx_out_bare), "internal error: out_n==" << out_n << " has unexpected type: " << source_tx.vout[out_n].type().name()); const tx_out_bare& source_tx_out = boost::get(source_tx.vout[out_n]); const txout_multisig& source_ms_out_target = boost::get(source_tx_out.target); @@ -4610,16 +4614,15 @@ bool blockchain_storage::check_ms_input(const transaction& tx, size_t in_index, // make sure normal tx does not have extra_attachment_info in etc_details LOC_CHK(!have_type_in_variant_container(txin.etc_details), "Incorrect using of extra_attachment_info in etc_details in input #" << in_index << " for tx " << tx_prefix_hash); } - + bool need_to_check_extra_sign = false; VARIANT_SWITCH_BEGIN(tx.signature); - VARIANT_CASE(void_sig, v); - VARIANT_CASE(NLSAG_sig, signatures) + VARIANT_CASE_CONST(void_sig, v); + VARIANT_CASE_CONST(NLSAG_sig, signatures) { - LOC_CHK(signatures.size() > in_index, "ms input index is out of signatures container bounds, signatures.size() = " << signatures.size()); + LOC_CHK(signatures.s.size() > in_index, "ms input index is out of signatures container bounds, signatures.size() = " << signatures.s.size()); const std::vector& input_signatures = signatures.s[in_index]; size_t expected_signatures_count = txin.sigs_count; - bool need_to_check_extra_sign = false; if (get_tx_flags(tx)&TX_FLAG_SIGNATURE_MODE_SEPARATE && in_index == tx.vin.size() - 1) // last input in TX_FLAG_SIGNATURE_MODE_SEPARATE must contain one more signature to ensure that tx was completed by an authorized subject { expected_signatures_count++; @@ -4652,21 +4655,21 @@ bool blockchain_storage::check_ms_input(const transaction& tx, size_t in_index, } } } - VARIANT_CASE(zarcanum_sig, s); + VARIANT_CASE_CONST(zarcanum_sig, s); //@#@ VARIANT_SWITCH_END(); if (need_to_check_extra_sign) { VARIANT_SWITCH_BEGIN(tx.signature); - VARIANT_CASE(void_sig, v); - VARIANT_CASE(NLSAG_sig, signatures) + VARIANT_CASE_CONST(void_sig, v); + VARIANT_CASE_CONST(NLSAG_sig, signatures) { //here we check extra signature to validate that transaction was finilized by authorized subject bool r = crypto::check_signature(tx_prefix_hash, get_tx_pub_key_from_extra(tx), signatures.s[in_index].back()); LOC_CHK(r, "failed to check extra signature for last out with TX_FLAG_SIGNATURE_MODE_SEPARATE"); } - VARIANT_CASE(zarcanum_sig, s); + VARIANT_CASE_CONST(zarcanum_sig, s); //@#@ VARIANT_SWITCH_END(); @@ -4677,7 +4680,7 @@ bool blockchain_storage::check_ms_input(const transaction& tx, size_t in_index, } //------------------------------------------------------------------ -bool blockchain_storage::check_tx_input(const transaction& tx, size_t in_index, const txin_multisig& txin, const crypto::hash& tx_prefix_hash, const std::vector& sig, uint64_t& max_related_block_height) const +bool blockchain_storage::check_tx_input(const transaction& tx, size_t in_index, const txin_multisig& txin, const crypto::hash& tx_prefix_hash, uint64_t& max_related_block_height) const { CRITICAL_REGION_LOCAL(m_read_lock); @@ -4694,12 +4697,12 @@ bool blockchain_storage::check_tx_input(const transaction& tx, size_t in_index, auto source_tx_ptr = m_db_transactions.find(source_tx_id); LOC_CHK(source_tx_ptr, "Can't find source transaction"); LOC_CHK(source_tx_ptr->tx.vout.size() > n, "ms output index is incorrect, source tx's vout size is " << source_tx_ptr->tx.vout.size()); - LOC_CHK(source_tx_ptr->tx.vout[n].type() != = typeid(tx_out_bare), "internal error: out_n==" << n << " has unexpected type: " << source_tx_ptr->tx.vout[n].type().name()); + LOC_CHK(source_tx_ptr->tx.vout[n].type() != typeid(tx_out_bare), "internal error: out_n==" << n << " has unexpected type: " << source_tx_ptr->tx.vout[n].type().name()); LOC_CHK(boost::get(source_tx_ptr->tx.vout[n]).target.type() == typeid(txout_multisig), "ms output has wrong type, txout_multisig expected"); LOC_CHK(source_tx_ptr->m_spent_flags.size() > n, "Internal error, m_spent_flags size (" << source_tx_ptr->m_spent_flags.size() << ") less then expected, n: " << n); LOC_CHK(source_tx_ptr->m_spent_flags[n] == false, "Internal error, ms output is already spent"); // should never happen as multisig_ptr->spent_height is checked above - if (!check_ms_input(tx, in_index, txin, tx_prefix_hash, sig, source_tx_ptr->tx, n)) + if (!check_ms_input(tx, in_index, txin, tx_prefix_hash, source_tx_ptr->tx, n)) return false; max_related_block_height = source_tx_ptr->m_keeper_block_height; @@ -4708,7 +4711,7 @@ bool blockchain_storage::check_tx_input(const transaction& tx, size_t in_index, #undef LOC_CHK } //------------------------------------------------------------------ -bool blockchain_storage::check_tx_input(const transaction& tx, size_t in_index, const txin_htlc& txin, const crypto::hash& tx_prefix_hash, const std::vector& sig, uint64_t& max_related_block_height)const +bool blockchain_storage::check_tx_input(const transaction& tx, size_t in_index, const txin_htlc& txin, const crypto::hash& tx_prefix_hash, uint64_t& max_related_block_height)const { CRITICAL_REGION_LOCAL(m_read_lock); @@ -4753,8 +4756,19 @@ bool blockchain_storage::check_tx_input(const transaction& tx, size_t in_index, output_keys_ptrs.push_back(&ptr); CHECK_AND_ASSERT_THROW_MES(output_keys_ptrs.size() == 1, "Internal error: output_keys_ptrs.size() is not equal 1 for HTLC"); - - return check_input_signature(tx, in_index, txin.amount, txin.k_image, txin.etc_details, tx_prefix_hash, sig, output_keys_ptrs); + + VARIANT_SWITCH_BEGIN(tx.signature); + VARIANT_CASE_CONST(NLSAG_sig, signatures); + { + CHECK_AND_ASSERT_MES(signatures.s.size() > in_index, false, "Unexpeted number of singatures in NLSAG_sig: " << signatures.s.size() << ", expected at least: " << in_index); + return check_input_signature(tx, in_index, txin.amount, txin.k_image, txin.etc_details, tx_prefix_hash, output_keys_ptrs); + } + VARIANT_CASE_CONST(zarcanum_sig, s); + //@#@ TODO + return false; + VARIANT_CASE_THROW_ON_OTHER(); + VARIANT_SWITCH_END(); + return false; } //------------------------------------------------------------------ uint64_t blockchain_storage::get_adjusted_time() const @@ -5054,13 +5068,13 @@ bool blockchain_storage::validate_tx_for_hardfork_specific_terms(const transacti for (const auto out : tx.vout) { VARIANT_SWITCH_BEGIN(out); - VARIANT_CASE(tx_out_bare, o) + VARIANT_CASE_CONST(tx_out_bare, o) if (o.target.type() == typeid(txout_htlc)) { if (!var_is_after_hardfork_3_zone) return false; } - VARIANT_CASE_TV(tx_out_zarcanum) + VARIANT_CASE_CONST(tx_out_zarcanum, toz) if (!var_is_after_hardfork_4_zone) return false; VARIANT_SWITCH_END(); @@ -5115,9 +5129,9 @@ bool blockchain_storage::validate_pos_coinbase_outs_unlock_time(const transactio if (unlock_value >= source_max_unlock_time) { VARIANT_SWITCH_BEGIN(miner_tx.vout[i]); - VARIANT_CASE(tx_out_bare, o) + VARIANT_CASE_CONST(tx_out_bare, o) amount_of_coins_in_unlock_in_range += o.amount; - VARIANT_CASE_TV(tx_out_zarcanum) + VARIANT_CASE_CONST(tx_out_zarcanum, toz) //@#@ VARIANT_SWITCH_END(); } @@ -5205,37 +5219,30 @@ bool blockchain_storage::validate_pos_block(const block& b, uint64_t max_related_block_height = 0; const txin_to_key& coinstake_in = boost::get(b.miner_tx.vin[1]); - VARIANT_SWITCH_BEGIN(b.miner_tx.signature); - VARIANT_CASE(void_sig, v); - VARIANT_CASE(NLSAG_sig, signatures) + if (!for_altchain) { - CHECK_AND_ASSERT_MES(signatures.s.size() == 1, false, "PoS block's miner_tx has incorrect signatures size = " << signatures.s.size() << ", block_id = " << get_block_hash(b)); - if (!for_altchain) - { - // Do coinstake input validation for main chain only. - // Txs in alternative PoS blocks (including miner_tx) are validated by validate_alt_block_txs() - uint64_t source_max_unlock_time_for_pos_coinbase = 0; - r = check_tx_input(b.miner_tx, 1, coinstake_in, id, signatures.s[0], max_related_block_height, source_max_unlock_time_for_pos_coinbase); - CHECK_AND_ASSERT_MES(r, false, "Failed to validate coinstake input in miner tx, block_id = " << get_block_hash(b)); + // Do coinstake input validation for main chain only. + // Txs in alternative PoS blocks (including miner_tx) are validated by validate_alt_block_txs() + uint64_t source_max_unlock_time_for_pos_coinbase = 0; + r = check_tx_input(b.miner_tx, 1, coinstake_in, id, max_related_block_height, source_max_unlock_time_for_pos_coinbase); + CHECK_AND_ASSERT_MES(r, false, "Failed to validate coinstake input in miner tx, block_id = " << get_block_hash(b)); - if (get_block_height(b) > m_core_runtime_config.hard_forks.hard_fork_01_starts_after_height) - { - uint64_t last_pow_h = get_last_x_block_height(false); - CHECK_AND_ASSERT_MES(max_related_block_height <= last_pow_h, false, "Failed to validate coinbase in PoS block, condition failed: max_related_block_height(" << max_related_block_height << ") <= last_pow_h(" << last_pow_h << ")"); - //let's check that coinbase amount and unlock time - r = validate_pos_coinbase_outs_unlock_time(b.miner_tx, coinstake_in.amount, source_max_unlock_time_for_pos_coinbase); - CHECK_AND_ASSERT_MES(r, false, "Failed to validate_pos_coinbase_outs_unlock_time() in miner tx, block_id = " << get_block_hash(b) - << "source_max_unlock_time_for_pos_coinbase=" << source_max_unlock_time_for_pos_coinbase); - } - else - { - CHECK_AND_ASSERT_MES(is_tx_spendtime_unlocked(source_max_unlock_time_for_pos_coinbase), false, "Failed to validate coinbase in PoS block, condition failed: is_tx_spendtime_unlocked(source_max_unlock_time_for_pos_coinbase)(" << source_max_unlock_time_for_pos_coinbase << ")"); - } + if (get_block_height(b) > m_core_runtime_config.hard_forks.hard_fork_01_starts_after_height) + { + uint64_t last_pow_h = get_last_x_block_height(false); + CHECK_AND_ASSERT_MES(max_related_block_height <= last_pow_h, false, "Failed to validate coinbase in PoS block, condition failed: max_related_block_height(" << max_related_block_height << ") <= last_pow_h(" << last_pow_h << ")"); + //let's check that coinbase amount and unlock time + r = validate_pos_coinbase_outs_unlock_time(b.miner_tx, coinstake_in.amount, source_max_unlock_time_for_pos_coinbase); + CHECK_AND_ASSERT_MES(r, false, "Failed to validate_pos_coinbase_outs_unlock_time() in miner tx, block_id = " << get_block_hash(b) + << "source_max_unlock_time_for_pos_coinbase=" << source_max_unlock_time_for_pos_coinbase); + } + else + { + CHECK_AND_ASSERT_MES(is_tx_spendtime_unlocked(source_max_unlock_time_for_pos_coinbase), false, "Failed to validate coinbase in PoS block, condition failed: is_tx_spendtime_unlocked(source_max_unlock_time_for_pos_coinbase)(" << source_max_unlock_time_for_pos_coinbase << ")"); } } - VARIANT_CASE(zarcanum_sig, s); - //@#@ - VARIANT_SWITCH_END(); + + uint64_t block_height = for_altchain ? split_height + alt_chain.size() : m_db_blocks.size(); uint64_t coinstake_age = block_height - max_related_block_height - 1; @@ -5540,7 +5547,7 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt VARIANT_SWITCH_BEGIN(tx.signature); VARIANT_CASE(NLSAG_sig, signatures) signatures.s.clear(); - VARIANT_CASE(zarcanum_sig, s); + VARIANT_CASE_CONST(zarcanum_sig, s); //@#@ VARIANT_SWITCH_END(); @@ -6360,7 +6367,6 @@ bool blockchain_storage::validate_alt_block_input(const transaction& input_tx, const crypto::hash& bl_id, const crypto::hash& input_tx_hash, size_t input_index, - const signature_v& input_sigs, uint64_t split_height, const alt_chain_type& alt_chain, const std::unordered_set& alt_chain_block_ids, @@ -6569,7 +6575,7 @@ bool blockchain_storage::validate_alt_block_input(const transaction& input_tx, CHECK_AND_ASSERT_MES(it->second.first.vout.size() > out_n, false, "Internal error: out_n(" << out_n << ") >= it->second.vout.size()(" << it->second.first.vout.size() << ")"); VARIANT_SWITCH_BEGIN(it->second.first.vout[out_n]); - VARIANT_CASE(tx_out_bare, o) + VARIANT_CASE_CONST(tx_out_bare, o) { /* here we do validation against compatibility of input and output type @@ -6606,7 +6612,7 @@ bool blockchain_storage::validate_alt_block_input(const transaction& input_tx, ASSERT_MES_AND_THROW("Unexpected out type for tx_in in altblock: " << out_target_v.type().name()); } } - VARIANT_CASE_TV(tx_out_zarcanum) + VARIANT_CASE_CONST(tx_out_zarcanum, toz) //@#@ VARIANT_SWITCH_END(); } @@ -6617,7 +6623,7 @@ bool blockchain_storage::validate_alt_block_input(const transaction& input_tx, CHECK_AND_ASSERT_MES(p != nullptr && out_n < p->tx.vout.size(), false, "can't find output #" << out_n << " for tx " << tx_id << " referred by offset #" << pk_n); VARIANT_SWITCH_BEGIN(p->tx.vout[out_n]); - VARIANT_CASE(tx_out_bare, o) + VARIANT_CASE_CONST(tx_out_bare, o) { auto &t = o.target; @@ -6666,22 +6672,16 @@ bool blockchain_storage::validate_alt_block_input(const transaction& input_tx, //CHECK_AND_ASSERT_MES(pk != null_pkey, false, "Can't determine output public key for offset " << pk_n << " in related tx: " << tx_id << ", out_n = " << out_n); pub_key_pointers.push_back(&pk); } - VARIANT_CASE_TV(tx_out_zarcanum) + VARIANT_CASE_CONST(tx_out_zarcanum, toz) //@#@ VARIANT_SWITCH_END(); } - VARIANT_SWITCH_BEGIN(input_sigs); - VARIANT_CASE(void_sig, v); - VARIANT_CASE(NLSAG_sig, signatures) - { - // do input checks (attachment_info, ring signature and extra signature, etc.) - r = check_input_signature(input_tx, input_index, input_to_key, input_tx_hash, signatures.s[input_index], pub_key_pointers); - CHECK_AND_ASSERT_MES(r, false, "to_key input validation failed"); - } - VARIANT_CASE(zarcanum_sig, s); - //@#@ - VARIANT_SWITCH_END(); + + // do input checks (attachment_info, ring signature and extra signature, etc.) + r = check_input_signature(input_tx, input_index, input_to_key, input_tx_hash, pub_key_pointers); + CHECK_AND_ASSERT_MES(r, false, "to_key input validation failed"); + // TODO: consider checking input_tx for valid extra attachment info as it's checked in check_tx_inputs() return true; @@ -6788,7 +6788,7 @@ bool blockchain_storage::validate_alt_block_ms_input(const transaction& input_tx && input_tx.signature.type() == typeid(NLSAG_sig), false, "invalid ms input index: " << input_index << " or type"); const txin_multisig& input = boost::get(input_tx.vin[input_index]); - const std::vector& input_sigs = boost::get(input_tx.signature).s[input_index]; + //const std::vector& input_sigs = boost::get(input_tx.signature).s[input_index]; // check corresponding ms out in the main chain auto p = m_db_multisig_outs.get(input.multisig_out_id); if (p != nullptr) @@ -6803,7 +6803,7 @@ bool blockchain_storage::validate_alt_block_ms_input(const transaction& input_tx if (p_source_tx->m_keeper_block_height < split_height) { // cases g1, g2 - return check_ms_input(input_tx, input_index, input, input_tx_hash, input_sigs, p_source_tx->tx, p->out_no); + return check_ms_input(input_tx, input_index, input, input_tx_hash, p_source_tx->tx, p->out_no); } // p_source_tx is above split_height in main chain B, so it can't be a source for this input @@ -6838,7 +6838,7 @@ bool blockchain_storage::validate_alt_block_ms_input(const transaction& input_tx for (size_t out_n = 0; out_n < tx.vout.size(); ++out_n) { VARIANT_SWITCH_BEGIN(tx.vout[out_n]); - VARIANT_CASE(tx_out_bare, o) + VARIANT_CASE_CONST(tx_out_bare, o) const tx_out_bare& out = o; if (out.target.type() == typeid(txout_multisig)) { @@ -6847,10 +6847,10 @@ bool blockchain_storage::validate_alt_block_ms_input(const transaction& input_tx { // cases g3, g4, g5 output_found = true; - return check_ms_input(input_tx, input_index, input, input_tx_hash, input_sigs, tx, out_n); + return check_ms_input(input_tx, input_index, input, input_tx_hash, tx, out_n); } } - VARIANT_CASE_TV(tx_out_zarcanum) + VARIANT_CASE_CONST(tx_out_zarcanum, toz) //@#@ VARIANT_SWITCH_END(); } @@ -6903,7 +6903,7 @@ bool blockchain_storage::update_alt_out_indexes_for_tx_in_block(const transactio for (auto ov : tx.vout) { VARIANT_SWITCH_BEGIN(ov); - VARIANT_CASE(tx_out_bare, o) + VARIANT_CASE_CONST(tx_out_bare, o) if (o.target.type() == typeid(txout_to_key) || o.target.type() == typeid(txout_htlc)) { //LOG_PRINT_MAGENTA("ALT_OUT KEY ON H[" << abei.height << "] AMOUNT: " << o.amount, LOG_LEVEL_0); @@ -6925,7 +6925,7 @@ bool blockchain_storage::update_alt_out_indexes_for_tx_in_block(const transactio //TODO: At the moment we ignore check of mix_attr again mixing to simplify alt chain check, but in future consider it for stronger validation } - VARIANT_CASE_TV(tx_out_zarcanum) + VARIANT_CASE_CONST(tx_out_zarcanum, toz) //@#@ VARIANT_SWITCH_END(); } @@ -6981,14 +6981,14 @@ bool blockchain_storage::validate_alt_block_txs(const block& b, const crypto::ha // check PoS block miner tx in a special way VARIANT_SWITCH_BEGIN(b.miner_tx.signature); - VARIANT_CASE(void_sig, v); - VARIANT_CASE(NLSAG_sig, signatures); + VARIANT_CASE_CONST(void_sig, v); + VARIANT_CASE_CONST(NLSAG_sig, signatures); { CHECK_AND_ASSERT_MES(signatures.s.size() == 1 && b.miner_tx.vin.size() == 2, false, "invalid PoS block's miner_tx, signatures size = " << signatures.s.size() << ", miner_tx.vin.size() = " << b.miner_tx.vin.size()); - r = validate_alt_block_input(b.miner_tx, collected_keyimages, alt_chain_tx_ids, id, get_block_hash(b), 1, signatures.s[0], split_height, alt_chain, alt_chain_block_ids, ki_lookup, &max_related_block_height); + r = validate_alt_block_input(b.miner_tx, collected_keyimages, alt_chain_tx_ids, id, get_block_hash(b), 1, split_height, alt_chain, alt_chain_block_ids, ki_lookup, &max_related_block_height); CHECK_AND_ASSERT_MES(r, false, "miner tx " << get_transaction_hash(b.miner_tx) << ": validation failed"); } - VARIANT_CASE(zarcanum_sig, s); + VARIANT_CASE_CONST(zarcanum_sig, s); //@#@ VARIANT_SWITCH_END(); @@ -7020,7 +7020,7 @@ bool blockchain_storage::validate_alt_block_txs(const block& b, const crypto::ha if (tx.vin[n].type() == typeid(txin_to_key) || tx.vin[n].type() == typeid(txin_htlc)) { uint64_t ki_lookup = 0; - r = validate_alt_block_input(tx, collected_keyimages, alt_chain_tx_ids, id, tx_id, n, tx.signature, split_height, alt_chain, alt_chain_block_ids, ki_lookup); + r = validate_alt_block_input(tx, collected_keyimages, alt_chain_tx_ids, id, tx_id, n, split_height, alt_chain, alt_chain_block_ids, ki_lookup); CHECK_AND_ASSERT_MES(r, false, "tx " << tx_id << ", input #" << n << ": validation failed"); ki_lookup_time_total += ki_lookup; } diff --git a/src/currency_core/blockchain_storage.h b/src/currency_core/blockchain_storage.h index ef864b8a..e927398a 100644 --- a/src/currency_core/blockchain_storage.h +++ b/src/currency_core/blockchain_storage.h @@ -39,7 +39,7 @@ #include "dispatch_core_events.h" #include "bc_attachments_service_manager.h" #include "common/median_db_cache.h" - +#include "common/variant_helper.h" MARK_AS_POD_C11(crypto::key_image); @@ -286,25 +286,24 @@ namespace currency uint64_t get_aliases_count()const; uint64_t get_block_h_older_then(uint64_t timestamp) const; bool validate_tx_service_attachmens_in_services(const tx_service_attachment& a, size_t i, const transaction& tx)const; - bool check_tx_input(const transaction& tx, size_t in_index, const txin_to_key& txin, const crypto::hash& tx_prefix_hash, const signature_v& sig, uint64_t& max_related_block_height, uint64_t& source_max_unlock_time_for_pos_coinbase)const; - bool check_tx_input(const transaction& tx, size_t in_index, const txin_multisig& txin, const crypto::hash& tx_prefix_hash, const signature_v& sig, uint64_t& max_related_block_height)const; - bool check_tx_input(const transaction& tx, size_t in_index, const txin_htlc& txin, const crypto::hash& tx_prefix_hash, const signature_v& sig, uint64_t& max_related_block_height)const; + bool check_tx_input(const transaction& tx, size_t in_index, const txin_to_key& txin, const crypto::hash& tx_prefix_hash, uint64_t& max_related_block_height, uint64_t& source_max_unlock_time_for_pos_coinbase)const; + bool check_tx_input(const transaction& tx, size_t in_index, const txin_multisig& txin, const crypto::hash& tx_prefix_hash, uint64_t& max_related_block_height)const; + bool check_tx_input(const transaction& tx, size_t in_index, const txin_htlc& txin, const crypto::hash& tx_prefix_hash, uint64_t& max_related_block_height)const; bool check_tx_inputs(const transaction& tx, const crypto::hash& tx_prefix_hash, uint64_t& max_used_block_height)const; bool check_tx_inputs(const transaction& tx, const crypto::hash& tx_prefix_hash) const; bool check_tx_inputs(const transaction& tx, const crypto::hash& tx_prefix_hash, uint64_t& max_used_block_height, crypto::hash& max_used_block_id)const; - bool check_ms_input(const transaction& tx, size_t in_index, const txin_multisig& txin, const crypto::hash& tx_prefix_hash, const signature_v& sig, const transaction& source_tx, size_t out_n) const; + bool check_ms_input(const transaction& tx, size_t in_index, const txin_multisig& txin, const crypto::hash& tx_prefix_hash, const transaction& source_tx, size_t out_n) const; bool validate_tx_for_hardfork_specific_terms(const transaction& tx, const crypto::hash& tx_id, uint64_t block_height) const; bool validate_tx_for_hardfork_specific_terms(const transaction& tx, const crypto::hash& tx_id) const; bool get_output_keys_for_input_with_checks(const transaction& tx, const txin_v& verified_input, std::vector& output_keys, uint64_t& max_related_block_height, uint64_t& source_max_unlock_time_for_pos_coinbase, scan_for_keys_context& scan_context) const; bool get_output_keys_for_input_with_checks(const transaction& tx, const txin_v& verified_input, std::vector& output_keys, uint64_t& max_related_block_height, uint64_t& source_max_unlock_time_for_pos_coinbase) const; - bool check_input_signature(const transaction& tx, size_t in_index, const txin_to_key& txin, const crypto::hash& tx_prefix_hash, const std::vector& sig, const std::vector& output_keys_ptrs) const; + bool check_input_signature(const transaction& tx, size_t in_index, const txin_to_key& txin, const crypto::hash& tx_prefix_hash, const std::vector& output_keys_ptrs) const; bool check_input_signature(const transaction& tx, size_t in_index, uint64_t in_amount, const crypto::key_image& k_image, const std::vector& in_etc_details, const crypto::hash& tx_prefix_hash, - const std::vector& sig, const std::vector& output_keys_ptrs) const; uint64_t get_current_comulative_blocksize_limit()const; @@ -597,7 +596,6 @@ namespace currency const crypto::hash& bl_id, const crypto::hash& input_tx_hash, size_t input_index, - const signature_v& input_sigs, //const std::vector& input_sigs, uint64_t split_height, const alt_chain_type& alt_chain, const std::unordered_set& alt_chain_block_ids, @@ -782,7 +780,7 @@ namespace currency */ VARIANT_SWITCH_BEGIN(tx_ptr->tx.vout[n]); - VARIANT_CASE(tx_out_bare, o) + VARIANT_CASE_CONST(tx_out_bare, o) { bool r = is_output_allowed_for_input(o.target, verified_input, get_current_blockchain_size() - tx_ptr->m_keeper_block_height); CHECK_AND_ASSERT_MES(r, false, "Input and output incompatible type"); @@ -821,21 +819,22 @@ namespace currency return false; } - TIME_MEASURE_START_PD(tx_check_inputs_loop_scan_outputkeys_loop_handle_output); - if (!vis.handle_output(tx_ptr->tx, validated_tx, tx_ptr->tx.vout[n], n)) + + if (!vis.handle_output(tx_ptr->tx, validated_tx, o, n)) { LOG_PRINT_L0("Failed to handle_output for output id = " << tx_id << ", no " << n); return false; } + TIME_MEASURE_FINISH_PD(tx_check_inputs_loop_scan_outputkeys_loop_handle_output); } - VARIANT_CASE_TV(tx_out_zarcanum) + VARIANT_CASE_CONST(tx_out_zarcanum, oz) //@#@ + return false; VARIANT_CASE_THROW_ON_OTHER(); VARIANT_SWITCH_END(); - TIME_MEASURE_FINISH_PD(tx_check_inputs_loop_scan_outputkeys_loop_handle_output); if (max_related_block_height < tx_ptr->m_keeper_block_height) max_related_block_height = tx_ptr->m_keeper_block_height; diff --git a/src/currency_core/currency_basic.h b/src/currency_core/currency_basic.h index 8c24ac27..e5c022d7 100644 --- a/src/currency_core/currency_basic.h +++ b/src/currency_core/currency_basic.h @@ -659,16 +659,24 @@ namespace currency struct NLSAG_sig { std::vector > s; + + BEGIN_SERIALIZE_OBJECT() + FIELD(s) + END_SERIALIZE() }; struct zarcanum_sig { //TODO: + BEGIN_SERIALIZE_OBJECT() + END_SERIALIZE() }; struct void_sig { //TODO: + BEGIN_SERIALIZE_OBJECT() + END_SERIALIZE() }; typedef boost::variant signature_v; @@ -740,7 +748,7 @@ namespace currency vin.clear(); vout.clear(); extra.clear(); - signatures.clear(); + signature = void_sig(); attachment.clear(); } diff --git a/src/currency_core/currency_basic_backward_comp.inl b/src/currency_core/currency_basic_backward_comp.inl index fbd47181..9be0dc9c 100644 --- a/src/currency_core/currency_basic_backward_comp.inl +++ b/src/currency_core/currency_basic_backward_comp.inl @@ -75,7 +75,8 @@ bool transition_convert(const transaction_prefix_v1& from, transaction_prefix_cu } -class transaction_v1: + +class transaction_v1 { public: std::vector > signatures; //count signatures always the same as inputs count From 217a54c8b1a2989615e7c98bb2f350d25780ac32 Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Wed, 25 May 2022 22:31:23 +0200 Subject: [PATCH 10/10] fixed all core tests --- src/currency_core/blockchain_storage.cpp | 13 +++- src/currency_core/currency_basic.h | 14 +++- .../currency_basic_backward_comp.inl | 2 - src/currency_core/currency_format_utils.cpp | 78 +++++++++++-------- src/currency_core/currency_format_utils.h | 5 +- .../currency_format_utils_transactions.cpp | 6 +- src/currency_core/tx_pool.cpp | 8 +- src/rpc/core_rpc_server.cpp | 4 +- src/wallet/wallet2.cpp | 48 ++++++------ src/wallet/wallet2_escrow.cpp | 41 +++++----- tests/core_tests/alias_tests.cpp | 8 +- tests/core_tests/block_reward.cpp | 6 +- tests/core_tests/block_validation.cpp | 8 +- tests/core_tests/chain_switch_pow_pos.cpp | 11 ++- tests/core_tests/chaingen.cpp | 20 ++--- tests/core_tests/double_spend.inl | 2 +- tests/core_tests/emission_test.cpp | 7 +- tests/core_tests/escrow_wallet_tests.cpp | 4 +- tests/core_tests/hard_fork_2.cpp | 12 +-- tests/core_tests/integer_overflow.cpp | 4 +- tests/core_tests/mixin_attr.cpp | 2 +- tests/core_tests/multisig_wallet_tests.cpp | 19 +++-- tests/core_tests/tx_validation.cpp | 4 +- tests/core_tests/wallet_tests.cpp | 5 +- .../transactions_flow_test.cpp | 6 +- tests/performance_tests/is_out_to_acc.h | 2 +- tests/performance_tests/multi_tx_test_base.h | 4 +- 27 files changed, 196 insertions(+), 147 deletions(-) diff --git a/src/currency_core/blockchain_storage.cpp b/src/currency_core/blockchain_storage.cpp index 667fa2fc..9e81bee4 100644 --- a/src/currency_core/blockchain_storage.cpp +++ b/src/currency_core/blockchain_storage.cpp @@ -4526,8 +4526,13 @@ bool blockchain_storage::check_input_signature(const transaction& tx, CHECK_AND_ASSERT_MES(tx.signature.type() == typeid(NLSAG_sig), false, "Unexpected type of sig in check_input_signature: " << tx.signature.type().name()); auto s = boost::get(tx.signature).s; - CHECK_AND_ASSERT_MES(s.size() > in_index, false, "Failed to check s.size(){" << s.size() << "} > in_index {" << in_index << "}" ); - const std::vector& sig = s[in_index]; + uint64_t actual_sig_index = in_index; + if (is_pos_coinbase(tx)) + { + actual_sig_index = 0; + } + CHECK_AND_ASSERT_MES(s.size() > actual_sig_index, false, "Failed to check s.size(){" << s.size() << "} > actual_sig_index {" << actual_sig_index << "}" ); + const std::vector& sig = s[actual_sig_index]; if (get_tx_flags(tx) & TX_FLAG_SIGNATURE_MODE_SEPARATE) { // check attachments, mentioned directly in this input @@ -4585,7 +4590,7 @@ bool blockchain_storage::check_ms_input(const transaction& tx, size_t in_index, LOC_CHK(is_tx_spendtime_unlocked(unlock_time), "Source transaction is LOCKED! unlock_time: " << unlock_time << ", now is " << m_core_runtime_config.get_core_time() << ", blockchain size is " << get_current_blockchain_size()); LOC_CHK(source_tx.vout.size() > out_n, "internal error: out_n==" << out_n << " is out-of-bounds of source_tx.vout, size=" << source_tx.vout.size()); - LOC_CHK(source_tx.vout[out_n].type() != typeid(tx_out_bare), "internal error: out_n==" << out_n << " has unexpected type: " << source_tx.vout[out_n].type().name()); + LOC_CHK(source_tx.vout[out_n].type() == typeid(tx_out_bare), "internal error: out_n==" << out_n << " has unexpected type: " << source_tx.vout[out_n].type().name()); const tx_out_bare& source_tx_out = boost::get(source_tx.vout[out_n]); const txout_multisig& source_ms_out_target = boost::get(source_tx_out.target); @@ -4697,7 +4702,7 @@ bool blockchain_storage::check_tx_input(const transaction& tx, size_t in_index, auto source_tx_ptr = m_db_transactions.find(source_tx_id); LOC_CHK(source_tx_ptr, "Can't find source transaction"); LOC_CHK(source_tx_ptr->tx.vout.size() > n, "ms output index is incorrect, source tx's vout size is " << source_tx_ptr->tx.vout.size()); - LOC_CHK(source_tx_ptr->tx.vout[n].type() != typeid(tx_out_bare), "internal error: out_n==" << n << " has unexpected type: " << source_tx_ptr->tx.vout[n].type().name()); + LOC_CHK(source_tx_ptr->tx.vout[n].type() == typeid(tx_out_bare), "internal error: out_n==" << n << " has unexpected type: " << source_tx_ptr->tx.vout[n].type().name()); LOC_CHK(boost::get(source_tx_ptr->tx.vout[n]).target.type() == typeid(txout_multisig), "ms output has wrong type, txout_multisig expected"); LOC_CHK(source_tx_ptr->m_spent_flags.size() > n, "Internal error, m_spent_flags size (" << source_tx_ptr->m_spent_flags.size() << ") less then expected, n: " << n); LOC_CHK(source_tx_ptr->m_spent_flags[n] == false, "Internal error, ms output is already spent"); // should never happen as multisig_ptr->spent_height is checked above diff --git a/src/currency_core/currency_basic.h b/src/currency_core/currency_basic.h index e5c022d7..3f17ca18 100644 --- a/src/currency_core/currency_basic.h +++ b/src/currency_core/currency_basic.h @@ -663,6 +663,10 @@ namespace currency BEGIN_SERIALIZE_OBJECT() FIELD(s) END_SERIALIZE() + + BEGIN_BOOST_SERIALIZATION() + BOOST_SERIALIZE(s) + END_BOOST_SERIALIZATION() }; struct zarcanum_sig @@ -670,6 +674,9 @@ namespace currency //TODO: BEGIN_SERIALIZE_OBJECT() END_SERIALIZE() + + BEGIN_BOOST_SERIALIZATION() + END_BOOST_SERIALIZATION() }; struct void_sig @@ -677,9 +684,12 @@ namespace currency //TODO: BEGIN_SERIALIZE_OBJECT() END_SERIALIZE() + + BEGIN_BOOST_SERIALIZATION() + END_BOOST_SERIALIZATION() }; - typedef boost::variant signature_v; + typedef boost::variant signature_v; @@ -748,7 +758,7 @@ namespace currency vin.clear(); vout.clear(); extra.clear(); - signature = void_sig(); + signature = NLSAG_sig(); attachment.clear(); } diff --git a/src/currency_core/currency_basic_backward_comp.inl b/src/currency_core/currency_basic_backward_comp.inl index 9be0dc9c..b6e9a684 100644 --- a/src/currency_core/currency_basic_backward_comp.inl +++ b/src/currency_core/currency_basic_backward_comp.inl @@ -46,7 +46,6 @@ public: template bool transition_convert(const transaction_prefix_current_t& from, transaction_prefix_v1& to) { - to.version = from.version; to.extra = from.extra; to.vin = from.vin; for (const auto& v : from.vout) @@ -64,7 +63,6 @@ bool transition_convert(const transaction_prefix_current_t& from, transaction_pr template bool transition_convert(const transaction_prefix_v1& from, transaction_prefix_current_t& to) { - to.version = from.version; to.extra = from.extra; to.vin = from.vin; for (const auto& v : from.vout) diff --git a/src/currency_core/currency_format_utils.cpp b/src/currency_core/currency_format_utils.cpp index d02623d2..83a807da 100644 --- a/src/currency_core/currency_format_utils.cpp +++ b/src/currency_core/currency_format_utils.cpp @@ -1132,7 +1132,7 @@ namespace currency for (auto ov : tx.vout) { VARIANT_SWITCH_BEGIN(ov); - VARIANT_CASE(tx_out_bare, o) + VARIANT_CASE_CONST(tx_out_bare, o) if (o.target.type() == typeid(txout_htlc)) { htlc_out = o; @@ -1158,13 +1158,18 @@ namespace currency return get_tx_type_ex(tx, htlc_out, htlc_in); } //--------------------------------------------------------------- - size_t get_multisig_out_index(const std::vector& outs) + size_t get_multisig_out_index(const std::vector& outs) { size_t n = 0; for (; n != outs.size(); n++) { - if (outs[n].target.type() == typeid(txout_multisig)) - break; + VARIANT_SWITCH_BEGIN(outs[n]); + VARIANT_CASE_CONST(tx_out_bare, o) + if (o.target.type() == typeid(txout_multisig)) + break; + VARIANT_CASE_CONST(tx_out_zarcanum, o) + //@#@ + VARIANT_SWITCH_END(); } return n; } @@ -1278,7 +1283,7 @@ namespace currency { tx.vin.clear(); tx.vout.clear(); - tx.signature.clear(); + tx.signature = NLSAG_sig(); tx.extra = extra; tx.version = ftp.tx_version; @@ -1604,9 +1609,9 @@ namespace currency for (auto& out : tx.vout) { VARIANT_SWITCH_BEGIN(out); - VARIANT_CASE(tx_out_bare, o) + VARIANT_CASE_CONST(tx_out_bare, o) reward += o.amount; - VARIANT_CASE_TV(tx_out_zarcanum) + VARIANT_CASE_CONST(tx_out_zarcanum, o) //@#@ VARIANT_SWITCH_END(); } @@ -1661,13 +1666,13 @@ namespace currency { VARIANT_SWITCH_BEGIN(source_tx.vout[i]); - VARIANT_CASE(tx_out_bare, o) + VARIANT_CASE_CONST(tx_out_bare, o) if (o.target.type() == typeid(txout_multisig) && ms_in.multisig_out_id == get_multisig_out_id(source_tx, i)) { ms_out_index = i; break; } - VARIANT_CASE_TV(tx_out_zarcanum) + VARIANT_CASE_CONST(tx_out_zarcanum, o) //@#@ VARIANT_SWITCH_END(); } @@ -1826,20 +1831,20 @@ namespace currency { VARIANT_SWITCH_BEGIN(vo); - VARIANT_CASE(tx_out_bare, out) + VARIANT_CASE_CONST(tx_out_bare, out) { CHECK_AND_NO_ASSERT_MES(0 < out.amount, false, "zero amount output in transaction id=" << get_transaction_hash(tx)); VARIANT_SWITCH_BEGIN(out.target); - VARIANT_CASE(txout_to_key, tk) + VARIANT_CASE_CONST(txout_to_key, tk) if (!check_key(tk.key)) return false; - VARIANT_CASE(txout_htlc, htlc) + VARIANT_CASE_CONST(txout_htlc, htlc) if (!check_key(htlc.pkey_redeem)) return false; if (!check_key(htlc.pkey_refund)) return false; - VARIANT_CASE(txout_multisig, ms) + VARIANT_CASE_CONST(txout_multisig, ms) if (!(ms.keys.size() > 0 && ms.minimum_sigs > 0 && ms.minimum_sigs <= ms.keys.size())) { LOG_ERROR("wrong multisig in transaction id=" << get_transaction_hash(tx)); @@ -1850,7 +1855,7 @@ namespace currency << ", in transaction id=" << get_transaction_hash(tx)); VARIANT_SWITCH_END(); } - VARIANT_CASE_TV(tx_out_zarcanum) + VARIANT_CASE_CONST(tx_out_zarcanum, o) //@#@ VARIANT_SWITCH_END(); } @@ -1901,11 +1906,11 @@ namespace currency BOOST_FOREACH(const auto& o, tx.vout) { VARIANT_SWITCH_BEGIN(o); - VARIANT_CASE(tx_out_bare, o) + VARIANT_CASE_CONST(tx_out_bare, o) if (money > o.amount + money) return false; money += o.amount; - VARIANT_CASE_TV(tx_out_zarcanum) + VARIANT_CASE_CONST(tx_out_zarcanum, o) //@#@ VARIANT_SWITCH_END(); } @@ -1918,9 +1923,9 @@ namespace currency for (const auto& o : tx.vout) { VARIANT_SWITCH_BEGIN(o); - VARIANT_CASE(tx_out_bare, o) + VARIANT_CASE_CONST(tx_out_bare, o) outputs_amount += o.amount; - VARIANT_CASE_TV(tx_out_zarcanum) + VARIANT_CASE_CONST(tx_out_zarcanum, o) //@#@ VARIANT_SWITCH_END(); } @@ -2034,22 +2039,22 @@ namespace currency for(const auto& ov : tx.vout) { VARIANT_SWITCH_BEGIN(ov); - VARIANT_CASE(tx_out_bare, o) + VARIANT_CASE_CONST(tx_out_bare, o) { VARIANT_SWITCH_BEGIN(o.target); - VARIANT_CASE(txout_to_key, t) + VARIANT_CASE_CONST(txout_to_key, t) if (is_out_to_acc(acc, t, derivation, i)) { outs.push_back(i); money_transfered += o.amount; } - VARIANT_CASE(txout_multisig, t) + VARIANT_CASE_CONST(txout_multisig, t) if (is_out_to_acc(acc, t, derivation, i)) { outs.push_back(i); //don't count this money } - VARIANT_CASE(txout_htlc, htlc) + VARIANT_CASE_CONST(txout_htlc, htlc) htlc_info hi = AUTO_VAL_INIT(hi); if (is_out_to_acc(acc, htlc.pkey_redeem, derivation, i)) { @@ -2068,7 +2073,7 @@ namespace currency return false; VARIANT_SWITCH_END(); } - VARIANT_CASE_TV(tx_out_zarcanum) + VARIANT_CASE_CONST(tx_out_zarcanum, o) //@#@ VARIANT_SWITCH_END(); i++; @@ -2542,14 +2547,14 @@ namespace currency for (const auto& out : tx.vout) { VARIANT_SWITCH_BEGIN(out); - VARIANT_CASE(tx_out_bare, out) + VARIANT_CASE_CONST(tx_out_bare, out) if (out.target.type() != typeid(txout_to_key)) continue; const txout_to_key& o = boost::get(out.target); if (o.key == null_pkey) found_alias_reward += out.amount; - VARIANT_CASE_TV(tx_out_zarcanum) + VARIANT_CASE_CONST(tx_out_zarcanum, o) //@#@ VARIANT_SWITCH_END(); @@ -2790,29 +2795,29 @@ namespace currency tei.outs.back().is_spent = ptce ? ptce->m_spent_flags[i] : false; tei.outs.back().global_index = ptce ? ptce->m_global_output_indexes[i] : 0; VARIANT_SWITCH_BEGIN(out); - VARIANT_CASE(tx_out_bare, out) + VARIANT_CASE_CONST(tx_out_bare, out) { tei.outs.back().amount = out.amount; VARIANT_SWITCH_BEGIN(out.target); - VARIANT_CASE(txout_to_key, otk) + VARIANT_CASE_CONST(txout_to_key, otk) tei.outs.back().pub_keys.push_back(epee::string_tools::pod_to_hex(otk.key)); if (otk.mix_attr == CURRENCY_TO_KEY_OUT_FORCED_NO_MIX) tei.outs.back().pub_keys.back() += "(FORCED_NO_MIX)"; if (otk.mix_attr >= CURRENCY_TO_KEY_OUT_FORCED_MIX_LOWER_BOUND) tei.outs.back().pub_keys.back() += std::string("(FORCED_MIX_LOWER_BOUND: ") + std::to_string(otk.mix_attr) + ")"; - VARIANT_CASE(txout_multisig, otm) + VARIANT_CASE_CONST(txout_multisig, otm) for (auto& k : otm.keys) { tei.outs.back().pub_keys.push_back(epee::string_tools::pod_to_hex(k)); } tei.outs.back().minimum_sigs = otm.minimum_sigs; - VARIANT_CASE(txout_htlc, otk) + VARIANT_CASE_CONST(txout_htlc, otk) tei.outs.back().pub_keys.push_back(epee::string_tools::pod_to_hex(otk.pkey_redeem) + "(htlc_pkey_redeem)"); tei.outs.back().pub_keys.push_back(epee::string_tools::pod_to_hex(otk.pkey_refund) + "(htlc_pkey_refund)"); VARIANT_SWITCH_END(); } - VARIANT_CASE_TV(tx_out_zarcanum) + VARIANT_CASE_CONST(tx_out_zarcanum, o) //@#@ VARIANT_SWITCH_END(); ++i; @@ -2923,13 +2928,13 @@ namespace currency for (size_t n = 0; n < tx.vout.size(); ++n) { VARIANT_SWITCH_BEGIN(tx.vout[n]); - VARIANT_CASE(tx_out_bare, o) + VARIANT_CASE_CONST(tx_out_bare, o) if (o.target.type() == typeid(txout_to_key) || o.target.type() == typeid(txout_htlc)) { uint64_t amount = o.amount; gindices[amount] += 1; } - VARIANT_CASE_TV(tx_out_zarcanum) + VARIANT_CASE_CONST(tx_out_zarcanum, o) //@#@ VARIANT_SWITCH_END(); } @@ -3024,6 +3029,15 @@ namespace currency return true; } //----------------------------------------------------------------------- + bool is_pos_coinbase(const transaction& tx) + { + bool pos = false; + if (!is_coinbase(tx, pos) || !pos) + return false; + + return true; + } + //----------------------------------------------------------------------- bool is_coinbase(const transaction& tx, bool& pos_coinbase) { if (!is_coinbase(tx)) diff --git a/src/currency_core/currency_format_utils.h b/src/currency_core/currency_format_utils.h index eb94538d..d6f9fd3c 100644 --- a/src/currency_core/currency_format_utils.h +++ b/src/currency_core/currency_format_utils.h @@ -301,7 +301,7 @@ namespace currency void load_wallet_transfer_info_flags(tools::wallet_public::wallet_transfer_info& x); uint64_t get_tx_type(const transaction& tx); uint64_t get_tx_type_ex(const transaction& tx, tx_out_bare& htlc_out, txin_htlc& htlc_in); - size_t get_multisig_out_index(const std::vector& outs); + size_t get_multisig_out_index(const std::vector& outs); size_t get_multisig_in_index(const std::vector& inputs); uint64_t get_reward_from_miner_tx(const transaction& tx); @@ -418,6 +418,7 @@ namespace currency bool parse_payment_id_from_hex_str(const std::string& payment_id_str, payment_id_t& payment_id); bool is_coinbase(const transaction& tx); bool is_coinbase(const transaction& tx, bool& pos_coinbase); + bool is_pos_coinbase(const transaction& tx); bool have_attachment_service_in_container(const std::vector& av, const std::string& service_id, const std::string& instruction); crypto::hash prepare_prefix_hash_for_sign(const transaction& tx, uint64_t in_index, const crypto::hash& tx_id); @@ -699,7 +700,7 @@ namespace currency uint64_t operator()(const txin_gen& i) const {return 0;} }; //--------------------------------------------------------------- - const tx_out_bare& get_tx_out_bare_from_out_v(const tx_out_v& o) + inline const tx_out_bare& get_tx_out_bare_from_out_v(const tx_out_v& o) { //this function will throw if type is not matching return boost::get(o); diff --git a/src/currency_core/currency_format_utils_transactions.cpp b/src/currency_core/currency_format_utils_transactions.cpp index 78744d9a..bb12d893 100644 --- a/src/currency_core/currency_format_utils_transactions.cpp +++ b/src/currency_core/currency_format_utils_transactions.cpp @@ -8,7 +8,7 @@ #include "serialization/serialization.h" #include "currency_format_utils.h" #include "currency_format_utils_abstract.h" -#include "variant_helper.h" +#include "common/variant_helper.h" namespace currency { @@ -44,13 +44,13 @@ namespace currency for (auto& o : tx.vout) { VARIANT_SWITCH_BEGIN(o); - VARIANT_CASE(tx_out_bare, o) + VARIANT_CASE_CONST(tx_out_bare, o) if (o.target.type() == typeid(txout_to_key)) { if (boost::get(o.target).key == null_pkey) res += o.amount; } - VARIANT_CASE_TV(tx_out_zarcanum) + VARIANT_CASE_CONST(tx_out_zarcanum, o) //@#@ VARIANT_CASE_THROW_ON_OTHER(); VARIANT_SWITCH_END(); diff --git a/src/currency_core/tx_pool.cpp b/src/currency_core/tx_pool.cpp index 266f2e4b..2193e89e 100644 --- a/src/currency_core/tx_pool.cpp +++ b/src/currency_core/tx_pool.cpp @@ -1331,11 +1331,11 @@ namespace currency for (const auto& out : tx.vout) { VARIANT_SWITCH_BEGIN(out); - VARIANT_CASE(tx_out_bare, o) + VARIANT_CASE_CONST(tx_out_bare, o) if (o.target.type() == typeid(txout_multisig)) result.push_back(ms_out_info({ get_multisig_out_id(tx, idx), idx, false })); - VARIANT_CASE_TV(tx_out_zarcanum) + VARIANT_CASE_CONST(tx_out_zarcanum, o) //@#@ VARIANT_CASE_THROW_ON_OTHER(); VARIANT_SWITCH_END(); @@ -1355,10 +1355,10 @@ namespace currency for (const auto& out : tx.vout) { VARIANT_SWITCH_BEGIN(out); - VARIANT_CASE(tx_out_bare, o) + VARIANT_CASE_CONST(tx_out_bare, o) if (o.target.type() == typeid(txout_multisig) && get_multisig_out_id(tx, idx) == multisig_id) return true; - VARIANT_CASE_TV(tx_out_zarcanum) + VARIANT_CASE_CONST(tx_out_zarcanum, o) //@#@ VARIANT_SWITCH_END(); ++idx; diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index 159349b4..c9ad06c6 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -973,9 +973,9 @@ namespace currency BOOST_FOREACH(const auto& out, blk.miner_tx.vout) { VARIANT_SWITCH_BEGIN(out); - VARIANT_CASE(tx_out_bare, out) + VARIANT_CASE_CONST(tx_out_bare, out) reward += out.amount; - VARIANT_CASE_TV(tx_out_zarcanum) + VARIANT_CASE_CONST(tx_out_zarcanum, out) //@#@ VARIANT_SWITCH_END(); } diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index cce55f04..19b981cb 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -36,6 +36,7 @@ using namespace epee; #endif #include "storages/levin_abstract_invoke2.h" +#include "common/variant_helper.h" using namespace currency; @@ -87,14 +88,14 @@ namespace tools { CHECK_AND_ASSERT_THROW_MES(ri < tx.vout.size(), "Internal error: wrong tx transfer details: reciev index=" << ri << " is greater than transaction outputs vector " << tx.vout.size()); VARIANT_SWITCH_BEGIN(tx.vout[ri]); - VARIANT_CASE(tx_out_bare, o) + VARIANT_CASE_CONST(tx_out_bare, o) if (o.target.type() == typeid(currency::txout_to_key)) { //update unlock_time if needed if (ut2.unlock_time_array[ri] > max_unlock_time) max_unlock_time = ut2.unlock_time_array[ri]; } - VARIANT_CASE_TV(tx_out_zarcanum); + VARIANT_CASE_CONST(tx_out_zarcanum, o); VARIANT_SWITCH_END(); } @@ -115,12 +116,12 @@ void wallet2::fill_transfer_details(const currency::transaction& tx, const tools { WLT_CHECK_AND_ASSERT_MES(ri < tx.vout.size(), void(), "Internal error: wrong tx transfer details: reciev index=" << ri << " is greater than transaction outputs vector " << tx.vout.size()); VARIANT_SWITCH_BEGIN(tx.vout[ri]); - VARIANT_CASE(tx_out_bare, o) + VARIANT_CASE_CONST(tx_out_bare, o) if (o.target.type() == typeid(currency::txout_to_key)) { res_td.rcv.push_back(o.amount); } - VARIANT_CASE_TV(tx_out_zarcanum); + VARIANT_CASE_CONST(tx_out_zarcanum, o); //@#@ VARIANT_SWITCH_END(); @@ -478,7 +479,7 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t size_t o = outs[i_in_outs]; WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(o < tx.vout.size(), "wrong out in transaction: internal index=" << o << ", total_outs=" << tx.vout.size()); VARIANT_SWITCH_BEGIN(tx.vout[o]); - VARIANT_CASE(tx_out_bare, out) + VARIANT_CASE_CONST(tx_out_bare, out) { if (out.target.type() == typeid(txout_to_key) || out.target.type() == typeid(txout_htlc)) { @@ -674,7 +675,7 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t WLT_LOG_L0("Received multisig, multisig out id: " << multisig_id << ", amount: " << tdb.amount() << ", with tx: " << get_transaction_hash(tx)); } } - VARIANT_CASE_TV(tx_out_zarcanum); + VARIANT_CASE_CONST(tx_out_zarcanum, o); //@#@ VARIANT_SWITCH_END(); } @@ -1401,7 +1402,7 @@ void wallet2::unprocess_htlc_triggers_on_block_removed(uint64_t height) tr.m_spent_height = 0; } //re-add to active contracts - THROW_IF_FALSE_WALLET_EX(tr.m_ptx_wallet_info->m_tx.vout[tr.m_internal_output_index].type() == typeid(tx_out_bare), "Unexprected type of out in unprocess_htlc_triggers_on_block_removed : " << tr.m_ptx_wallet_info->m_tx.vout[tr.m_internal_output_index].type().name()); + WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(tr.m_ptx_wallet_info->m_tx.vout[tr.m_internal_output_index].type() == typeid(tx_out_bare), std::string("Unexprected type of out in unprocess_htlc_triggers_on_block_removed : ") + tr.m_ptx_wallet_info->m_tx.vout[tr.m_internal_output_index].type().name()); auto pair_key = std::make_pair(boost::get(tr.m_ptx_wallet_info->m_tx.vout[tr.m_internal_output_index]).amount, tr.m_global_output_index); auto it_active_htlc = m_active_htlcs.find(pair_key); if (it_active_htlc != m_active_htlcs.end()) @@ -1467,7 +1468,7 @@ void wallet2::process_htlc_triggers_on_block_added(uint64_t height) CHECK_AND_ASSERT_MES(tr.m_ptx_wallet_info->m_tx.vout[tr.m_internal_output_index].type() == typeid(tx_out_bare), void(), "Unexpected type out in process_htlc_triggers_on_block_added: " << tr.m_ptx_wallet_info->m_tx.vout[tr.m_internal_output_index].type().name()); uint64_t amount = boost::get(tr.m_ptx_wallet_info->m_tx.vout[tr.m_internal_output_index]).amount; - auto it_active_htlc = m_active_htlcs.find(std::make_pair(, tr.m_global_output_index)); + auto it_active_htlc = m_active_htlcs.find(std::make_pair(amount, tr.m_global_output_index)); if (it_active_htlc == m_active_htlcs.end()) { LOG_ERROR("Erasing active htlc(m_active_htlcs), but it seems to be already erased"); @@ -3093,7 +3094,7 @@ void wallet2::sign_transfer(const std::string& tx_sources_blob, std::string& sig for (size_t i = 0; i < ft.tx.vout.size(); ++i) { VARIANT_SWITCH_BEGIN(ft.tx.vout[i]); - VARIANT_CASE(tx_out_bare, out) + VARIANT_CASE_CONST(tx_out_bare, out) { if (out.target.type() != typeid(txout_to_key)) continue; @@ -3117,7 +3118,7 @@ void wallet2::sign_transfer(const std::string& tx_sources_blob, std::string& sig ft.outs_key_images.push_back(make_serializable_pair(static_cast(i), ki)); } } - VARIANT_CASE_TV(tx_out_zarcanum); + VARIANT_CASE_CONST(tx_out_zarcanum, o); //@#@ VARIANT_SWITCH_END(); } @@ -3484,10 +3485,11 @@ bool wallet2::prepare_and_sign_pos_block(currency::block& b, { //@#@ TODO: add proper support of Zarcanum WLT_THROW_IF_FALSE_WALLET_CMN_ERR_EX(false, "ZRCANUM BLOCKS NOT IMPLEMENTED YET"); + return false; // to get rid of warning }else { NLSAG_sig& signatures = boost::get(b.miner_tx.signature); - WLT_CHECK_AND_ASSERT_MES(signatures.size() == 1 && signatures[0].size() == txin.key_offsets.size(), + WLT_CHECK_AND_ASSERT_MES(signatures.s.size() == 1 && signatures.s[0].size() == txin.key_offsets.size(), false, "Wrong signatures amount in coinbase transacton"); @@ -3515,12 +3517,12 @@ bool wallet2::prepare_and_sign_pos_block(currency::block& b, keys_ptrs, derived_secret_ephemeral_key, 0, - &signatures[0][0]); + &signatures.s[0][0]); WLT_LOG_L4("GENERATED RING SIGNATURE: block_id " << block_hash << "txin.k_image" << txin.k_image << "key_ptr:" << *keys_ptrs[0] - << "signature:" << signatures[0][0]); + << "signature:" << signatures.s[0][0]); return true; } @@ -4554,12 +4556,12 @@ bool wallet2::prepare_tx_sources(size_t fake_outputs_count, std::vectorm_tx.vout[td.m_internal_output_index]); - VARIANT_CASE(tx_out_bare, o) + VARIANT_CASE_CONST(tx_out_bare, o) { - VARIANT_SWITCH_BEGIN(o); - VARIANT_CASE(txout_to_key, o) + VARIANT_SWITCH_BEGIN(o.target); + VARIANT_CASE_CONST(txout_to_key, o) real_oe.second = o.key; - VARIANT_CASE(txout_htlc, htlc) + VARIANT_CASE_CONST(txout_htlc, htlc) real_oe.second = htlc.pkey_refund; VARIANT_CASE_OTHER() { @@ -4575,7 +4577,7 @@ bool wallet2::prepare_tx_sources(size_t fake_outputs_count, std::vector it->second, "Internal error: index in m_active_htlcs_txid <" << it->second << "> is bigger then size of m_transfers <" << m_transfers.size() << ">", API_RETURN_CODE_INTERNAL_ERROR); + const transfer_details& td = m_transfers[it->second]; //@#@ WLT_THROW_IF_FALSE_WITH_CODE(td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index].type() == typeid(tx_out_bare), - "Unexpected out type in prepare_tx_sources_htlc:" << td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index].type().name()); + "Unexpected out type in prepare_tx_sources_htlc:" << td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index].type().name(), API_RETURN_CODE_INTERNAL_ERROR); const tx_out_bare& out_bare = boost::get(td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index]); - const transfer_details& td = m_transfers[it->second]; WLT_THROW_IF_FALSE_WITH_CODE(out_bare.target.type() == typeid(txout_htlc), "Unexpected type in active htlc", API_RETURN_CODE_INTERNAL_ERROR); @@ -5015,7 +5017,7 @@ bool wallet2::is_transfer_able_to_go(const transfer_details& td, uint64_t fake_o if (!td.is_spendable()) return false; VARIANT_SWITCH_BEGIN(td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index]); - VARIANT_CASE(tx_out_bare, o); + VARIANT_CASE_CONST(tx_out_bare, o); { if (o.target.type() == typeid(txout_htlc)) { @@ -5028,7 +5030,7 @@ bool wallet2::is_transfer_able_to_go(const transfer_details& td, uint64_t fake_o return false; } } - VARIANT_CASE_TV(tx_out_zarcanum); + VARIANT_CASE_CONST(tx_out_zarcanum, o); //@#@ VARIANT_SWITCH_END(); return true; @@ -5047,7 +5049,7 @@ bool wallet2::prepare_free_transfers_cache(uint64_t fake_outputs_count) if (is_transfer_able_to_go(td, fake_outputs_count)) { //@#@ - boost::get(m_found_free_amounts[td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index].amount]).insert(i); + m_found_free_amounts[boost::get(td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index]).amount].insert(i); count++; } } diff --git a/src/wallet/wallet2_escrow.cpp b/src/wallet/wallet2_escrow.cpp index 9c7e342c..af4f735e 100644 --- a/src/wallet/wallet2_escrow.cpp +++ b/src/wallet/wallet2_escrow.cpp @@ -7,6 +7,7 @@ #define KEEP_WALLET_LOG_MACROS #include "wallet2.h" #include "currency_core/currency_format_utils.h" +#include "common/variant_helper.h" #undef LOG_DEFAULT_CHANNEL #define LOG_DEFAULT_CHANNEL "wallet" @@ -75,7 +76,7 @@ bool wallet2::validate_escrow_proposal(const wallet_public::wallet_transfer_info for (size_t i = 0; i != prop.tx_template.vout.size(); ++i) { VARIANT_SWITCH_BEGIN(prop.tx_template.vout[i]); - VARIANT_CASE(tx_out_bare, o) + VARIANT_CASE_CONST(tx_out_bare, o) { if (o.target.type() == typeid(txout_multisig)) { @@ -87,7 +88,7 @@ bool wallet2::validate_escrow_proposal(const wallet_public::wallet_transfer_info else LOC_CHK(false, "Invalid output type: " << o.target.type().name()); } - VARIANT_CASE_TV(tx_out_zarcanum); + VARIANT_CASE_CONST(tx_out_zarcanum, o); //@#@ VARIANT_SWITCH_END(); } @@ -191,7 +192,7 @@ bool wallet2::validate_escrow_release(const transaction& tx, bool release_type_n for (size_t i = 0; i != tx.vout.size(); ++i) { VARIANT_SWITCH_BEGIN(tx.vout[i]); - VARIANT_CASE(tx_out_bare, o); + VARIANT_CASE_CONST(tx_out_bare, o); { if (o.target.type() == typeid(txout_to_key)) { @@ -208,8 +209,8 @@ bool wallet2::validate_escrow_release(const transaction& tx, bool release_type_n else LOC_CHK(false, "Invalid output type: " << o.target.type().name()); } - VARIANT_CASE(tx_out_zarcanum, o) - LOC_CHK(false, "Invalid output type: " << o.type().name()); + VARIANT_CASE_CONST(tx_out_zarcanum, o) + LOC_CHK(false, "Invalid output type: " << typeid(o).name()); VARIANT_SWITCH_END(); } @@ -234,9 +235,9 @@ bool wallet2::validate_escrow_release(const transaction& tx, bool release_type_n // (5/5) signatures VARIANT_SWITCH_BEGIN(tx.signature); - VARIANT_CASE(NLSAG_sig, signatures) + VARIANT_CASE_CONST(NLSAG_sig, signatures) { - LOC_CHK(signatures.size() == 1, "invalid singatures size: " << signatures.size()); // only 1 input means only 1 signature vector + LOC_CHK(signatures.s.size() == 1, "invalid singatures size: " << signatures.s.size()); // only 1 input means only 1 signature vector // As we don't have b_keys we can't be sure which signature is B's and which is reserved for A (should be a null-placeholder, if present). // Having a_keys, we determine index of A key in multisig output keys array. @@ -249,17 +250,17 @@ bool wallet2::validate_escrow_release(const transaction& tx, bool release_type_n LOC_CHK(r, "derive_public_key failed"); LOC_CHK(source_ms_out.keys.size() == 2, "internal error: invalid ms output keys array, size: " << source_ms_out.keys.size()); - LOC_CHK(signatures[0].size() == 2, "internal error: invalid signature size for input #0: " << signatures[0].size()) + LOC_CHK(signatures.s[0].size() == 2, "internal error: invalid signature size for input #0: " << signatures.s[0].size()) size_t ms_out_key_a_index = std::find(source_ms_out.keys.begin(), source_ms_out.keys.end(), ephemeral_pub_key) - source_ms_out.keys.begin(); LOC_CHK(ms_out_key_a_index < source_ms_out.keys.size(), "internal error: can't find A ephemeral pub key within ms output keys"); size_t ms_out_key_b_index = 1 - ms_out_key_a_index; - // in this particular case (source_ms_out.minimum_sigs == source_ms_out.keys.size() == 2) index in 'keys' is the same as index in signatures[0] + // in this particular case (source_ms_out.minimum_sigs == source_ms_out.keys.size() == 2) index in 'keys' is the same as index in signatures.s[0] crypto::hash tx_hash_for_signature = prepare_prefix_hash_for_sign(tx, 0, get_transaction_hash(tx)); - r = crypto::check_signature(tx_hash_for_signature, source_ms_out.keys[ms_out_key_b_index], signatures[0][ms_out_key_b_index]); + r = crypto::check_signature(tx_hash_for_signature, source_ms_out.keys[ms_out_key_b_index], signatures.s[0][ms_out_key_b_index]); LOC_CHK(r, "B signature for multisig input is invalid"); } - VARIANT_CASE(zarcanum_sig, s); + VARIANT_CASE_CONST(zarcanum_sig, s); //@#@ VARIANT_CASE_THROW_ON_OTHER(); VARIANT_SWITCH_END(); @@ -388,7 +389,7 @@ bool wallet2::validate_escrow_cancel_release(const currency::transaction& tx, co for (size_t i = 0; i != tx.vout.size(); ++i) { VARIANT_SWITCH_BEGIN(tx.vout[i]); - VARIANT_CASE(tx_out_bare, o) + VARIANT_CASE_CONST(tx_out_bare, o) if (o.target.type() == typeid(txout_to_key)) { total_outputs_amount += o.amount; @@ -401,8 +402,8 @@ bool wallet2::validate_escrow_cancel_release(const currency::transaction& tx, co } else LOC_CHK(false, "Invalid output type: " << o.target.type().name()); - VARIANT_CASE_TV(tx_out_zarcanum) - LOC_CHK(false, "Invalid output type: " << tv.type().name()); + VARIANT_CASE_CONST(tx_out_zarcanum, o) + LOC_CHK(false, "Invalid output type: " << typeid(o).name()); VARIANT_SWITCH_END(); } @@ -418,19 +419,19 @@ bool wallet2::validate_escrow_cancel_release(const currency::transaction& tx, co // (5/5) signatures VARIANT_SWITCH_BEGIN(tx.signature); - VARIANT_CASE(NLSAG_sig, signatures) + VARIANT_CASE_CONST(NLSAG_sig, signatures) { - LOC_CHK(signatures.size() == 1, "invalid singatures size: " << signatures.size()); // only 1 input means only 1 signature vector - LOC_CHK(signatures[0].size() == 2, "invalid signature[0] size: " << signatures[0].size()); // it's expected to contain A-party signature and null-sig placeholder + LOC_CHK(signatures.s.size() == 1, "invalid singatures size: " << signatures.s.size()); // only 1 input means only 1 signature vector + LOC_CHK(signatures.s[0].size() == 2, "invalid signature[0] size: " << signatures.s[0].size()); // it's expected to contain A-party signature and null-sig placeholder LOC_CHK(source_ms_out.keys.size() == 2, "internal error: invalid source ms output keys array, size: " << source_ms_out.keys.size()); - size_t a_sign_index = (signatures[0][0] != null_sig) ? 0 : 1; + size_t a_sign_index = (signatures.s[0][0] != null_sig) ? 0 : 1; crypto::hash tx_hash_for_signature = prepare_prefix_hash_for_sign(tx, 0, get_transaction_hash(tx)); - r = crypto::check_signature(tx_hash_for_signature, source_ms_out.keys[a_sign_index], signatures[0][a_sign_index]); + r = crypto::check_signature(tx_hash_for_signature, source_ms_out.keys[a_sign_index], signatures.s[0][a_sign_index]); LOC_CHK(r, "A signature for multisig input is invalid"); } - VARIANT_CASE(zarcanum_sig, s); + VARIANT_CASE_CONST(zarcanum_sig, s); //@#@ VARIANT_CASE_THROW_ON_OTHER(); VARIANT_SWITCH_END(); diff --git a/tests/core_tests/alias_tests.cpp b/tests/core_tests/alias_tests.cpp index 761caea9..6156e7a2 100644 --- a/tests/core_tests/alias_tests.cpp +++ b/tests/core_tests/alias_tests.cpp @@ -884,8 +884,8 @@ bool gen_alias_reg_with_locked_money::generate(std::vector& ev ai.m_address = miner_acc.get_public_address(); currency::tx_source_entry se = AUTO_VAL_INIT(se); - se.amount = blk_0.boost::get(miner_tx.vout[0]).amount; - se.outputs.push_back(make_serializable_pair(0, boost::get(blk_0.boost::get(miner_tx.vout[0]).target).key)); + se.amount = boost::get(blk_0.miner_tx.vout[0]).amount; + se.outputs.push_back(make_serializable_pair(0, boost::get(boost::get(blk_0.miner_tx.vout[0]).target).key)); se.real_output = 0; se.real_output_in_tx_index = 0; se.real_out_tx_key = currency::get_tx_pub_key_from_extra(blk_0.miner_tx); @@ -1159,8 +1159,8 @@ bool gen_alias_tx_no_outs::generate(std::vector& events) const ai.m_address = miner_acc.get_public_address(); currency::tx_source_entry se = AUTO_VAL_INIT(se); - se.amount = blk_0.boost::get(miner_tx.vout[0]).amount; - se.outputs.push_back(make_serializable_pair(0, boost::get(blk_0.boost::get(miner_tx.vout[0]).target).key)); + se.amount = boost::get(blk_0.miner_tx.vout[0]).amount; + se.outputs.push_back(make_serializable_pair(0, boost::get(boost::get(blk_0.miner_tx.vout[0]).target).key)); se.real_output = 0; se.real_output_in_tx_index = 0; se.real_out_tx_key = currency::get_tx_pub_key_from_extra(blk_0.miner_tx); diff --git a/tests/core_tests/block_reward.cpp b/tests/core_tests/block_reward.cpp index 1550175a..b2d4056a 100644 --- a/tests/core_tests/block_reward.cpp +++ b/tests/core_tests/block_reward.cpp @@ -59,9 +59,9 @@ bool block_template_against_txs_size::c1(currency::core& c, size_t ev_index, con keypair ephemeral = AUTO_VAL_INIT(ephemeral); r = generate_key_image_helper(miner_acc.get_keys(), get_tx_pub_key_from_extra(blk_0.miner_tx), 0, ephemeral, ki); CHECK_AND_ASSERT_MES(r, false, "generate_key_image_helper failed"); - CHECK_AND_ASSERT_MES(boost::get(blk_0.boost::get(miner_tx.vout[0]).target).key == ephemeral.pub, false, "ephemeral.pub doesn't match with output key"); + CHECK_AND_ASSERT_MES(boost::get(boost::get(blk_0.miner_tx.vout[0]).target).key == ephemeral.pub, false, "ephemeral.pub doesn't match with output key"); pos_entry pe = AUTO_VAL_INIT(pe); - pe.amount = blk_0.boost::get(miner_tx.vout[0]).amount; + pe.amount = boost::get(blk_0.miner_tx.vout[0]).amount; pe.block_timestamp = UINT64_MAX; // doesn't matter pe.index = 0; // global index pe.keyimage = ki; @@ -100,7 +100,7 @@ bool block_template_against_txs_size::c1(currency::core& c, size_t ev_index, con r = bcs.validate_miner_transaction(b, cumulative_block_size, g_block_txs_fee, base_reward, bcs.total_coins()); CHECK_AND_ASSERT_MES(r, false, "validate_miner_transaction failed, txs_total_size = " << txs_total_size); - uint64_t generated_coins = get_outs_money_amount(b.miner_tx) - (is_pos != 0 ? b.miner_tx.vout.back().amount : 0) - g_block_txs_fee / 2; + uint64_t generated_coins = get_outs_money_amount(b.miner_tx) - (is_pos != 0 ? boost::get(b.miner_tx.vout.back()).amount : 0) - g_block_txs_fee / 2; uint64_t base_block_reward = is_pos != 0 ? base_block_reward_pos : base_block_reward_pow; if (txs_total_size % 1000 == 0) diff --git a/tests/core_tests/block_validation.cpp b/tests/core_tests/block_validation.cpp index 9b7915b7..8f39feb0 100644 --- a/tests/core_tests/block_validation.cpp +++ b/tests/core_tests/block_validation.cpp @@ -311,8 +311,8 @@ bool gen_block_miner_tx_has_2_in::generate(std::vector& events GENERATE_ACCOUNT(alice); tx_source_entry se = AUTO_VAL_INIT(se); - se.amount = blk_0.boost::get(miner_tx.vout[0]).amount; - se.outputs.push_back(make_serializable_pair(0, boost::get(blk_0.boost::get(miner_tx.vout[0]).target).key)); + se.amount = boost::get(blk_0.miner_tx.vout[0]).amount; + se.outputs.push_back(make_serializable_pair(0, boost::get(boost::get(blk_0.miner_tx.vout[0]).target).key)); se.real_output = 0; se.real_out_tx_key = get_tx_pub_key_from_extra(blk_0.miner_tx); se.real_output_in_tx_index = 0; @@ -356,8 +356,8 @@ bool gen_block_miner_tx_with_txin_to_key::generate(std::vector REWIND_BLOCKS(events, blk_1r, blk_1, miner_account); tx_source_entry se = AUTO_VAL_INIT(se); - se.amount = blk_1.boost::get(miner_tx.vout[0]).amount; - se.outputs.push_back(make_serializable_pair(0, boost::get(blk_1.boost::get(miner_tx.vout[0]).target).key)); + se.amount = boost::get(blk_1.miner_tx.vout[0]).amount; + se.outputs.push_back(make_serializable_pair(0, boost::get(boost::get(blk_1.miner_tx.vout[0]).target).key)); se.real_output = 0; se.real_out_tx_key = get_tx_pub_key_from_extra(blk_1.miner_tx); se.real_output_in_tx_index = 0; diff --git a/tests/core_tests/chain_switch_pow_pos.cpp b/tests/core_tests/chain_switch_pow_pos.cpp index f936db7c..f036dd5c 100644 --- a/tests/core_tests/chain_switch_pow_pos.cpp +++ b/tests/core_tests/chain_switch_pow_pos.cpp @@ -119,7 +119,16 @@ bool gen_chain_switch_pow_pos::generate(std::vector& events) c crypto::public_key stake_tx_pub_key = get_tx_pub_key_from_extra(stake); size_t stake_output_idx = 0, i = 0; uint64_t stake_output_amount = 0; - std::for_each(stake.vout.begin(), stake.vout.end(), [&stake_output_amount, &stake_output_idx, &i](const tx_out_bare& o){ if (o.amount > stake_output_amount) { stake_output_amount = o.amount; stake_output_idx = i; } ++i; }); + std::for_each(stake.vout.begin(), stake.vout.end(), [&stake_output_amount, &stake_output_idx, &i](const tx_out_v& o_) + { + auto& o = boost::get(o_); + if (o.amount > stake_output_amount) + { + stake_output_amount = o.amount; + stake_output_idx = i; + } + ++i; + }); size_t stake_output_gidx = generator.get_tx_out_gindex(prev_id, currency::get_transaction_hash(stake), stake_output_idx); crypto::key_image stake_output_key_image; keypair kp; diff --git a/tests/core_tests/chaingen.cpp b/tests/core_tests/chaingen.cpp index 714efaee..a70b691c 100644 --- a/tests/core_tests/chaingen.cpp +++ b/tests/core_tests/chaingen.cpp @@ -620,8 +620,8 @@ bool test_generator::build_outputs_indext_for_chain(const blockchain_vector& blo std::vector& coinbase_outs = txs_outs[currency::get_transaction_hash(blocks[h]->b.miner_tx)]; for (size_t out_i = 0; out_i != blocks[h]->b.miner_tx.vout.size(); out_i++) { - coinbase_outs.push_back(index[blocks[h]->b.boost::get(miner_tx.vout[out_i]).amount].size()); - index[blocks[h]->b.boost::get(miner_tx.vout[out_i]).amount].push_back(std::tuple(h, 0, out_i)); + coinbase_outs.push_back(index[boost::get(blocks[h]->b.miner_tx.vout[out_i]).amount].size()); + index[boost::get(blocks[h]->b.miner_tx.vout[out_i]).amount].push_back(std::tuple(h, 0, out_i)); } for (size_t tx_index = 0; tx_index != blocks[h]->m_transactions.size(); tx_index++) @@ -629,8 +629,8 @@ bool test_generator::build_outputs_indext_for_chain(const blockchain_vector& blo std::vector& tx_outs_indx = txs_outs[currency::get_transaction_hash(blocks[h]->m_transactions[tx_index])]; for (size_t out_i = 0; out_i != blocks[h]->m_transactions[tx_index].vout.size(); out_i++) { - tx_outs_indx.push_back(index[blocks[h]->m_transactions[tx_index]boost::get(.vout[out_i]).amount].size()); - index[blocks[h]->m_transactions[tx_index]boost::get(.vout[out_i]).amount].push_back(std::tuple(h, tx_index + 1, out_i)); + tx_outs_indx.push_back(index[boost::get(blocks[h]->m_transactions[tx_index].vout[out_i]).amount].size()); + index[boost::get(blocks[h]->m_transactions[tx_index].vout[out_i]).amount].push_back(std::tuple(h, tx_index + 1, out_i)); } } } @@ -663,13 +663,13 @@ bool test_generator::get_output_details_by_global_index(const test_generator::bl CHECK_AND_ASSERT_THROW_MES(tx_out_index < tx->vout.size(), "tx_index < blck_chain[h].m_transactions.size()"); tx_pub_key = get_tx_pub_key_from_extra(*tx); - CHECK_AND_ASSERT_THROW_MES(tx->vout[tx_out_index].target.type() == typeid(currency::txout_to_key), + CHECK_AND_ASSERT_THROW_MES(boost::get(tx->vout[tx_out_index]).target.type() == typeid(currency::txout_to_key), "blck_chain[h]->m_transactions[tx_index]boost::get(.vout[tx_out_index]).target.type() == typeid(currency::txout_to_key)"); - CHECK_AND_ASSERT_THROW_MES(tx->vout[tx_out_index].amount == amount, + CHECK_AND_ASSERT_THROW_MES(boost::get(tx->vout[tx_out_index]).amount == amount, "blck_chain[h]->m_transactions[tx_index]boost::get(.vout[tx_out_index]).amount == amount"); - output_key = boost::get(tx->vout[tx_out_index].target).key; + output_key = boost::get(boost::get(tx->vout[tx_out_index]).target).key; return true; } //------------------------------------------------------------------ @@ -1093,7 +1093,7 @@ bool init_output_indices(map_output_idx_t& outs, map_output_t& outs_mine, const for (size_t j = 0; j < tx.vout.size(); ++j) { - const tx_out_bare &out = tx.vout[j]; + const tx_out_bare &out = boost::get(tx.vout[j]); output_index oi(out.target, out.amount, boost::get(*blk.miner_tx.vin.begin()).height, i, j, &blk, vtx[i]); if (out.target.type() == typeid(txout_to_key)) @@ -1773,7 +1773,7 @@ bool find_global_index_for_output(const std::vector& events, c auto process_tx = [&reference_tx, &reference_tx_out_index, &global_outputs](const currency::transaction& tx) -> uint64_t { for (size_t tx_out_index = 0; tx_out_index < tx.vout.size(); ++tx_out_index) { - const tx_out_bare &out = tx.vout[tx_out_index]; + const tx_out_bare &out = boost::get(tx.vout[tx_out_index]); if (out.target.type() == typeid(txout_to_key)) { uint64_t global_out_index = global_outputs[out.amount]++; @@ -2053,7 +2053,7 @@ bool check_ring_signature_at_gen_time(const std::vector& event auto it = mtx.find(rbi.tx_id); CHECK_AND_ASSERT_MES(it != mtx.end(), false, "it == end"); CHECK_AND_ASSERT_MES(rbi.n < it->second->vout.size(), false, "FAIL: rbi.n < it->second->vout.size()"); - auto& pub_key = boost::get(it->second->vout[rbi.n].target).key; + auto& pub_key = boost::get(boost::get(it->second->vout[rbi.n]).target).key; pub_keys.push_back(pub_key); pub_keys_ptrs.push_back(&pub_keys.back()); diff --git a/tests/core_tests/double_spend.inl b/tests/core_tests/double_spend.inl index 28da7a36..3b557131 100644 --- a/tests/core_tests/double_spend.inl +++ b/tests/core_tests/double_spend.inl @@ -71,7 +71,7 @@ bool gen_double_spend_in_tx::generate(std::vector(out).amount; if (se.amount == send_amount) break; ++se.real_output_in_tx_index; diff --git a/tests/core_tests/emission_test.cpp b/tests/core_tests/emission_test.cpp index 734844a4..976a51a1 100644 --- a/tests/core_tests/emission_test.cpp +++ b/tests/core_tests/emission_test.cpp @@ -124,7 +124,12 @@ bool emission_test::c1(currency::core& c, size_t ev_index, const std::vector(l).amount < boost::get(r).amount; + }) - pb.m_block.miner_tx.vout.begin(); + stake_tx_outs.pop_front(); stake_tx_outs.push_back(std::make_pair(get_transaction_hash(pb.m_block.miner_tx), biggest_output_idx)); diff --git a/tests/core_tests/escrow_wallet_tests.cpp b/tests/core_tests/escrow_wallet_tests.cpp index 5df3a67c..93c66656 100644 --- a/tests/core_tests/escrow_wallet_tests.cpp +++ b/tests/core_tests/escrow_wallet_tests.cpp @@ -108,8 +108,8 @@ bool escrow_wallet_test::prepare_proposal_accepted_test(currency::core& c, const cpd.title = "Afterlife? If I thought I had to live another life, I'd kill myself right now!"; wallet_buyer->send_escrow_proposal(cpd, 0, 0, 3600, TESTS_DEFAULT_FEE, TESTS_DEFAULT_FEE, "", escrow_proposal_tx, escrow_template_tx); - auto it = std::find_if(escrow_template_tx.vout.begin(), escrow_template_tx.vout.end(), [](const tx_out_bare& o){ - if (o.target.type() == typeid(txout_multisig)) + auto it = std::find_if(escrow_template_tx.vout.begin(), escrow_template_tx.vout.end(), [](const tx_out_v& o){ + if (boost::get(o).target.type() == typeid(txout_multisig)) return true; return false; }); diff --git a/tests/core_tests/hard_fork_2.cpp b/tests/core_tests/hard_fork_2.cpp index 497a21cf..c7bd2c45 100644 --- a/tests/core_tests/hard_fork_2.cpp +++ b/tests/core_tests/hard_fork_2.cpp @@ -653,9 +653,9 @@ bool hard_fork_2_auditable_addresses_basics::generate(std::vector(out).amount != MK_TEST_COINS(5)) continue; // skip change - uint8_t mix_attr = boost::get(out.target).mix_attr; + uint8_t mix_attr = boost::get(boost::get(out).target).mix_attr; CHECK_AND_ASSERT_MES(mix_attr == CURRENCY_TO_KEY_OUT_FORCED_NO_MIX, false, "Incorrect mix_attr in tx_1: " << mix_attr); } @@ -686,9 +686,9 @@ bool hard_fork_2_auditable_addresses_basics::c1(currency::core& c, size_t ev_ind // make sure all Bob's outputs has mix_attr = 1 for (auto& out : tx.vout) { - if (out.amount != MK_TEST_COINS(1)) + if (boost::get(out).amount != MK_TEST_COINS(1)) continue; // skip change - uint8_t mix_attr = boost::get(out.target).mix_attr; + uint8_t mix_attr = boost::get(boost::get(out).target).mix_attr; CHECK_AND_ASSERT_MES(mix_attr == CURRENCY_TO_KEY_OUT_FORCED_NO_MIX, false, "Incorrect mix_attr in tx: " << mix_attr); } @@ -711,9 +711,9 @@ bool hard_fork_2_auditable_addresses_basics::c1(currency::core& c, size_t ev_ind // make sure all Bob's outputs has mix_attr = 1 for (auto& out : tx.vout) { - if (out.amount != MK_TEST_COINS(1)) + if (boost::get(out).amount != MK_TEST_COINS(1)) continue; // skip change - uint8_t mix_attr = boost::get(out.target).mix_attr; + uint8_t mix_attr = boost::get(boost::get(out).target).mix_attr; CHECK_AND_ASSERT_MES(mix_attr == CURRENCY_TO_KEY_OUT_FORCED_NO_MIX, false, "Incorrect mix_attr in tx: " << mix_attr); } diff --git a/tests/core_tests/integer_overflow.cpp b/tests/core_tests/integer_overflow.cpp index b12b098e..9e1ad68f 100644 --- a/tests/core_tests/integer_overflow.cpp +++ b/tests/core_tests/integer_overflow.cpp @@ -134,7 +134,7 @@ bool gen_uint_overflow_2::generate(std::vector& events) const std::vector sources; for (size_t i = 0; i < blk_0.miner_tx.vout.size(); ++i) { - if (TESTS_DEFAULT_FEE < blk_0.boost::get(miner_tx.vout[i]).amount) + if (TESTS_DEFAULT_FEE < boost::get(blk_0.miner_tx.vout[i]).amount) { append_tx_source_entry(sources, blk_0.miner_tx, i); break; @@ -165,7 +165,7 @@ bool gen_uint_overflow_2::generate(std::vector& events) const sources.clear(); for (size_t i = 0; i < tx_1.vout.size(); ++i) { - auto& tx_1_out = tx_1.vout[i]; + auto& tx_1_out = boost::get(tx_1.vout[i]); if (tx_1_out.amount < TX_MAX_TRANSFER_AMOUNT - 1) continue; diff --git a/tests/core_tests/mixin_attr.cpp b/tests/core_tests/mixin_attr.cpp index cb9d4df3..c57d18a2 100644 --- a/tests/core_tests/mixin_attr.cpp +++ b/tests/core_tests/mixin_attr.cpp @@ -209,7 +209,7 @@ bool mix_in_spent_outs::generate(std::vector& events) const m_test_amount = MK_TEST_COINS(6); for(auto& o : blk_0.miner_tx.vout) { - CHECK_AND_ASSERT_MES(o.amount != m_test_amount, false, "Premine surprisingly has test amount output, change m_test_amount"); + CHECK_AND_ASSERT_MES(boost::get(o).amount != m_test_amount, false, "Premine surprisingly has test amount output, change m_test_amount"); } MAKE_TX_LIST_START(events, txs, miner_acc, alice_acc, m_test_amount, blk_0r); diff --git a/tests/core_tests/multisig_wallet_tests.cpp b/tests/core_tests/multisig_wallet_tests.cpp index 717be7f0..eec48869 100644 --- a/tests/core_tests/multisig_wallet_tests.cpp +++ b/tests/core_tests/multisig_wallet_tests.cpp @@ -299,7 +299,10 @@ bool multisig_wallet_test_many_dst::c1(currency::core& c, size_t ev_index, const miner_wlt->transfer(std::vector({ de }), 0, 0, TESTS_DEFAULT_FEE, std::vector(), std::vector(), tools::detail::ssi_digit, tools::tx_dust_policy(DEFAULT_DUST_THRESHOLD), result_tx); TMP_LOG_RESTORE; - auto it = std::find_if(result_tx.vout.begin(), result_tx.vout.end(), [](tx_out_bare& o) { return o.target.type() == typeid(txout_multisig); }); + auto it = std::find_if(result_tx.vout.begin(), result_tx.vout.end(), [](tx_out_v& o) + { + return boost::get(o).target.type() == typeid(txout_multisig); + }); CHECK_AND_ASSERT_MES(it != result_tx.vout.end(), false, "Can't find output txout_multisig"); size_t multisig_index = it - result_tx.vout.begin(); @@ -1411,7 +1414,7 @@ bool multisig_and_coinbase::generate(std::vector& events) cons se.multisig_id = get_multisig_out_id(blk_1.miner_tx, se.real_output_in_tx_index); //se.participants.push_back(alice_acc.get_keys()); se.real_out_tx_key = get_tx_pub_key_from_extra(blk_1.miner_tx); - se.ms_keys_count = boost::get(blk_1.boost::get(miner_tx.vout[se.real_output_in_tx_index]).target).keys.size(); + se.ms_keys_count = boost::get(boost::get(blk_1.miner_tx.vout[se.real_output_in_tx_index]).target).keys.size(); se.ms_sigs_count = 1; sources.assign({ se }); @@ -1457,9 +1460,9 @@ bool multisig_and_coinbase::generate(std::vector& events) cons miner_tx.vin.assign({ in_gen }); // remove all outputs except the multisig - auto it = std::find_if(miner_tx.vout.begin(), miner_tx.vout.end(), [](const tx_out_bare& o) {return o.target.type() == typeid(txout_multisig); }); + auto it = std::find_if(miner_tx.vout.begin(), miner_tx.vout.end(), [](const tx_out_v& o) {return boost::get(o).target.type() == typeid(txout_multisig); }); CHECK_AND_ASSERT_MES(it != miner_tx.vout.end(), false, "construct_tx didn't create multisig output as expected"); - tx_out_bare ms_out = *it; + tx_out_bare ms_out = boost::get(*it); miner_tx.vout.assign({ ms_out }); CHECK_AND_ASSERT_MES(ms_out.amount == blk_2_reward, false, "unexpected amount for found ms output"); @@ -1477,7 +1480,7 @@ bool multisig_and_coinbase::generate(std::vector& events) cons se.multisig_id = get_multisig_out_id(blk_3.miner_tx, 0); se.real_output_in_tx_index = 0; se.real_out_tx_key = get_tx_pub_key_from_extra(blk_3.miner_tx); - se.ms_keys_count= boost::get(blk_3.boost::get(miner_tx.vout[se.real_output_in_tx_index]).target).keys.size(); + se.ms_keys_count= boost::get(boost::get(blk_3.miner_tx.vout[se.real_output_in_tx_index]).target).keys.size(); se.ms_sigs_count = 1; transaction tx_2 = AUTO_VAL_INIT(tx_2); @@ -1874,7 +1877,7 @@ bool multisig_and_checkpoints_bad_txs::generate(std::vector& e txb.step1_init(); txb.step2_fill_inputs(miner_acc.get_keys(), sources); txb.step3_fill_outputs(destinations, 0, 1); - boost::get(txb.boost::get(m_tx.vout[0]).target).keys.clear(); // zero keys + boost::get(boost::get(txb.m_tx.vout[0]).target).keys.clear(); // zero keys txb.step4_calc_hash(); txb.step5_sign(sources); transaction tx_4 = txb.m_tx; @@ -1888,8 +1891,8 @@ bool multisig_and_checkpoints_bad_txs::generate(std::vector& e txb.step1_init(); txb.step2_fill_inputs(miner_acc.get_keys(), sources); txb.step3_fill_outputs(destinations, 0, 1); - crypto::public_key k = boost::get(txb.boost::get(m_tx.vout[0]).target).keys[0]; - boost::get(txb.boost::get(m_tx.vout[0]).target).keys.resize(1500, k); + crypto::public_key k = boost::get(boost::get(txb.m_tx.vout[0]).target).keys[0]; + boost::get(boost::get(txb.m_tx.vout[0]).target).keys.resize(1500, k); txb.step4_calc_hash(); txb.step5_sign(sources); boost::get(txb.m_tx.signature).s.clear(); diff --git a/tests/core_tests/tx_validation.cpp b/tests/core_tests/tx_validation.cpp index f83ad53a..60a18a43 100644 --- a/tests/core_tests/tx_validation.cpp +++ b/tests/core_tests/tx_validation.cpp @@ -494,7 +494,7 @@ bool gen_tx_txout_to_key_has_invalid_key::generate(std::vector builder.step2_fill_inputs(miner_account.get_keys(), sources); builder.step3_fill_outputs(destinations); - txout_to_key& out_to_key = boost::get(builder.m_tx.vout.front().target); + txout_to_key& out_to_key = boost::get(boost::get(builder.m_tx.vout.front()).target); out_to_key.key = tx_builder::generate_invalid_pub_key(); builder.step4_calc_hash(); @@ -523,7 +523,7 @@ bool gen_tx_output_with_zero_amount::generate(std::vector& eve builder.step2_fill_inputs(miner_account.get_keys(), sources); builder.step3_fill_outputs(destinations); - builder.m_tx.vout.front().amount = 0; + boost::get(builder.m_tx.vout.front()).amount = 0; builder.step4_calc_hash(); builder.step5_sign(sources); diff --git a/tests/core_tests/wallet_tests.cpp b/tests/core_tests/wallet_tests.cpp index 142a020a..54333221 100644 --- a/tests/core_tests/wallet_tests.cpp +++ b/tests/core_tests/wallet_tests.cpp @@ -21,7 +21,7 @@ const std::wstring g_wallet_filename = L"~coretests.wallet.file.tmp"; const std::string g_wallet_password = "dofatibmzibeziyekigo"; const currency::account_base null_account = AUTO_VAL_INIT(null_account); - +//@#@: TODO: need refactoring, unsafe operations POD_MAKE_COMPARABLE(currency, tx_out_bare); // Determines which output is real and actually spent in tx inputs, when there are fake outputs. @@ -39,7 +39,8 @@ bool determine_tx_real_inputs(currency::core& c, const currency::transaction& tx bool handle_output(const transaction& source_tx, const transaction& validated_tx, const tx_out_bare& out, uint64_t out_i) { CHECK_AND_ASSERT_MES(!m_found, false, "Internal error: m_found is true but the visitor is still being applied"); - auto it = std::find(validated_tx.vout.begin(), validated_tx.vout.end(), out); + auto is_even = [&](const tx_out_v& v) { return boost::get(v) == out; }; + auto it = std::find_if(validated_tx.vout.begin(), validated_tx.vout.end(), is_even); if (it == validated_tx.vout.end()) return false; size_t output_tx_index = it - validated_tx.vout.begin(); diff --git a/tests/functional_tests/transactions_flow_test.cpp b/tests/functional_tests/transactions_flow_test.cpp index 2ab26623..41dd6f45 100644 --- a/tests/functional_tests/transactions_flow_test.cpp +++ b/tests/functional_tests/transactions_flow_test.cpp @@ -196,7 +196,7 @@ uint64_t got_money_in_first_transfers(const tools::wallet2::transfer_container& size_t count = 0; BOOST_FOREACH(const tools::wallet2::transfer_details& td, incoming_transfers) { - summ += td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index].amount; + summ += boost::get(td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index]).amount; if(++count >= n_transfers) return summ; } @@ -459,9 +459,9 @@ bool transactions_flow_test( ++count; currency::transaction tx_s; - if (w1.unlocked_balance() >= td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index].amount) + if (w1.unlocked_balance() >= boost::get(td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index]).amount) { - bool r = do_send_money_by_fractions(w1, w1, 0, td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index].amount - TX_DEFAULT_FEE, tx_s, transfer_size); + bool r = do_send_money_by_fractions(w1, w1, 0, boost::get(td.m_ptx_wallet_info->m_tx.vout[td.m_internal_output_index]).amount - TX_DEFAULT_FEE, tx_s, transfer_size); CHECK_AND_ASSERT_MES(r, false, "Failed to send starter tx " << get_transaction_hash(tx_s)); } else diff --git a/tests/performance_tests/is_out_to_acc.h b/tests/performance_tests/is_out_to_acc.h index 5da47308..7af0cd22 100644 --- a/tests/performance_tests/is_out_to_acc.h +++ b/tests/performance_tests/is_out_to_acc.h @@ -17,7 +17,7 @@ public: bool test() { - const currency::txout_to_key& tx_out = boost::get(m_tx.vout[0].target); + const currency::txout_to_key& tx_out = boost::get(boost::get(m_tx.vout[0]).target); return currency::is_out_to_acc(m_bob.get_keys(), tx_out, m_tx_pub_key, 0); } }; diff --git a/tests/performance_tests/multi_tx_test_base.h b/tests/performance_tests/multi_tx_test_base.h index f04be41a..dc0f5c55 100644 --- a/tests/performance_tests/multi_tx_test_base.h +++ b/tests/performance_tests/multi_tx_test_base.h @@ -32,13 +32,13 @@ public: if (!construct_miner_tx(0, 0, 0, 2, 0, m_miners[i].get_keys().m_account_address, m_miner_txs[i], TRANSACTION_VERSION_PRE_HF4)) return false; - txout_to_key tx_out = boost::get(m_miner_txs[i].vout[0].target); + txout_to_key tx_out = boost::get(boost::get(m_miner_txs[i].vout[0]).target); output_entries.push_back(make_serializable_pair(i, tx_out.key)); m_public_keys[i] = tx_out.key; m_public_key_ptrs[i] = &m_public_keys[i]; } - m_source_amount = m_miner_txs[0].vout[0].amount; + m_source_amount = boost::get(m_miner_txs[0].vout[0]).amount; tx_source_entry source_entry; source_entry.amount = m_source_amount;