diff options
author | moneromooo-monero <moneromooo-monero@users.noreply.github.com> | 2015-11-21 00:26:48 +0000 |
---|---|---|
committer | moneromooo-monero <moneromooo-monero@users.noreply.github.com> | 2015-11-21 00:56:21 +0000 |
commit | 932994c0cb25d21ccc5795c23b0e342427260625 (patch) | |
tree | 70c92777fc82a486b459d89dac53bdfd4bbbc377 /src/cryptonote_core/tx_pool.cpp | |
parent | Merge pull request #490 (diff) | |
download | monero-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.cpp | 59 |
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); |