aboutsummaryrefslogtreecommitdiff
path: root/src/cryptonote_core/tx_pool.cpp
diff options
context:
space:
mode:
authormoneromooo-monero <moneromooo-monero@users.noreply.github.com>2015-11-21 00:26:48 +0000
committermoneromooo-monero <moneromooo-monero@users.noreply.github.com>2015-11-21 00:56:21 +0000
commit932994c0cb25d21ccc5795c23b0e342427260625 (patch)
tree70c92777fc82a486b459d89dac53bdfd4bbbc377 /src/cryptonote_core/tx_pool.cpp
parentMerge pull request #490 (diff)
downloadmonero-932994c0cb25d21ccc5795c23b0e342427260625.tar.xz
Relay transactions when they linger too long in the pool
The last relayed time of a transaction is maintained, and transactions will be relayed again if they are still in the pool after a certain amount of time, which increases with the transaction's age. All such transactions are resent, whether or not they originated on the local node.
Diffstat (limited to 'src/cryptonote_core/tx_pool.cpp')
-rw-r--r--src/cryptonote_core/tx_pool.cpp59
1 files changed, 55 insertions, 4 deletions
diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp
index dce64db99..defbeb3b3 100644
--- a/src/cryptonote_core/tx_pool.cpp
+++ b/src/cryptonote_core/tx_pool.cpp
@@ -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);