diff options
author | moneromooo-monero <moneromooo-monero@users.noreply.github.com> | 2018-04-11 15:27:56 +0100 |
---|---|---|
committer | moneromooo-monero <moneromooo-monero@users.noreply.github.com> | 2018-04-11 15:27:56 +0100 |
commit | 08343abaf432c56124651a20099d0e5b029aa62e (patch) | |
tree | 4230410cc03a126c5cbabbe88dfe07bab9170eef /src/cryptonote_core/tx_pool.cpp | |
parent | Merge pull request #3434 (diff) | |
download | monero-08343abaf432c56124651a20099d0e5b029aa62e.tar.xz |
tx_pool: fix loading with colliding key images
A key image may be present more than once if all but one of the
txes spending that key image are coming from blocks. When loading
a txpool from storage, we must load the one that's not from a
block first to avoid rejection
Diffstat (limited to 'src/cryptonote_core/tx_pool.cpp')
-rw-r--r-- | src/cryptonote_core/tx_pool.cpp | 43 |
1 files changed, 26 insertions, 17 deletions
diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp index 0af9737a7..5dfbc1dd4 100644 --- a/src/cryptonote_core/tx_pool.cpp +++ b/src/cryptonote_core/tx_pool.cpp @@ -1268,24 +1268,33 @@ namespace cryptonote m_spent_key_images.clear(); m_txpool_size = 0; std::vector<crypto::hash> remove; - bool r = m_blockchain.for_all_txpool_txes([this, &remove](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *bd) { - cryptonote::transaction tx; - if (!parse_and_validate_tx_from_blob(*bd, tx)) - { - MWARNING("Failed to parse tx from txpool, removing"); - remove.push_back(txid); - } - if (!insert_key_images(tx, meta.kept_by_block)) - { - MFATAL("Failed to insert key images from txpool tx"); + + // first add the not kept by block, then the kept by block, + // to avoid rejection due to key image collision + for (int pass = 0; pass < 2; ++pass) + { + const bool kept = pass == 1; + bool r = m_blockchain.for_all_txpool_txes([this, &remove, kept](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *bd) { + if (!!kept != !!meta.kept_by_block) + return true; + cryptonote::transaction tx; + if (!parse_and_validate_tx_from_blob(*bd, tx)) + { + MWARNING("Failed to parse tx from txpool, removing"); + remove.push_back(txid); + } + if (!insert_key_images(tx, meta.kept_by_block)) + { + MFATAL("Failed to insert key images from txpool tx"); + return false; + } + m_txs_by_fee_and_receive_time.emplace(std::pair<double, time_t>(meta.fee / (double)meta.blob_size, meta.receive_time), txid); + m_txpool_size += meta.blob_size; + return true; + }, true); + if (!r) return false; - } - m_txs_by_fee_and_receive_time.emplace(std::pair<double, time_t>(meta.fee / (double)meta.blob_size, meta.receive_time), txid); - m_txpool_size += meta.blob_size; - return true; - }, true); - if (!r) - return false; + } if (!remove.empty()) { LockedTXN lock(m_blockchain); |