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
This commit is contained in:
moneromooo-monero 2018-04-11 15:27:56 +01:00
parent 8361d60aef
commit 08343abaf4
No known key found for this signature in database
GPG Key ID: 686F07454D6CEFC3
1 changed files with 26 additions and 17 deletions

View File

@ -1268,24 +1268,33 @@ namespace cryptonote
m_spent_key_images.clear(); m_spent_key_images.clear();
m_txpool_size = 0; m_txpool_size = 0;
std::vector<crypto::hash> remove; 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; // first add the not kept by block, then the kept by block,
if (!parse_and_validate_tx_from_blob(*bd, tx)) // to avoid rejection due to key image collision
{ for (int pass = 0; pass < 2; ++pass)
MWARNING("Failed to parse tx from txpool, removing"); {
remove.push_back(txid); 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 (!insert_key_images(tx, meta.kept_by_block)) if (!!kept != !!meta.kept_by_block)
{ return true;
MFATAL("Failed to insert key images from txpool tx"); 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; 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()) if (!remove.empty())
{ {
LockedTXN lock(m_blockchain); LockedTXN lock(m_blockchain);