diff options
author | Wladimir J. van der Laan <laanwj@protonmail.com> | 2019-10-02 16:55:03 +0200 |
---|---|---|
committer | Wladimir J. van der Laan <laanwj@protonmail.com> | 2019-10-02 16:55:36 +0200 |
commit | ccaef6c28b1997bd40faad2e1c66e22cdda11edc (patch) | |
tree | bec38b34fad46cea3a4102299a38ae6032dd7456 /src | |
parent | 19ba43ae2d00d00fde280b43fba4af98d863f547 (diff) | |
parent | faec689bed7a5b66e2a7675853d10205b933cec8 (diff) |
Merge #16908: txmempool: Make entry time type-safe (std::chrono)
faec689bed7a5b66e2a7675853d10205b933cec8 txmempool: Make entry time type-safe (std::chrono) (MarcoFalke)
faaa1f01daba94b021ca77515266a16d27f0364e util: Add count_seconds time helper (MarcoFalke)
1111170f2f0141084b5b4ed565b2f07eba48599a test: mempool entry time is persisted (MarcoFalke)
Pull request description:
This changes the type of the entry time of txs into the mempool from `int64_t` to `std::chrono::seconds`.
The benefits:
* Documents the type for developers
* Type violations result in compile errors
* After compilation, the two are equivalent (at no run time cost)
ACKs for top commit:
ajtowns:
utACK faec689bed7a5b66e2a7675853d10205b933cec8
laanwj:
ACK faec689bed7a5b66e2a7675853d10205b933cec8
Tree-SHA512: d958e058755d1a1d54cef536a8b30a11cc502b7df0d6ecf84a0ab1d38bc8105a67668a99cd5087a444f6de2421238111c5fca133cdf8e2e2273cb12cb6957845
Diffstat (limited to 'src')
-rw-r--r-- | src/net.h | 2 | ||||
-rw-r--r-- | src/net_processing.cpp | 6 | ||||
-rw-r--r-- | src/rpc/blockchain.cpp | 2 | ||||
-rw-r--r-- | src/txmempool.cpp | 3 | ||||
-rw-r--r-- | src/txmempool.h | 6 | ||||
-rw-r--r-- | src/util/time.h | 8 | ||||
-rw-r--r-- | src/validation.cpp | 12 |
7 files changed, 24 insertions, 15 deletions
@@ -761,7 +761,7 @@ public: // Used for BIP35 mempool sending bool fSendMempool GUARDED_BY(cs_tx_inventory){false}; // Last time a "MEMPOOL" request was serviced. - std::atomic<int64_t> timeLastMempoolReq{0}; + std::atomic<std::chrono::seconds> m_last_mempool_req{std::chrono::seconds{0}}; int64_t nNextInvSend{0}; CCriticalSection cs_feeFilter; diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 34d349e8e9..e345af604c 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -1541,11 +1541,11 @@ void static ProcessGetData(CNode* pfrom, const CChainParams& chainparams, CConnm if (mi != mapRelay.end()) { connman->PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::TX, *mi->second)); push = true; - } else if (pfrom->m_tx_relay->timeLastMempoolReq) { + } else if (pfrom->m_tx_relay->m_last_mempool_req.load().count()) { auto txinfo = mempool.info(inv.hash); // To protect privacy, do not answer getdata using the mempool when // that TX couldn't have been INVed in reply to a MEMPOOL request. - if (txinfo.tx && txinfo.nTime <= pfrom->m_tx_relay->timeLastMempoolReq) { + if (txinfo.tx && txinfo.m_time <= pfrom->m_tx_relay->m_last_mempool_req.load()) { connman->PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::TX, *txinfo.tx)); push = true; } @@ -3873,7 +3873,7 @@ bool PeerLogicValidation::SendMessages(CNode* pto) vInv.clear(); } } - pto->m_tx_relay->timeLastMempoolReq = GetTime(); + pto->m_tx_relay->m_last_mempool_req = GetTime<std::chrono::seconds>(); } // Determine transactions to relay diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 02717fa80f..3463145f75 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -418,7 +418,7 @@ static void entryToJSON(const CTxMemPool& pool, UniValue& info, const CTxMemPool info.pushKV("weight", (int)e.GetTxWeight()); info.pushKV("fee", ValueFromAmount(e.GetFee())); info.pushKV("modifiedfee", ValueFromAmount(e.GetModifiedFee())); - info.pushKV("time", e.GetTime()); + info.pushKV("time", count_seconds(e.GetTime())); info.pushKV("height", (int)e.GetHeight()); info.pushKV("descendantcount", e.GetCountWithDescendants()); info.pushKV("descendantsize", e.GetSizeWithDescendants()); diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 9257cff718..835b8d63bd 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -917,7 +917,8 @@ void CTxMemPool::RemoveStaged(setEntries &stage, bool updateDescendants, MemPool } } -int CTxMemPool::Expire(int64_t time) { +int CTxMemPool::Expire(std::chrono::seconds time) +{ AssertLockHeld(cs); indexed_transaction_set::index<entry_time>::type::iterator it = mapTx.get<entry_time>().begin(); setEntries toremove; diff --git a/src/txmempool.h b/src/txmempool.h index 6e5ba445d3..f2fc1c8310 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -102,7 +102,7 @@ public: const CAmount& GetFee() const { return nFee; } size_t GetTxSize() const; size_t GetTxWeight() const { return nTxWeight; } - int64_t GetTime() const { return nTime; } + std::chrono::seconds GetTime() const { return std::chrono::seconds{nTime}; } unsigned int GetHeight() const { return entryHeight; } int64_t GetSigOpCost() const { return sigOpCost; } int64_t GetModifiedFee() const { return nFee + feeDelta; } @@ -332,7 +332,7 @@ struct TxMempoolInfo CTransactionRef tx; /** Time the transaction entered the mempool. */ - int64_t nTime; + std::chrono::seconds m_time; /** Feerate of the transaction. */ CFeeRate feeRate; @@ -657,7 +657,7 @@ public: void TrimToSize(size_t sizelimit, std::vector<COutPoint>* pvNoSpendsRemaining = nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs); /** Expire all transaction (and their dependencies) in the mempool older than time. Return the number of removed transactions. */ - int Expire(int64_t time) EXCLUSIVE_LOCKS_REQUIRED(cs); + int Expire(std::chrono::seconds time) EXCLUSIVE_LOCKS_REQUIRED(cs); /** * Calculate the ancestor and descendant count for the given transaction. diff --git a/src/util/time.h b/src/util/time.h index e4f9996777..c0470a2136 100644 --- a/src/util/time.h +++ b/src/util/time.h @@ -11,6 +11,14 @@ #include <chrono> /** + * Helper to count the seconds of a duration. + * + * All durations should be using std::chrono and calling this should generally be avoided in code. Though, it is still + * preferred to an inline t.count() to protect against a reliance on the exact type of t. + */ +inline int64_t count_seconds(std::chrono::seconds t) { return t.count(); } + +/** * DEPRECATED * Use either GetSystemTimeInSeconds (not mockable) or GetTime<T> (mockable) */ diff --git a/src/validation.cpp b/src/validation.cpp index ac98bd61c7..726f251c5a 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -314,10 +314,10 @@ bool CheckSequenceLocks(const CTxMemPool& pool, const CTransaction& tx, int flag // Returns the script flags which should be checked for a given block static unsigned int GetBlockScriptFlags(const CBlockIndex* pindex, const Consensus::Params& chainparams); -static void LimitMempoolSize(CTxMemPool& pool, size_t limit, unsigned long age) +static void LimitMempoolSize(CTxMemPool& pool, size_t limit, std::chrono::seconds age) EXCLUSIVE_LOCKS_REQUIRED(pool.cs, ::cs_main) { - int expired = pool.Expire(GetTime() - age); + int expired = pool.Expire(GetTime<std::chrono::seconds>() - age); if (expired != 0) { LogPrint(BCLog::MEMPOOL, "Expired %i transactions from the memory pool\n", expired); } @@ -389,7 +389,7 @@ static void UpdateMempoolForReorg(DisconnectedBlockTransactions& disconnectpool, // We also need to remove any now-immature transactions mempool.removeForReorg(&::ChainstateActive().CoinsTip(), ::ChainActive().Tip()->nHeight + 1, STANDARD_LOCKTIME_VERIFY_FLAGS); // Re-limit mempool size, in case we added any transactions - LimitMempoolSize(mempool, gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000, gArgs.GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY) * 60 * 60); + LimitMempoolSize(mempool, gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000, std::chrono::hours{gArgs.GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY)}); } // Used to avoid mempool polluting consensus critical paths if CCoinsViewMempool @@ -1011,7 +1011,7 @@ bool MemPoolAccept::Finalize(ATMPArgs& args, Workspace& ws) // trim mempool and check if tx was trimmed if (!bypass_limits) { - LimitMempoolSize(m_pool, gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000, gArgs.GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY) * 60 * 60); + LimitMempoolSize(m_pool, gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000, std::chrono::hours{gArgs.GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY)}); if (!m_pool.exists(hash)) return state.Invalid(ValidationInvalidReason::TX_MEMPOOL_POLICY, false, REJECT_INSUFFICIENTFEE, "mempool full"); } @@ -5041,8 +5041,8 @@ bool DumpMempool(const CTxMemPool& pool) file << (uint64_t)vinfo.size(); for (const auto& i : vinfo) { file << *(i.tx); - file << (int64_t)i.nTime; - file << (int64_t)i.nFeeDelta; + file << int64_t{count_seconds(i.m_time)}; + file << int64_t{i.nFeeDelta}; mapDeltas.erase(i.tx->GetHash()); } |