diff --git a/src/chain.h b/src/chain.h index 47d1e3096774f..9e2d539b9fc78 100644 --- a/src/chain.h +++ b/src/chain.h @@ -12,6 +12,7 @@ #include #include #include +#include #include @@ -255,6 +256,11 @@ class CBlockIndex */ bool HaveTxsDownloaded() const { return nChainTx != 0; } + NodeSeconds Time() const + { + return NodeSeconds{std::chrono::seconds{nTime}}; + } + int64_t GetBlockTime() const { return (int64_t)nTime; diff --git a/src/coinjoin/coinjoin.h b/src/coinjoin/coinjoin.h index 9a15be8b6c03f..61e6576adf54f 100644 --- a/src/coinjoin/coinjoin.h +++ b/src/coinjoin/coinjoin.h @@ -212,7 +212,7 @@ class CCoinJoinQueue [[nodiscard]] bool CheckSignature(const CBLSPublicKey& blsPubKey) const; /// Check if a queue is too old or too far into the future - [[nodiscard]] bool IsTimeOutOfBounds(int64_t current_time = GetAdjustedTime()) const; + [[nodiscard]] bool IsTimeOutOfBounds(int64_t current_time = TicksSinceEpoch(GetAdjustedTime())) const; [[nodiscard]] std::string ToString() const; diff --git a/src/coinjoin/server.cpp b/src/coinjoin/server.cpp index 98069a79cf112..494913c4c0816 100644 --- a/src/coinjoin/server.cpp +++ b/src/coinjoin/server.cpp @@ -360,7 +360,7 @@ void CCoinJoinServer::CommitFinalTransaction() // create and sign masternode dstx transaction if (!m_dstxman.GetDSTX(hashTx)) { CCoinJoinBroadcastTx dstxNew(finalTransaction, m_mn_activeman.GetOutPoint(), m_mn_activeman.GetProTxHash(), - GetAdjustedTime()); + TicksSinceEpoch(GetAdjustedTime())); dstxNew.vchSig = m_mn_activeman.SignBasic(dstxNew.GetSignatureHash()); m_dstxman.AddDSTX(dstxNew); } @@ -517,7 +517,7 @@ void CCoinJoinServer::CheckForCompleteQueue() SetState(POOL_STATE_ACCEPTING_ENTRIES); CCoinJoinQueue dsq(nSessionDenom, m_mn_activeman.GetOutPoint(), m_mn_activeman.GetProTxHash(), - GetAdjustedTime(), true); + TicksSinceEpoch(GetAdjustedTime()), true); LogPrint(BCLog::COINJOIN, "CCoinJoinServer::CheckForCompleteQueue -- queue is ready, signing and relaying (%s) " /* Continued */ "with %d participants\n", dsq.ToString(), vecSessionCollaterals.size()); dsq.vchSig = m_mn_activeman.SignBasic(dsq.GetSignatureHash()); @@ -728,7 +728,7 @@ bool CCoinJoinServer::CreateNewSession(const CCoinJoinAccept& dsa, PoolMessage& if (!fUnitTest) { //broadcast that I'm accepting entries, only if it's the first entry through CCoinJoinQueue dsq(nSessionDenom, m_mn_activeman.GetOutPoint(), m_mn_activeman.GetProTxHash(), - GetAdjustedTime(), false); + TicksSinceEpoch(GetAdjustedTime()), false); LogPrint(BCLog::COINJOIN, "CCoinJoinServer::CreateNewSession -- signing and relaying new queue: %s\n", dsq.ToString()); dsq.vchSig = m_mn_activeman.SignBasic(dsq.GetSignatureHash()); m_peerman.RelayDSQ(dsq); diff --git a/src/consensus/params.h b/src/consensus/params.h index 09cbd8c83fa58..81e1652ddc92e 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -9,6 +9,7 @@ #include #include +#include #include #include @@ -170,6 +171,10 @@ struct Params { int64_t nPowTargetTimespan; int nPowKGWHeight; int nPowDGWHeight; + std::chrono::seconds PowTargetSpacing() const + { + return std::chrono::seconds{nPowTargetSpacing}; + } int64_t DifficultyAdjustmentInterval() const { return nPowTargetTimespan / nPowTargetSpacing; } uint256 nMinimumChainWork; uint256 defaultAssumeValid; diff --git a/src/crypto/ripemd160.cpp b/src/crypto/ripemd160.cpp index 29a4ad906fc7a..a2f7c6e1563b1 100644 --- a/src/crypto/ripemd160.cpp +++ b/src/crypto/ripemd160.cpp @@ -239,7 +239,7 @@ void Transform(uint32_t* s, const unsigned char* chunk) ////// RIPEMD160 -CRIPEMD160::CRIPEMD160() : bytes(0) +CRIPEMD160::CRIPEMD160() { ripemd160::Initialize(s); } diff --git a/src/crypto/ripemd160.h b/src/crypto/ripemd160.h index 025121f24ad15..d4a526e5587f7 100644 --- a/src/crypto/ripemd160.h +++ b/src/crypto/ripemd160.h @@ -14,7 +14,7 @@ class CRIPEMD160 private: uint32_t s[5]; unsigned char buf[64]; - uint64_t bytes; + uint64_t bytes{0}; public: static const size_t OUTPUT_SIZE = 20; diff --git a/src/crypto/sha1.cpp b/src/crypto/sha1.cpp index 1fb9bb2b72f2f..2610108f60752 100644 --- a/src/crypto/sha1.cpp +++ b/src/crypto/sha1.cpp @@ -146,7 +146,7 @@ void Transform(uint32_t* s, const unsigned char* chunk) ////// SHA1 -CSHA1::CSHA1() : bytes(0) +CSHA1::CSHA1() { sha1::Initialize(s); } diff --git a/src/crypto/sha1.h b/src/crypto/sha1.h index f1b7dffab43d8..e991362393cf4 100644 --- a/src/crypto/sha1.h +++ b/src/crypto/sha1.h @@ -14,7 +14,7 @@ class CSHA1 private: uint32_t s[5]; unsigned char buf[64]; - uint64_t bytes; + uint64_t bytes{0}; public: static const size_t OUTPUT_SIZE = 20; diff --git a/src/crypto/sha256.cpp b/src/crypto/sha256.cpp index 884719a1b097f..c99b5697366db 100644 --- a/src/crypto/sha256.cpp +++ b/src/crypto/sha256.cpp @@ -690,7 +690,7 @@ std::string SHA256AutoDetect(sha256_implementation::UseImplementation use_implem ////// SHA-256 -CSHA256::CSHA256() : bytes(0) +CSHA256::CSHA256() { sha256::Initialize(s); } diff --git a/src/crypto/sha256.h b/src/crypto/sha256.h index 60b2237a74307..456c65746c32d 100644 --- a/src/crypto/sha256.h +++ b/src/crypto/sha256.h @@ -15,7 +15,7 @@ class CSHA256 private: uint32_t s[8]; unsigned char buf[64]; - uint64_t bytes; + uint64_t bytes{0}; public: static const size_t OUTPUT_SIZE = 32; diff --git a/src/crypto/sha512.cpp b/src/crypto/sha512.cpp index 59b79609dd8c8..5e4a1c3cc3290 100644 --- a/src/crypto/sha512.cpp +++ b/src/crypto/sha512.cpp @@ -151,7 +151,7 @@ void Transform(uint64_t* s, const unsigned char* chunk) ////// SHA-512 -CSHA512::CSHA512() : bytes(0) +CSHA512::CSHA512() { sha512::Initialize(s); } diff --git a/src/crypto/sha512.h b/src/crypto/sha512.h index 7356dff6d9b3c..4d5815afa7c4a 100644 --- a/src/crypto/sha512.h +++ b/src/crypto/sha512.h @@ -14,7 +14,7 @@ class CSHA512 private: uint64_t s[8]; unsigned char buf[128]; - uint64_t bytes; + uint64_t bytes{0}; public: static constexpr size_t OUTPUT_SIZE = 64; diff --git a/src/cuckoocache.h b/src/cuckoocache.h index 22c06d89735a6..833254b40b367 100644 --- a/src/cuckoocache.h +++ b/src/cuckoocache.h @@ -164,7 +164,7 @@ class cache std::vector table; /** size stores the total available slots in the hash table */ - uint32_t size; + uint32_t size{0}; /** The bit_packed_atomic_flags array is marked mutable because we want * garbage collection to be allowed to occur from const methods */ @@ -181,7 +181,7 @@ class cache * decremented on insert and reset to the new number of inserts which would * cause the epoch to reach epoch_size when it reaches zero. */ - uint32_t epoch_heuristic_counter; + uint32_t epoch_heuristic_counter{0}; /** epoch_size is set to be the number of elements supposed to be in a * epoch. When the number of non-erased elements in an epoch @@ -191,12 +191,12 @@ class cache * one "dead" which has been erased, one "dying" which has been marked to be * erased next, and one "living" which new inserts add to. */ - uint32_t epoch_size; + uint32_t epoch_size{0}; /** depth_limit determines how many elements insert should try to replace. * Should be set to log2(n). */ - uint8_t depth_limit; + uint8_t depth_limit{0}; /** hash_function is a const instance of the hash function. It cannot be * static or initialized at call time as it may have internal state (such as @@ -320,8 +320,7 @@ class cache /** You must always construct a cache with some elements via a subsequent * call to setup or setup_bytes, otherwise operations may segfault. */ - cache() : table(), size(), collection_flags(0), epoch_flags(), - epoch_heuristic_counter(), epoch_size(), depth_limit(0), hash_function() + cache() : table(), collection_flags(0), epoch_flags(), hash_function() { } diff --git a/src/dbwrapper.h b/src/dbwrapper.h index bd6e847180a69..62f9d5a63db2b 100644 --- a/src/dbwrapper.h +++ b/src/dbwrapper.h @@ -79,13 +79,13 @@ class CDBBatch CDataStream ssKey; CDataStream ssValue; - size_t size_estimate; + size_t size_estimate{0}; public: /** * @param[in] _parent CDBWrapper that this batch is to be submitted to */ - explicit CDBBatch(const CDBWrapper &_parent) : parent(_parent), ssKey(SER_DISK, CLIENT_VERSION), ssValue(SER_DISK, CLIENT_VERSION), size_estimate(0) { }; + explicit CDBBatch(const CDBWrapper &_parent) : parent(_parent), ssKey(SER_DISK, CLIENT_VERSION), ssValue(SER_DISK, CLIENT_VERSION) { }; void Clear() { diff --git a/src/governance/governance.cpp b/src/governance/governance.cpp index 108f3690b1633..aa4ef3794d3b4 100644 --- a/src/governance/governance.cpp +++ b/src/governance/governance.cpp @@ -371,7 +371,7 @@ void CGovernanceManager::CheckOrphanVotes(CGovernanceObject& govobj) ScopedLockBool guard(cs_store, fRateChecksEnabled, false); - int64_t nNow = GetAdjustedTime(); + int64_t nNow = TicksSinceEpoch(GetAdjustedTime()); const auto tip_mn_list = Assert(m_dmnman)->GetListAtChainTip(); for (const auto& pairVote : vecVotePairs) { const auto& [vote, time] = pairVote; @@ -860,7 +860,7 @@ bool CGovernanceManager::MasternodeRateCheck(const CGovernanceObject& govobj, bo const COutPoint& masternodeOutpoint = govobj.GetMasternodeOutpoint(); int64_t nTimestamp = govobj.GetCreationTime(); - int64_t nNow = GetAdjustedTime(); + int64_t nNow = TicksSinceEpoch(GetAdjustedTime()); int64_t nSuperblockCycleSeconds = Params().GetConsensus().nSuperblockCycle * Params().GetConsensus().nPowTargetSpacing; std::string strHash = govobj.GetHash().ToString(); @@ -1014,7 +1014,7 @@ void CGovernanceManager::CheckPostponedObjects() // Perform additional relays for triggers - int64_t nNow = GetAdjustedTime(); + int64_t nNow = TicksSinceEpoch(GetAdjustedTime()); int64_t nSuperblockCycleSeconds = Params().GetConsensus().nSuperblockCycle * Params().GetConsensus().nPowTargetSpacing; for (auto it = setAdditionalRelayObjects.begin(); it != setAdditionalRelayObjects.end();) { diff --git a/src/governance/object.cpp b/src/governance/object.cpp index 173d2ab8db889..53fa9883796cf 100644 --- a/src/governance/object.cpp +++ b/src/governance/object.cpp @@ -120,7 +120,7 @@ bool CGovernanceObject::ProcessVote(CMasternodeMetaMan& mn_metaman, CGovernanceM LogPrint(BCLog::GOBJECT, "%s\n", msg); } - int64_t nNow = GetAdjustedTime(); + int64_t nNow = TicksSinceEpoch(GetAdjustedTime()); int64_t nVoteTimeUpdate = voteInstanceRef.nTime; if (govman.AreRateChecksEnabled()) { int64_t nTimeDelta = nNow - voteInstanceRef.nTime; diff --git a/src/governance/signing.cpp b/src/governance/signing.cpp index ea06dee330513..fd21c7cb5010d 100644 --- a/src/governance/signing.cpp +++ b/src/governance/signing.cpp @@ -127,7 +127,7 @@ std::optional GovernanceSigner::CreateGovernanceTrigger LOCK(::cs_main); // Check if identical trigger (equal DataHash()) is already created (signed by other masternode) - CGovernanceObject gov_sb(uint256(), 1, GetAdjustedTime(), uint256(), sb_opt.value().GetHexStrData()); + CGovernanceObject gov_sb(uint256(), 1, TicksSinceEpoch(GetAdjustedTime()), uint256(), sb_opt.value().GetHexStrData()); if (auto identical_sb = m_govman.FindGovernanceObjectByDataHash(gov_sb.GetDataHash())) { // Somebody submitted a trigger with the same data, support it instead of submitting a duplicate return std::make_optional(*identical_sb); @@ -261,7 +261,7 @@ void GovernanceSigner::VoteGovernanceTriggers(const std::optional(GetAdjustedTime())); vote.SetSignature(m_mn_activeman.SignBasic(vote.GetSignatureHash())); CGovernanceException exception; diff --git a/src/governance/validators.cpp b/src/governance/validators.cpp index bbe10d90439da..e061ca6a60935 100644 --- a/src/governance/validators.cpp +++ b/src/governance/validators.cpp @@ -136,7 +136,7 @@ bool CProposalValidator::ValidateStartEndEpoch(bool fCheckExpiration) return false; } - if (fCheckExpiration && nEndEpoch <= GetAdjustedTime()) { + if (fCheckExpiration && nEndEpoch <= TicksSinceEpoch(GetAdjustedTime())) { strErrorMessages += "expired;"; return false; } diff --git a/src/governance/vote.cpp b/src/governance/vote.cpp index 2a013465e38c6..a09e8b7640e77 100644 --- a/src/governance/vote.cpp +++ b/src/governance/vote.cpp @@ -87,7 +87,7 @@ CGovernanceVote::CGovernanceVote(const COutPoint& outpointMasternodeIn, const ui nParentHash(nParentHashIn), nVoteOutcome(eVoteOutcomeIn), nVoteSignal(eVoteSignalIn), - nTime(GetAdjustedTime()) + nTime(TicksSinceEpoch(GetAdjustedTime())) { UpdateHash(); } @@ -154,8 +154,8 @@ bool CGovernanceVote::CheckSignature(const CBLSPublicKey& pubKey) const bool CGovernanceVote::IsValid(const CDeterministicMNList& tip_mn_list, bool useVotingKey) const { - if (nTime > GetAdjustedTime() + (60 * 60)) { - LogPrint(BCLog::GOBJECT, "CGovernanceVote::IsValid -- vote is too far ahead of current time - %s - nTime %lli - Max Time %lli\n", GetHash().ToString(), nTime, GetAdjustedTime() + (60 * 60)); + if (nTime > TicksSinceEpoch(GetAdjustedTime() + 1h)) { + LogPrint(BCLog::GOBJECT, "CGovernanceVote::IsValid -- vote is too far ahead of current time - %s - nTime %lli - Max Time %lli\n", GetHash().ToString(), nTime, TicksSinceEpoch(GetAdjustedTime() + 1h)); return false; } diff --git a/src/key.h b/src/key.h index babffd406b0af..c1688815a5176 100644 --- a/src/key.h +++ b/src/key.h @@ -48,10 +48,10 @@ class CKey private: //! Whether this private key is valid. We check for correctness when modifying the key //! data, so fValid should always correspond to the actual state. - bool fValid; + bool fValid{false}; //! Whether the public key corresponding to this private key is (to be) compressed. - bool fCompressed; + bool fCompressed{false}; //! The actual byte data std::vector > keydata; @@ -61,7 +61,7 @@ class CKey public: //! Construct an invalid private key. - CKey() : fValid(false), fCompressed(false) + CKey() { // Important: vch must be 32 bytes in length to not break serialization keydata.resize(32); diff --git a/src/llmq/debug.cpp b/src/llmq/debug.cpp index 3445924990dcb..1dbdf17aa44bb 100644 --- a/src/llmq/debug.cpp +++ b/src/llmq/debug.cpp @@ -154,7 +154,7 @@ void CDKGDebugManager::ResetLocalSessionStatus(Consensus::LLMQType llmqType, int } localStatus.sessions.erase(it); - localStatus.nTime = GetAdjustedTime(); + localStatus.nTime = TicksSinceEpoch(GetAdjustedTime()); } void CDKGDebugManager::InitLocalSessionStatus(const Consensus::LLMQParams& llmqParams, int quorumIndex, const uint256& quorumHash, int quorumHeight) @@ -186,7 +186,7 @@ void CDKGDebugManager::UpdateLocalSessionStatus(Consensus::LLMQType llmqType, in } if (func(it->second)) { - localStatus.nTime = GetAdjustedTime(); + localStatus.nTime = TicksSinceEpoch(GetAdjustedTime()); } } @@ -200,7 +200,7 @@ void CDKGDebugManager::UpdateLocalMemberStatus(Consensus::LLMQType llmqType, int } if (func(it->second.members.at(memberIdx))) { - localStatus.nTime = GetAdjustedTime(); + localStatus.nTime = TicksSinceEpoch(GetAdjustedTime()); } } diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 9176e393987ed..55a4b316fb478 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -1353,7 +1353,7 @@ bool PeerManagerImpl::TipMayBeStale() bool PeerManagerImpl::CanDirectFetch() { - return m_chainman.ActiveChain().Tip()->GetBlockTime() > GetAdjustedTime() - m_chainparams.GetConsensus().nPowTargetSpacing * 20; + return m_chainman.ActiveChain().Tip()->Time() > GetAdjustedTime() - m_chainparams.GetConsensus().PowTargetSpacing() * 20; } static bool PeerHasHeader(CNodeState *state, const CBlockIndex *pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main) @@ -6004,7 +6004,7 @@ bool PeerManagerImpl::SendMessages(CNode* pto) if (!state.fSyncStarted && CanServeBlocks(*peer) && !fImporting && !fReindex && pto->CanRelay()) { // Only actively request headers from a single peer, unless we're close to end of initial download. - if ((nSyncStarted == 0 && sync_blocks_and_headers_from_peer) || m_chainman.m_best_header->GetBlockTime() > GetAdjustedTime() - nMaxTipAge) { + if ((nSyncStarted == 0 && sync_blocks_and_headers_from_peer) || m_chainman.m_best_header->Time() > GetAdjustedTime() - 24h) { const CBlockIndex* pindexStart = m_chainman.m_best_header; /* If possible, start at the block preceding the currently best known header. This ensures that we always get a @@ -6025,7 +6025,7 @@ bool PeerManagerImpl::SendMessages(CNode* pto) // Convert HEADERS_DOWNLOAD_TIMEOUT_PER_HEADER to microseconds before scaling // to maintain precision std::chrono::microseconds{HEADERS_DOWNLOAD_TIMEOUT_PER_HEADER} * - (GetAdjustedTime() - m_chainman.m_best_header->GetBlockTime()) / consensusParams.nPowTargetSpacing + Ticks(GetAdjustedTime() - m_chainman.m_best_header->Time()) / consensusParams.nPowTargetSpacing ); nSyncStarted++; } @@ -6407,7 +6407,7 @@ bool PeerManagerImpl::SendMessages(CNode* pto) // Check for headers sync timeouts if (state.fSyncStarted && state.m_headers_sync_timeout < std::chrono::microseconds::max()) { // Detect whether this is a stalling initial-headers-sync peer - if (m_chainman.m_best_header->GetBlockTime() <= GetAdjustedTime() - nMaxTipAge) { + if (m_chainman.m_best_header->Time() <= GetAdjustedTime() - 24h) { if (current_time > state.m_headers_sync_timeout && nSyncStarted == 1 && (m_num_preferred_download_peers - state.fPreferredDownload >= 1)) { // Disconnect a peer (without NetPermissionFlags::NoBan permission) if it is our only sync peer, // and we have others we could be using instead. diff --git a/src/node/miner.cpp b/src/node/miner.cpp index e00d905fc6de1..72128019bddfd 100644 --- a/src/node/miner.cpp +++ b/src/node/miner.cpp @@ -49,7 +49,7 @@ namespace node { int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev) { int64_t nOldTime = pblock->nTime; - int64_t nNewTime = std::max(pindexPrev->GetMedianTimePast() + 1, GetAdjustedTime()); + int64_t nNewTime{std::max(pindexPrev->GetMedianTimePast() + 1, TicksSinceEpoch(GetAdjustedTime()))}; if (nOldTime < nNewTime) { pblock->nTime = nNewTime; @@ -219,7 +219,7 @@ std::unique_ptr BlockAssembler::CreateNewBlock(const CScript& sc pblock->nVersion = gArgs.GetIntArg("-blockversion", pblock->nVersion); } - pblock->nTime = GetAdjustedTime(); + pblock->nTime = TicksSinceEpoch(GetAdjustedTime()); m_lock_time_cutoff = pindexPrev->GetMedianTimePast(); if (fDIP0003Active_context) { diff --git a/src/policy/fees.cpp b/src/policy/fees.cpp index e0586637450a3..03b629e7b9e61 100644 --- a/src/policy/fees.cpp +++ b/src/policy/fees.cpp @@ -543,7 +543,6 @@ bool CBlockPolicyEstimator::_removeTx(const uint256& hash, bool inBlock) } CBlockPolicyEstimator::CBlockPolicyEstimator() - : nBestSeenHeight(0), firstRecordedHeight(0), historicalFirst(0), historicalBest(0), trackedTxs(0), untrackedTxs(0) { static_assert(MIN_BUCKET_FEERATE > 0, "Min feerate must be nonzero"); size_t bucketIndex = 0; diff --git a/src/policy/fees.h b/src/policy/fees.h index 3a0ed2dc1b116..45bc40ab75c05 100644 --- a/src/policy/fees.h +++ b/src/policy/fees.h @@ -240,16 +240,16 @@ class CBlockPolicyEstimator private: mutable Mutex m_cs_fee_estimator; - unsigned int nBestSeenHeight GUARDED_BY(m_cs_fee_estimator); - unsigned int firstRecordedHeight GUARDED_BY(m_cs_fee_estimator); - unsigned int historicalFirst GUARDED_BY(m_cs_fee_estimator); - unsigned int historicalBest GUARDED_BY(m_cs_fee_estimator); + unsigned int nBestSeenHeight GUARDED_BY(m_cs_fee_estimator){0}; + unsigned int firstRecordedHeight GUARDED_BY(m_cs_fee_estimator){0}; + unsigned int historicalFirst GUARDED_BY(m_cs_fee_estimator){0}; + unsigned int historicalBest GUARDED_BY(m_cs_fee_estimator){0}; struct TxStatsInfo { - unsigned int blockHeight; - unsigned int bucketIndex; - TxStatsInfo() : blockHeight(0), bucketIndex(0) {} + unsigned int blockHeight{0}; + unsigned int bucketIndex{0}; + TxStatsInfo() {} }; // map of txids to information about that transaction @@ -260,8 +260,8 @@ class CBlockPolicyEstimator std::unique_ptr shortStats PT_GUARDED_BY(m_cs_fee_estimator); std::unique_ptr longStats PT_GUARDED_BY(m_cs_fee_estimator); - unsigned int trackedTxs GUARDED_BY(m_cs_fee_estimator); - unsigned int untrackedTxs GUARDED_BY(m_cs_fee_estimator); + unsigned int trackedTxs GUARDED_BY(m_cs_fee_estimator){0}; + unsigned int untrackedTxs GUARDED_BY(m_cs_fee_estimator){0}; std::vector buckets GUARDED_BY(m_cs_fee_estimator); // The upper-bound of the range for the bucket (inclusive) std::map bucketMap GUARDED_BY(m_cs_fee_estimator); // Map of bucket upper-bound to index into all vectors by bucket diff --git a/src/primitives/block.h b/src/primitives/block.h index f33e44ad39049..d2eff8851d73c 100644 --- a/src/primitives/block.h +++ b/src/primitives/block.h @@ -12,6 +12,7 @@ #include #include #include +#include /** Nodes collect new transactions into a block, hash them into a hash tree, * and scan through nonce values to make the block's hash satisfy proof-of-work @@ -55,6 +56,11 @@ class CBlockHeader uint256 GetHash() const; + NodeSeconds Time() const + { + return NodeSeconds{std::chrono::seconds{nTime}}; + } + int64_t GetBlockTime() const { return (int64_t)nTime; diff --git a/src/rpc/governance.cpp b/src/rpc/governance.cpp index 985a43818ebae..e3e9a24706999 100644 --- a/src/rpc/governance.cpp +++ b/src/rpc/governance.cpp @@ -124,7 +124,7 @@ static RPCHelpMan gobject_check() int nRevision = 1; - int64_t nTime = GetAdjustedTime(); + int64_t nTime = TicksSinceEpoch(GetAdjustedTime()); std::string strDataHex = request.params[0].get_str(); CGovernanceObject govobj(hashParent, nRevision, nTime, uint256(), strDataHex); diff --git a/src/rpc/request.cpp b/src/rpc/request.cpp index f1cd256e3549a..c00c0b552fc38 100644 --- a/src/rpc/request.cpp +++ b/src/rpc/request.cpp @@ -78,6 +78,8 @@ static fs::path GetAuthCookieFile(bool temp=false) return AbsPathForConfigVal(arg); } +static bool g_generated_cookie = false; + bool GenerateAuthCookie(std::string *cookie_out) { const size_t COOKIE_SIZE = 32; @@ -103,6 +105,7 @@ bool GenerateAuthCookie(std::string *cookie_out) LogPrintf("Unable to rename cookie authentication file %s to %s\n", fs::PathToString(filepath_tmp), fs::PathToString(filepath)); return false; } + g_generated_cookie = true; LogPrintf("Generated RPC authentication cookie %s\n", fs::PathToString(filepath)); if (cookie_out) @@ -129,7 +132,10 @@ bool GetAuthCookie(std::string *cookie_out) void DeleteAuthCookie() { try { - fs::remove(GetAuthCookieFile()); + if (g_generated_cookie) { + // Delete the cookie file if it was generated by this process + fs::remove(GetAuthCookieFile()); + } } catch (const fs::filesystem_error& e) { LogPrintf("%s: Unable to remove random auth cookie file: %s\n", __func__, fsbridge::get_filesystem_error_message(e)); } diff --git a/src/rpc/util.cpp b/src/rpc/util.cpp index 9aae2d7e0c963..9d070409a46e8 100644 --- a/src/rpc/util.cpp +++ b/src/rpc/util.cpp @@ -725,7 +725,7 @@ void RPCResult::ToSections(Sections& sections, const OuterType outer_type, const // Elements in a JSON structure (dictionary or array) are separated by a comma const std::string maybe_separator{outer_type != OuterType::NONE ? "," : ""}; - // The key name if recursed into an dictionary + // The key name if recursed into a dictionary const std::string maybe_key{ outer_type == OuterType::OBJ ? "\"" + this->m_key_name + "\" : " : @@ -816,10 +816,11 @@ void RPCResult::ToSections(Sections& sections, const OuterType outer_type, const bool RPCResult::MatchesType(const UniValue& result) const { - switch (m_type) { - case Type::ELISION: { - return false; + if (m_skip_type_check) { + return true; } + switch (m_type) { + case Type::ELISION: case Type::ANY: { return true; } @@ -840,11 +841,52 @@ bool RPCResult::MatchesType(const UniValue& result) const } case Type::ARR_FIXED: case Type::ARR: { - return UniValue::VARR == result.getType(); + if (UniValue::VARR != result.getType()) return false; + for (size_t i{0}; i < result.get_array().size(); ++i) { + // If there are more results than documented, re-use the last doc_inner. + const RPCResult& doc_inner{m_inner.at(std::min(m_inner.size() - 1, i))}; + if (!doc_inner.MatchesType(result.get_array()[i])) return false; + } + return true; // empty result array is valid } case Type::OBJ_DYN: case Type::OBJ: { - return UniValue::VOBJ == result.getType(); + if (UniValue::VOBJ != result.getType()) return false; + if (!m_inner.empty() && m_inner.at(0).m_type == Type::ELISION) return true; + if (m_type == Type::OBJ_DYN) { + const RPCResult& doc_inner{m_inner.at(0)}; // Assume all types are the same, randomly pick the first + for (size_t i{0}; i < result.get_obj().size(); ++i) { + if (!doc_inner.MatchesType(result.get_obj()[i])) { + return false; + } + } + return true; // empty result obj is valid + } + std::set doc_keys; + for (const auto& doc_entry : m_inner) { + doc_keys.insert(doc_entry.m_key_name); + } + std::map result_obj; + result.getObjMap(result_obj); + for (const auto& result_entry : result_obj) { + if (doc_keys.find(result_entry.first) == doc_keys.end()) { + return false; // missing documentation + } + } + + for (const auto& doc_entry : m_inner) { + const auto result_it{result_obj.find(doc_entry.m_key_name)}; + if (result_it == result_obj.end()) { + if (!doc_entry.m_optional) { + return false; // result is missing a required key + } + continue; + } + if (!doc_entry.MatchesType(result_it->second)) { + return false; // wrong type + } + } + return true; } } // no default case, so the compiler can warn about missing cases NONFATAL_UNREACHABLE(); diff --git a/src/rpc/util.h b/src/rpc/util.h index fe12b4cbaf4fe..cc50c75ddce2c 100644 --- a/src/rpc/util.h +++ b/src/rpc/util.h @@ -266,6 +266,7 @@ struct RPCResult { const std::string m_key_name; //!< Only used for dicts const std::vector m_inner; //!< Only used for arrays or dicts const bool m_optional; + const bool m_skip_type_check; const std::string m_description; const std::string m_cond; @@ -280,6 +281,7 @@ struct RPCResult { m_key_name{std::move(m_key_name)}, m_inner{std::move(inner)}, m_optional{optional}, + m_skip_type_check{false}, m_description{std::move(description)}, m_cond{std::move(cond)} { @@ -300,11 +302,13 @@ struct RPCResult { const std::string m_key_name, const bool optional, const std::string description, - const std::vector inner = {}) + const std::vector inner = {}, + bool skip_type_check = false) : m_type{std::move(type)}, m_key_name{std::move(m_key_name)}, m_inner{std::move(inner)}, m_optional{optional}, + m_skip_type_check{skip_type_check}, m_description{std::move(description)}, m_cond{} { @@ -315,8 +319,9 @@ struct RPCResult { const Type type, const std::string m_key_name, const std::string description, - const std::vector inner = {}) - : RPCResult{type, m_key_name, false, description, inner} {} + const std::vector inner = {}, + bool skip_type_check = false) + : RPCResult{type, m_key_name, false, description, inner, skip_type_check} {} /** Append the sections of the result. */ void ToSections(Sections& sections, OuterType outer_type = OuterType::NONE, const int current_indent = 0) const; diff --git a/src/serialize.h b/src/serialize.h index d0ac4e8f8917a..027f9d87c4349 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -1347,11 +1347,11 @@ struct CSerActionUnserialize class CSizeComputer { protected: - size_t nSize; + size_t nSize{0}; const int nVersion; public: - explicit CSizeComputer(int nVersionIn) : nSize(0), nVersion(nVersionIn) {} + explicit CSizeComputer(int nVersionIn) : nVersion(nVersionIn) {} void write(Span src) { diff --git a/src/span.h b/src/span.h index 6e6b58dbaa0bc..fd9cdbc9eec5f 100644 --- a/src/span.h +++ b/src/span.h @@ -96,7 +96,7 @@ template class Span { C* m_data; - std::size_t m_size; + std::size_t m_size{0}; template struct is_Span_int : public std::false_type {}; @@ -107,7 +107,7 @@ class Span public: - constexpr Span() noexcept : m_data(nullptr), m_size(0) {} + constexpr Span() noexcept : m_data(nullptr) {} /** Construct a span from a begin pointer and a size. * diff --git a/src/spork.cpp b/src/spork.cpp index 9842e44226f63..409efc180910d 100644 --- a/src/spork.cpp +++ b/src/spork.cpp @@ -145,7 +145,7 @@ MessageProcessingResult CSporkManager::ProcessSpork(NodeId from, CDataStream& vR MessageProcessingResult ret{}; ret.m_to_erase = CInv{MSG_SPORK, hash}; - if (spork.nTimeSigned > GetAdjustedTime() + 2 * 60 * 60) { + if (spork.nTimeSigned > TicksSinceEpoch(GetAdjustedTime() + 2 * 60 * 60)) { LogPrint(BCLog::SPORK, "CSporkManager::ProcessSpork -- ERROR: too far into the future\n"); ret.m_error = MisbehavingError{100}; return ret; @@ -207,7 +207,7 @@ void CSporkManager::ProcessGetSporks(CNode& peer, CConnman& connman) std::optional CSporkManager::UpdateSpork(SporkId nSporkID, SporkValue nValue) { - CSporkMessage spork(nSporkID, nValue, GetAdjustedTime()); + CSporkMessage spork(nSporkID, nValue, TicksSinceEpoch(GetAdjustedTime())); LOCK(cs); @@ -249,7 +249,7 @@ bool CSporkManager::IsSporkActive(SporkId nSporkID) const SporkValue nSporkValue = GetSporkValue(nSporkID); // Get time is somewhat costly it looks like - bool ret = nSporkValue < GetAdjustedTime(); + bool ret = nSporkValue < TicksSinceEpoch(GetAdjustedTime()); // Only cache true values if (ret) { LOCK(cs_cache); diff --git a/src/streams.h b/src/streams.h index 9790914f47cde..150c420c789bb 100644 --- a/src/streams.h +++ b/src/streams.h @@ -624,8 +624,8 @@ class CBufferedFile const int nVersion; FILE *src; //!< source file - uint64_t nSrcPos; //!< how many bytes have been read from source - uint64_t m_read_pos; //!< how many bytes have been read from this + uint64_t nSrcPos{0}; //!< how many bytes have been read from source + uint64_t m_read_pos{0}; //!< how many bytes have been read from this uint64_t nReadLimit; //!< up to which position we're allowed to read uint64_t nRewind; //!< how many bytes we guarantee to rewind std::vector vchBuf; //!< the buffer @@ -671,7 +671,7 @@ class CBufferedFile public: CBufferedFile(FILE* fileIn, uint64_t nBufSize, uint64_t nRewindIn, int nTypeIn, int nVersionIn) - : nType(nTypeIn), nVersion(nVersionIn), nSrcPos(0), m_read_pos(0), nReadLimit(std::numeric_limits::max()), nRewind(nRewindIn), vchBuf(nBufSize, std::byte{0}) + : nType(nTypeIn), nVersion(nVersionIn), nReadLimit(std::numeric_limits::max()), nRewind(nRewindIn), vchBuf(nBufSize, std::byte{0}) { if (nRewindIn >= nBufSize) throw std::ios_base::failure("Rewind limit must be less than buffer size"); diff --git a/src/support/lockedpool.cpp b/src/support/lockedpool.cpp index 5682211630a31..6c3aaa9f04fae 100644 --- a/src/support/lockedpool.cpp +++ b/src/support/lockedpool.cpp @@ -281,8 +281,8 @@ size_t PosixLockedPageAllocator::GetLimit() /*******************************************************************************/ // Implementation: LockedPool -LockedPool::LockedPool(std::unique_ptr allocator_in, LockingFailed_Callback lf_cb_in): - allocator(std::move(allocator_in)), lf_cb(lf_cb_in), cumulative_bytes_locked(0) +LockedPool::LockedPool(std::unique_ptr allocator_in, LockingFailed_Callback lf_cb_in) + : allocator(std::move(allocator_in)), lf_cb(lf_cb_in) { } diff --git a/src/support/lockedpool.h b/src/support/lockedpool.h index 794e51cc6baa4..81e0df513a33b 100644 --- a/src/support/lockedpool.h +++ b/src/support/lockedpool.h @@ -198,7 +198,7 @@ class LockedPool std::list arenas; LockingFailed_Callback lf_cb; - size_t cumulative_bytes_locked; + size_t cumulative_bytes_locked{0}; /** Mutex protects access to this pool's data structures, including arenas. */ mutable std::mutex mutex; diff --git a/src/test/coinjoin_basemanager_tests.cpp b/src/test/coinjoin_basemanager_tests.cpp index 5e4bd4b0e1a00..3a5ade54e8064 100644 --- a/src/test/coinjoin_basemanager_tests.cpp +++ b/src/test/coinjoin_basemanager_tests.cpp @@ -43,7 +43,7 @@ BOOST_AUTO_TEST_CASE(checkqueue_removes_timeouts) { TestBaseManager man; const int denom = CoinJoin::AmountToDenomination(CoinJoin::GetSmallestDenomination()); - const int64_t now = GetAdjustedTime(); + const int64_t now = TicksSinceEpoch(GetAdjustedTime()); // Non-expired man.PushQueue(MakeQueue(denom, now, false, COutPoint(uint256S("11"), 0))); // Expired (too old) @@ -59,7 +59,7 @@ BOOST_AUTO_TEST_CASE(getqueueitem_marks_tried_once) { TestBaseManager man; const int denom = CoinJoin::AmountToDenomination(CoinJoin::GetSmallestDenomination()); - const int64_t now = GetAdjustedTime(); + const int64_t now = TicksSinceEpoch(GetAdjustedTime()); CCoinJoinQueue dsq = MakeQueue(denom, now, false, COutPoint(uint256S("21"), 0)); man.PushQueue(dsq); diff --git a/src/test/coinjoin_inouts_tests.cpp b/src/test/coinjoin_inouts_tests.cpp index 94bbedc3caa8b..dbdcd4bd23b00 100644 --- a/src/test/coinjoin_inouts_tests.cpp +++ b/src/test/coinjoin_inouts_tests.cpp @@ -90,7 +90,7 @@ BOOST_AUTO_TEST_CASE(queue_timeout_bounds) CCoinJoinQueue dsq; dsq.nDenom = CoinJoin::AmountToDenomination(CoinJoin::GetSmallestDenomination()); dsq.m_protxHash = uint256::ONE; - dsq.nTime = GetAdjustedTime(); + dsq.nTime = TicksSinceEpoch(GetAdjustedTime()); // current time -> not out of bounds BOOST_CHECK(!dsq.IsTimeOutOfBounds()); @@ -100,7 +100,7 @@ BOOST_AUTO_TEST_CASE(queue_timeout_bounds) // Too far in the future SetMockTime(GetTime() - 2 * (COINJOIN_QUEUE_TIMEOUT + 1)); // move back to anchor baseline - dsq.nTime = GetAdjustedTime() + (COINJOIN_QUEUE_TIMEOUT + 1); + dsq.nTime = TicksSinceEpoch(GetAdjustedTime()) + (COINJOIN_QUEUE_TIMEOUT + 1); BOOST_CHECK(dsq.IsTimeOutOfBounds()); // Reset mock time diff --git a/src/test/coinjoin_queue_tests.cpp b/src/test/coinjoin_queue_tests.cpp index fda668146477c..45ed59b6e6dd2 100644 --- a/src/test/coinjoin_queue_tests.cpp +++ b/src/test/coinjoin_queue_tests.cpp @@ -30,7 +30,7 @@ BOOST_AUTO_TEST_CASE(queue_sign_and_verify) q.nDenom = CoinJoin::AmountToDenomination(CoinJoin::GetSmallestDenomination()); q.masternodeOutpoint = COutPoint(uint256S("aa"), 1); q.m_protxHash = uint256::ONE; - q.nTime = GetAdjustedTime(); + q.nTime = TicksSinceEpoch(GetAdjustedTime()); q.fReady = false; // Sign and verify with corresponding pubkey @@ -45,7 +45,7 @@ BOOST_AUTO_TEST_CASE(queue_hashes_and_equality) a.nDenom = b.nDenom = CoinJoin::AmountToDenomination(CoinJoin::GetSmallestDenomination()); a.masternodeOutpoint = b.masternodeOutpoint = COutPoint(uint256S("bb"), 2); a.m_protxHash = b.m_protxHash = uint256::ONE; - a.nTime = b.nTime = GetAdjustedTime(); + a.nTime = b.nTime = TicksSinceEpoch(GetAdjustedTime()); a.fReady = b.fReady = true; BOOST_CHECK(a == b); @@ -72,7 +72,7 @@ BOOST_AUTO_TEST_CASE(queue_timestamp_validation) q.masternodeOutpoint = COutPoint(uint256S("cc"), 3); q.m_protxHash = uint256::ONE; - int64_t current_time = GetAdjustedTime(); + int64_t current_time = TicksSinceEpoch(GetAdjustedTime()); // Test valid timestamp (current time) q.nTime = current_time; diff --git a/src/test/util/net.h b/src/test/util/net.h index a52a3ec753d10..fbe8b7d6e00a9 100644 --- a/src/test/util/net.h +++ b/src/test/util/net.h @@ -133,7 +133,7 @@ constexpr auto ALL_NETWORKS = std::array{ class StaticContentsSock : public Sock { public: - explicit StaticContentsSock(const std::string& contents) : m_contents{contents}, m_consumed{0} + explicit StaticContentsSock(const std::string& contents) : m_contents{contents} { // Just a dummy number that is not INVALID_SOCKET. m_socket = INVALID_SOCKET - 1; @@ -224,7 +224,7 @@ class StaticContentsSock : public Sock private: const std::string m_contents; - mutable size_t m_consumed; + mutable size_t m_consumed{0}; }; std::vector GetRandomNodeEvictionCandidates(int n_candidates, FastRandomContext& random_context); diff --git a/src/timedata.cpp b/src/timedata.cpp index ceee08e68c4ef..fe9a5fbed7fc9 100644 --- a/src/timedata.cpp +++ b/src/timedata.cpp @@ -32,9 +32,9 @@ int64_t GetTimeOffset() return nTimeOffset; } -int64_t GetAdjustedTime() +NodeClock::time_point GetAdjustedTime() { - return GetTime() + GetTimeOffset(); + return NodeClock::now() + std::chrono::seconds{GetTimeOffset()}; } #define BITCOIN_TIMEDATA_MAX_SAMPLES 200 diff --git a/src/timedata.h b/src/timedata.h index 3779486c1f880..fae4d60b3b9ad 100644 --- a/src/timedata.h +++ b/src/timedata.h @@ -75,7 +75,7 @@ class CMedianFilter /** Functions to keep track of adjusted P2P time */ int64_t GetTimeOffset(); -int64_t GetAdjustedTime(); +NodeClock::time_point GetAdjustedTime(); void AddTimeData(const CNetAddr& ip, int64_t nTime); /** diff --git a/src/tinyformat.h b/src/tinyformat.h index 3d128a98929c3..d4cf079286797 100644 --- a/src/tinyformat.h +++ b/src/tinyformat.h @@ -508,9 +508,6 @@ class FormatArg { public: FormatArg() - : m_value(nullptr), - m_formatImpl(nullptr), - m_toIntImpl(nullptr) { } template @@ -549,10 +546,10 @@ class FormatArg return convertToInt::invoke(*static_cast(value)); } - const void* m_value; + const void* m_value{nullptr}; void (*m_formatImpl)(std::ostream& out, const char* fmtBegin, - const char* fmtEnd, int ntrunc, const void* value); - int (*m_toIntImpl)(const void* value); + const char* fmtEnd, int ntrunc, const void* value){nullptr}; + int (*m_toIntImpl)(const void* value){nullptr}; }; diff --git a/src/torcontrol.cpp b/src/torcontrol.cpp index 67958c521596f..018864a1018ba 100644 --- a/src/torcontrol.cpp +++ b/src/torcontrol.cpp @@ -63,8 +63,8 @@ static const uint16_t DEFAULT_TOR_SOCKS_PORT = 9050; /****** Low-level TorControlConnection ********/ -TorControlConnection::TorControlConnection(struct event_base *_base): - base(_base), b_conn(nullptr) +TorControlConnection::TorControlConnection(struct event_base* _base) + : base(_base) { } diff --git a/src/torcontrol.h b/src/torcontrol.h index f97dcd82ef4f5..afc18a1b3fc0e 100644 --- a/src/torcontrol.h +++ b/src/torcontrol.h @@ -86,7 +86,7 @@ class TorControlConnection /** Libevent event base */ struct event_base *base; /** Connection to control socket */ - struct bufferevent *b_conn; + struct bufferevent* b_conn{nullptr}; /** Message being received */ TorControlReply message; /** Response handlers */ diff --git a/src/univalue/include/univalue_utffilter.h b/src/univalue/include/univalue_utffilter.h index f688eaaa30f97..41d8e6bb05f7c 100644 --- a/src/univalue/include/univalue_utffilter.h +++ b/src/univalue/include/univalue_utffilter.h @@ -13,8 +13,8 @@ class JSONUTF8StringFilter { public: - explicit JSONUTF8StringFilter(std::string &s): - str(s), is_valid(true), codepoint(0), state(0), surpair(0) + explicit JSONUTF8StringFilter(std::string& s) + : str(s) { } // Write single 8-bit char (may be part of UTF-8 sequence) @@ -79,10 +79,10 @@ class JSONUTF8StringFilter } private: std::string &str; - bool is_valid; + bool is_valid{true}; // Current UTF-8 decoding state - unsigned int codepoint; - int state; // Top bit to be filled in for next UTF-8 byte, or 0 + unsigned int codepoint{0}; + int state{0}; // Top bit to be filled in for next UTF-8 byte, or 0 // Keep track of the following state to handle the following section of // RFC4627: @@ -94,7 +94,7 @@ class JSONUTF8StringFilter // "\uD834\uDD1E". // // Two subsequent \u.... may have to be replaced with one actual codepoint. - unsigned int surpair; // First half of open UTF-16 surrogate pair, or 0 + unsigned int surpair{0}; // First half of open UTF-16 surrogate pair, or 0 void append_codepoint(unsigned int codepoint_) { diff --git a/src/util/sock.h b/src/util/sock.h index cae0437f4bc14..4e7e85ccb83d3 100644 --- a/src/util/sock.h +++ b/src/util/sock.h @@ -284,9 +284,9 @@ class Sock * Auxiliary requested/occurred events to wait for in `WaitMany()`. */ struct Events { - explicit Events(Event req, Event ocr = 0) : requested{req}, occurred{ocr} {} + explicit Events(Event req, Event ocr = 0) : requested{req} {} Event requested; - Event occurred; + Event occurred{0}; }; /** diff --git a/src/validation.cpp b/src/validation.cpp index 7686968416c23..6229c6a196813 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -4055,7 +4055,7 @@ bool CheckBlock(const CBlock& block, BlockValidationState& state, const Consensu * in ConnectBlock(). * Note that -reindex-chainstate skips the validation that happens here! */ -static bool ContextualCheckBlockHeader(const CBlockHeader& block, BlockValidationState& state, BlockManager& blockman, const CChainParams& params, const CBlockIndex* pindexPrev, int64_t nAdjustedTime) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) +static bool ContextualCheckBlockHeader(const CBlockHeader& block, BlockValidationState& state, BlockManager& blockman, const CChainParams& params, const CBlockIndex* pindexPrev, NodeClock::time_point now) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) { AssertLockHeld(::cs_main); assert(pindexPrev != nullptr); @@ -4095,9 +4095,9 @@ static bool ContextualCheckBlockHeader(const CBlockHeader& block, BlockValidatio return state.Invalid(BlockValidationResult::BLOCK_INVALID_HEADER, "time-too-old", strprintf("block's timestamp is too early %d %d", block.GetBlockTime(), pindexPrev->GetMedianTimePast())); // Check timestamp - if (block.GetBlockTime() > nAdjustedTime + MAX_FUTURE_BLOCK_TIME) + if (block.Time() > now + std::chrono::seconds{MAX_FUTURE_BLOCK_TIME}) { return state.Invalid(BlockValidationResult::BLOCK_TIME_FUTURE, "time-too-new", strprintf("block timestamp too far in the future %d %d", block.GetBlockTime(), nAdjustedTime + 2 * 60 * 60)); - + } // Reject blocks with outdated version if ((block.nVersion < 2 && DeploymentActiveAfter(pindexPrev, consensusParams, Consensus::DEPLOYMENT_HEIGHTINCB)) || (block.nVersion < 3 && DeploymentActiveAfter(pindexPrev, consensusParams, Consensus::DEPLOYMENT_DERSIG)) || @@ -4234,7 +4234,7 @@ bool ChainstateManager::AcceptBlockHeader(const CBlockHeader& block, BlockValida return state.Invalid(BlockValidationResult::BLOCK_CHAINLOCK, "bad-prevblk-chainlock"); } - if (!ContextualCheckBlockHeader(block, state, m_blockman, chainparams, pindexPrev, GetAdjustedTime())) { + if (!ContextualCheckBlockHeader(block, state, m_blockman, chainparams, pindexPrev, TicksSinceEpoch(GetAdjustedTime()))) { LogPrint(BCLog::VALIDATION, "%s: Consensus::ContextualCheckBlockHeader: %s, %s\n", __func__, hash.ToString(), state.ToString()); return false; } @@ -4522,7 +4522,7 @@ bool TestBlockValidity(BlockValidationState& state, auto dbTx = evoDb.BeginTransaction(); // NOTE: CheckBlockHeader is called by CheckBlock - if (!ContextualCheckBlockHeader(block, state, chainstate.m_blockman, chainparams, pindexPrev, GetAdjustedTime())) + if (!ContextualCheckBlockHeader(block, state, chainstate.m_blockman, chainparams, pindexPrev, TicksSinceEpoch(GetAdjustedTime()))) return error("%s: Consensus::ContextualCheckBlockHeader: %s", __func__, state.ToString()); if (!CheckBlock(block, state, chainparams.GetConsensus(), fCheckPOW, fCheckMerkleRoot)) return error("%s: Consensus::CheckBlock: %s", __func__, state.ToString()); diff --git a/src/wallet/bdb.cpp b/src/wallet/bdb.cpp index c5c3870fd6fa1..8eea1ddbbb29b 100644 --- a/src/wallet/bdb.cpp +++ b/src/wallet/bdb.cpp @@ -318,7 +318,7 @@ BerkeleyDatabase::~BerkeleyDatabase() } } -BerkeleyBatch::BerkeleyBatch(BerkeleyDatabase& database, const bool read_only, bool fFlushOnCloseIn) : pdb(nullptr), activeTxn(nullptr), m_cursor(nullptr), m_database(database) +BerkeleyBatch::BerkeleyBatch(BerkeleyDatabase& database, const bool read_only, bool fFlushOnCloseIn) : m_cursor(nullptr), m_database(database) { database.AddRef(); database.Open(); diff --git a/src/wallet/bdb.h b/src/wallet/bdb.h index 1d5f21e88d234..9ce1312871381 100644 --- a/src/wallet/bdb.h +++ b/src/wallet/bdb.h @@ -189,9 +189,9 @@ class BerkeleyBatch : public DatabaseBatch bool HasKey(CDataStream&& key) override; protected: - Db* pdb; + Db* pdb{nullptr}; std::string strFile; - DbTxn* activeTxn; + DbTxn* activeTxn{nullptr}; Dbc* m_cursor; bool fReadOnly; bool fFlushOnClose; diff --git a/src/wallet/db.h b/src/wallet/db.h index dba86c8a90bd4..a7533c7ca532a 100644 --- a/src/wallet/db.h +++ b/src/wallet/db.h @@ -106,7 +106,7 @@ class WalletDatabase { public: /** Create dummy DB handle */ - WalletDatabase() : nUpdateCounter(0), nLastSeen(0), nLastFlushed(0), nLastWalletUpdate(0) {} + WalletDatabase() : nUpdateCounter(0) {} virtual ~WalletDatabase() {}; /** Open the database if it is not already opened. */ @@ -148,9 +148,9 @@ class WalletDatabase virtual std::string Format() = 0; std::atomic nUpdateCounter; - unsigned int nLastSeen; - unsigned int nLastFlushed; - int64_t nLastWalletUpdate; + unsigned int nLastSeen{0}; + unsigned int nLastFlushed{0}; + int64_t nLastWalletUpdate{0}; /** Make a DatabaseBatch connected to this database */ virtual std::unique_ptr MakeBatch(bool flush_on_close = true) = 0; diff --git a/src/wallet/init.cpp b/src/wallet/init.cpp index 444e066b00216..e1be2e7eefb68 100644 --- a/src/wallet/init.cpp +++ b/src/wallet/init.cpp @@ -125,8 +125,6 @@ void WalletInit::AddWalletOptions(ArgsManager& argsman) const argsman.AddArg("-walletrejectlongchains", strprintf("Wallet will not create transactions that violate mempool chain limits (default: %u)", DEFAULT_WALLET_REJECT_LONG_CHAINS), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::WALLET_DEBUG_TEST); argsman.AddArg("-walletcrosschain", strprintf("Allow reusing wallet files across chains (default: %u)", DEFAULT_WALLETCROSSCHAIN), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::WALLET_DEBUG_TEST); - - argsman.AddHiddenArgs({"-zapwallettxes"}); } bool WalletInit::ParameterInteraction() const @@ -150,10 +148,6 @@ bool WalletInit::ParameterInteraction() const LogPrintf("%s: parameter interaction: -blocksonly=1 -> setting -walletbroadcast=0\n", __func__); } - if (gArgs.IsArgSet("-zapwallettxes")) { - return InitError(Untranslated("-zapwallettxes has been removed. If you are attempting to remove a stuck transaction from your wallet, please use abandontransaction instead.")); - } - int rescan_mode = gArgs.GetIntArg("-rescan", 0); if (rescan_mode < 0 || rescan_mode > 2) { LogPrintf("%s: Warning: incorrect -rescan mode, falling back to default value.\n", __func__); diff --git a/src/wallet/rpc/wallet.cpp b/src/wallet/rpc/wallet.cpp index 2da9377513026..d130f74ae805f 100644 --- a/src/wallet/rpc/wallet.cpp +++ b/src/wallet/rpc/wallet.cpp @@ -189,7 +189,7 @@ static RPCHelpMan getwalletinfo() { {RPCResult::Type::NUM, "duration", "elapsed seconds since scan start"}, {RPCResult::Type::NUM, "progress", "scanning progress percentage [0.0, 1.0]"}, - }}, + }, /*skip_type_check=*/true}, {RPCResult::Type::BOOL, "descriptors", "whether this wallet uses descriptors for scriptPubKey management"}, {RPCResult::Type::BOOL, "external_signer", "whether this wallet is configured to use an external signer such as a hardware wallet"}, RESULT_LAST_PROCESSED_BLOCK, diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index aeaccbf22653f..85fd00c100774 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -1084,10 +1084,10 @@ class WalletRescanReserver using Clock = std::chrono::steady_clock; using NowFn = std::function; CWallet& m_wallet; - bool m_could_reserve; + bool m_could_reserve{false}; NowFn m_now; public: - explicit WalletRescanReserver(CWallet& w) : m_wallet(w), m_could_reserve(false) {} + explicit WalletRescanReserver(CWallet& w) : m_wallet(w) {} bool reserve() { diff --git a/src/zmq/zmqabstractnotifier.h b/src/zmq/zmqabstractnotifier.h index 2f115b93d001f..725a98fe8fb3c 100644 --- a/src/zmq/zmqabstractnotifier.h +++ b/src/zmq/zmqabstractnotifier.h @@ -35,7 +35,7 @@ class CZMQAbstractNotifier public: static const int DEFAULT_ZMQ_SNDHWM {1000}; - CZMQAbstractNotifier() : psocket(nullptr), outbound_message_high_water_mark(DEFAULT_ZMQ_SNDHWM) { } + CZMQAbstractNotifier() : outbound_message_high_water_mark(DEFAULT_ZMQ_SNDHWM) {} virtual ~CZMQAbstractNotifier(); template @@ -78,7 +78,7 @@ class CZMQAbstractNotifier virtual bool NotifyRecoveredSig(const std::shared_ptr& sig); protected: - void *psocket; + void* psocket{nullptr}; std::string type; std::string address; int outbound_message_high_water_mark; // aka SNDHWM diff --git a/src/zmq/zmqnotificationinterface.cpp b/src/zmq/zmqnotificationinterface.cpp index 423089ed1d945..f0169a05ca5e9 100644 --- a/src/zmq/zmqnotificationinterface.cpp +++ b/src/zmq/zmqnotificationinterface.cpp @@ -16,13 +16,7 @@ #include -#include -#include -#include -#include -#include - -CZMQNotificationInterface::CZMQNotificationInterface() : pcontext(nullptr) +CZMQNotificationInterface::CZMQNotificationInterface() { } diff --git a/src/zmq/zmqnotificationinterface.h b/src/zmq/zmqnotificationinterface.h index 1151941aec512..bfc5b0b4680c2 100644 --- a/src/zmq/zmqnotificationinterface.h +++ b/src/zmq/zmqnotificationinterface.h @@ -45,7 +45,7 @@ class CZMQNotificationInterface final : public CValidationInterface private: CZMQNotificationInterface(); - void *pcontext; + void* pcontext{nullptr}; std::list> notifiers; }; diff --git a/test/functional/feature_filelock.py b/test/functional/feature_filelock.py index 54c5956274f06..404766fba5ba9 100755 --- a/test/functional/feature_filelock.py +++ b/test/functional/feature_filelock.py @@ -28,6 +28,9 @@ def run_test(self): expected_msg = f"Error: Cannot obtain a lock on data directory {datadir}. {self.config['environment']['PACKAGE_NAME']} is probably already running." self.nodes[1].assert_start_raises_init_error(extra_args=[f'-datadir={self.nodes[0].datadir}', '-noserver'], expected_msg=expected_msg) + cookie_file = datadir / ".cookie" + assert cookie_file.exists() # should not be deleted during the second bitcoind instance shutdown + if self.is_wallet_compiled(): def check_wallet_filelock(descriptors): wallet_name = ''.join([random.choice(string.ascii_lowercase) for _ in range(6)]) diff --git a/test/functional/p2p_getaddr_caching.py b/test/functional/p2p_getaddr_caching.py index 58f8040918abe..a5c74cf77a725 100755 --- a/test/functional/p2p_getaddr_caching.py +++ b/test/functional/p2p_getaddr_caching.py @@ -4,7 +4,6 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test addr response caching""" -from test_framework.messages import msg_getaddr from test_framework.p2p import ( P2PInterface, p2p_lock @@ -19,6 +18,7 @@ MAX_ADDR_TO_SEND = 1000 MAX_PCT_ADDR_TO_SEND = 23 + class AddrReceiver(P2PInterface): def __init__(self): @@ -68,11 +68,8 @@ def run_test(self): cur_mock_time = self.mocktime for i in range(N): addr_receiver_local = self.nodes[0].add_p2p_connection(AddrReceiver()) - addr_receiver_local.send_and_ping(msg_getaddr()) addr_receiver_onion1 = self.nodes[0].add_p2p_connection(AddrReceiver(), dstport=self.onion_port1) - addr_receiver_onion1.send_and_ping(msg_getaddr()) addr_receiver_onion2 = self.nodes[0].add_p2p_connection(AddrReceiver(), dstport=self.onion_port2) - addr_receiver_onion2.send_and_ping(msg_getaddr()) # Trigger response cur_mock_time += 5 * 60 @@ -103,11 +100,8 @@ def run_test(self): self.log.info('After time passed, see a new response to addr request') addr_receiver_local = self.nodes[0].add_p2p_connection(AddrReceiver()) - addr_receiver_local.send_and_ping(msg_getaddr()) addr_receiver_onion1 = self.nodes[0].add_p2p_connection(AddrReceiver(), dstport=self.onion_port1) - addr_receiver_onion1.send_and_ping(msg_getaddr()) addr_receiver_onion2 = self.nodes[0].add_p2p_connection(AddrReceiver(), dstport=self.onion_port2) - addr_receiver_onion2.send_and_ping(msg_getaddr()) # Trigger response cur_mock_time += 5 * 60 @@ -121,5 +115,6 @@ def run_test(self): assert(set(last_response_on_onion_bind1) != set(addr_receiver_onion1.get_received_addrs())) assert(set(last_response_on_onion_bind2) != set(addr_receiver_onion2.get_received_addrs())) + if __name__ == '__main__': AddrTest().main() diff --git a/test/functional/p2p_leak_tx.py b/test/functional/p2p_leak_tx.py index df30ab74844da..2d6faccee3870 100755 --- a/test/functional/p2p_leak_tx.py +++ b/test/functional/p2p_leak_tx.py @@ -2,7 +2,7 @@ # Copyright (c) 2017-2020 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. -"""Test that we don't leak txs to inbound peers that we haven't yet announced to""" +"""Test transaction upload""" from test_framework.messages import msg_getdata, CInv, MSG_TX from test_framework.p2p import p2p_lock, P2PDataStore @@ -23,19 +23,40 @@ def set_test_params(self): self.num_nodes = 1 def run_test(self): - gen_node = self.nodes[0] # The block and tx generating node - miniwallet = MiniWallet(gen_node) + self.gen_node = self.nodes[0] # The block and tx generating node + self.miniwallet = MiniWallet(self.gen_node) # Add enough mature utxos to the wallet, so that all txs spend confirmed coins - self.generate(miniwallet, 1) - self.generate(gen_node, 100) + self.generate(self.miniwallet, 1) + self.generate(self.gen_node, 100) - inbound_peer = self.nodes[0].add_p2p_connection(P2PNode()) # An "attacking" inbound peer + self.test_tx_in_block() + self.test_notfound_on_unannounced_tx() + + def test_tx_in_block(self): + self.log.info("Check that a transaction in the last block is uploaded (beneficial for compact block relay)") + inbound_peer = self.gen_node.add_p2p_connection(P2PNode()) + + self.log.debug("Generate transaction and block") + inbound_peer.last_message.pop("inv", None) + wtxid = self.miniwallet.send_self_transfer(from_node=self.gen_node)["wtxid"] + inbound_peer.wait_until(lambda: "inv" in inbound_peer.last_message and inbound_peer.last_message.get("inv").inv[0].hash == int(wtxid, 16)) + want_tx = msg_getdata(inv=inbound_peer.last_message.get("inv").inv) + self.generate(self.gen_node, 1) + + self.log.debug("Request transaction") + inbound_peer.last_message.pop("tx", None) + inbound_peer.send_and_ping(want_tx) + assert_equal(inbound_peer.last_message.get("tx").tx.getwtxid(), wtxid) + + def test_notfound_on_unannounced_tx(self): + self.log.info("Check that we don't leak txs to inbound peers that we haven't yet announced to") + inbound_peer = self.gen_node.add_p2p_connection(P2PNode()) # An "attacking" inbound peer MAX_REPEATS = 100 self.log.info("Running test up to {} times.".format(MAX_REPEATS)) for i in range(MAX_REPEATS): self.log.info('Run repeat {}'.format(i + 1)) - txid = miniwallet.send_self_transfer(from_node=gen_node)['txid'] + txid = self.miniwallet.send_self_transfer(from_node=self.gen_node)['txid'] want_tx = msg_getdata() want_tx.inv.append(CInv(t=MSG_TX, h=int(txid, 16))) diff --git a/test/functional/test_framework/test_node.py b/test/functional/test_framework/test_node.py index a93a05ffb66a4..59499548b56ad 100755 --- a/test/functional/test_framework/test_node.py +++ b/test/functional/test_framework/test_node.py @@ -698,10 +698,11 @@ def add_p2p_connection(self, p2p_conn, *, wait_for_verack=True, send_version=Tru p2p_conn.sync_with_ping() # Consistency check that the node received our user agent string. - # Find our connection in getpeerinfo by our address:port, as it is unique. + # Find our connection in getpeerinfo by our address:port and theirs, as this combination is unique. sockname = p2p_conn._transport.get_extra_info("socket").getsockname() our_addr_and_port = f"{sockname[0]}:{sockname[1]}" - info = [peer for peer in self.getpeerinfo() if peer["addr"] == our_addr_and_port] + dst_addr_and_port = f"{p2p_conn.dstaddr}:{p2p_conn.dstport}" + info = [peer for peer in self.getpeerinfo() if peer["addr"] == our_addr_and_port and peer["addrbind"] == dst_addr_and_port] assert_equal(len(info), 1) assert_equal(info[0]["subver"], p2p_conn.strSubVer) diff --git a/test/lint/check-doc.py b/test/lint/check-doc.py index 7955dd4f3e65c..dd7cb0306eb08 100755 --- a/test/lint/check-doc.py +++ b/test/lint/check-doc.py @@ -23,7 +23,7 @@ CMD_GREP_WALLET_HIDDEN_ARGS = r"git grep --function-context 'void DummyWalletInit::AddWalletOptions' -- {}".format(CMD_ROOT_DIR) CMD_GREP_DOCS = r"git grep --perl-regexp '{}' {}".format(REGEX_DOC, CMD_ROOT_DIR) # list unsupported, deprecated and duplicate args as they need no documentation -SET_DOC_OPTIONAL = set(['-h', '-help', '-dbcrashratio', '-forcecompactdb', '-zapwallettxes']) +SET_DOC_OPTIONAL = set(['-h', '-help', '-dbcrashratio', '-forcecompactdb']) def lint_missing_argument_documentation():