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();
|
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 :(
|
//not the best implementation at this time, sorry :(
|
||||||
//check is ring_signature already checked ?
|
//check is ring_signature already checked ?
|
||||||
if(txd.max_used_block_id == null_hash)
|
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
|
return false;//we already sure that this tx is broken for this height
|
||||||
|
|
||||||
tx_verification_context tvc;
|
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_height = m_blockchain.get_current_blockchain_height()-1;
|
||||||
txd.last_failed_id = m_blockchain.get_block_id_by_height(txd.last_failed_height);
|
txd.last_failed_id = m_blockchain.get_block_id_by_height(txd.last_failed_height);
|
||||||
|
@ -955,7 +973,7 @@ namespace cryptonote
|
||||||
return false;
|
return false;
|
||||||
//check ring signature again, it is possible (with very small chance) that this transaction become again valid
|
//check ring signature again, it is possible (with very small chance) that this transaction become again valid
|
||||||
tx_verification_context tvc;
|
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_height = m_blockchain.get_current_blockchain_height()-1;
|
||||||
txd.last_failed_id = m_blockchain.get_block_id_by_height(txd.last_failed_height);
|
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 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;
|
txd.double_spend_seen = true;
|
||||||
return false;
|
return false;
|
||||||
|
@ -1140,18 +1158,21 @@ namespace cryptonote
|
||||||
|
|
||||||
cryptonote::blobdata txblob = m_blockchain.get_txpool_tx_blob(sorted_it->second);
|
cryptonote::blobdata txblob = m_blockchain.get_txpool_tx_blob(sorted_it->second);
|
||||||
cryptonote::transaction tx;
|
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
|
// Skip transactions that are not ready to be
|
||||||
// included into the blockchain or that are
|
// included into the blockchain or that are
|
||||||
// missing key images
|
// missing key images
|
||||||
const cryptonote::txpool_tx_meta_t original_meta = meta;
|
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)))
|
if (memcmp(&original_meta, &meta, sizeof(meta)))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|
|
@ -499,10 +499,12 @@ namespace cryptonote
|
||||||
* @brief check if a transaction is a valid candidate for inclusion in a block
|
* @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 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
|
* @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
|
* @brief mark all transactions double spending the one passed
|
||||||
|
|
Loading…
Reference in New Issue