|
|
|
@ -55,6 +55,17 @@ namespace cryptonote
|
|
|
|
|
namespace
|
|
|
|
|
{
|
|
|
|
|
size_t const TRANSACTION_SIZE_LIMIT = (((CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE * 125) / 100) - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE);
|
|
|
|
|
time_t const MIN_RELAY_TIME = (60 * 5); // only start re-relaying transactions after that many seconds
|
|
|
|
|
time_t const MAX_RELAY_TIME = (60 * 60 * 4); // at most that many seconds between resends
|
|
|
|
|
|
|
|
|
|
// a kind of increasing backoff within min/max bounds
|
|
|
|
|
time_t get_relay_delay(time_t now, time_t received)
|
|
|
|
|
{
|
|
|
|
|
time_t d = (now - received + MIN_RELAY_TIME) / MIN_RELAY_TIME * MIN_RELAY_TIME;
|
|
|
|
|
if (d > MAX_RELAY_TIME)
|
|
|
|
|
d = MAX_RELAY_TIME;
|
|
|
|
|
return d;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//---------------------------------------------------------------------------------
|
|
|
|
|
#if BLOCKCHAIN_DB == DB_LMDB
|
|
|
|
@ -70,7 +81,7 @@ namespace cryptonote
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
//---------------------------------------------------------------------------------
|
|
|
|
|
bool tx_memory_pool::add_tx(const transaction &tx, /*const crypto::hash& tx_prefix_hash,*/ const crypto::hash &id, size_t blob_size, tx_verification_context& tvc, bool kept_by_block)
|
|
|
|
|
bool tx_memory_pool::add_tx(const transaction &tx, /*const crypto::hash& tx_prefix_hash,*/ const crypto::hash &id, size_t blob_size, tx_verification_context& tvc, bool kept_by_block, bool relayed)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -154,6 +165,8 @@ namespace cryptonote
|
|
|
|
|
txd_p.first->second.max_used_block_height = 0;
|
|
|
|
|
txd_p.first->second.kept_by_block = kept_by_block;
|
|
|
|
|
txd_p.first->second.receive_time = time(nullptr);
|
|
|
|
|
txd_p.first->second.last_relayed_time = time(NULL);
|
|
|
|
|
txd_p.first->second.relayed = relayed;
|
|
|
|
|
tvc.m_verifivation_impossible = true;
|
|
|
|
|
tvc.m_added_to_pool = true;
|
|
|
|
|
}else
|
|
|
|
@ -176,6 +189,8 @@ namespace cryptonote
|
|
|
|
|
txd_p.first->second.last_failed_height = 0;
|
|
|
|
|
txd_p.first->second.last_failed_id = null_hash;
|
|
|
|
|
txd_p.first->second.receive_time = time(nullptr);
|
|
|
|
|
txd_p.first->second.last_relayed_time = time(NULL);
|
|
|
|
|
txd_p.first->second.relayed = relayed;
|
|
|
|
|
tvc.m_added_to_pool = true;
|
|
|
|
|
|
|
|
|
|
if(txd_p.first->second.fee > 0)
|
|
|
|
@ -202,12 +217,12 @@ namespace cryptonote
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
//---------------------------------------------------------------------------------
|
|
|
|
|
bool tx_memory_pool::add_tx(const transaction &tx, tx_verification_context& tvc, bool keeped_by_block)
|
|
|
|
|
bool tx_memory_pool::add_tx(const transaction &tx, tx_verification_context& tvc, bool keeped_by_block, bool relayed)
|
|
|
|
|
{
|
|
|
|
|
crypto::hash h = null_hash;
|
|
|
|
|
size_t blob_size = 0;
|
|
|
|
|
get_transaction_hash(tx, h, blob_size);
|
|
|
|
|
return add_tx(tx, h, blob_size, tvc, keeped_by_block);
|
|
|
|
|
return add_tx(tx, h, blob_size, tvc, keeped_by_block, relayed);
|
|
|
|
|
}
|
|
|
|
|
//---------------------------------------------------------------------------------
|
|
|
|
|
bool tx_memory_pool::remove_transaction_keyimages(const transaction& tx)
|
|
|
|
@ -240,7 +255,7 @@ namespace cryptonote
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
//---------------------------------------------------------------------------------
|
|
|
|
|
bool tx_memory_pool::take_tx(const crypto::hash &id, transaction &tx, size_t& blob_size, uint64_t& fee)
|
|
|
|
|
bool tx_memory_pool::take_tx(const crypto::hash &id, transaction &tx, size_t& blob_size, uint64_t& fee, bool &relayed)
|
|
|
|
|
{
|
|
|
|
|
CRITICAL_REGION_LOCAL(m_transactions_lock);
|
|
|
|
|
auto it = m_transactions.find(id);
|
|
|
|
@ -255,6 +270,7 @@ namespace cryptonote
|
|
|
|
|
tx = it->second.tx;
|
|
|
|
|
blob_size = it->second.blob_size;
|
|
|
|
|
fee = it->second.fee;
|
|
|
|
|
relayed = it->second.relayed;
|
|
|
|
|
remove_transaction_keyimages(it->second.tx);
|
|
|
|
|
m_transactions.erase(it);
|
|
|
|
|
m_txs_by_fee.erase(sorted_it);
|
|
|
|
@ -304,6 +320,41 @@ namespace cryptonote
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
//---------------------------------------------------------------------------------
|
|
|
|
|
bool tx_memory_pool::get_relayable_transactions(std::list<std::pair<crypto::hash, cryptonote::transaction>> &txs) const
|
|
|
|
|
{
|
|
|
|
|
CRITICAL_REGION_LOCAL(m_transactions_lock);
|
|
|
|
|
const time_t now = time(NULL);
|
|
|
|
|
for(auto it = m_transactions.begin(); it!= m_transactions.end();)
|
|
|
|
|
{
|
|
|
|
|
// 0 fee transactions are never relayed
|
|
|
|
|
if(it->second.fee > 0 && now - it->second.last_relayed_time > get_relay_delay(now, it->second.receive_time))
|
|
|
|
|
{
|
|
|
|
|
// if the tx is older than half the max lifetime, we don't re-relay it, to avoid a problem
|
|
|
|
|
// mentioned by smooth where nodes would flush txes at slightly different times, causing
|
|
|
|
|
// flushed txes to be re-added when received from a node which was just about to flush it
|
|
|
|
|
time_t max_age = it->second.kept_by_block ? CRYPTONOTE_MEMPOOL_TX_FROM_ALT_BLOCK_LIVETIME : CRYPTONOTE_MEMPOOL_TX_LIVETIME;
|
|
|
|
|
if (now - it->second.receive_time <= max_age / 2)
|
|
|
|
|
{
|
|
|
|
|
txs.push_back(std::make_pair(it->first, it->second.tx));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
++it;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
//---------------------------------------------------------------------------------
|
|
|
|
|
void tx_memory_pool::set_relayed(const std::list<std::pair<crypto::hash, cryptonote::transaction>> &txs)
|
|
|
|
|
{
|
|
|
|
|
CRITICAL_REGION_LOCAL(m_transactions_lock);
|
|
|
|
|
const time_t now = time(NULL);
|
|
|
|
|
for (auto it = txs.begin(); it != txs.end(); ++it)
|
|
|
|
|
{
|
|
|
|
|
auto i = m_transactions.find(it->first);
|
|
|
|
|
if (i != m_transactions.end())
|
|
|
|
|
i->second.last_relayed_time = now;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//---------------------------------------------------------------------------------
|
|
|
|
|
size_t tx_memory_pool::get_transactions_count() const
|
|
|
|
|
{
|
|
|
|
|
CRITICAL_REGION_LOCAL(m_transactions_lock);
|
|
|
|
|