diff --git a/src/common/boost_serialization_maps.h b/src/common/boost_serialization_maps.h index bd8436d9..12a10d74 100644 --- a/src/common/boost_serialization_maps.h +++ b/src/common/boost_serialization_maps.h @@ -6,6 +6,17 @@ #define BEGIN_BOOST_SERIALIZATION() template inline void serialize(t_archive &_arch, const unsigned int ver) { +template struct TAssertEquality { + static_assert(A == B, "Serialization map is not updated, sizeof() missmatch"); + static constexpr bool _cResult = (A == B); +}; + +//experemental feature: self-validated serialization map, needed to not forget add new members to serialization maps +#define BEGIN_BOOST_SERIALIZATION_SV(sz) BEGIN_BOOST_SERIALIZATION() \ + static constexpr bool _cIsEqual = TAssertEquality::_cResult; + + + #define BOOST_SERIALIZE(x) _arch & x; #define END_BOOST_SERIALIZATION() } diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 898cf5d8..bc45bf27 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -834,7 +834,7 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t } } - if (has_in_transfers || has_out_transfers) + if (has_in_transfers || has_out_transfers || is_derivation_used_to_encrypt(tx, derivation)) { ptc.timestamp = get_block_datetime(b); handle_money(b, ptc); @@ -1202,6 +1202,15 @@ void wallet2::change_contract_state(wallet_public::escrow_contract_details_basic contract.state = new_state; } //----------------------------------------------------------------------------------------------------- +void from_outs_to_received_items(const std::vector& outs, std::vector& received, const currency::transaction& tx) +{ + for (const auto& item : outs) + { + if(!out_is_multisig(tx.vout[item.index])) + received.push_back(tools::wallet2::payment_details_subtransfer{ item.asset_id, item.amount}); + } +} +//----------------------------------------------------------------------------------------------------- bool wallet2::handle_proposal(wallet_public::wallet_transfer_info& wti, const bc_services::proposal_body& prop) { PROFILE_FUNC("wallet2::handle_proposal"); @@ -1237,8 +1246,9 @@ bool wallet2::handle_proposal(wallet_public::wallet_transfer_info& wti, const bc std::vector outs; bool r = lookup_acc_outs(m_account.get_keys(), prop.tx_template, outs, derivation); THROW_IF_FALSE_WALLET_INT_ERR_EX(r, "Failed to lookup_acc_outs for tx: " << get_transaction_hash(prop.tx_template)); - - add_transfers_to_expiration_list(found_transfers, ed.expiration_time, wti.tx_hash); + std::vector received; + from_outs_to_received_items(outs, received, prop.tx_template); + add_transfers_to_expiration_list(found_transfers, received, ed.expiration_time, wti.tx_hash); WLT_LOG_GREEN("Locked " << found_transfers.size() << " transfers due to proposal " << ms_id, LOG_LEVEL_0); } @@ -2129,6 +2139,9 @@ void wallet2::handle_unconfirmed_tx(process_transaction_context& ptc) //collect incomes for (auto& o : outs) { + if(out_is_multisig(tx.vout[o.index])) + continue; + ptc.total_balance_change[o.asset_id] += o.amount; ptc.employed_entries.receive.push_back(wallet_public::employed_tx_entry{ o.index, o.amount, o.asset_id }); } @@ -4876,7 +4889,7 @@ void wallet2::build_escrow_template(const bc_services::contract_private_details& finalize_transaction(ftp, tx, one_time_key, false); } //---------------------------------------------------------------------------------------------------- -void wallet2::add_transfers_to_expiration_list(const std::vector& selected_transfers, uint64_t expiration, const crypto::hash& related_tx_id) +void wallet2::add_transfers_to_expiration_list(const std::vector& selected_transfers, const std::vector& received, uint64_t expiration, const crypto::hash& related_tx_id) { // check all elements in selected_transfers for being already mentioned in m_money_expirations std::vector selected_transfers_local; @@ -4899,6 +4912,7 @@ void wallet2::add_transfers_to_expiration_list(const std::vector& sele m_money_expirations.back().expiration_time = expiration; m_money_expirations.back().selected_transfers = selected_transfers_local; m_money_expirations.back().related_tx_id = related_tx_id; + m_money_expirations.back().receved = received; std::stringstream ss; for (auto tr_ind : m_money_expirations.back().selected_transfers) @@ -5158,6 +5172,7 @@ bool wallet2::build_ionic_swap_template(const wallet_public::ionic_swap_proposal ctp.dsts[i].asset_id = proposal_detais.to_bob[i].asset_id; } // Here is an expected in return funds + std::vector for_expiration_list; for (size_t j = 0; j != proposal_detais.to_alice.size(); j++, i++) { ctp.dsts[i].amount = proposal_detais.to_alice[j].amount; @@ -5165,6 +5180,7 @@ bool wallet2::build_ionic_swap_template(const wallet_public::ionic_swap_proposal ctp.dsts[i].flags |= tx_destination_entry_flags::tdef_explicit_amount_to_provide; ctp.dsts[i].addr.push_back(m_account.get_public_address()); ctp.dsts[i].asset_id = proposal_detais.to_alice[j].asset_id; + for_expiration_list.push_back(payment_details_subtransfer{ ctp.dsts[i].asset_id, ctp.dsts[i].amount}); } currency::finalize_tx_param ftp = AUTO_VAL_INIT(ftp); @@ -5175,7 +5191,7 @@ bool wallet2::build_ionic_swap_template(const wallet_public::ionic_swap_proposal selected_transfers = ftp.selected_transfers; currency::finalized_tx finalize_result = AUTO_VAL_INIT(finalize_result); finalize_transaction(ftp, finalize_result, false); - add_transfers_to_expiration_list(selected_transfers, proposal_detais.expiration_time, currency::null_hash); + add_transfers_to_expiration_list(selected_transfers, for_expiration_list, proposal_detais.expiration_time, currency::null_hash); //wrap it all proposal.tx_template = finalize_result.tx; diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 12689ca6..7d06135e 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -488,6 +488,14 @@ namespace tools std::vector selected_transfers; uint64_t expiration_time = 0; crypto::hash related_tx_id = currency::null_hash; // tx id which caused money lock, if any (ex: escrow proposal transport tx) + std::vector receved; + + BEGIN_BOOST_SERIALIZATION_SV(104) + BOOST_SERIALIZE(selected_transfers) + BOOST_SERIALIZE(expiration_time) + BOOST_SERIALIZE(related_tx_id) + BOOST_SERIALIZE(receved) + END_BOOST_SERIALIZATION() }; /* @@ -993,7 +1001,7 @@ private: // -------- t_transport_state_notifier ------------------------------------------------ virtual void notify_state_change(const std::string& state_code, const std::string& details = std::string()); // ------------------------------------------------------------------------------------ - void add_transfers_to_expiration_list(const std::vector& selected_transfers, uint64_t expiration, const crypto::hash& related_tx_id); + void add_transfers_to_expiration_list(const std::vector& selected_transfers, const std::vector& received, uint64_t expiration, const crypto::hash& related_tx_id); void remove_transfer_from_expiration_list(uint64_t transfer_index); void load_keys(const std::string& keys_file_name, const std::string& password, uint64_t file_signature, keys_file_data& kf_data); void process_new_transaction(const currency::transaction& tx, uint64_t height, const currency::block& b, const std::vector* pglobal_indexes); @@ -1288,18 +1296,6 @@ namespace boost a & x.contract_id; } - - template - inline void serialize(Archive& a, tools::wallet2::expiration_entry_info& x, const boost::serialization::version_type ver) - { - a & x.expiration_time; - a & x.selected_transfers; - a & x.related_tx_id; - } - - - - } } diff --git a/tests/core_tests/chaingen.cpp b/tests/core_tests/chaingen.cpp index 1990ead4..d27f4af2 100644 --- a/tests/core_tests/chaingen.cpp +++ b/tests/core_tests/chaingen.cpp @@ -2067,7 +2067,7 @@ bool make_tx_multisig_to_key(const currency::transaction& source_tx, return true; } -bool estimate_wallet_balance_blocked_for_escrow(const tools::wallet2& w, uint64_t& result) +bool estimate_wallet_balance_blocked_for_escrow(const tools::wallet2& w, uint64_t& result, bool substruct_change_from_result /* = true */) { std::deque transfers; w.get_transfers(transfers); @@ -2078,6 +2078,24 @@ bool estimate_wallet_balance_blocked_for_escrow(const tools::wallet2& w, uint64_ if (td.m_flags == (WALLET_TRANSFER_DETAIL_FLAG_BLOCKED | WALLET_TRANSFER_DETAIL_FLAG_ESCROW_PROPOSAL_RESERVATION)) result += td.amount(); } + if (substruct_change_from_result) + { + const std::list& ee = w.get_expiration_entries(); + for (auto &e : ee) + { + uint64_t change_amount_native = 0; + for (const auto rd : e.receved) + { + if (rd.asset_id == currency::native_coin_asset_id) + change_amount_native += rd.amount; + } + + CHECK_AND_ASSERT_MES(result >= change_amount_native, false, "wrong transfers: result: " << print_money(result) << " is expected to be NOT LESS than change_amount: " << print_money(change_amount_native)); + result -= change_amount_native; + } + } + + return true; } diff --git a/tests/core_tests/chaingen.h b/tests/core_tests/chaingen.h index 6ab7b76b..ba47f464 100644 --- a/tests/core_tests/chaingen.h +++ b/tests/core_tests/chaingen.h @@ -724,7 +724,7 @@ bool make_tx_multisig_to_key(const currency::transaction& source_tx, const std::vector& attachments = empty_attachment, const std::vector& extra = empty_extra); -bool estimate_wallet_balance_blocked_for_escrow(const tools::wallet2& w, uint64_t& result); +bool estimate_wallet_balance_blocked_for_escrow(const tools::wallet2& w, uint64_t& result, bool substruct_change_from_result = true); bool check_wallet_balance_blocked_for_escrow(const tools::wallet2& w, const char* wallet_name, uint64_t expected_amount); bool refresh_wallet_and_check_balance(const char* intro_log_message, const char* wallet_name, std::shared_ptr wallet, uint64_t expected_total, bool print_transfers = false,