tx_pool: hold off parsing a tx blob till we actually need it
This commit is contained in:
parent
8a7b3ff138
commit
2b0c632f32
|
@ -927,8 +927,26 @@ namespace cryptonote
|
|||
m_transactions_lock.unlock();
|
||||
}
|
||||
//---------------------------------------------------------------------------------
|
||||
bool tx_memory_pool::is_transaction_ready_to_go(txpool_tx_meta_t& txd, transaction &tx) const
|
||||
bool tx_memory_pool::is_transaction_ready_to_go(txpool_tx_meta_t& txd, const cryptonote::blobdata &txblob, transaction &tx) const
|
||||
{
|
||||
struct transction_parser
|
||||
{
|
||||
transction_parser(const cryptonote::blobdata &txblob, transaction &tx): txblob(txblob), tx(tx), parsed(false) {}
|
||||
cryptonote::transaction &operator()()
|
||||
{
|
||||
if (!parsed)
|
||||
{
|
||||
if (!parse_and_validate_tx_from_blob(txblob, tx))
|
||||
throw std::runtime_error("failed to parse transaction blob");
|
||||
parsed = true;
|
||||
}
|
||||
return tx;
|
||||
}
|
||||
const cryptonote::blobdata &txblob;
|
||||
transaction &tx;
|
||||
bool parsed;
|
||||
} lazy_tx(txblob, tx);
|
||||
|
||||
//not the best implementation at this time, sorry :(
|
||||
//check is ring_signature already checked ?
|
||||
if(txd.max_used_block_id == null_hash)
|
||||
|
@ -938,7 +956,7 @@ namespace cryptonote
|
|||
return false;//we already sure that this tx is broken for this height
|
||||
|
||||
tx_verification_context tvc;
|
||||
if(!m_blockchain.check_tx_inputs(tx, txd.max_used_block_height, txd.max_used_block_id, tvc))
|
||||
if(!m_blockchain.check_tx_inputs(lazy_tx(), txd.max_used_block_height, txd.max_used_block_id, tvc))
|
||||
{
|
||||
txd.last_failed_height = m_blockchain.get_current_blockchain_height()-1;
|
||||
txd.last_failed_id = m_blockchain.get_block_id_by_height(txd.last_failed_height);
|
||||
|
@ -955,7 +973,7 @@ namespace cryptonote
|
|||
return false;
|
||||
//check ring signature again, it is possible (with very small chance) that this transaction become again valid
|
||||
tx_verification_context tvc;
|
||||
if(!m_blockchain.check_tx_inputs(tx, txd.max_used_block_height, txd.max_used_block_id, tvc))
|
||||
if(!m_blockchain.check_tx_inputs(lazy_tx(), txd.max_used_block_height, txd.max_used_block_id, tvc))
|
||||
{
|
||||
txd.last_failed_height = m_blockchain.get_current_blockchain_height()-1;
|
||||
txd.last_failed_id = m_blockchain.get_block_id_by_height(txd.last_failed_height);
|
||||
|
@ -964,7 +982,7 @@ namespace cryptonote
|
|||
}
|
||||
}
|
||||
//if we here, transaction seems valid, but, anyway, check for key_images collisions with blockchain, just to be sure
|
||||
if(m_blockchain.have_tx_keyimges_as_spent(tx))
|
||||
if(m_blockchain.have_tx_keyimges_as_spent(lazy_tx()))
|
||||
{
|
||||
txd.double_spend_seen = true;
|
||||
return false;
|
||||
|
@ -1140,18 +1158,21 @@ namespace cryptonote
|
|||
|
||||
cryptonote::blobdata txblob = m_blockchain.get_txpool_tx_blob(sorted_it->second);
|
||||
cryptonote::transaction tx;
|
||||
if (!parse_and_validate_tx_from_blob(txblob, tx))
|
||||
{
|
||||
MERROR("Failed to parse tx from txpool");
|
||||
sorted_it++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip transactions that are not ready to be
|
||||
// included into the blockchain or that are
|
||||
// missing key images
|
||||
const cryptonote::txpool_tx_meta_t original_meta = meta;
|
||||
bool ready = is_transaction_ready_to_go(meta, tx);
|
||||
bool ready = false;
|
||||
try
|
||||
{
|
||||
ready = is_transaction_ready_to_go(meta, txblob, tx);
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
MERROR("Failed to check transaction readiness: " << e.what());
|
||||
// continue, not fatal
|
||||
}
|
||||
if (memcmp(&original_meta, &meta, sizeof(meta)))
|
||||
{
|
||||
try
|
||||
|
|
|
@ -499,10 +499,12 @@ namespace cryptonote
|
|||
* @brief check if a transaction is a valid candidate for inclusion in a block
|
||||
*
|
||||
* @param txd the transaction to check (and info about it)
|
||||
* @param txblob the transaction blob to check
|
||||
* @param tx the parsed transaction, if successful
|
||||
*
|
||||
* @return true if the transaction is good to go, otherwise false
|
||||
*/
|
||||
bool is_transaction_ready_to_go(txpool_tx_meta_t& txd, transaction &tx) const;
|
||||
bool is_transaction_ready_to_go(txpool_tx_meta_t& txd, const cryptonote::blobdata &txblob, transaction &tx) const;
|
||||
|
||||
/**
|
||||
* @brief mark all transactions double spending the one passed
|
||||
|
|
Loading…
Reference in New Issue