Skip to content

Commit

Permalink
wallet: fix multisig key memory leak
Browse files Browse the repository at this point in the history
Multisig keys per-transfer were being wiped, but not erased, which lead to a ginormous
quadratic bloat the more transfers and exports you performed with the wallet.
  • Loading branch information
jeffro256 committed Nov 3, 2023
1 parent d9b765a commit fe47806
Showing 1 changed file with 26 additions and 0 deletions.
26 changes: 26 additions & 0 deletions src/wallet/wallet2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6244,6 +6244,20 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass
if (!m_persistent_rpc_client_id)
set_rpc_client_secret_key(rct::rct2sk(rct::skGen()));

// Wallets used to wipe, but not erase, old unused multisig key info, which lead to huge memory leaks.
// Here we erase these multisig keys if they're zero'd out to free up space.
for (auto &td : m_transfers)
{
auto mk_it = td.m_multisig_k.begin();
while (mk_it != td.m_multisig_k.end())
{
if (*mk_it == rct::zero())
mk_it = td.m_multisig_k.erase(mk_it);
else
++mk_it;
}
}

cryptonote::block genesis;
generate_genesis(genesis);
crypto::hash genesis_hash = get_block_hash(genesis);
Expand Down Expand Up @@ -7123,7 +7137,10 @@ void wallet2::commit_tx(pending_tx& ptx)

// tx generated, get rid of used k values
for (size_t idx: ptx.selected_transfers)
{
memwipe(m_transfers[idx].m_multisig_k.data(), m_transfers[idx].m_multisig_k.size() * sizeof(m_transfers[idx].m_multisig_k[0]));
m_transfers[idx].m_multisig_k.clear();
}

//fee includes dust if dust policy specified it.
LOG_PRINT_L1("Transaction successfully sent. <" << txid << ">" << ENDL
Expand Down Expand Up @@ -7627,7 +7644,10 @@ std::string wallet2::save_multisig_tx(multisig_tx_set txs)
// txes generated, get rid of used k values
for (size_t n = 0; n < txs.m_ptx.size(); ++n)
for (size_t idx: txs.m_ptx[n].construction_data.selected_transfers)
{
memwipe(m_transfers[idx].m_multisig_k.data(), m_transfers[idx].m_multisig_k.size() * sizeof(m_transfers[idx].m_multisig_k[0]));
m_transfers[idx].m_multisig_k.clear();
}

// zero out some data we don't want to share
for (auto &ptx: txs.m_ptx)
Expand Down Expand Up @@ -7951,7 +7971,10 @@ bool wallet2::sign_multisig_tx(multisig_tx_set &exported_txs, std::vector<crypto
// inputs in the transactions worked on here)
for (size_t n = 0; n < exported_txs.m_ptx.size(); ++n)
for (size_t idx: exported_txs.m_ptx[n].construction_data.selected_transfers)
{
memwipe(m_transfers[idx].m_multisig_k.data(), m_transfers[idx].m_multisig_k.size() * sizeof(m_transfers[idx].m_multisig_k[0]));
m_transfers[idx].m_multisig_k.clear();
}

exported_txs.m_signers.insert(get_multisig_signer_public_key());

Expand Down Expand Up @@ -14266,7 +14289,10 @@ cryptonote::blobdata wallet2::export_multisig()
transfer_details &td = m_transfers[n];
crypto::key_image ki;
if (td.m_multisig_k.size())
{
memwipe(td.m_multisig_k.data(), td.m_multisig_k.size() * sizeof(td.m_multisig_k[0]));
td.m_multisig_k.clear();
}
info[n].m_LR.clear();
info[n].m_partial_key_images.clear();

Expand Down

0 comments on commit fe47806

Please sign in to comment.