Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 56 additions & 2 deletions src/wallet/wallet2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1047,6 +1047,53 @@ crypto::chacha_key derive_cache_key(const crypto::chacha_key& keys_data_key, con

return cache_key;
}

void recover_dests(
std::unordered_map<crypto::hash, tools::wallet2::unconfirmed_transfer_details> &m_unconfirmed_txs,
std::unordered_map<crypto::hash, tools::wallet2::confirmed_transfer_details> &m_confirmed_txs,
std::unordered_map<crypto::hash, wallet2_basic::destination_details> &m_recoverable_dests)
{
if (m_recoverable_dests.empty())
return;

for (auto it = m_recoverable_dests.begin(); it != m_recoverable_dests.end();)
{
auto confirmed_it = m_confirmed_txs.find(it->first);
if (confirmed_it != m_confirmed_txs.end())
{
confirmed_it->second.m_dests = std::move(it->second.m_dests);
confirmed_it->second.m_payment_id = it->second.m_payment_id;
it = m_recoverable_dests.erase(it);
continue;
}

auto unconfirmed_it = m_unconfirmed_txs.find(it->first);
if (unconfirmed_it != m_unconfirmed_txs.end())
{
unconfirmed_it->second.m_dests = std::move(it->second.m_dests);
unconfirmed_it->second.m_payment_id = it->second.m_payment_id;
it = m_recoverable_dests.erase(it);
continue;
}

++it;
}
}

std::unordered_map<crypto::hash, wallet2_basic::destination_details> save_recoverable_dests(
const std::unordered_map<crypto::hash, tools::wallet2::unconfirmed_transfer_details> &m_unconfirmed_txs,
const std::unordered_map<crypto::hash, tools::wallet2::confirmed_transfer_details> &m_confirmed_txs)
{
std::unordered_map<crypto::hash, wallet2_basic::destination_details> recoverable_dests;

for (const auto &unconfirmed_tx : m_unconfirmed_txs)
recoverable_dests[unconfirmed_tx.first] = wallet2_basic::destination_details{ .m_dests = unconfirmed_tx.second.m_dests, .m_payment_id = unconfirmed_tx.second.m_payment_id };
for (const auto &confirmed_tx : m_confirmed_txs)
recoverable_dests[confirmed_tx.first] = wallet2_basic::destination_details{ .m_dests = confirmed_tx.second.m_dests, .m_payment_id = confirmed_tx.second.m_payment_id };

return recoverable_dests;
}

//-----------------------------------------------------------------
} //namespace

Expand Down Expand Up @@ -4567,6 +4614,9 @@ void wallet2::refresh(bool trusted_daemon, uint64_t start_height, uint64_t & blo
m_multisig_rescan_k = std::vector<std::vector<rct::key>>{};

LOG_PRINT_L1("Refresh done, blocks received: " << blocks_fetched << ", current sync height: " << m_blockchain.size() << ", balance (all accounts): " << print_money(balance_all(false)) << ", unlocked: " << print_money(unlocked_balance_all(false)));

// Recover dests if there are any to recover
recover_dests(m_unconfirmed_txs, m_confirmed_txs, m_recoverable_dests);
}
//----------------------------------------------------------------------------------------------------
bool wallet2::refresh(bool trusted_daemon, uint64_t & blocks_fetched, bool& received_money, bool& ok)
Expand Down Expand Up @@ -6823,8 +6873,12 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass

if (m_tree_cache.n_synced_blocks() == 0 && !m_transfers.empty() && m_has_ever_refreshed_from_node)
{
// clear the wallet so that we re-sync the tree and get received output paths
// TODO: may want to warn users that this is happening before doing it, esp. because it'll delete tx dests
// We must be upgrading a pre-FCMP++ wallet to a FCMP++ wallet.
// Unfortunately, we have to clear the wallet and re-sync from the wallet's restore height, in order to sync the
// FCMP++ tree and get received output paths.
// But first, we save destination details, so that we don't lose them. We recover any recoverable dests after
// refreshing (recovery happens via recover_dests).
m_recoverable_dests = save_recoverable_dests(m_unconfirmed_txs, m_confirmed_txs);
this->clear_soft(true);
}

Expand Down
4 changes: 4 additions & 0 deletions src/wallet/wallet2.h
Original file line number Diff line number Diff line change
Expand Up @@ -959,6 +959,7 @@ namespace tools
if (version < 3)
return true;
FIELD(m_tree_cache)
FIELD(m_recoverable_dests)
END_SERIALIZE()

/*!
Expand Down Expand Up @@ -1576,6 +1577,9 @@ namespace tools
std::vector<std::vector<rct::key>> m_multisig_rescan_k;
std::unordered_map<crypto::public_key, crypto::key_image> m_cold_key_images;

// This struct is used to make sure wallets upgrading from pre-FCMP++ to FCMP++ maintain saved destination details
std::unordered_map<crypto::hash, wallet2_basic::destination_details> m_recoverable_dests;

uint64_t m_sync_blocks_time_ms;
uint64_t m_outs_by_last_locked_time_ms;

Expand Down
8 changes: 8 additions & 0 deletions src/wallet/wallet2_basic/wallet2_boost_serialization.h
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,13 @@ void serialize(Archive &a, wallet2_basic::confirmed_transfer_details &x, const u
a & x.m_rings;
}

template <class Archive>
void serialize(Archive &a, wallet2_basic::destination_details &x, const unsigned int ver)
{
a & x.m_dests;
a & x.m_payment_id;
}

template <class Archive>
void serialize(Archive& a, wallet2_basic::payment_details& x, const unsigned int ver)
{
Expand Down Expand Up @@ -423,6 +430,7 @@ BOOST_CLASS_VERSION(wallet2_basic::multisig_info::LR, 0)
BOOST_CLASS_VERSION(wallet2_basic::multisig_info, 1)
BOOST_CLASS_VERSION(wallet2_basic::unconfirmed_transfer_details, 8)
BOOST_CLASS_VERSION(wallet2_basic::confirmed_transfer_details, 6)
BOOST_CLASS_VERSION(wallet2_basic::destination_details, 0)
BOOST_CLASS_VERSION(wallet2_basic::payment_details, 5)
BOOST_CLASS_VERSION(wallet2_basic::pool_payment_details, 1)
BOOST_CLASS_VERSION(wallet2_basic::address_book_row, 18)
Expand Down
6 changes: 6 additions & 0 deletions src/wallet/wallet2_basic/wallet2_cocobo_serialization.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,12 @@ BEGIN_SERIALIZE_OBJECT_FN(confirmed_transfer_details)
FIELD_F(m_rings)
END_SERIALIZE()

BEGIN_SERIALIZE_OBJECT_FN(destination_details)
VERSION_FIELD(0)
FIELD_F(m_dests)
FIELD_F(m_payment_id)
END_SERIALIZE()

BEGIN_SERIALIZE_OBJECT_FN(payment_details)
VERSION_FIELD(0)
FIELD_F(m_tx_hash)
Expand Down
6 changes: 6 additions & 0 deletions src/wallet/wallet2_basic/wallet2_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,12 @@ struct confirmed_transfer_details
{}
};

struct destination_details
{
std::vector<cryptonote::tx_destination_entry> m_dests;
crypto::hash m_payment_id{crypto::null_hash};
};

typedef std::vector<uint64_t> amounts_container;
struct payment_details
{
Expand Down
Loading