diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 76731545..55106fa9 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -490,6 +490,7 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, uint64_ LOG_PRINT_L0("Spent money: " << print_money(amount) << ", with tx: " << get_transaction_hash(tx)); tx_money_spent_in_ins += amount; td.m_spent = true; + td.m_spent_height = height; if (0 != m_callback) m_callback->on_money_spent(height, td.m_tx, amount, tx); } @@ -1167,6 +1168,17 @@ void wallet2::detach_blockchain(uint64_t height) LOG_PRINT_L0("Detaching blockchain on height " << height); size_t transfers_detached = 0; + for (size_t i = 0; i < m_transfers.size(); ++i) + { + wallet2::transfer_details &td = m_transfers[i]; + if (td.m_spent && td.m_spent_height >= height) + { + LOG_PRINT_L1("Resetting spent status for output " << i << ": " << td.m_key_image); + td.m_spent = false; + td.m_spent_height = 0; + } + } + auto it = std::find_if(m_transfers.begin(), m_transfers.end(), [&](const transfer_details& td){return td.m_block_height >= height;}); size_t i_start = it - m_transfers.begin(); @@ -1980,10 +1992,12 @@ void wallet2::rescan_spent() if (td.m_spent) { LOG_PRINT_L0("Marking output " << i << "(" << td.m_key_image << ") as unspent, it was marked as spent"); + td.m_spent_height = 0; } else { LOG_PRINT_L0("Marking output " << i << "(" << td.m_key_image << ") as spent, it was marked as unspent"); + // unknown height, if this gets reorged, it might still be missed } td.m_spent = daemon_resp.spent_status[i] != COMMAND_RPC_IS_KEY_IMAGE_SPENT::UNSPENT; } @@ -2293,7 +2307,10 @@ void wallet2::commit_tx(pending_tx& ptx) LOG_PRINT_L2("transaction " << txid << " generated ok and sent to daemon, key_images: [" << ptx.key_images << "]"); BOOST_FOREACH(transfer_container::iterator it, ptx.selected_transfers) + { it->m_spent = true; + it->m_spent_height = 0; + } //fee includes dust if dust policy specified it. LOG_PRINT_L0("Transaction successfully sent. <" << txid << ">" << ENDL @@ -2371,7 +2388,10 @@ std::vector wallet2::create_transactions(std::vectorm_spent = true; + it->m_spent_height = 0; + } } // if we made it this far, we've selected our transactions. committing them will mark them spent, @@ -2381,7 +2401,10 @@ std::vector wallet2::create_transactions(std::vectorm_spent = false; + it2->m_spent_height = 0; + } } @@ -2398,8 +2421,10 @@ std::vector wallet2::create_transactions(std::vectorm_spent = false; - + it2->m_spent_height = 0; + } } if (attempt_count >= MAX_SPLIT_ATTEMPTS) @@ -2416,8 +2441,10 @@ std::vector wallet2::create_transactions(std::vectorm_spent = false; - + it2->m_spent_height = 0; + } } throw; @@ -3860,7 +3887,10 @@ std::vector wallet2::create_unmixable_sweep_transactions(bo // mark transfers to be used as "spent" BOOST_FOREACH(transfer_container::iterator it, ptx.selected_transfers) + { it->m_spent = true; + it->m_spent_height = 0; + } } // if we made it this far, we've selected our transactions. committing them will mark them spent, @@ -3870,8 +3900,10 @@ std::vector wallet2::create_unmixable_sweep_transactions(bo { // mark transfers to be used as not spent BOOST_FOREACH(transfer_container::iterator it2, ptx.selected_transfers) + { it2->m_spent = false; - + it2->m_spent_height = 0; + } } // if we made it this far, we're OK to actually send the transactions @@ -3887,8 +3919,10 @@ std::vector wallet2::create_unmixable_sweep_transactions(bo { // mark transfers to be used as not spent BOOST_FOREACH(transfer_container::iterator it2, ptx.selected_transfers) + { it2->m_spent = false; - + it2->m_spent_height = 0; + } } if (attempt_count >= MAX_SPLIT_ATTEMPTS) @@ -3905,8 +3939,10 @@ std::vector wallet2::create_unmixable_sweep_transactions(bo { // mark transfers to be used as not spent BOOST_FOREACH(transfer_container::iterator it2, ptx.selected_transfers) + { it2->m_spent = false; - + it2->m_spent_height = 0; + } } throw; diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 125f8edb..1c835429 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -103,6 +103,7 @@ namespace tools size_t m_internal_output_index; uint64_t m_global_output_index; bool m_spent; + uint64_t m_spent_height; crypto::key_image m_key_image; //TODO: key_image stored twice :( rct::key m_mask; uint64_t m_amount; @@ -490,7 +491,7 @@ namespace tools }; } BOOST_CLASS_VERSION(tools::wallet2, 13) -BOOST_CLASS_VERSION(tools::wallet2::transfer_details, 1) +BOOST_CLASS_VERSION(tools::wallet2::transfer_details, 2) BOOST_CLASS_VERSION(tools::wallet2::payment_details, 1) BOOST_CLASS_VERSION(tools::wallet2::unconfirmed_transfer_details, 4) BOOST_CLASS_VERSION(tools::wallet2::confirmed_transfer_details, 2) @@ -500,14 +501,21 @@ namespace boost namespace serialization { template - inline void initialize_transfer_details(Archive &a, tools::wallet2::transfer_details &x) + inline void initialize_transfer_details(Archive &a, tools::wallet2::transfer_details &x, const boost::serialization::version_type ver) { } template<> - inline void initialize_transfer_details(boost::archive::binary_iarchive &a, tools::wallet2::transfer_details &x) + inline void initialize_transfer_details(boost::archive::binary_iarchive &a, tools::wallet2::transfer_details &x, const boost::serialization::version_type ver) { - x.m_mask = rct::identity(); - x.m_amount = x.m_tx.vout[x.m_internal_output_index].amount; + if (ver < 1) + { + x.m_mask = rct::identity(); + x.m_amount = x.m_tx.vout[x.m_internal_output_index].amount; + } + if (ver < 2) + { + x.m_spent_height = 0; + } } template @@ -522,11 +530,17 @@ namespace boost if (ver < 1) { // ensure mask and amount are set - initialize_transfer_details(a, x); + initialize_transfer_details(a, x, ver); return; } a & x.m_mask; a & x.m_amount; + if (ver < 2) + { + initialize_transfer_details(a, x, ver); + return; + } + a & x.m_spent_height; } template