mirror of
https://github.com/dashpay/dash.git
synced 2024-12-25 03:52:49 +01:00
Merge pull request #5163 from kittywhiskers/mempool_deglob
backport: merge bitcoin#20222, #18766, #14033, #19486, #19607, #20291, partial #20187, #20228 (deglobalize addrman and feeEstimator)
This commit is contained in:
commit
7e57ae6956
@ -268,7 +268,17 @@ protected:
|
||||
//! Select several addresses at once.
|
||||
void GetAddr_(std::vector<CAddress> &vAddr) EXCLUSIVE_LOCKS_REQUIRED(cs);
|
||||
|
||||
//! Mark an entry as currently-connected-to.
|
||||
/** We have successfully connected to this peer. Calling this function
|
||||
* updates the CAddress's nTime, which is used in our IsTerrible()
|
||||
* decisions and gossiped to peers. Callers should be careful that updating
|
||||
* this information doesn't leak topology information to network spies.
|
||||
*
|
||||
* net_processing calls this function when it *disconnects* from a peer to
|
||||
* not leak information about currently connected peers.
|
||||
*
|
||||
* @param[in] addr The address of the peer we were connected to
|
||||
* @param[in] nTime The time that we were last connected to this peer
|
||||
*/
|
||||
void Connected_(const CService& addr, int64_t nTime) EXCLUSIVE_LOCKS_REQUIRED(cs);
|
||||
|
||||
//! Update an entry's service bits.
|
||||
@ -710,7 +720,7 @@ public:
|
||||
return vAddr;
|
||||
}
|
||||
|
||||
//! Mark an entry as currently-connected-to.
|
||||
//! Outer function for Connected_()
|
||||
void Connected(const CService &addr, int64_t nTime = GetAdjustedTime())
|
||||
{
|
||||
LOCK(cs);
|
||||
|
@ -54,7 +54,6 @@ void CCoinJoinClientQueueManager::ProcessDSQueue(const CNode& peer, CDataStream&
|
||||
vRecv >> dsq;
|
||||
|
||||
if (dsq.masternodeOutpoint.IsNull() && dsq.m_protxHash.IsNull()) {
|
||||
LOCK(cs_main);
|
||||
Misbehaving(peer.GetId(), 100);
|
||||
return;
|
||||
}
|
||||
@ -64,7 +63,6 @@ void CCoinJoinClientQueueManager::ProcessDSQueue(const CNode& peer, CDataStream&
|
||||
if (auto dmn = mnList.GetValidMN(dsq.m_protxHash)) {
|
||||
dsq.masternodeOutpoint = dmn->collateralOutpoint;
|
||||
} else {
|
||||
LOCK(cs_main);
|
||||
Misbehaving(peer.GetId(), 10);
|
||||
return;
|
||||
}
|
||||
@ -100,7 +98,6 @@ void CCoinJoinClientQueueManager::ProcessDSQueue(const CNode& peer, CDataStream&
|
||||
}
|
||||
|
||||
if (!dsq.CheckSignature(dmn->pdmnState->pubKeyOperator.Get())) {
|
||||
LOCK(cs_main);
|
||||
Misbehaving(peer.GetId(), 10);
|
||||
return;
|
||||
}
|
||||
@ -756,7 +753,7 @@ bool CCoinJoinClientManager::CheckAutomaticBackup()
|
||||
//
|
||||
// Passively run mixing in the background to mix funds based on the given configuration.
|
||||
//
|
||||
bool CCoinJoinClientSession::DoAutomaticDenominating(CTxMemPool& mempool, CConnman& connman, bool fDryRun)
|
||||
bool CCoinJoinClientSession::DoAutomaticDenominating(CConnman& connman, CBlockPolicyEstimator& fee_estimator, CTxMemPool& mempool, bool fDryRun)
|
||||
{
|
||||
if (fMasternodeMode) return false; // no client-side mixing on masternodes
|
||||
if (nState != POOL_STATE_IDLE) return false;
|
||||
@ -875,12 +872,12 @@ bool CCoinJoinClientSession::DoAutomaticDenominating(CTxMemPool& mempool, CConnm
|
||||
// there are funds to denominate and denominated balance does not exceed
|
||||
// max amount to mix yet.
|
||||
if (nBalanceAnonimizableNonDenom >= nValueMin + CCoinJoin::GetCollateralAmount() && nBalanceToDenominate > 0) {
|
||||
CreateDenominated(nBalanceToDenominate);
|
||||
CreateDenominated(fee_estimator, nBalanceToDenominate);
|
||||
}
|
||||
|
||||
//check if we have the collateral sized inputs
|
||||
if (!mixingWallet.HasCollateralInputs()) {
|
||||
return !mixingWallet.HasCollateralInputs(false) && MakeCollateralAmounts();
|
||||
return !mixingWallet.HasCollateralInputs(false) && MakeCollateralAmounts(fee_estimator);
|
||||
}
|
||||
|
||||
if (nSessionID) {
|
||||
@ -936,7 +933,7 @@ bool CCoinJoinClientSession::DoAutomaticDenominating(CTxMemPool& mempool, CConnm
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CCoinJoinClientManager::DoAutomaticDenominating(CTxMemPool& mempool, CConnman& connman, bool fDryRun)
|
||||
bool CCoinJoinClientManager::DoAutomaticDenominating(CConnman& connman, CBlockPolicyEstimator& fee_estimator, CTxMemPool& mempool, bool fDryRun)
|
||||
{
|
||||
if (fMasternodeMode) return false; // no client-side mixing on masternodes
|
||||
if (!CCoinJoinClientOptions::IsEnabled() || !IsMixing()) return false;
|
||||
@ -978,7 +975,7 @@ bool CCoinJoinClientManager::DoAutomaticDenominating(CTxMemPool& mempool, CConnm
|
||||
return false;
|
||||
}
|
||||
|
||||
fResult &= session.DoAutomaticDenominating(mempool, connman, fDryRun);
|
||||
fResult &= session.DoAutomaticDenominating(connman, fee_estimator, mempool, fDryRun);
|
||||
}
|
||||
|
||||
return fResult;
|
||||
@ -1372,7 +1369,7 @@ bool CCoinJoinClientSession::PrepareDenominate(int nMinRounds, int nMaxRounds, s
|
||||
}
|
||||
|
||||
// Create collaterals by looping through inputs grouped by addresses
|
||||
bool CCoinJoinClientSession::MakeCollateralAmounts()
|
||||
bool CCoinJoinClientSession::MakeCollateralAmounts(const CBlockPolicyEstimator& fee_estimator)
|
||||
{
|
||||
if (!CCoinJoinClientOptions::IsEnabled()) return false;
|
||||
|
||||
@ -1395,13 +1392,13 @@ bool CCoinJoinClientSession::MakeCollateralAmounts()
|
||||
|
||||
// First try to use only non-denominated funds
|
||||
for (const auto& item : vecTally) {
|
||||
if (!MakeCollateralAmounts(item, false)) continue;
|
||||
if (!MakeCollateralAmounts(fee_estimator, item, false)) continue;
|
||||
return true;
|
||||
}
|
||||
|
||||
// There should be at least some denominated funds we should be able to break in pieces to continue mixing
|
||||
for (const auto& item : vecTally) {
|
||||
if (!MakeCollateralAmounts(item, true)) continue;
|
||||
if (!MakeCollateralAmounts(fee_estimator, item, true)) continue;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1411,7 +1408,7 @@ bool CCoinJoinClientSession::MakeCollateralAmounts()
|
||||
}
|
||||
|
||||
// Split up large inputs or create fee sized inputs
|
||||
bool CCoinJoinClientSession::MakeCollateralAmounts(const CompactTallyItem& tallyItem, bool fTryDenominated)
|
||||
bool CCoinJoinClientSession::MakeCollateralAmounts(const CBlockPolicyEstimator& fee_estimator, const CompactTallyItem& tallyItem, bool fTryDenominated)
|
||||
{
|
||||
AssertLockHeld(mixingWallet.cs_wallet);
|
||||
|
||||
@ -1434,7 +1431,7 @@ bool CCoinJoinClientSession::MakeCollateralAmounts(const CompactTallyItem& tally
|
||||
return false;
|
||||
}
|
||||
|
||||
CTransactionBuilder txBuilder(pwallet, tallyItem);
|
||||
CTransactionBuilder txBuilder(pwallet, tallyItem, fee_estimator);
|
||||
|
||||
LogPrint(BCLog::COINJOIN, "CCoinJoinClientSession::%s -- Start %s\n", __func__, txBuilder.ToString());
|
||||
|
||||
@ -1553,7 +1550,7 @@ bool CCoinJoinClientSession::CreateCollateralTransaction(CMutableTransaction& tx
|
||||
}
|
||||
|
||||
// Create denominations by looping through inputs grouped by addresses
|
||||
bool CCoinJoinClientSession::CreateDenominated(CAmount nBalanceToDenominate)
|
||||
bool CCoinJoinClientSession::CreateDenominated(CBlockPolicyEstimator& fee_estimator, CAmount nBalanceToDenominate)
|
||||
{
|
||||
if (!CCoinJoinClientOptions::IsEnabled()) return false;
|
||||
|
||||
@ -1577,7 +1574,7 @@ bool CCoinJoinClientSession::CreateDenominated(CAmount nBalanceToDenominate)
|
||||
bool fCreateMixingCollaterals = !mixingWallet.HasCollateralInputs();
|
||||
|
||||
for (const auto& item : vecTally) {
|
||||
if (!CreateDenominated(nBalanceToDenominate, item, fCreateMixingCollaterals)) continue;
|
||||
if (!CreateDenominated(fee_estimator, nBalanceToDenominate, item, fCreateMixingCollaterals)) continue;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1586,7 +1583,7 @@ bool CCoinJoinClientSession::CreateDenominated(CAmount nBalanceToDenominate)
|
||||
}
|
||||
|
||||
// Create denominations
|
||||
bool CCoinJoinClientSession::CreateDenominated(CAmount nBalanceToDenominate, const CompactTallyItem& tallyItem, bool fCreateMixingCollaterals)
|
||||
bool CCoinJoinClientSession::CreateDenominated(CBlockPolicyEstimator& fee_estimator, CAmount nBalanceToDenominate, const CompactTallyItem& tallyItem, bool fCreateMixingCollaterals)
|
||||
{
|
||||
AssertLockHeld(mixingWallet.cs_wallet);
|
||||
|
||||
@ -1604,7 +1601,7 @@ bool CCoinJoinClientSession::CreateDenominated(CAmount nBalanceToDenominate, con
|
||||
return false;
|
||||
}
|
||||
|
||||
CTransactionBuilder txBuilder(pwallet, tallyItem);
|
||||
CTransactionBuilder txBuilder(pwallet, tallyItem, fee_estimator);
|
||||
|
||||
LogPrint(BCLog::COINJOIN, "CCoinJoinClientSession::%s -- Start %s\n", __func__, txBuilder.ToString());
|
||||
|
||||
@ -1815,7 +1812,7 @@ void CCoinJoinClientQueueManager::DoMaintenance()
|
||||
CheckQueue();
|
||||
}
|
||||
|
||||
void CCoinJoinClientManager::DoMaintenance(CTxMemPool& mempool, CConnman& connman)
|
||||
void CCoinJoinClientManager::DoMaintenance(CConnman& connman, CBlockPolicyEstimator& fee_estimator, CTxMemPool& mempool)
|
||||
{
|
||||
if (!CCoinJoinClientOptions::IsEnabled()) return;
|
||||
if (m_mn_sync == nullptr) return;
|
||||
@ -1830,7 +1827,7 @@ void CCoinJoinClientManager::DoMaintenance(CTxMemPool& mempool, CConnman& connma
|
||||
CheckTimeout();
|
||||
ProcessPendingDsaRequest(connman);
|
||||
if (nDoAutoNextRun == nTick) {
|
||||
DoAutomaticDenominating(mempool, connman);
|
||||
DoAutomaticDenominating(connman, fee_estimator, mempool);
|
||||
nDoAutoNextRun = nTick + COINJOIN_AUTO_TIMEOUT_MIN + GetRandInt(COINJOIN_AUTO_TIMEOUT_MAX - COINJOIN_AUTO_TIMEOUT_MIN);
|
||||
}
|
||||
}
|
||||
@ -1867,14 +1864,13 @@ void CCoinJoinClientManager::GetJsonInfo(UniValue& obj) const
|
||||
obj.pushKV("sessions", arrSessions);
|
||||
}
|
||||
|
||||
void DoCoinJoinMaintenance(CTxMemPool& mempool, CConnman& connman)
|
||||
void DoCoinJoinMaintenance(CConnman& connman, CBlockPolicyEstimator& fee_estimator, CTxMemPool& mempool)
|
||||
{
|
||||
if (coinJoinClientQueueManager != nullptr) {
|
||||
coinJoinClientQueueManager->DoMaintenance();
|
||||
}
|
||||
|
||||
for (const auto& pair : coinJoinClientManagers) {
|
||||
pair.second->DoMaintenance(mempool, connman);
|
||||
pair.second->DoMaintenance(connman, fee_estimator, mempool);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,7 @@ using CDeterministicMNCPtr = std::shared_ptr<const CDeterministicMN>;
|
||||
class CCoinJoinClientManager;
|
||||
class CCoinJoinClientQueueManager;
|
||||
|
||||
class CBlockPolicyEstimator;
|
||||
class CConnman;
|
||||
class CNode;
|
||||
class CTxMemPool;
|
||||
@ -88,12 +89,12 @@ private:
|
||||
CWallet& mixingWallet;
|
||||
|
||||
/// Create denominations
|
||||
bool CreateDenominated(CAmount nBalanceToDenominate);
|
||||
bool CreateDenominated(CAmount nBalanceToDenominate, const CompactTallyItem& tallyItem, bool fCreateMixingCollaterals);
|
||||
bool CreateDenominated(CBlockPolicyEstimator& fee_estimator, CAmount nBalanceToDenominate);
|
||||
bool CreateDenominated(CBlockPolicyEstimator& fee_estimator, CAmount nBalanceToDenominate, const CompactTallyItem& tallyItem, bool fCreateMixingCollaterals);
|
||||
|
||||
/// Split up large inputs or make fee sized inputs
|
||||
bool MakeCollateralAmounts();
|
||||
bool MakeCollateralAmounts(const CompactTallyItem& tallyItem, bool fTryDenominated);
|
||||
bool MakeCollateralAmounts(const CBlockPolicyEstimator& fee_estimator);
|
||||
bool MakeCollateralAmounts(const CBlockPolicyEstimator& fee_estimator, const CompactTallyItem& tallyItem, bool fTryDenominated);
|
||||
|
||||
bool CreateCollateralTransaction(CMutableTransaction& txCollateral, std::string& strReason);
|
||||
|
||||
@ -138,7 +139,7 @@ public:
|
||||
bool GetMixingMasternodeInfo(CDeterministicMNCPtr& ret) const;
|
||||
|
||||
/// Passively run mixing in the background according to the configuration in settings
|
||||
bool DoAutomaticDenominating(CTxMemPool& mempool, CConnman& connman, bool fDryRun = false) LOCKS_EXCLUDED(cs_coinjoin);
|
||||
bool DoAutomaticDenominating(CConnman& connman, CBlockPolicyEstimator& fee_estimator, CTxMemPool& mempool, bool fDryRun = false) LOCKS_EXCLUDED(cs_coinjoin);
|
||||
|
||||
/// As a client, submit part of a future mixing transaction to a Masternode to start the process
|
||||
bool SubmitDenominate(CConnman& connman);
|
||||
@ -221,7 +222,7 @@ public:
|
||||
bool GetMixingMasternodesInfo(std::vector<CDeterministicMNCPtr>& vecDmnsRet) const LOCKS_EXCLUDED(cs_deqsessions);
|
||||
|
||||
/// Passively run mixing in the background according to the configuration in settings
|
||||
bool DoAutomaticDenominating(CTxMemPool& mempool, CConnman& connman, bool fDryRun = false) LOCKS_EXCLUDED(cs_deqsessions);
|
||||
bool DoAutomaticDenominating(CConnman& connman, CBlockPolicyEstimator& fee_estimator, CTxMemPool& mempool, bool fDryRun = false) LOCKS_EXCLUDED(cs_deqsessions);
|
||||
|
||||
bool TrySubmitDenominate(const CService& mnAddr, CConnman& connman) LOCKS_EXCLUDED(cs_deqsessions);
|
||||
bool MarkAlreadyJoinedQueueAsTried(CCoinJoinQueue& dsq) const LOCKS_EXCLUDED(cs_deqsessions);
|
||||
@ -237,12 +238,12 @@ public:
|
||||
|
||||
void UpdatedBlockTip(const CBlockIndex* pindex);
|
||||
|
||||
void DoMaintenance(CTxMemPool& mempool, CConnman& connman);
|
||||
void DoMaintenance(CConnman& connman, CBlockPolicyEstimator& fee_estimator, CTxMemPool& mempool);
|
||||
|
||||
void GetJsonInfo(UniValue& obj) const LOCKS_EXCLUDED(cs_deqsessions);
|
||||
};
|
||||
|
||||
|
||||
void DoCoinJoinMaintenance(CTxMemPool& mempool, CConnman& connman);
|
||||
void DoCoinJoinMaintenance(CConnman& connman, CBlockPolicyEstimator& fee_estimator, CTxMemPool& mempool);
|
||||
|
||||
#endif // BITCOIN_COINJOIN_CLIENT_H
|
||||
|
@ -113,7 +113,6 @@ void CCoinJoinServer::ProcessDSQUEUE(const CNode& peer, CDataStream& vRecv)
|
||||
vRecv >> dsq;
|
||||
|
||||
if (dsq.masternodeOutpoint.IsNull() && dsq.m_protxHash.IsNull()) {
|
||||
LOCK(cs_main);
|
||||
Misbehaving(peer.GetId(), 100);
|
||||
return;
|
||||
}
|
||||
@ -123,7 +122,6 @@ void CCoinJoinServer::ProcessDSQUEUE(const CNode& peer, CDataStream& vRecv)
|
||||
if (auto dmn = mnList.GetValidMN(dsq.m_protxHash)) {
|
||||
dsq.masternodeOutpoint = dmn->collateralOutpoint;
|
||||
} else {
|
||||
LOCK(cs_main);
|
||||
Misbehaving(peer.GetId(), 10);
|
||||
return;
|
||||
}
|
||||
@ -159,7 +157,6 @@ void CCoinJoinServer::ProcessDSQUEUE(const CNode& peer, CDataStream& vRecv)
|
||||
}
|
||||
|
||||
if (!dsq.CheckSignature(dmn->pdmnState->pubKeyOperator.Get())) {
|
||||
LOCK(cs_main);
|
||||
Misbehaving(peer.GetId(), 10);
|
||||
return;
|
||||
}
|
||||
|
@ -107,7 +107,7 @@ bool CTransactionBuilderOutput::UpdateAmount(const CAmount nNewAmount)
|
||||
return true;
|
||||
}
|
||||
|
||||
CTransactionBuilder::CTransactionBuilder(std::shared_ptr<CWallet> pwalletIn, const CompactTallyItem& tallyItemIn) :
|
||||
CTransactionBuilder::CTransactionBuilder(std::shared_ptr<CWallet> pwalletIn, const CompactTallyItem& tallyItemIn, const CBlockPolicyEstimator& fee_estimator) :
|
||||
pwallet(pwalletIn),
|
||||
dummyReserveDestination(pwalletIn.get()),
|
||||
tallyItem(tallyItemIn)
|
||||
@ -115,7 +115,7 @@ CTransactionBuilder::CTransactionBuilder(std::shared_ptr<CWallet> pwalletIn, con
|
||||
// Generate a feerate which will be used to consider if the remainder is dust and will go into fees or not
|
||||
coinControl.m_discard_feerate = ::GetDiscardRate(*pwallet);
|
||||
// Generate a feerate which will be used by calculations of this class and also by CWallet::CreateTransaction
|
||||
coinControl.m_feerate = std::max(::feeEstimator.estimateSmartFee(int(pwallet->m_confirm_target), nullptr, true), pwallet->m_pay_tx_fee);
|
||||
coinControl.m_feerate = std::max(fee_estimator.estimateSmartFee(int(pwallet->m_confirm_target), nullptr, true), pwallet->m_pay_tx_fee);
|
||||
// Change always goes back to origin
|
||||
coinControl.destChange = tallyItemIn.txdest;
|
||||
// Only allow tallyItems inputs for tx creation
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include <wallet/wallet.h>
|
||||
|
||||
class CBlockPolicyEstimator;
|
||||
class CTransactionBuilder;
|
||||
struct bilingual_str;
|
||||
|
||||
@ -100,7 +101,7 @@ class CTransactionBuilder
|
||||
friend class CTransactionBuilderOutput;
|
||||
|
||||
public:
|
||||
CTransactionBuilder(std::shared_ptr<CWallet> pwalletIn, const CompactTallyItem& tallyItemIn);
|
||||
CTransactionBuilder(std::shared_ptr<CWallet> pwalletIn, const CompactTallyItem& tallyItemIn, const CBlockPolicyEstimator& fee_estimator);
|
||||
~CTransactionBuilder();
|
||||
/// Check it would be possible to add a single output with the amount nAmount. Returns true if its possible and false if not.
|
||||
bool CouldAddOutput(CAmount nAmountOutput) const;
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
class ChainstateManager;
|
||||
class CTxMemPool;
|
||||
class CBlockPolicyEstimator;
|
||||
struct LLMQContext;
|
||||
struct NodeContext;
|
||||
struct WalletContext;
|
||||
@ -19,6 +20,7 @@ using CoreContext = std::variant<std::nullopt_t,
|
||||
std::reference_wrapper<WalletContext>,
|
||||
std::reference_wrapper<CTxMemPool>,
|
||||
std::reference_wrapper<ChainstateManager>,
|
||||
std::reference_wrapper<CBlockPolicyEstimator>,
|
||||
std::reference_wrapper<LLMQContext>>;
|
||||
|
||||
template<typename T>
|
||||
|
@ -70,26 +70,22 @@ void CMNAuth::ProcessMessage(CNode& peer, CConnman& connman, std::string_view ms
|
||||
|
||||
// only one MNAUTH allowed
|
||||
if (!peer.GetVerifiedProRegTxHash().IsNull()) {
|
||||
LOCK(cs_main);
|
||||
Misbehaving(peer.GetId(), 100, "duplicate mnauth");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((~peer.nServices) & (NODE_NETWORK | NODE_BLOOM)) {
|
||||
// either NODE_NETWORK or NODE_BLOOM bit is missing in node's services
|
||||
LOCK(cs_main);
|
||||
Misbehaving(peer.GetId(), 100, "mnauth from a node with invalid services");
|
||||
return;
|
||||
}
|
||||
|
||||
if (mnauth.proRegTxHash.IsNull()) {
|
||||
LOCK(cs_main);
|
||||
Misbehaving(peer.GetId(), 100, "empty mnauth proRegTxHash");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mnauth.sig.IsValid()) {
|
||||
LOCK(cs_main);
|
||||
Misbehaving(peer.GetId(), 100, "invalid mnauth signature");
|
||||
return;
|
||||
}
|
||||
@ -97,7 +93,6 @@ void CMNAuth::ProcessMessage(CNode& peer, CConnman& connman, std::string_view ms
|
||||
const auto mnList = deterministicMNManager->GetListAtChainTip();
|
||||
const auto dmn = mnList.GetMN(mnauth.proRegTxHash);
|
||||
if (!dmn) {
|
||||
LOCK(cs_main);
|
||||
// in case node was unlucky and not up to date, just let it be connected as a regular node, which gives it
|
||||
// a chance to get up-to-date and thus realize that it's not a MN anymore. We still give it a
|
||||
// low DoS score.
|
||||
@ -122,7 +117,6 @@ void CMNAuth::ProcessMessage(CNode& peer, CConnman& connman, std::string_view ms
|
||||
LogPrint(BCLog::NET_NETCONN, "CMNAuth::%s -- constructed signHash for nVersion %d, peer=%d\n", __func__, peer.nVersion, peer.GetId());
|
||||
|
||||
if (!mnauth.sig.VerifyInsecure(dmn->pdmnState->pubKeyOperator.Get(), signHash)) {
|
||||
LOCK(cs_main);
|
||||
// Same as above, MN seems to not know its fate yet, so give it a chance to update. If this is a
|
||||
// malicious node (DoSing us), it'll get banned soon.
|
||||
Misbehaving(peer.GetId(), 10, "mnauth signature verification failed");
|
||||
|
@ -219,7 +219,6 @@ void CGovernanceManager::ProcessMessage(CNode& peer, CConnman& connman, std::str
|
||||
} else {
|
||||
LogPrint(BCLog::GOBJECT, "MNGOVERNANCEOBJECTVOTE -- Rejected vote, error = %s\n", exception.what());
|
||||
if ((exception.GetNodePenalty() != 0) && ::masternodeSync->IsSynced()) {
|
||||
LOCK(cs_main);
|
||||
Misbehaving(peer.GetId(), exception.GetNodePenalty());
|
||||
}
|
||||
return;
|
||||
@ -625,7 +624,6 @@ void CGovernanceManager::SyncObjects(CNode& peer, CConnman& connman) const
|
||||
if (netfulfilledman.HasFulfilledRequest(peer.addr, NetMsgType::MNGOVERNANCESYNC)) {
|
||||
// Asking for the whole list multiple times in a short period of time is no good
|
||||
LogPrint(BCLog::GOBJECT, "CGovernanceManager::%s -- peer already asked me for the list\n", __func__);
|
||||
LOCK(cs_main);
|
||||
Misbehaving(peer.GetId(), 20);
|
||||
return;
|
||||
}
|
||||
|
63
src/init.cpp
63
src/init.cpp
@ -120,7 +120,6 @@
|
||||
#include <zmq/zmqrpc.h>
|
||||
#endif
|
||||
|
||||
static bool fFeeEstimatesInitialized = false;
|
||||
static const bool DEFAULT_PROXYRANDOMIZE = true;
|
||||
static const bool DEFAULT_REST_ENABLE = false;
|
||||
static const bool DEFAULT_STOPAFTERBLOCKIMPORT = false;
|
||||
@ -136,8 +135,6 @@ static CDSNotificationInterface* pdsNotificationInterface = nullptr;
|
||||
#define MIN_CORE_FILEDESCRIPTORS 150
|
||||
#endif
|
||||
|
||||
static const char* FEE_ESTIMATES_FILENAME="fee_estimates.dat";
|
||||
|
||||
static const char* DEFAULT_ASMAP_FILENAME="ip_asn.map";
|
||||
/**
|
||||
* The PID file facilities.
|
||||
@ -281,22 +278,14 @@ void PrepareShutdown(NodeContext& node)
|
||||
node.peer_logic.reset();
|
||||
node.connman.reset();
|
||||
node.banman.reset();
|
||||
node.addrman.reset();
|
||||
|
||||
if (node.mempool && node.mempool->IsLoaded() && node.args->GetArg("-persistmempool", DEFAULT_PERSIST_MEMPOOL)) {
|
||||
DumpMempool(*node.mempool);
|
||||
}
|
||||
|
||||
if (fFeeEstimatesInitialized)
|
||||
{
|
||||
::feeEstimator.FlushUnconfirmed();
|
||||
fs::path est_path = GetDataDir() / FEE_ESTIMATES_FILENAME;
|
||||
CAutoFile est_fileout(fsbridge::fopen(est_path, "wb"), SER_DISK, CLIENT_VERSION);
|
||||
if (!est_fileout.IsNull())
|
||||
::feeEstimator.Write(est_fileout);
|
||||
else
|
||||
LogPrintf("%s: Failed to write fee estimates to %s\n", __func__, est_path.string());
|
||||
fFeeEstimatesInitialized = false;
|
||||
}
|
||||
// Drop transactions we were still watching, and record fee estimations.
|
||||
if (node.fee_estimator) node.fee_estimator->Flush();
|
||||
|
||||
// FlushStateToDisk generates a ChainStateFlushed callback, which we should avoid missing
|
||||
if (node.chainman) {
|
||||
@ -405,6 +394,7 @@ void Shutdown(NodeContext& node)
|
||||
globalVerifyHandle.reset();
|
||||
ECC_Stop();
|
||||
node.mempool.reset();
|
||||
node.fee_estimator.reset();
|
||||
node.chainman = nullptr;
|
||||
node.scheduler.reset();
|
||||
|
||||
@ -1761,28 +1751,33 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc
|
||||
// is not yet setup and may end up being set up twice if we
|
||||
// need to reindex later.
|
||||
|
||||
// see Step 2: parameter interactions for more information about these
|
||||
fListen = args.GetBoolArg("-listen", DEFAULT_LISTEN);
|
||||
fDiscover = args.GetBoolArg("-discover", true);
|
||||
g_relay_txes = !args.GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY);
|
||||
|
||||
assert(!node.addrman);
|
||||
node.addrman = std::make_unique<CAddrMan>();
|
||||
assert(!node.banman);
|
||||
node.banman = std::make_unique<BanMan>(GetDataDir() / "banlist.dat", &uiInterface, args.GetArg("-bantime", DEFAULT_MISBEHAVING_BANTIME));
|
||||
assert(!node.connman);
|
||||
node.connman = std::make_unique<CConnman>(GetRand(std::numeric_limits<uint64_t>::max()), GetRand(std::numeric_limits<uint64_t>::max()));
|
||||
node.connman = std::make_unique<CConnman>(GetRand(std::numeric_limits<uint64_t>::max()), GetRand(std::numeric_limits<uint64_t>::max()), *node.addrman);
|
||||
|
||||
assert(!node.fee_estimator);
|
||||
// Don't initialize fee estimation with old data if we don't relay transactions,
|
||||
// as they would never get updated.
|
||||
if (g_relay_txes) node.fee_estimator = std::make_unique<CBlockPolicyEstimator>();
|
||||
|
||||
// Make mempool generally available in the node context. For example the connection manager, wallet, or RPC threads,
|
||||
// which are all started after this, may use it from the node context.
|
||||
assert(!node.mempool);
|
||||
node.mempool = std::make_unique<CTxMemPool>(&::feeEstimator);
|
||||
if (node.mempool) {
|
||||
int ratio = std::min<int>(std::max<int>(args.GetArg("-checkmempool", chainparams.DefaultConsistencyChecks() ? 1 : 0), 0), 1000000);
|
||||
if (ratio != 0) {
|
||||
node.mempool->setSanityCheck(1.0 / ratio);
|
||||
}
|
||||
}
|
||||
int check_ratio = std::min<int>(std::max<int>(args.GetArg("-checkmempool", chainparams.DefaultConsistencyChecks() ? 1 : 0), 0), 1000000);
|
||||
node.mempool = std::make_unique<CTxMemPool>(node.fee_estimator.get(), check_ratio);
|
||||
|
||||
assert(!node.chainman);
|
||||
node.chainman = &g_chainman;
|
||||
ChainstateManager& chainman = *Assert(node.chainman);
|
||||
|
||||
node.peer_logic.reset(new PeerLogicValidation(
|
||||
*node.connman, node.banman.get(), *node.scheduler, chainman, *node.mempool, node.llmq_ctx
|
||||
*node.connman, *node.addrman, node.banman.get(), *node.scheduler, chainman, *node.mempool, node.llmq_ctx
|
||||
));
|
||||
RegisterValidationInterface(node.peer_logic.get());
|
||||
|
||||
@ -1894,11 +1889,6 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc
|
||||
}
|
||||
}
|
||||
|
||||
// see Step 2: parameter interactions for more information about these
|
||||
fListen = args.GetBoolArg("-listen", DEFAULT_LISTEN);
|
||||
fDiscover = args.GetBoolArg("-discover", true);
|
||||
g_relay_txes = !args.GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY);
|
||||
|
||||
for (const std::string& strAddr : args.GetArgs("-externalip")) {
|
||||
CService addrLocal;
|
||||
if (Lookup(strAddr, addrLocal, GetListenPort(), fNameLookup) && addrLocal.IsValid())
|
||||
@ -2264,13 +2254,6 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc
|
||||
return false;
|
||||
}
|
||||
|
||||
fs::path est_path = GetDataDir() / FEE_ESTIMATES_FILENAME;
|
||||
CAutoFile est_filein(fsbridge::fopen(est_path, "rb"), SER_DISK, CLIENT_VERSION);
|
||||
// Allowed to fail as this file IS missing on first startup.
|
||||
if (!est_filein.IsNull())
|
||||
::feeEstimator.Read(est_filein);
|
||||
fFeeEstimatesInitialized = true;
|
||||
|
||||
// ********************************************************* Step 8: start indexers
|
||||
if (args.GetBoolArg("-txindex", DEFAULT_TXINDEX)) {
|
||||
g_txindex = std::make_unique<TxIndex>(nTxIndexCache, false, fReindex);
|
||||
@ -2325,7 +2308,9 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc
|
||||
|
||||
::coinJoinServer = std::make_unique<CCoinJoinServer>(*node.mempool, *node.connman, ::masternodeSync);
|
||||
#ifdef ENABLE_WALLET
|
||||
if (g_relay_txes) {
|
||||
::coinJoinClientQueueManager = std::make_unique<CCoinJoinClientQueueManager>(*node.connman, ::masternodeSync);
|
||||
}
|
||||
#endif // ENABLE_WALLET
|
||||
|
||||
g_wallet_init_interface.InitCoinJoinSettings();
|
||||
@ -2396,8 +2381,8 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc
|
||||
node.scheduler->scheduleEvery(std::bind(&CCoinJoinServer::DoMaintenance, std::ref(*::coinJoinServer)), std::chrono::seconds{1});
|
||||
node.scheduler->scheduleEvery(std::bind(&llmq::CDKGSessionManager::CleanupOldContributions, std::ref(*node.llmq_ctx->qdkgsman)), std::chrono::hours{1});
|
||||
#ifdef ENABLE_WALLET
|
||||
} else if(CCoinJoinClientOptions::IsEnabled()) {
|
||||
node.scheduler->scheduleEvery(std::bind(&DoCoinJoinMaintenance, std::ref(*node.mempool), std::ref(*node.connman)), std::chrono::seconds{1});
|
||||
} else if (g_relay_txes && CCoinJoinClientOptions::IsEnabled()) {
|
||||
node.scheduler->scheduleEvery(std::bind(&DoCoinJoinMaintenance, std::ref(*node.connman), std::ref(*node.fee_estimator), std::ref(*node.mempool)), std::chrono::seconds{1});
|
||||
#endif // ENABLE_WALLET
|
||||
}
|
||||
|
||||
|
@ -312,11 +312,13 @@ public:
|
||||
}
|
||||
CFeeRate estimateSmartFee(int num_blocks, bool conservative, FeeCalculation* calc) override
|
||||
{
|
||||
return ::feeEstimator.estimateSmartFee(num_blocks, calc, conservative);
|
||||
if (!m_node.fee_estimator) return {};
|
||||
return m_node.fee_estimator->estimateSmartFee(num_blocks, calc, conservative);
|
||||
}
|
||||
unsigned int estimateMaxBlocks() override
|
||||
{
|
||||
return ::feeEstimator.HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE);
|
||||
if (!m_node.fee_estimator) return 0;
|
||||
return m_node.fee_estimator->HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE);
|
||||
}
|
||||
CFeeRate mempoolMinFee() override
|
||||
{
|
||||
|
@ -332,15 +332,6 @@ public:
|
||||
}
|
||||
}
|
||||
bool getNetworkActive() override { return m_context->connman && m_context->connman->GetNetworkActive(); }
|
||||
CFeeRate estimateSmartFee(int num_blocks, bool conservative, int* returned_target = nullptr) override
|
||||
{
|
||||
FeeCalculation fee_calc;
|
||||
CFeeRate result = ::feeEstimator.estimateSmartFee(num_blocks, &fee_calc, conservative);
|
||||
if (returned_target) {
|
||||
*returned_target = fee_calc.returnedTarget;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
CFeeRate getDustRelayFee() override { return ::dustRelayFee; }
|
||||
UniValue executeRpc(const std::string& command, const UniValue& params, const std::string& uri) override
|
||||
{
|
||||
|
@ -253,9 +253,6 @@ public:
|
||||
//! Get network active.
|
||||
virtual bool getNetworkActive() = 0;
|
||||
|
||||
//! Estimate smart fee.
|
||||
virtual CFeeRate estimateSmartFee(int num_blocks, bool conservative, int* returned_target = nullptr) = 0;
|
||||
|
||||
//! Get dust relay fee.
|
||||
virtual CFeeRate getDustRelayFee() = 0;
|
||||
|
||||
|
@ -55,14 +55,14 @@ void CQuorumBlockProcessor::ProcessMessage(const CNode& peer, std::string_view m
|
||||
|
||||
if (qc.IsNull()) {
|
||||
LogPrint(BCLog::LLMQ, "CQuorumBlockProcessor::%s -- null commitment from peer=%d\n", __func__, peer.GetId());
|
||||
WITH_LOCK(cs_main, Misbehaving(peer.GetId(), 100));
|
||||
Misbehaving(peer.GetId(), 100);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Params().HasLLMQ(qc.llmqType)) {
|
||||
LogPrint(BCLog::LLMQ, "CQuorumBlockProcessor::%s -- invalid commitment type %d from peer=%d\n", __func__,
|
||||
ToUnderlying(qc.llmqType), peer.GetId());
|
||||
WITH_LOCK(cs_main, Misbehaving(peer.GetId(), 100));
|
||||
Misbehaving(peer.GetId(), 100);
|
||||
return;
|
||||
}
|
||||
auto type = qc.llmqType;
|
||||
@ -125,7 +125,7 @@ void CQuorumBlockProcessor::ProcessMessage(const CNode& peer, std::string_view m
|
||||
LogPrint(BCLog::LLMQ, "CQuorumBlockProcessor::%s -- commitment for quorum %s:%d is not valid quorumIndex[%d] nversion[%d], peer=%d\n",
|
||||
__func__, qc.quorumHash.ToString(),
|
||||
ToUnderlying(qc.llmqType), qc.quorumIndex, qc.nVersion, peer.GetId());
|
||||
WITH_LOCK(cs_main, Misbehaving(peer.GetId(), 100));
|
||||
Misbehaving(peer.GetId(), 100);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -125,7 +125,6 @@ void CChainLocksHandler::ProcessNewChainLock(const NodeId from, const llmq::CCha
|
||||
if (!llmq::CSigningManager::VerifyRecoveredSig(Params().GetConsensus().llmqTypeChainLocks, *llmq::quorumManager, clsig.getHeight(), requestId, clsig.getBlockHash(), clsig.getSig())) {
|
||||
LogPrint(BCLog::CHAINLOCKS, "CChainLocksHandler::%s -- invalid CLSIG (%s), peer=%d\n", __func__, clsig.ToString(), from);
|
||||
if (from != -1) {
|
||||
LOCK(cs_main);
|
||||
Misbehaving(from, 10);
|
||||
}
|
||||
return;
|
||||
|
@ -429,7 +429,6 @@ bool ProcessPendingMessageBatch(CDKGSession& session, CDKGPendingMessages& pendi
|
||||
if (!p.second) {
|
||||
LogPrint(BCLog::LLMQ_DKG, "%s -- failed to deserialize message, peer=%d\n", __func__, nodeId);
|
||||
{
|
||||
LOCK(cs_main);
|
||||
Misbehaving(nodeId, 100);
|
||||
}
|
||||
continue;
|
||||
@ -439,7 +438,6 @@ bool ProcessPendingMessageBatch(CDKGSession& session, CDKGPendingMessages& pendi
|
||||
if (ban) {
|
||||
LogPrint(BCLog::LLMQ_DKG, "%s -- banning node due to failed preverification, peer=%d\n", __func__, nodeId);
|
||||
{
|
||||
LOCK(cs_main);
|
||||
Misbehaving(nodeId, 100);
|
||||
}
|
||||
}
|
||||
@ -470,7 +468,6 @@ bool ProcessPendingMessageBatch(CDKGSession& session, CDKGPendingMessages& pendi
|
||||
session.ReceiveMessage(*p.second, ban);
|
||||
if (ban) {
|
||||
LogPrint(BCLog::LLMQ_DKG, "%s -- banning node after ReceiveMessage failed, peer=%d\n", __func__, nodeId);
|
||||
LOCK(cs_main);
|
||||
Misbehaving(nodeId, 100);
|
||||
badNodes.emplace(nodeId);
|
||||
}
|
||||
|
@ -185,7 +185,6 @@ void CDKGSessionManager::ProcessMessage(CNode& pfrom, const CQuorumManager& quor
|
||||
}
|
||||
|
||||
if (vRecv.empty()) {
|
||||
LOCK(cs_main);
|
||||
Misbehaving(pfrom.GetId(), 100);
|
||||
return;
|
||||
}
|
||||
@ -198,7 +197,6 @@ void CDKGSessionManager::ProcessMessage(CNode& pfrom, const CQuorumManager& quor
|
||||
vRecv.Rewind(sizeof(uint8_t));
|
||||
|
||||
if (!Params().HasLLMQ(llmqType)) {
|
||||
LOCK(cs_main);
|
||||
LogPrintf("CDKGSessionManager -- invalid llmqType [%d]\n", ToUnderlying(llmqType));
|
||||
Misbehaving(pfrom.GetId(), 100);
|
||||
return;
|
||||
@ -219,7 +217,6 @@ void CDKGSessionManager::ProcessMessage(CNode& pfrom, const CQuorumManager& quor
|
||||
if (quorumIndex == -1) {
|
||||
CBlockIndex* pQuorumBaseBlockIndex = WITH_LOCK(cs_main, return LookupBlockIndex(quorumHash));
|
||||
if (pQuorumBaseBlockIndex == nullptr) {
|
||||
LOCK(cs_main);
|
||||
LogPrintf("CDKGSessionManager -- unknown quorumHash %s\n", quorumHash.ToString());
|
||||
// NOTE: do not insta-ban for this, we might be lagging behind
|
||||
Misbehaving(pfrom.GetId(), 10);
|
||||
@ -227,7 +224,6 @@ void CDKGSessionManager::ProcessMessage(CNode& pfrom, const CQuorumManager& quor
|
||||
}
|
||||
|
||||
if (!utils::IsQuorumTypeEnabled(llmqType, quorum_manager, pQuorumBaseBlockIndex->pprev)) {
|
||||
LOCK(cs_main);
|
||||
LogPrintf("CDKGSessionManager -- llmqType [%d] quorums aren't active\n", ToUnderlying(llmqType));
|
||||
Misbehaving(pfrom.GetId(), 100);
|
||||
return;
|
||||
@ -239,14 +235,12 @@ void CDKGSessionManager::ProcessMessage(CNode& pfrom, const CQuorumManager& quor
|
||||
llmqParams.signingActiveQuorumCount - 1 : 0;
|
||||
|
||||
if (quorumIndex > quorumIndexMax) {
|
||||
LOCK(cs_main);
|
||||
LogPrintf("CDKGSessionManager -- invalid quorumHash %s\n", quorumHash.ToString());
|
||||
Misbehaving(pfrom.GetId(), 100);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!dkgSessionHandlers.count(std::make_pair(llmqType, quorumIndex))) {
|
||||
LOCK(cs_main);
|
||||
LogPrintf("CDKGSessionManager -- no session handlers for quorumIndex [%d]\n", quorumIndex);
|
||||
Misbehaving(pfrom.GetId(), 100);
|
||||
return;
|
||||
|
@ -788,7 +788,6 @@ void CInstantSendManager::ProcessMessageInstantSendLock(const CNode& pfrom, cons
|
||||
}
|
||||
|
||||
if (!islock->TriviallyValid()) {
|
||||
LOCK(cs_main);
|
||||
Misbehaving(pfrom.GetId(), 100);
|
||||
return;
|
||||
}
|
||||
@ -798,14 +797,14 @@ void CInstantSendManager::ProcessMessageInstantSendLock(const CNode& pfrom, cons
|
||||
const auto blockIndex = WITH_LOCK(cs_main, return LookupBlockIndex(islock->cycleHash));
|
||||
if (blockIndex == nullptr) {
|
||||
// Maybe we don't have the block yet or maybe some peer spams invalid values for cycleHash
|
||||
WITH_LOCK(cs_main, Misbehaving(pfrom.GetId(), 1));
|
||||
Misbehaving(pfrom.GetId(), 1);
|
||||
return;
|
||||
}
|
||||
|
||||
// Deterministic islocks MUST use rotation based llmq
|
||||
auto llmqType = Params().GetConsensus().llmqTypeDIP0024InstantSend;
|
||||
if (blockIndex->nHeight % GetLLMQParams(llmqType).dkgInterval != 0) {
|
||||
WITH_LOCK(cs_main, Misbehaving(pfrom.GetId(), 100));
|
||||
Misbehaving(pfrom.GetId(), 100);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -611,7 +611,6 @@ void CQuorumManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, C
|
||||
auto errorHandler = [&](const std::string& strError, int nScore = 10) {
|
||||
LogPrint(BCLog::LLMQ, "CQuorumManager::%s -- %s: %s, from peer=%d\n", strFunc, msg_type, strError, pfrom.GetId());
|
||||
if (nScore > 0) {
|
||||
LOCK(cs_main);
|
||||
Misbehaving(pfrom.GetId(), nScore);
|
||||
}
|
||||
};
|
||||
|
@ -577,7 +577,6 @@ void CSigningManager::ProcessMessageRecoveredSig(const CNode& pfrom, const std::
|
||||
bool ban = false;
|
||||
if (!PreVerifyRecoveredSig(qman, *recoveredSig, ban)) {
|
||||
if (ban) {
|
||||
LOCK(cs_main);
|
||||
Misbehaving(pfrom.GetId(), 100);
|
||||
}
|
||||
return;
|
||||
@ -752,7 +751,6 @@ bool CSigningManager::ProcessPendingRecoveredSigs()
|
||||
|
||||
if (batchVerifier.badSources.count(nodeId)) {
|
||||
LogPrint(BCLog::LLMQ, "CSigningManager::%s -- invalid recSig from other node, banning peer=%d\n", __func__, nodeId);
|
||||
LOCK(cs_main);
|
||||
Misbehaving(nodeId, 100);
|
||||
continue;
|
||||
}
|
||||
|
@ -1402,7 +1402,6 @@ void CSigSharesManager::BanNode(NodeId nodeId)
|
||||
}
|
||||
|
||||
{
|
||||
LOCK(cs_main);
|
||||
Misbehaving(nodeId, 100);
|
||||
}
|
||||
|
||||
|
31
src/net.cpp
31
src/net.cpp
@ -2949,9 +2949,8 @@ void CConnman::SetNetworkActive(bool active)
|
||||
uiInterface.NotifyNetworkActiveChanged(fNetworkActive);
|
||||
}
|
||||
|
||||
CConnman::CConnman(uint64_t nSeed0In, uint64_t nSeed1In) :
|
||||
addrman(Params().AllowMultiplePorts()),
|
||||
nSeed0(nSeed0In), nSeed1(nSeed1In)
|
||||
CConnman::CConnman(uint64_t nSeed0In, uint64_t nSeed1In, CAddrMan& addrman_in) :
|
||||
addrman(addrman_in), nSeed0(nSeed0In), nSeed1(nSeed1In)
|
||||
{
|
||||
SetTryNewOutboundPeer(false);
|
||||
|
||||
@ -3309,11 +3308,7 @@ void CConnman::Stop()
|
||||
void CConnman::DeleteNode(CNode* pnode)
|
||||
{
|
||||
assert(pnode);
|
||||
bool fUpdateConnectionTime = false;
|
||||
m_msgproc->FinalizeNode(pnode->GetId(), fUpdateConnectionTime);
|
||||
if(fUpdateConnectionTime) {
|
||||
addrman.Connected(pnode->addr);
|
||||
}
|
||||
m_msgproc->FinalizeNode(*pnode);
|
||||
delete pnode;
|
||||
}
|
||||
|
||||
@ -3323,26 +3318,6 @@ CConnman::~CConnman()
|
||||
Stop();
|
||||
}
|
||||
|
||||
size_t CConnman::GetAddressCount() const
|
||||
{
|
||||
return addrman.size();
|
||||
}
|
||||
|
||||
void CConnman::SetServices(const CService &addr, ServiceFlags nServices)
|
||||
{
|
||||
addrman.SetServices(addr, nServices);
|
||||
}
|
||||
|
||||
void CConnman::MarkAddressGood(const CAddress& addr)
|
||||
{
|
||||
addrman.Good(addr);
|
||||
}
|
||||
|
||||
void CConnman::AddNewAddresses(const std::vector<CAddress>& vAddr, const CAddress& addrFrom, int64_t nTimePenalty)
|
||||
{
|
||||
addrman.Add(vAddr, addrFrom, nTimePenalty);
|
||||
}
|
||||
|
||||
std::vector<CAddress> CConnman::GetAddresses()
|
||||
{
|
||||
return addrman.GetAddr();
|
||||
|
10
src/net.h
10
src/net.h
@ -213,7 +213,7 @@ public:
|
||||
socketEventsMode = connOptions.socketEventsMode;
|
||||
}
|
||||
|
||||
CConnman(uint64_t seed0, uint64_t seed1);
|
||||
CConnman(uint64_t seed0, uint64_t seed1, CAddrMan& addrman);
|
||||
~CConnman();
|
||||
bool Start(CScheduler& scheduler, const Options& options);
|
||||
|
||||
@ -399,10 +399,6 @@ public:
|
||||
void RelayInvFiltered(CInv &inv, const uint256 &relatedTxHash, const int minProtoVersion = MIN_PEER_PROTO_VERSION);
|
||||
|
||||
// Addrman functions
|
||||
size_t GetAddressCount() const;
|
||||
void SetServices(const CService &addr, ServiceFlags nServices);
|
||||
void MarkAddressGood(const CAddress& addr);
|
||||
void AddNewAddresses(const std::vector<CAddress>& vAddr, const CAddress& addrFrom, int64_t nTimePenalty = 0);
|
||||
std::vector<CAddress> GetAddresses();
|
||||
|
||||
// This allows temporarily exceeding m_max_outbound_full_relay, with the goal of finding
|
||||
@ -581,7 +577,7 @@ private:
|
||||
std::vector<ListenSocket> vhListenSocket;
|
||||
std::atomic<bool> fNetworkActive{true};
|
||||
bool fAddressesInitialized{false};
|
||||
CAddrMan addrman;
|
||||
CAddrMan& addrman;
|
||||
std::deque<std::string> vOneShots GUARDED_BY(cs_vOneShots);
|
||||
CCriticalSection cs_vOneShots;
|
||||
std::vector<std::string> vAddedNodes GUARDED_BY(cs_vAddedNodes);
|
||||
@ -709,7 +705,7 @@ public:
|
||||
virtual bool ProcessMessages(CNode* pnode, std::atomic<bool>& interrupt) = 0;
|
||||
virtual bool SendMessages(CNode* pnode) = 0;
|
||||
virtual void InitializeNode(CNode* pnode) = 0;
|
||||
virtual void FinalizeNode(NodeId id, bool& update_connection_time) = 0;
|
||||
virtual void FinalizeNode(const CNode& node) = 0;
|
||||
|
||||
protected:
|
||||
/**
|
||||
|
@ -266,14 +266,6 @@ namespace {
|
||||
struct CNodeState {
|
||||
//! The peer's address
|
||||
const CService address;
|
||||
//! Whether we have a fully established connection.
|
||||
bool fCurrentlyConnected;
|
||||
//! Accumulated misbehaviour score for this peer.
|
||||
int nMisbehavior;
|
||||
//! Whether this peer should be disconnected and marked as discouraged (unless it has the noban permission).
|
||||
bool m_should_discourage;
|
||||
//! String name of this peer (debugging/logging purposes).
|
||||
const std::string name;
|
||||
//! The best known block we know this peer has announced.
|
||||
const CBlockIndex *pindexBestKnownBlock;
|
||||
//! The hash of the last unknown block this peer has announced.
|
||||
@ -410,13 +402,9 @@ struct CNodeState {
|
||||
//! Whether this peer is a manual connection
|
||||
bool m_is_manual_connection;
|
||||
|
||||
CNodeState(CAddress addrIn, std::string addrNameIn, bool is_inbound, bool is_manual) :
|
||||
address(addrIn), name(std::move(addrNameIn)), m_is_inbound(is_inbound),
|
||||
m_is_manual_connection (is_manual)
|
||||
CNodeState(CAddress addrIn, bool is_inbound, bool is_manual) :
|
||||
address(addrIn), m_is_inbound(is_inbound), m_is_manual_connection(is_manual)
|
||||
{
|
||||
fCurrentlyConnected = false;
|
||||
nMisbehavior = 0;
|
||||
m_should_discourage = false;
|
||||
pindexBestKnownBlock = nullptr;
|
||||
hashLastUnknownBlock.SetNull();
|
||||
pindexLastCommonBlock = nullptr;
|
||||
@ -453,6 +441,50 @@ static CNodeState *State(NodeId pnode) EXCLUSIVE_LOCKS_REQUIRED(cs_main) {
|
||||
return &it->second;
|
||||
}
|
||||
|
||||
/**
|
||||
* Data structure for an individual peer. This struct is not protected by
|
||||
* cs_main since it does not contain validation-critical data.
|
||||
*
|
||||
* Memory is owned by shared pointers and this object is destructed when
|
||||
* the refcount drops to zero.
|
||||
*
|
||||
* TODO: move most members from CNodeState to this structure.
|
||||
* TODO: move remaining application-layer data members from CNode to this structure.
|
||||
*/
|
||||
struct Peer {
|
||||
/** Same id as the CNode object for this peer */
|
||||
const NodeId m_id{0};
|
||||
|
||||
/** Protects misbehavior data members */
|
||||
Mutex m_misbehavior_mutex;
|
||||
/** Accumulated misbehavior score for this peer */
|
||||
int nMisbehavior GUARDED_BY(m_misbehavior_mutex){0};
|
||||
/** Whether this peer should be disconnected and marked as discouraged (unless it has the noban permission). */
|
||||
bool m_should_discourage GUARDED_BY(m_misbehavior_mutex){false};
|
||||
|
||||
Peer(NodeId id) : m_id(id) {}
|
||||
};
|
||||
|
||||
using PeerRef = std::shared_ptr<Peer>;
|
||||
|
||||
/**
|
||||
* Map of all Peer objects, keyed by peer id. This map is protected
|
||||
* by the global g_peer_mutex. Once a shared pointer reference is
|
||||
* taken, the lock may be released. Individual fields are protected by
|
||||
* their own locks.
|
||||
*/
|
||||
Mutex g_peer_mutex;
|
||||
static std::map<NodeId, PeerRef> g_peer_map GUARDED_BY(g_peer_mutex);
|
||||
|
||||
/** Get a shared pointer to the Peer object.
|
||||
* May return nullptr if the Peer object can't be found. */
|
||||
static PeerRef GetPeerRef(NodeId id)
|
||||
{
|
||||
LOCK(g_peer_mutex);
|
||||
auto it = g_peer_map.find(id);
|
||||
return it != g_peer_map.end() ? it->second : nullptr;
|
||||
}
|
||||
|
||||
static void UpdatePreferredDownload(const CNode& node, CNodeState* state) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
||||
{
|
||||
nPreferredDownload -= state->fPreferredDownload;
|
||||
@ -906,11 +938,15 @@ static bool IsOutboundDisconnectionCandidate(const CNode& node)
|
||||
|
||||
void PeerLogicValidation::InitializeNode(CNode *pnode) {
|
||||
CAddress addr = pnode->addr;
|
||||
std::string addrName = pnode->GetAddrName();
|
||||
NodeId nodeid = pnode->GetId();
|
||||
{
|
||||
LOCK(cs_main);
|
||||
mapNodeState.emplace_hint(mapNodeState.end(), std::piecewise_construct, std::forward_as_tuple(nodeid), std::forward_as_tuple(addr, std::move(addrName), pnode->fInbound, pnode->m_manual_connection));
|
||||
mapNodeState.emplace_hint(mapNodeState.end(), std::piecewise_construct, std::forward_as_tuple(nodeid), std::forward_as_tuple(addr, pnode->fInbound, pnode->m_manual_connection));
|
||||
}
|
||||
{
|
||||
PeerRef peer = std::make_shared<Peer>(nodeid);
|
||||
LOCK(g_peer_mutex);
|
||||
g_peer_map.emplace_hint(g_peer_map.end(), nodeid, std::move(peer));
|
||||
}
|
||||
if (!pnode->fInbound)
|
||||
PushNodeVersion(*pnode, m_connman, GetTime());
|
||||
@ -929,19 +965,24 @@ void PeerLogicValidation::ReattemptInitialBroadcast(CScheduler& scheduler) const
|
||||
scheduler.scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
|
||||
}
|
||||
|
||||
void PeerLogicValidation::FinalizeNode(NodeId nodeid, bool& fUpdateConnectionTime) {
|
||||
fUpdateConnectionTime = false;
|
||||
void PeerLogicValidation::FinalizeNode(const CNode& node) {
|
||||
NodeId nodeid = node.GetId();
|
||||
int misbehavior{0};
|
||||
LOCK(cs_main);
|
||||
{
|
||||
{
|
||||
PeerRef peer = GetPeerRef(nodeid);
|
||||
assert(peer != nullptr);
|
||||
misbehavior = WITH_LOCK(peer->m_misbehavior_mutex, return peer->nMisbehavior);
|
||||
LOCK(g_peer_mutex);
|
||||
g_peer_map.erase(nodeid);
|
||||
}
|
||||
CNodeState *state = State(nodeid);
|
||||
assert(state != nullptr);
|
||||
|
||||
if (state->fSyncStarted)
|
||||
nSyncStarted--;
|
||||
|
||||
if (state->nMisbehavior == 0 && state->fCurrentlyConnected) {
|
||||
fUpdateConnectionTime = true;
|
||||
}
|
||||
|
||||
for (const QueuedBlock& entry : state->vBlocksInFlight) {
|
||||
mapBlocksInFlight.erase(entry.hash);
|
||||
}
|
||||
@ -961,21 +1002,36 @@ void PeerLogicValidation::FinalizeNode(NodeId nodeid, bool& fUpdateConnectionTim
|
||||
assert(nPeersWithValidatedDownloads == 0);
|
||||
assert(g_outbound_peers_with_protect_from_disconnect == 0);
|
||||
}
|
||||
} // cs_main
|
||||
|
||||
if (node.fSuccessfullyConnected && misbehavior == 0 && !node.m_block_relay_only_peer && !node.fInbound) {
|
||||
// Only change visible addrman state for full outbound peers. We don't
|
||||
// call Connected() for feeler connections since they don't have
|
||||
// fSuccessfullyConnected set.
|
||||
m_addrman.Connected(node.addr);
|
||||
}
|
||||
|
||||
LogPrint(BCLog::NET, "Cleared nodestate for peer=%d\n", nodeid);
|
||||
}
|
||||
|
||||
bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats) {
|
||||
{
|
||||
LOCK(cs_main);
|
||||
CNodeState* state = State(nodeid);
|
||||
if (state == nullptr)
|
||||
return false;
|
||||
stats.nMisbehavior = state->nMisbehavior;
|
||||
stats.nSyncHeight = state->pindexBestKnownBlock ? state->pindexBestKnownBlock->nHeight : -1;
|
||||
stats.nCommonHeight = state->pindexLastCommonBlock ? state->pindexLastCommonBlock->nHeight : -1;
|
||||
for (const QueuedBlock& queue : state->vBlocksInFlight) {
|
||||
if (queue.pindex)
|
||||
stats.vHeightInFlight.push_back(queue.pindex->nHeight);
|
||||
}
|
||||
}
|
||||
|
||||
PeerRef peer = GetPeerRef(nodeid);
|
||||
if (peer == nullptr) return false;
|
||||
stats.nMisbehavior = WITH_LOCK(peer->m_misbehavior_mutex, return peer->nMisbehavior);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1125,33 +1181,35 @@ void static ProcessOrphanTx(CConnman& connman, CTxMemPool& mempool, std::set<uin
|
||||
/**
|
||||
* Increment peer's misbehavior score. If the new value surpasses banscore (specified on startup or by default), mark node to be discouraged, meaning the peer might be disconnected & added to the discouragement filter.
|
||||
*/
|
||||
void Misbehaving(const NodeId pnode, const int howmuch, const std::string& message) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
||||
void Misbehaving(const NodeId pnode, const int howmuch, const std::string& message)
|
||||
{
|
||||
assert(howmuch > 0);
|
||||
|
||||
CNodeState* const state = State(pnode);
|
||||
if (state == nullptr) return;
|
||||
PeerRef peer = GetPeerRef(pnode);
|
||||
if (peer == nullptr) return;
|
||||
|
||||
state->nMisbehavior += howmuch;
|
||||
LOCK(peer->m_misbehavior_mutex);
|
||||
peer->nMisbehavior += howmuch;
|
||||
const int banscore = gArgs.GetArg("-banscore", DEFAULT_BANSCORE_THRESHOLD);
|
||||
const std::string message_prefixed = message.empty() ? "" : (": " + message);
|
||||
if (state->nMisbehavior >= banscore && state->nMisbehavior - howmuch < banscore)
|
||||
if (peer->nMisbehavior >= banscore && peer->nMisbehavior - howmuch < banscore)
|
||||
{
|
||||
LogPrint(BCLog::NET, "Misbehaving: peer=%d (%d -> %d) DISCOURAGE THRESHOLD EXCEEDED%s\n", pnode, state->nMisbehavior - howmuch, state->nMisbehavior, message_prefixed);
|
||||
state->m_should_discourage = true;
|
||||
LogPrint(BCLog::NET, "Misbehaving: peer=%d (%d -> %d) DISCOURAGE THRESHOLD EXCEEDED%s\n", pnode, peer->nMisbehavior - howmuch, peer->nMisbehavior, message_prefixed);
|
||||
peer->m_should_discourage = true;
|
||||
statsClient.inc("misbehavior.banned", 1.0f);
|
||||
} else {
|
||||
LogPrint(BCLog::NET, "Misbehaving: peer=%d (%d -> %d)%s\n", pnode, state->nMisbehavior - howmuch, state->nMisbehavior, message_prefixed);
|
||||
LogPrint(BCLog::NET, "Misbehaving: peer=%d (%d -> %d)%s\n", pnode, peer->nMisbehavior - howmuch, peer->nMisbehavior, message_prefixed);
|
||||
statsClient.count("misbehavior.amount", howmuch, 1.0);
|
||||
}
|
||||
}
|
||||
|
||||
bool IsBanned(NodeId pnode)
|
||||
{
|
||||
CNodeState *state = State(pnode);
|
||||
if (state == nullptr)
|
||||
PeerRef peer = GetPeerRef(pnode);
|
||||
if (peer == nullptr)
|
||||
return false;
|
||||
if (state->m_should_discourage) {
|
||||
LOCK(peer->m_misbehavior_mutex);
|
||||
if (peer->m_should_discourage) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -1176,7 +1234,6 @@ static bool MaybePunishNode(NodeId nodeid, const CValidationState& state, bool v
|
||||
case ValidationInvalidReason::CONSENSUS:
|
||||
case ValidationInvalidReason::BLOCK_MUTATED:
|
||||
if (!via_compact_block) {
|
||||
LOCK(cs_main);
|
||||
Misbehaving(nodeid, 100, message);
|
||||
return true;
|
||||
}
|
||||
@ -1200,21 +1257,14 @@ static bool MaybePunishNode(NodeId nodeid, const CValidationState& state, bool v
|
||||
case ValidationInvalidReason::BLOCK_INVALID_HEADER:
|
||||
case ValidationInvalidReason::BLOCK_CHECKPOINT:
|
||||
case ValidationInvalidReason::BLOCK_INVALID_PREV:
|
||||
{
|
||||
LOCK(cs_main);
|
||||
Misbehaving(nodeid, 100, message);
|
||||
}
|
||||
return true;
|
||||
// Conflicting (but not necessarily invalid) data or different policy:
|
||||
case ValidationInvalidReason::BLOCK_MISSING_PREV:
|
||||
case ValidationInvalidReason::BLOCK_CHAINLOCK:
|
||||
case ValidationInvalidReason::TX_BAD_SPECIAL:
|
||||
case ValidationInvalidReason::TX_CONFLICT_LOCK:
|
||||
{
|
||||
// TODO: Handle this much more gracefully (10 DoS points is super arbitrary)
|
||||
LOCK(cs_main);
|
||||
Misbehaving(nodeid, 10, message);
|
||||
}
|
||||
return true;
|
||||
case ValidationInvalidReason::RECENT_CONSENSUS_CHANGE:
|
||||
case ValidationInvalidReason::BLOCK_TIME_FUTURE:
|
||||
@ -1250,9 +1300,10 @@ static bool BlockRequestAllowed(const CBlockIndex* pindex, const Consensus::Para
|
||||
(GetBlockProofEquivalentTime(*pindexBestHeader, *pindex, *pindexBestHeader, consensusParams) < STALE_RELAY_AGE_LIMIT);
|
||||
}
|
||||
|
||||
PeerLogicValidation::PeerLogicValidation(CConnman& connman, BanMan* banman, CScheduler &scheduler, ChainstateManager& chainman, CTxMemPool& pool,
|
||||
PeerLogicValidation::PeerLogicValidation(CConnman& connman, CAddrMan& addrman, BanMan* banman, CScheduler &scheduler, ChainstateManager& chainman, CTxMemPool& pool,
|
||||
std::unique_ptr<LLMQContext>& llmq_ctx)
|
||||
: m_connman(connman),
|
||||
m_addrman(addrman),
|
||||
m_banman(banman),
|
||||
m_chainman(chainman),
|
||||
m_mempool(pool),
|
||||
@ -1603,7 +1654,7 @@ static void RelayAddress(const CAddress& addr, bool fReachable, CConnman& connma
|
||||
assert(nRelayNodes <= best.size());
|
||||
|
||||
auto sortfunc = [&best, &hasher, nRelayNodes, addr](CNode* pnode) {
|
||||
if (pnode->nVersion >= CADDR_TIME_VERSION && pnode->IsAddrRelayPeer() && pnode->IsAddrCompatible(addr)) {
|
||||
if (pnode->IsAddrRelayPeer() && pnode->IsAddrCompatible(addr)) {
|
||||
uint64_t hashKey = CSipHasher(hasher).Write(pnode->GetId()).Finalize();
|
||||
for (unsigned int i = 0; i < nRelayNodes; i++) {
|
||||
if (hashKey > best[i].first) {
|
||||
@ -1998,7 +2049,6 @@ inline void static SendBlockTransactions(const CBlock& block, const BlockTransac
|
||||
BlockTransactions resp(req);
|
||||
for (size_t i = 0; i < req.indexes.size(); i++) {
|
||||
if (req.indexes[i] >= block.vtx.size()) {
|
||||
LOCK(cs_main);
|
||||
Misbehaving(pfrom.GetId(), 100, "getblocktxn with out-of-bounds tx indices");
|
||||
return;
|
||||
}
|
||||
@ -2570,7 +2620,6 @@ void PeerLogicValidation::ProcessMessage(
|
||||
(msg_type == NetMsgType::FILTERLOAD ||
|
||||
msg_type == NetMsgType::FILTERADD))
|
||||
{
|
||||
LOCK(cs_main);
|
||||
Misbehaving(pfrom.GetId(), 100);
|
||||
return;
|
||||
}
|
||||
@ -2579,7 +2628,6 @@ void PeerLogicValidation::ProcessMessage(
|
||||
// Each connection can only send one version message
|
||||
if (pfrom.nVersion != 0)
|
||||
{
|
||||
LOCK(cs_main);
|
||||
Misbehaving(pfrom.GetId(), 1, "redundant version message");
|
||||
return;
|
||||
}
|
||||
@ -2601,7 +2649,7 @@ void PeerLogicValidation::ProcessMessage(
|
||||
nServices = ServiceFlags(nServiceInt);
|
||||
if (!pfrom.fInbound)
|
||||
{
|
||||
m_connman.SetServices(pfrom.addr, nServices);
|
||||
m_addrman.SetServices(pfrom.addr, nServices);
|
||||
}
|
||||
if (!pfrom.fInbound && !pfrom.fFeeler && !pfrom.m_manual_connection && !HasAllDesirableServiceFlags(nServices))
|
||||
{
|
||||
@ -2668,7 +2716,6 @@ void PeerLogicValidation::ProcessMessage(
|
||||
|
||||
if (Params().NetworkIDString() == CBaseChainParams::DEVNET) {
|
||||
if (cleanSubVer.find(strprintf("devnet.%s", gArgs.GetDevNetName())) == std::string::npos) {
|
||||
LOCK(cs_main);
|
||||
LogPrintf("connected to wrong devnet. Reported version is %s, expected devnet name is %s\n", cleanSubVer, gArgs.GetDevNetName());
|
||||
if (!pfrom.fInbound)
|
||||
Misbehaving(pfrom.GetId(), 100); // don't try to connect again
|
||||
@ -2738,12 +2785,9 @@ void PeerLogicValidation::ProcessMessage(
|
||||
}
|
||||
|
||||
// Get recent addresses
|
||||
if (pfrom.fOneShot || pfrom.nVersion >= CADDR_TIME_VERSION || m_connman.GetAddressCount() < 1000)
|
||||
{
|
||||
m_connman.PushMessage(&pfrom, CNetMsgMaker(nSendVersion).Make(NetMsgType::GETADDR));
|
||||
pfrom.fGetAddr = true;
|
||||
}
|
||||
m_connman.MarkAddressGood(pfrom.addr);
|
||||
m_addrman.Good(pfrom.addr);
|
||||
}
|
||||
|
||||
std::string remoteAddr;
|
||||
@ -2769,7 +2813,6 @@ void PeerLogicValidation::ProcessMessage(
|
||||
|
||||
if (pfrom.nVersion == 0) {
|
||||
// Must have a version message before anything else
|
||||
LOCK(cs_main);
|
||||
Misbehaving(pfrom.GetId(), 1, "non-version message before version handshake");
|
||||
return;
|
||||
}
|
||||
@ -2784,9 +2827,6 @@ void PeerLogicValidation::ProcessMessage(
|
||||
pfrom.SetRecvVersion(std::min(pfrom.nVersion.load(), PROTOCOL_VERSION));
|
||||
|
||||
if (!pfrom.fInbound) {
|
||||
// Mark this node as currently connected, so we update its timestamp later.
|
||||
LOCK(cs_main);
|
||||
State(pfrom.GetId())->fCurrentlyConnected = true;
|
||||
LogPrintf("New outbound peer connected: version: %d, blocks=%d, peer=%d%s (%s)\n",
|
||||
pfrom.nVersion.load(), pfrom.nStartingHeight,
|
||||
pfrom.GetId(), (fLogIPs ? strprintf(", peeraddr=%s", pfrom.addr.ToString()) : ""),
|
||||
@ -2844,7 +2884,6 @@ void PeerLogicValidation::ProcessMessage(
|
||||
|
||||
if (!pfrom.fSuccessfullyConnected) {
|
||||
// Must have a verack message before anything else
|
||||
LOCK(cs_main);
|
||||
Misbehaving(pfrom.GetId(), 1, "non-verack message before version handshake");
|
||||
return;
|
||||
}
|
||||
@ -2882,16 +2921,11 @@ void PeerLogicValidation::ProcessMessage(
|
||||
|
||||
s >> vAddr;
|
||||
|
||||
// Don't want addr from older versions unless seeding
|
||||
if (pfrom.nVersion < CADDR_TIME_VERSION && m_connman.GetAddressCount() > 1000)
|
||||
return;
|
||||
|
||||
if (!pfrom.IsAddrRelayPeer()) {
|
||||
return;
|
||||
}
|
||||
if (vAddr.size() > 1000)
|
||||
{
|
||||
LOCK(cs_main);
|
||||
Misbehaving(pfrom.GetId(), 20, strprintf("%s message size = %u", msg_type, vAddr.size()));
|
||||
return;
|
||||
}
|
||||
@ -2925,12 +2959,11 @@ void PeerLogicValidation::ProcessMessage(
|
||||
if (fReachable)
|
||||
vAddrOk.push_back(addr);
|
||||
}
|
||||
m_connman.AddNewAddresses(vAddrOk, pfrom.addr, 2 * 60 * 60);
|
||||
m_addrman.Add(vAddrOk, pfrom.addr, 2 * 60 * 60);
|
||||
if (vAddr.size() < 1000)
|
||||
pfrom.fGetAddr = false;
|
||||
if (pfrom.fOneShot)
|
||||
pfrom.fDisconnect = true;
|
||||
statsClient.gauge("peers.knownAddresses", m_connman.GetAddressCount(), 1.0f);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2981,7 +3014,6 @@ void PeerLogicValidation::ProcessMessage(
|
||||
vRecv >> vInv;
|
||||
if (vInv.size() > MAX_INV_SZ)
|
||||
{
|
||||
LOCK(cs_main);
|
||||
Misbehaving(pfrom.GetId(), 20, strprintf("message inv size() = %u", vInv.size()));
|
||||
return;
|
||||
}
|
||||
@ -3072,7 +3104,6 @@ void PeerLogicValidation::ProcessMessage(
|
||||
vRecv >> vInv;
|
||||
if (vInv.size() > MAX_INV_SZ)
|
||||
{
|
||||
LOCK(cs_main);
|
||||
Misbehaving(pfrom.GetId(), 20, strprintf("message getdata size() = %u", vInv.size()));
|
||||
return;
|
||||
}
|
||||
@ -3756,7 +3787,6 @@ void PeerLogicValidation::ProcessMessage(
|
||||
// Bypass the normal CBlock deserialization, as we don't want to risk deserializing 2000 full blocks.
|
||||
unsigned int nCount = ReadCompactSize(vRecv);
|
||||
if (nCount > MAX_HEADERS_RESULTS) {
|
||||
LOCK(cs_main);
|
||||
Misbehaving(pfrom.GetId(), 20, strprintf("headers message size = %u", nCount));
|
||||
return;
|
||||
}
|
||||
@ -3958,7 +3988,6 @@ void PeerLogicValidation::ProcessMessage(
|
||||
if (!filter.IsWithinSizeConstraints())
|
||||
{
|
||||
// There is no excuse for sending a too-large filter
|
||||
LOCK(cs_main);
|
||||
Misbehaving(pfrom.GetId(), 100, "too-large bloom filter");
|
||||
}
|
||||
else if (!pfrom.m_block_relay_only_peer)
|
||||
@ -3988,7 +4017,6 @@ void PeerLogicValidation::ProcessMessage(
|
||||
}
|
||||
}
|
||||
if (bad) {
|
||||
LOCK(cs_main);
|
||||
Misbehaving(pfrom.GetId(), 100, "bad filteradd message");
|
||||
}
|
||||
return;
|
||||
@ -4041,7 +4069,6 @@ void PeerLogicValidation::ProcessMessage(
|
||||
|
||||
if (msg_type == NetMsgType::MNLISTDIFF) {
|
||||
// we have never requested this
|
||||
LOCK(cs_main);
|
||||
Misbehaving(pfrom.GetId(), 100, strprintf("received not-requested mnlistdiff. peer=%d", pfrom.GetId()));
|
||||
return;
|
||||
}
|
||||
@ -4065,7 +4092,6 @@ void PeerLogicValidation::ProcessMessage(
|
||||
|
||||
if (msg_type == NetMsgType::QUORUMROTATIONINFO) {
|
||||
// we have never requested this
|
||||
LOCK(cs_main);
|
||||
Misbehaving(pfrom.GetId(), 100, strprintf("received not-requested quorumrotationinfo. peer=%d", pfrom.GetId()));
|
||||
return;
|
||||
}
|
||||
@ -4142,15 +4168,17 @@ void PeerLogicValidation::ProcessMessage(
|
||||
bool PeerLogicValidation::MaybeDiscourageAndDisconnect(CNode& pnode)
|
||||
{
|
||||
const NodeId peer_id{pnode.GetId()};
|
||||
PeerRef peer = GetPeerRef(peer_id);
|
||||
if (peer == nullptr) return false;
|
||||
|
||||
{
|
||||
LOCK(cs_main);
|
||||
CNodeState& state = *State(peer_id);
|
||||
LOCK(peer->m_misbehavior_mutex);
|
||||
|
||||
// There's nothing to do if the m_should_discourage flag isn't set
|
||||
if (!state.m_should_discourage) return false;
|
||||
if (!peer->m_should_discourage) return false;
|
||||
|
||||
state.m_should_discourage = false;
|
||||
} // cs_main
|
||||
peer->m_should_discourage = false;
|
||||
} // peer.m_misbehavior_mutex
|
||||
|
||||
if (pnode.HasPermission(PF_NOBAN)) {
|
||||
// We never disconnect or discourage peers for bad behavior if they have the NOBAN permission flag
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <sync.h>
|
||||
#include <validationinterface.h>
|
||||
|
||||
class CAddrMan;
|
||||
class CTxMemPool;
|
||||
class ChainstateManager;
|
||||
struct LLMQContext;
|
||||
@ -28,6 +29,7 @@ class PeerLogicValidation final : public CValidationInterface, public NetEventsI
|
||||
private:
|
||||
CConnman& m_connman;
|
||||
BanMan* const m_banman;
|
||||
CAddrMan& m_addrman;
|
||||
ChainstateManager& m_chainman;
|
||||
CTxMemPool& m_mempool;
|
||||
std::unique_ptr<LLMQContext>& m_llmq_ctx;
|
||||
@ -35,7 +37,7 @@ private:
|
||||
bool MaybeDiscourageAndDisconnect(CNode& pnode);
|
||||
|
||||
public:
|
||||
PeerLogicValidation(CConnman& connman, BanMan* banman, CScheduler &scheduler, ChainstateManager& chainman, CTxMemPool& pool,
|
||||
PeerLogicValidation(CConnman& connman, CAddrMan& addrman, BanMan* banman, CScheduler &scheduler, ChainstateManager& chainman, CTxMemPool& pool,
|
||||
std::unique_ptr<LLMQContext>& llmq_ctx);
|
||||
|
||||
/**
|
||||
@ -59,7 +61,7 @@ public:
|
||||
/** Initialize a peer by adding it to mapNodeState and pushing a message requesting its version */
|
||||
void InitializeNode(CNode* pnode) override;
|
||||
/** Handle removal of a peer by updating various state and removing it from mapNodeState */
|
||||
void FinalizeNode(NodeId nodeid, bool& fUpdateConnectionTime) override;
|
||||
void FinalizeNode(const CNode& node) override;
|
||||
/**
|
||||
* Process protocol messages received from a given node
|
||||
*
|
||||
@ -104,7 +106,7 @@ bool IsBanned(NodeId nodeid) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||
// Upstream moved this into net_processing.cpp (13417), however since we use Misbehaving in a number of dash specific
|
||||
// files such as mnauth.cpp and governance.cpp it makes sense to keep it in the header
|
||||
/** Increase a node's misbehavior score. */
|
||||
void Misbehaving(NodeId nodeid, int howmuch, const std::string& message="") EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||
void Misbehaving(const NodeId pnode, const int howmuch, const std::string& message="");
|
||||
|
||||
void EraseObjectRequest(NodeId nodeId, const CInv& inv) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||
void RequestObject(NodeId nodeId, const CInv& inv, std::chrono::microseconds current_time, bool fForce=false) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||
|
@ -4,12 +4,14 @@
|
||||
|
||||
#include <node/context.h>
|
||||
|
||||
#include <addrman.h>
|
||||
#include <banman.h>
|
||||
#include <interfaces/chain.h>
|
||||
#include <llmq/context.h>
|
||||
#include <evo/evodb.h>
|
||||
#include <net.h>
|
||||
#include <net_processing.h>
|
||||
#include <policy/fees.h>
|
||||
#include <scheduler.h>
|
||||
#include <txmempool.h>
|
||||
|
||||
|
@ -12,6 +12,8 @@
|
||||
|
||||
class ArgsManager;
|
||||
class BanMan;
|
||||
class CAddrMan;
|
||||
class CBlockPolicyEstimator;
|
||||
class CConnman;
|
||||
class CScheduler;
|
||||
class CTxMemPool;
|
||||
@ -36,8 +38,10 @@ class WalletClient;
|
||||
//! any member functions. It should just be a collection of references that can
|
||||
//! be used without pulling in unwanted dependencies or functionality.
|
||||
struct NodeContext {
|
||||
std::unique_ptr<CAddrMan> addrman;
|
||||
std::unique_ptr<CConnman> connman;
|
||||
std::unique_ptr<CTxMemPool> mempool;
|
||||
std::unique_ptr<CBlockPolicyEstimator> fee_estimator;
|
||||
std::unique_ptr<PeerLogicValidation> peer_logic;
|
||||
ChainstateManager* chainman{nullptr}; // Currently a raw pointer because the memory is not managed by this struct
|
||||
std::unique_ptr<BanMan> banman;
|
||||
|
@ -10,6 +10,8 @@
|
||||
#include <txmempool.h>
|
||||
#include <util/system.h>
|
||||
|
||||
static const char* FEE_ESTIMATES_FILENAME="fee_estimates.dat";
|
||||
|
||||
static constexpr double INF_FEERATE = 1e99;
|
||||
|
||||
std::string StringForFeeEstimateHorizon(FeeEstimateHorizon horizon) {
|
||||
@ -488,6 +490,7 @@ CBlockPolicyEstimator::CBlockPolicyEstimator()
|
||||
{
|
||||
static_assert(MIN_BUCKET_FEERATE > 0, "Min feerate must be nonzero");
|
||||
size_t bucketIndex = 0;
|
||||
|
||||
for (double bucketBoundary = MIN_BUCKET_FEERATE; bucketBoundary <= MAX_BUCKET_FEERATE; bucketBoundary *= FEE_SPACING, bucketIndex++) {
|
||||
buckets.push_back(bucketBoundary);
|
||||
bucketMap[bucketBoundary] = bucketIndex;
|
||||
@ -499,6 +502,13 @@ CBlockPolicyEstimator::CBlockPolicyEstimator()
|
||||
feeStats = std::make_unique<TxConfirmStats>(buckets, bucketMap, MED_BLOCK_PERIODS, MED_DECAY, MED_SCALE);
|
||||
shortStats = std::make_unique<TxConfirmStats>(buckets, bucketMap, SHORT_BLOCK_PERIODS, SHORT_DECAY, SHORT_SCALE);
|
||||
longStats = std::make_unique<TxConfirmStats>(buckets, bucketMap, LONG_BLOCK_PERIODS, LONG_DECAY, LONG_SCALE);
|
||||
|
||||
// If the fee estimation file is present, read recorded estimations
|
||||
fs::path est_filepath = GetDataDir() / FEE_ESTIMATES_FILENAME;
|
||||
CAutoFile est_file(fsbridge::fopen(est_filepath, "rb"), SER_DISK, CLIENT_VERSION);
|
||||
if (est_file.IsNull() || !Read(est_file)) {
|
||||
LogPrintf("Failed to read fee estimates from %s. Continue anyway.\n", est_filepath.string());
|
||||
}
|
||||
}
|
||||
|
||||
CBlockPolicyEstimator::~CBlockPolicyEstimator()
|
||||
@ -854,6 +864,15 @@ CFeeRate CBlockPolicyEstimator::estimateSmartFee(int confTarget, FeeCalculation
|
||||
return CFeeRate(llround(median));
|
||||
}
|
||||
|
||||
void CBlockPolicyEstimator::Flush() {
|
||||
FlushUnconfirmed();
|
||||
|
||||
fs::path est_filepath = GetDataDir() / FEE_ESTIMATES_FILENAME;
|
||||
CAutoFile est_file(fsbridge::fopen(est_filepath, "wb"), SER_DISK, CLIENT_VERSION);
|
||||
if (est_file.IsNull() || !Write(est_file)) {
|
||||
LogPrintf("Failed to write fee estimates to %s\n", est_filepath.string());
|
||||
}
|
||||
}
|
||||
|
||||
bool CBlockPolicyEstimator::Write(CAutoFile& fileout) const
|
||||
{
|
||||
|
@ -222,6 +222,9 @@ public:
|
||||
/** Calculation of highest target that estimates are tracked for */
|
||||
unsigned int HighestTargetTracked(FeeEstimateHorizon horizon) const;
|
||||
|
||||
/** Drop still unconfirmed transactions and record current estimations, if the fee estimation file is present. */
|
||||
void Flush();
|
||||
|
||||
private:
|
||||
mutable CCriticalSection m_cs_fee_estimator;
|
||||
|
||||
|
@ -408,7 +408,13 @@ public:
|
||||
READWRITE(nVersion);
|
||||
}
|
||||
if ((s.GetType() & SER_DISK) ||
|
||||
(nVersion >= CADDR_TIME_VERSION && !(s.GetType() & SER_GETHASH))) {
|
||||
(nVersion != INIT_PROTO_VERSION && !(s.GetType() & SER_GETHASH))) {
|
||||
// The only time we serialize a CAddress object without nTime is in
|
||||
// the initial VERSION messages which contain two CAddress records.
|
||||
// At that point, the serialization version is INIT_PROTO_VERSION.
|
||||
// After the version handshake, serialization version is >=
|
||||
// MIN_PEER_PROTO_VERSION and all ADDR messages are serialized with
|
||||
// nTime.
|
||||
READWRITE(obj.nTime);
|
||||
}
|
||||
if (nVersion & ADDRV2_FORMAT) {
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include <node/coinstats.h>
|
||||
#include <node/context.h>
|
||||
#include <node/utxo_snapshot.h>
|
||||
#include <policy/fees.h>
|
||||
#include <policy/policy.h>
|
||||
#include <primitives/transaction.h>
|
||||
#include <rpc/server.h>
|
||||
@ -91,6 +92,15 @@ ChainstateManager& EnsureChainman(const CoreContext& context)
|
||||
return *node.chainman;
|
||||
}
|
||||
|
||||
CBlockPolicyEstimator& EnsureFeeEstimator(const CoreContext& context)
|
||||
{
|
||||
NodeContext& node = EnsureNodeContext(context);
|
||||
if (!node.fee_estimator) {
|
||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Fee estimation disabled");
|
||||
}
|
||||
return *node.fee_estimator;
|
||||
}
|
||||
|
||||
LLMQContext& EnsureLLMQContext(const CoreContext& context)
|
||||
{
|
||||
NodeContext& node = EnsureNodeContext(context);
|
||||
|
@ -16,6 +16,7 @@ extern RecursiveMutex cs_main;
|
||||
|
||||
class CBlock;
|
||||
class CBlockIndex;
|
||||
class CBlockPolicyEstimator;
|
||||
class CTxMemPool;
|
||||
class ChainstateManager;
|
||||
class UniValue;
|
||||
@ -55,8 +56,9 @@ UniValue blockheaderToJSON(const CBlockIndex* tip, const CBlockIndex* blockindex
|
||||
void CalculatePercentilesBySize(CAmount result[NUM_GETBLOCKSTATS_PERCENTILES], std::vector<std::pair<CAmount, int64_t>>& scores, int64_t total_size);
|
||||
|
||||
NodeContext& EnsureNodeContext(const CoreContext& context);
|
||||
LLMQContext& EnsureLLMQContext(const CoreContext& context);
|
||||
CTxMemPool& EnsureMemPool(const CoreContext& context);
|
||||
ChainstateManager& EnsureChainman(const CoreContext& context);
|
||||
CBlockPolicyEstimator& EnsureFeeEstimator(const CoreContext& context);
|
||||
LLMQContext& EnsureLLMQContext(const CoreContext& context);
|
||||
|
||||
#endif
|
||||
|
@ -64,7 +64,7 @@ static UniValue coinjoin(const JSONRPCRequest& request)
|
||||
|
||||
const NodeContext& node = EnsureNodeContext(request.context);
|
||||
CTxMemPool& mempool = EnsureMemPool(request.context);
|
||||
bool result = it->second->DoAutomaticDenominating(mempool, *node.connman);
|
||||
bool result = it->second->DoAutomaticDenominating(*node.connman, *node.fee_estimator, mempool);
|
||||
return "Mixing " + (result ? "started successfully" : ("start failed: " + it->second->GetStatuses().original + ", will retry"));
|
||||
}
|
||||
|
||||
|
@ -1096,7 +1096,10 @@ static UniValue estimatesmartfee(const JSONRPCRequest& request)
|
||||
|
||||
RPCTypeCheck(request.params, {UniValue::VNUM, UniValue::VSTR});
|
||||
RPCTypeCheckArgument(request.params[0], UniValue::VNUM);
|
||||
unsigned int max_target = ::feeEstimator.HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE);
|
||||
|
||||
CBlockPolicyEstimator& fee_estimator = EnsureFeeEstimator(request.context);
|
||||
|
||||
unsigned int max_target = fee_estimator.HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE);
|
||||
unsigned int conf_target = ParseConfirmTarget(request.params[0], max_target);
|
||||
bool conservative = true;
|
||||
if (!request.params[1].isNull()) {
|
||||
@ -1110,7 +1113,7 @@ static UniValue estimatesmartfee(const JSONRPCRequest& request)
|
||||
UniValue result(UniValue::VOBJ);
|
||||
UniValue errors(UniValue::VARR);
|
||||
FeeCalculation feeCalc;
|
||||
CFeeRate feeRate = ::feeEstimator.estimateSmartFee(conf_target, &feeCalc, conservative);
|
||||
CFeeRate feeRate = fee_estimator.estimateSmartFee(conf_target, &feeCalc, conservative);
|
||||
if (feeRate != CFeeRate(0)) {
|
||||
result.pushKV("feerate", ValueFromAmount(feeRate.GetFeePerK()));
|
||||
} else {
|
||||
@ -1178,7 +1181,10 @@ static UniValue estimaterawfee(const JSONRPCRequest& request)
|
||||
|
||||
RPCTypeCheck(request.params, {UniValue::VNUM, UniValue::VNUM}, true);
|
||||
RPCTypeCheckArgument(request.params[0], UniValue::VNUM);
|
||||
unsigned int max_target = ::feeEstimator.HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE);
|
||||
|
||||
CBlockPolicyEstimator& fee_estimator = EnsureFeeEstimator(request.context);
|
||||
|
||||
unsigned int max_target = fee_estimator.HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE);
|
||||
unsigned int conf_target = ParseConfirmTarget(request.params[0], max_target);
|
||||
double threshold = 0.95;
|
||||
if (!request.params[1].isNull()) {
|
||||
@ -1195,9 +1201,9 @@ static UniValue estimaterawfee(const JSONRPCRequest& request)
|
||||
EstimationResult buckets;
|
||||
|
||||
// Only output results for horizons which track the target
|
||||
if (conf_target > ::feeEstimator.HighestTargetTracked(horizon)) continue;
|
||||
if (conf_target > fee_estimator.HighestTargetTracked(horizon)) continue;
|
||||
|
||||
feeRate = ::feeEstimator.estimateRawFee(conf_target, threshold, horizon, &buckets);
|
||||
feeRate = fee_estimator.estimateRawFee(conf_target, threshold, horizon, &buckets);
|
||||
UniValue horizon_result(UniValue::VOBJ);
|
||||
UniValue errors(UniValue::VARR);
|
||||
UniValue passbucket(UniValue::VOBJ);
|
||||
|
@ -130,7 +130,6 @@ void CSporkManager::ProcessSpork(const CNode& peer, CConnman& connman, CDataStre
|
||||
}
|
||||
|
||||
if (spork.nTimeSigned > GetAdjustedTime() + 2 * 60 * 60) {
|
||||
LOCK(cs_main);
|
||||
LogPrint(BCLog::SPORK, "CSporkManager::ProcessSpork -- ERROR: too far into the future\n");
|
||||
Misbehaving(peer.GetId(), 100);
|
||||
return;
|
||||
@ -139,7 +138,6 @@ void CSporkManager::ProcessSpork(const CNode& peer, CConnman& connman, CDataStre
|
||||
auto opt_keyIDSigner = spork.GetSignerKeyID();
|
||||
|
||||
if (opt_keyIDSigner == std::nullopt || WITH_LOCK(cs, return !setSporkPubKeyIDs.count(*opt_keyIDSigner))) {
|
||||
LOCK(cs_main);
|
||||
LogPrint(BCLog::SPORK, "CSporkManager::ProcessSpork -- ERROR: invalid signature\n");
|
||||
Misbehaving(peer.GetId(), 100);
|
||||
return;
|
||||
|
@ -80,9 +80,9 @@ BOOST_FIXTURE_TEST_SUITE(denialofservice_tests, TestingSetup)
|
||||
// work.
|
||||
BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction)
|
||||
{
|
||||
auto connman = std::make_unique<CConnman>(0x1337, 0x1337);
|
||||
auto connman = std::make_unique<CConnman>(0x1337, 0x1337, *m_node.addrman);
|
||||
auto peerLogic = std::make_unique<PeerLogicValidation>(
|
||||
*connman, nullptr, *m_node.scheduler, *m_node.chainman, *m_node.mempool, m_node.llmq_ctx
|
||||
*connman, *m_node.addrman, nullptr, *m_node.scheduler, *m_node.chainman, *m_node.mempool, m_node.llmq_ctx
|
||||
);
|
||||
|
||||
// Mock an outbound peer
|
||||
@ -133,8 +133,7 @@ BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction)
|
||||
BOOST_CHECK(dummyNode1.fDisconnect == true);
|
||||
SetMockTime(0);
|
||||
|
||||
bool dummy;
|
||||
peerLogic->FinalizeNode(dummyNode1.GetId(), dummy);
|
||||
peerLogic->FinalizeNode(dummyNode1);
|
||||
}
|
||||
|
||||
static void AddRandomOutboundPeer(std::vector<CNode *> &vNodes, PeerLogicValidation &peerLogic, CConnmanTest* connman)
|
||||
@ -153,9 +152,9 @@ static void AddRandomOutboundPeer(std::vector<CNode *> &vNodes, PeerLogicValidat
|
||||
|
||||
BOOST_AUTO_TEST_CASE(stale_tip_peer_management)
|
||||
{
|
||||
auto connman = std::make_unique<CConnmanTest>(0x1337, 0x1337);
|
||||
auto connman = std::make_unique<CConnmanTest>(0x1337, 0x1337, *m_node.addrman);
|
||||
auto peerLogic = std::make_unique<PeerLogicValidation>(
|
||||
*connman, nullptr, *m_node.scheduler, *m_node.chainman, *m_node.mempool, m_node.llmq_ctx
|
||||
*connman, *m_node.addrman, nullptr, *m_node.scheduler, *m_node.chainman, *m_node.mempool, m_node.llmq_ctx
|
||||
);
|
||||
|
||||
const Consensus::Params& consensusParams = Params().GetConsensus();
|
||||
@ -217,9 +216,8 @@ BOOST_AUTO_TEST_CASE(stale_tip_peer_management)
|
||||
BOOST_CHECK(vNodes[max_outbound_full_relay-1]->fDisconnect == true);
|
||||
BOOST_CHECK(vNodes.back()->fDisconnect == false);
|
||||
|
||||
bool dummy;
|
||||
for (const CNode *node : vNodes) {
|
||||
peerLogic->FinalizeNode(node->GetId(), dummy);
|
||||
peerLogic->FinalizeNode(*node);
|
||||
}
|
||||
|
||||
connman->ClearNodes();
|
||||
@ -228,9 +226,9 @@ BOOST_AUTO_TEST_CASE(stale_tip_peer_management)
|
||||
BOOST_AUTO_TEST_CASE(DoS_banning)
|
||||
{
|
||||
auto banman = std::make_unique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
|
||||
auto connman = std::make_unique<CConnman>(0x1337, 0x1337);
|
||||
auto connman = std::make_unique<CConnman>(0x1337, 0x1337, *m_node.addrman);
|
||||
auto peerLogic = std::make_unique<PeerLogicValidation>(
|
||||
*connman, banman.get(), *m_node.scheduler, *m_node.chainman, *m_node.mempool, m_node.llmq_ctx
|
||||
*connman, *m_node.addrman, banman.get(), *m_node.scheduler, *m_node.chainman, *m_node.mempool, m_node.llmq_ctx
|
||||
);
|
||||
|
||||
banman->ClearBanned();
|
||||
@ -240,10 +238,7 @@ BOOST_AUTO_TEST_CASE(DoS_banning)
|
||||
peerLogic->InitializeNode(&dummyNode1);
|
||||
dummyNode1.nVersion = 1;
|
||||
dummyNode1.fSuccessfullyConnected = true;
|
||||
{
|
||||
LOCK(cs_main);
|
||||
Misbehaving(dummyNode1.GetId(), 100); // Should get banned
|
||||
}
|
||||
{
|
||||
LOCK(dummyNode1.cs_sendProcessing);
|
||||
BOOST_CHECK(peerLogic->SendMessages(&dummyNode1));
|
||||
@ -257,37 +252,30 @@ BOOST_AUTO_TEST_CASE(DoS_banning)
|
||||
peerLogic->InitializeNode(&dummyNode2);
|
||||
dummyNode2.nVersion = 1;
|
||||
dummyNode2.fSuccessfullyConnected = true;
|
||||
{
|
||||
LOCK(cs_main);
|
||||
Misbehaving(dummyNode2.GetId(), 50);
|
||||
}
|
||||
{
|
||||
LOCK(dummyNode2.cs_sendProcessing);
|
||||
BOOST_CHECK(peerLogic->SendMessages(&dummyNode2));
|
||||
}
|
||||
BOOST_CHECK(!banman->IsDiscouraged(addr2)); // 2 not banned yet...
|
||||
BOOST_CHECK(banman->IsDiscouraged(addr1)); // ... but 1 still should be
|
||||
{
|
||||
LOCK(cs_main);
|
||||
Misbehaving(dummyNode2.GetId(), 50);
|
||||
}
|
||||
{
|
||||
LOCK(dummyNode2.cs_sendProcessing);
|
||||
BOOST_CHECK(peerLogic->SendMessages(&dummyNode2));
|
||||
}
|
||||
BOOST_CHECK(banman->IsDiscouraged(addr2));
|
||||
|
||||
bool dummy;
|
||||
peerLogic->FinalizeNode(dummyNode1.GetId(), dummy);
|
||||
peerLogic->FinalizeNode(dummyNode2.GetId(), dummy);
|
||||
peerLogic->FinalizeNode(dummyNode1);
|
||||
peerLogic->FinalizeNode(dummyNode2);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(DoS_banscore)
|
||||
{
|
||||
auto banman = std::make_unique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
|
||||
auto connman = std::make_unique<CConnman>(0x1337, 0x1337);
|
||||
auto connman = std::make_unique<CConnman>(0x1337, 0x1337, *m_node.addrman);
|
||||
auto peerLogic = std::make_unique<PeerLogicValidation>(
|
||||
*connman, banman.get(), *m_node.scheduler, *m_node.chainman, *m_node.mempool, m_node.llmq_ctx
|
||||
*connman, *m_node.addrman, banman.get(), *m_node.scheduler, *m_node.chainman, *m_node.mempool, m_node.llmq_ctx
|
||||
);
|
||||
|
||||
banman->ClearBanned();
|
||||
@ -299,7 +287,6 @@ BOOST_AUTO_TEST_CASE(DoS_banscore)
|
||||
dummyNode1.nVersion = 1;
|
||||
dummyNode1.fSuccessfullyConnected = true;
|
||||
{
|
||||
LOCK(cs_main);
|
||||
Misbehaving(dummyNode1.GetId(), 100);
|
||||
}
|
||||
{
|
||||
@ -308,7 +295,6 @@ BOOST_AUTO_TEST_CASE(DoS_banscore)
|
||||
}
|
||||
BOOST_CHECK(!banman->IsDiscouraged(addr1));
|
||||
{
|
||||
LOCK(cs_main);
|
||||
Misbehaving(dummyNode1.GetId(), 10);
|
||||
}
|
||||
{
|
||||
@ -317,7 +303,6 @@ BOOST_AUTO_TEST_CASE(DoS_banscore)
|
||||
}
|
||||
BOOST_CHECK(!banman->IsDiscouraged(addr1));
|
||||
{
|
||||
LOCK(cs_main);
|
||||
Misbehaving(dummyNode1.GetId(), 1);
|
||||
}
|
||||
{
|
||||
@ -327,16 +312,15 @@ BOOST_AUTO_TEST_CASE(DoS_banscore)
|
||||
BOOST_CHECK(banman->IsDiscouraged(addr1));
|
||||
gArgs.ForceSetArg("-banscore", ToString(DEFAULT_BANSCORE_THRESHOLD));
|
||||
|
||||
bool dummy;
|
||||
peerLogic->FinalizeNode(dummyNode1.GetId(), dummy);
|
||||
peerLogic->FinalizeNode(dummyNode1);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(DoS_bantime)
|
||||
{
|
||||
auto banman = std::make_unique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
|
||||
auto connman = std::make_unique<CConnman>(0x1337, 0x1337);
|
||||
auto connman = std::make_unique<CConnman>(0x1337, 0x1337, *m_node.addrman);
|
||||
auto peerLogic = std::make_unique<PeerLogicValidation>(
|
||||
*connman, banman.get(), *m_node.scheduler, *m_node.chainman, *m_node.mempool, m_node.llmq_ctx
|
||||
*connman, *m_node.addrman, banman.get(), *m_node.scheduler, *m_node.chainman, *m_node.mempool, m_node.llmq_ctx
|
||||
);
|
||||
|
||||
banman->ClearBanned();
|
||||
@ -350,18 +334,14 @@ BOOST_AUTO_TEST_CASE(DoS_bantime)
|
||||
dummyNode.nVersion = 1;
|
||||
dummyNode.fSuccessfullyConnected = true;
|
||||
|
||||
{
|
||||
LOCK(cs_main);
|
||||
Misbehaving(dummyNode.GetId(), 100);
|
||||
}
|
||||
{
|
||||
LOCK(dummyNode.cs_sendProcessing);
|
||||
BOOST_CHECK(peerLogic->SendMessages(&dummyNode));
|
||||
}
|
||||
BOOST_CHECK(banman->IsDiscouraged(addr));
|
||||
|
||||
bool dummy;
|
||||
peerLogic->FinalizeNode(dummyNode.GetId(), dummy);
|
||||
peerLogic->FinalizeNode(dummyNode);
|
||||
}
|
||||
|
||||
static CTransactionRef RandomOrphan()
|
||||
|
@ -23,116 +23,94 @@ void initialize_connman()
|
||||
FUZZ_TARGET_INIT(connman, initialize_connman)
|
||||
{
|
||||
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
|
||||
CConnman connman{fuzzed_data_provider.ConsumeIntegral<uint64_t>(), fuzzed_data_provider.ConsumeIntegral<uint64_t>()};
|
||||
CAddress random_address;
|
||||
CAddrMan addrman;
|
||||
CConnman connman{fuzzed_data_provider.ConsumeIntegral<uint64_t>(), fuzzed_data_provider.ConsumeIntegral<uint64_t>(), addrman};
|
||||
CNetAddr random_netaddr;
|
||||
CNode random_node = ConsumeNode(fuzzed_data_provider);
|
||||
CService random_service;
|
||||
CSubNet random_subnet;
|
||||
std::string random_string;
|
||||
while (fuzzed_data_provider.ConsumeBool()) {
|
||||
switch (fuzzed_data_provider.ConsumeIntegralInRange<int>(0, 28)) {
|
||||
switch (fuzzed_data_provider.ConsumeIntegralInRange<int>(0, 23)) {
|
||||
case 0:
|
||||
random_address = ConsumeAddress(fuzzed_data_provider);
|
||||
break;
|
||||
case 1:
|
||||
random_netaddr = ConsumeNetAddr(fuzzed_data_provider);
|
||||
break;
|
||||
case 2:
|
||||
random_service = ConsumeService(fuzzed_data_provider);
|
||||
break;
|
||||
case 3:
|
||||
case 1:
|
||||
random_subnet = ConsumeSubNet(fuzzed_data_provider);
|
||||
break;
|
||||
case 4:
|
||||
case 2:
|
||||
random_string = fuzzed_data_provider.ConsumeRandomLengthString(64);
|
||||
break;
|
||||
case 5: {
|
||||
std::vector<CAddress> addresses;
|
||||
while (fuzzed_data_provider.ConsumeBool()) {
|
||||
addresses.push_back(ConsumeAddress(fuzzed_data_provider));
|
||||
}
|
||||
// Limit nTimePenalty to int32_t to avoid signed integer overflow
|
||||
(void)connman.AddNewAddresses(addresses, ConsumeAddress(fuzzed_data_provider), fuzzed_data_provider.ConsumeIntegral<int32_t>());
|
||||
break;
|
||||
}
|
||||
case 6:
|
||||
case 3:
|
||||
connman.AddNode(random_string);
|
||||
break;
|
||||
case 7:
|
||||
case 4:
|
||||
connman.CheckIncomingNonce(fuzzed_data_provider.ConsumeIntegral<uint64_t>());
|
||||
break;
|
||||
case 8:
|
||||
case 5:
|
||||
connman.DisconnectNode(fuzzed_data_provider.ConsumeIntegral<NodeId>());
|
||||
break;
|
||||
case 9:
|
||||
case 6:
|
||||
connman.DisconnectNode(random_netaddr);
|
||||
break;
|
||||
case 10:
|
||||
case 7:
|
||||
connman.DisconnectNode(random_string);
|
||||
break;
|
||||
case 11:
|
||||
case 8:
|
||||
connman.DisconnectNode(random_subnet);
|
||||
break;
|
||||
case 12:
|
||||
case 9:
|
||||
connman.ForEachNode([](auto) {});
|
||||
break;
|
||||
case 13:
|
||||
case 10:
|
||||
connman.ForEachNodeThen([](auto) {}, []() {});
|
||||
break;
|
||||
case 14:
|
||||
case 11:
|
||||
(void)connman.ForNode(fuzzed_data_provider.ConsumeIntegral<NodeId>(), [&](auto) { return fuzzed_data_provider.ConsumeBool(); });
|
||||
break;
|
||||
case 15:
|
||||
case 12:
|
||||
(void)connman.GetAddresses();
|
||||
break;
|
||||
case 16: {
|
||||
case 13: {
|
||||
(void)connman.GetAddresses();
|
||||
break;
|
||||
}
|
||||
case 17:
|
||||
case 14:
|
||||
(void)connman.GetDeterministicRandomizer(fuzzed_data_provider.ConsumeIntegral<uint64_t>());
|
||||
break;
|
||||
case 18:
|
||||
case 15:
|
||||
(void)connman.GetNodeCount(fuzzed_data_provider.PickValueInArray({CConnman::CONNECTIONS_NONE, CConnman::CONNECTIONS_IN, CConnman::CONNECTIONS_OUT, CConnman::CONNECTIONS_ALL}));
|
||||
break;
|
||||
case 19:
|
||||
connman.MarkAddressGood(random_address);
|
||||
break;
|
||||
case 20:
|
||||
case 16:
|
||||
(void)connman.OutboundTargetReached(fuzzed_data_provider.ConsumeBool());
|
||||
break;
|
||||
case 21:
|
||||
case 17:
|
||||
// Limit now to int32_t to avoid signed integer overflow
|
||||
(void)connman.PoissonNextSendInbound(fuzzed_data_provider.ConsumeIntegral<int32_t>(), fuzzed_data_provider.ConsumeIntegral<int>());
|
||||
break;
|
||||
case 22: {
|
||||
case 18: {
|
||||
CSerializedNetMsg serialized_net_msg;
|
||||
serialized_net_msg.command = fuzzed_data_provider.ConsumeRandomLengthString(CMessageHeader::COMMAND_SIZE);
|
||||
serialized_net_msg.data = ConsumeRandomLengthByteVector(fuzzed_data_provider);
|
||||
connman.PushMessage(&random_node, std::move(serialized_net_msg));
|
||||
break;
|
||||
}
|
||||
case 23:
|
||||
case 19:
|
||||
connman.RemoveAddedNode(random_string);
|
||||
break;
|
||||
case 24: {
|
||||
case 20: {
|
||||
const std::vector<bool> asmap = ConsumeRandomLengthBitVector(fuzzed_data_provider);
|
||||
if (SanityCheckASMap(asmap)) {
|
||||
connman.SetAsmap(asmap);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 25:
|
||||
case 21:
|
||||
connman.SetBestHeight(fuzzed_data_provider.ConsumeIntegral<int>());
|
||||
break;
|
||||
case 26:
|
||||
case 22:
|
||||
connman.SetNetworkActive(fuzzed_data_provider.ConsumeBool());
|
||||
break;
|
||||
case 27:
|
||||
connman.SetServices(random_service, static_cast<ServiceFlags>(fuzzed_data_provider.ConsumeIntegral<uint64_t>()));
|
||||
break;
|
||||
case 28:
|
||||
case 23:
|
||||
connman.SetTryNewOutboundPeer(fuzzed_data_provider.ConsumeBool());
|
||||
break;
|
||||
}
|
||||
|
@ -52,7 +52,8 @@ FUZZ_TARGET_INIT(net, initialize_net)
|
||||
while (fuzzed_data_provider.ConsumeBool()) {
|
||||
switch (fuzzed_data_provider.ConsumeIntegralInRange<int>(0, 12)) {
|
||||
case 0: {
|
||||
CConnman connman{fuzzed_data_provider.ConsumeIntegral<uint64_t>(), fuzzed_data_provider.ConsumeIntegral<uint64_t>()};
|
||||
CAddrMan addrman;
|
||||
CConnman connman{fuzzed_data_provider.ConsumeIntegral<uint64_t>(), fuzzed_data_provider.ConsumeIntegral<uint64_t>(), addrman};
|
||||
node.CloseSocketDisconnect(&connman);
|
||||
break;
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
#include <test/util/setup_common.h>
|
||||
|
||||
#include <addrman.h>
|
||||
#include <banman.h>
|
||||
#include <chainparams.h>
|
||||
#include <consensus/consensus.h>
|
||||
@ -28,6 +29,7 @@
|
||||
#include <net.h>
|
||||
#include <net_processing.h>
|
||||
#include <noui.h>
|
||||
#include <policy/fees.h>
|
||||
#include <pow.h>
|
||||
#include <rpc/blockchain.h>
|
||||
#include <rpc/register.h>
|
||||
@ -130,11 +132,12 @@ BasicTestingSetup::BasicTestingSetup(const std::string& chainName, const std::ve
|
||||
SetupNetworking();
|
||||
InitSignatureCache();
|
||||
InitScriptExecutionCache();
|
||||
m_node.addrman = std::make_unique<CAddrMan>();
|
||||
m_node.chain = interfaces::MakeChain(m_node);
|
||||
g_wallet_init_interface.Construct(m_node);
|
||||
fCheckBlockIndex = true;
|
||||
m_node.evodb = std::make_unique<CEvoDB>(1 << 20, true, true);
|
||||
connman = std::make_unique<CConnman>(0x1337, 0x1337);
|
||||
connman = std::make_unique<CConnman>(0x1337, 0x1337, *m_node.addrman);
|
||||
deterministicMNManager.reset(new CDeterministicMNManager(*m_node.evodb, *connman));
|
||||
llmq::quorumSnapshotManager.reset(new llmq::CQuorumSnapshotManager(*m_node.evodb));
|
||||
static bool noui_connected = false;
|
||||
@ -169,12 +172,12 @@ ChainTestingSetup::ChainTestingSetup(const std::string& chainName, const std::ve
|
||||
|
||||
pblocktree.reset(new CBlockTreeDB(1 << 20, true));
|
||||
|
||||
m_node.mempool = std::make_unique<CTxMemPool>(&::feeEstimator);
|
||||
m_node.mempool->setSanityCheck(1.0);
|
||||
m_node.fee_estimator = std::make_unique<CBlockPolicyEstimator>();
|
||||
m_node.mempool = std::make_unique<CTxMemPool>(m_node.fee_estimator.get(), 1);
|
||||
|
||||
m_node.chainman = &::g_chainman;
|
||||
|
||||
m_node.connman = std::make_unique<CConnman>(0x1337, 0x1337); // Deterministic randomness for tests.
|
||||
m_node.connman = std::make_unique<CConnman>(0x1337, 0x1337, *m_node.addrman); // Deterministic randomness for tests.
|
||||
|
||||
::sporkManager = std::make_unique<CSporkManager>();
|
||||
::governance = std::make_unique<CGovernanceManager>();
|
||||
@ -210,10 +213,11 @@ ChainTestingSetup::~ChainTestingSetup()
|
||||
::governance.reset();
|
||||
::sporkManager.reset();
|
||||
m_node.connman.reset();
|
||||
m_node.addrman.reset();
|
||||
m_node.args = nullptr;
|
||||
m_node.banman.reset();
|
||||
UnloadBlockIndex(m_node.mempool.get());
|
||||
m_node.mempool.reset();
|
||||
m_node.args = nullptr;
|
||||
m_node.scheduler.reset();
|
||||
m_node.llmq_ctx.reset();
|
||||
m_node.chainman->Reset();
|
||||
@ -241,7 +245,7 @@ TestingSetup::TestingSetup(const std::string& chainName, const std::vector<const
|
||||
|
||||
m_node.banman = std::make_unique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
|
||||
m_node.peer_logic = std::make_unique<PeerLogicValidation>(
|
||||
*m_node.connman, m_node.banman.get(), *m_node.scheduler, *m_node.chainman, *m_node.mempool, m_node.llmq_ctx
|
||||
*m_node.connman, *m_node.addrman, m_node.banman.get(), *m_node.scheduler, *m_node.chainman, *m_node.mempool, m_node.llmq_ctx
|
||||
);
|
||||
{
|
||||
CConnman::Options options;
|
||||
|
@ -334,15 +334,10 @@ void CTxMemPoolEntry::UpdateAncestorState(int64_t modifySize, CAmount modifyFee,
|
||||
assert(int(nSigOpCountWithAncestors) >= 0);
|
||||
}
|
||||
|
||||
CTxMemPool::CTxMemPool(CBlockPolicyEstimator* estimator)
|
||||
: nTransactionsUpdated(0), minerPolicyEstimator(estimator), m_epoch(0), m_has_epoch_guard(false)
|
||||
CTxMemPool::CTxMemPool(CBlockPolicyEstimator* estimator, int check_ratio)
|
||||
: m_check_ratio(check_ratio), minerPolicyEstimator(estimator)
|
||||
{
|
||||
_clear(); //lock free clear
|
||||
|
||||
// Sanity checks off by default for performance, because otherwise
|
||||
// accepting transactions becomes O(N^2) where N is the number
|
||||
// of transactions in the pool
|
||||
nCheckFrequency = 0;
|
||||
}
|
||||
|
||||
bool CTxMemPool::isSpent(const COutPoint& outpoint) const
|
||||
@ -776,7 +771,7 @@ void CTxMemPool::removeForReorg(const CCoinsViewCache *pcoins, unsigned int nMem
|
||||
if (it2 != mapTx.end())
|
||||
continue;
|
||||
const Coin &coin = pcoins->AccessCoin(txin.prevout);
|
||||
if (nCheckFrequency != 0) assert(!coin.IsSpent());
|
||||
if (m_check_ratio != 0) assert(!coin.IsSpent());
|
||||
if (coin.IsSpent() || (coin.IsCoinBase() && ((signed long)nMemPoolHeight) - coin.nHeight < COINBASE_MATURITY)) {
|
||||
txToRemove.insert(it);
|
||||
break;
|
||||
@ -1035,13 +1030,11 @@ static void CheckInputsAndUpdateCoins(const CTransaction& tx, CCoinsViewCache& m
|
||||
|
||||
void CTxMemPool::check(const CCoinsViewCache *pcoins) const
|
||||
{
|
||||
if (m_check_ratio == 0) return;
|
||||
|
||||
if (GetRand(m_check_ratio) >= 1) return;
|
||||
|
||||
LOCK(cs);
|
||||
if (nCheckFrequency == 0)
|
||||
return;
|
||||
|
||||
if (GetRand(std::numeric_limits<uint32_t>::max()) >= nCheckFrequency)
|
||||
return;
|
||||
|
||||
LogPrint(BCLog::MEMPOOL, "Checking mempool with %u transactions and %u inputs\n", (unsigned int)mapTx.size(), (unsigned int)mapNextTx.size());
|
||||
|
||||
uint64_t checkTotal = 0;
|
||||
|
@ -449,8 +449,8 @@ public:
|
||||
class CTxMemPool
|
||||
{
|
||||
private:
|
||||
uint32_t nCheckFrequency GUARDED_BY(cs); //!< Value n means that n times in 2^32 we check.
|
||||
std::atomic<unsigned int> nTransactionsUpdated; //!< Used by getblocktemplate to trigger CreateNewBlock() invocation
|
||||
const int m_check_ratio; //!< Value n means that 1 times in n we check.
|
||||
std::atomic<unsigned int> nTransactionsUpdated{0}; //!< Used by getblocktemplate to trigger CreateNewBlock() invocation
|
||||
CBlockPolicyEstimator* minerPolicyEstimator;
|
||||
|
||||
uint64_t totalTxSize; //!< sum of all mempool tx' byte sizes
|
||||
@ -459,8 +459,8 @@ private:
|
||||
mutable int64_t lastRollingFeeUpdate;
|
||||
mutable bool blockSinceLastRollingFeeBump;
|
||||
mutable double rollingMinimumFeeRate; //!< minimum fee to get into the pool, decreases exponentially
|
||||
mutable uint64_t m_epoch;
|
||||
mutable bool m_has_epoch_guard;
|
||||
mutable uint64_t m_epoch{0};
|
||||
mutable bool m_has_epoch_guard{false};
|
||||
|
||||
void trackPackageRemoved(const CFeeRate& rate) EXCLUSIVE_LOCKS_REQUIRED(cs);
|
||||
|
||||
@ -581,8 +581,14 @@ public:
|
||||
std::map<uint256, CAmount> mapDeltas;
|
||||
|
||||
/** Create a new CTxMemPool.
|
||||
* Sanity checks will be off by default for performance, because otherwise
|
||||
* accepting transactions becomes O(N^2) where N is the number of transactions
|
||||
* in the pool.
|
||||
*
|
||||
* @param[in] estimator is used to estimate appropriate transaction fees.
|
||||
* @param[in] check_ratio is the ratio used to determine how often sanity checks will run.
|
||||
*/
|
||||
explicit CTxMemPool(CBlockPolicyEstimator* estimator = nullptr);
|
||||
explicit CTxMemPool(CBlockPolicyEstimator* estimator = nullptr, int check_ratio = 0);
|
||||
|
||||
/**
|
||||
* If sanity-checking is turned on, check makes sure the pool is
|
||||
@ -591,7 +597,6 @@ public:
|
||||
* check does nothing.
|
||||
*/
|
||||
void check(const CCoinsViewCache *pcoins) const;
|
||||
void setSanityCheck(double dFrequency = 1.0) { LOCK(cs); nCheckFrequency = static_cast<uint32_t>(dFrequency * 4294967295.0); }
|
||||
|
||||
// addUnchecked must updated state for all ancestors of a given transaction,
|
||||
// to track size/count of descendant transactions. First version of
|
||||
|
@ -21,7 +21,6 @@
|
||||
#include <index/txindex.h>
|
||||
#include <logging.h>
|
||||
#include <logging/timer.h>
|
||||
#include <policy/fees.h>
|
||||
#include <policy/policy.h>
|
||||
#include <policy/settings.h>
|
||||
#include <pow.h>
|
||||
@ -154,8 +153,6 @@ arith_uint256 nMinimumChainWork;
|
||||
|
||||
CFeeRate minRelayTxFee = CFeeRate(DEFAULT_MIN_RELAY_TX_FEE);
|
||||
|
||||
CBlockPolicyEstimator feeEstimator;
|
||||
|
||||
// Internal stuff
|
||||
namespace {
|
||||
CBlockIndex* pindexBestInvalid = nullptr;
|
||||
|
@ -50,7 +50,6 @@ class CChainParams;
|
||||
class CInv;
|
||||
class CConnman;
|
||||
class CScriptCheck;
|
||||
class CBlockPolicyEstimator;
|
||||
class CTxMemPool;
|
||||
class CValidationState;
|
||||
class ChainstateManager;
|
||||
@ -128,7 +127,6 @@ struct BlockHasher
|
||||
};
|
||||
|
||||
extern CCriticalSection cs_main;
|
||||
extern CBlockPolicyEstimator feeEstimator;
|
||||
typedef std::unordered_map<uint256, CBlockIndex*, BlockHasher> BlockMap;
|
||||
typedef std::unordered_multimap<uint256, CBlockIndex*, BlockHasher> PrevBlockMap;
|
||||
extern Mutex g_best_block_mutex;
|
||||
|
@ -22,10 +22,6 @@ static const int MIN_PEER_PROTO_VERSION = 70215;
|
||||
//! minimum proto version of masternode to accept in DKGs
|
||||
static const int MIN_MASTERNODE_PROTO_VERSION = 70221;
|
||||
|
||||
//! nTime field added to CAddress, starting with this version;
|
||||
//! if possible, avoid requesting addresses nodes older than this
|
||||
static const int CADDR_TIME_VERSION = 31402;
|
||||
|
||||
//! protocol version is included in MNAUTH starting with this version
|
||||
static const int MNAUTH_NODE_VER_VERSION = 70218;
|
||||
|
||||
|
@ -129,7 +129,8 @@ public:
|
||||
CTransactionBuilderTestSetup()
|
||||
{
|
||||
CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
|
||||
node.mempool = std::make_unique<CTxMemPool>(&::feeEstimator);
|
||||
node.fee_estimator = std::make_unique<CBlockPolicyEstimator>();
|
||||
node.mempool = std::make_unique<CTxMemPool>(node.fee_estimator.get());
|
||||
chain = interfaces::MakeChain(node);
|
||||
wallet = std::make_unique<CWallet>(chain.get(), "", CreateMockWalletDatabase());
|
||||
bool firstRun;
|
||||
@ -229,7 +230,7 @@ BOOST_FIXTURE_TEST_CASE(CTransactionBuilderTest, CTransactionBuilderTestSetup)
|
||||
// Tests with single outpoint tallyItem
|
||||
{
|
||||
CompactTallyItem tallyItem = GetTallyItem({4999});
|
||||
CTransactionBuilder txBuilder(wallet, tallyItem);
|
||||
CTransactionBuilder txBuilder(wallet, tallyItem, *m_node.fee_estimator);
|
||||
|
||||
BOOST_CHECK_EQUAL(txBuilder.CountOutputs(), 0);
|
||||
BOOST_CHECK_EQUAL(txBuilder.GetAmountInitial(), tallyItem.nAmount);
|
||||
@ -266,7 +267,7 @@ BOOST_FIXTURE_TEST_CASE(CTransactionBuilderTest, CTransactionBuilderTestSetup)
|
||||
// Tests with multiple outpoint tallyItem
|
||||
{
|
||||
CompactTallyItem tallyItem = GetTallyItem({10000, 20000, 30000, 40000, 50000});
|
||||
CTransactionBuilder txBuilder(wallet, tallyItem);
|
||||
CTransactionBuilder txBuilder(wallet, tallyItem, *m_node.fee_estimator);
|
||||
std::vector<CTransactionBuilderOutput*> vecOutputs;
|
||||
bilingual_str strResult;
|
||||
|
||||
|
@ -88,7 +88,8 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup)
|
||||
CBlockIndex* newTip = ::ChainActive().Tip();
|
||||
|
||||
NodeContext node;
|
||||
node.mempool = std::make_unique<CTxMemPool>(&::feeEstimator);
|
||||
node.fee_estimator = std::make_unique<CBlockPolicyEstimator>();
|
||||
node.mempool = std::make_unique<CTxMemPool>(node.fee_estimator.get());
|
||||
auto chain = interfaces::MakeChain(node);
|
||||
|
||||
// Verify ScanForWalletTransactions accommodates a null start block.
|
||||
@ -189,7 +190,8 @@ BOOST_FIXTURE_TEST_CASE(importmulti_rescan, TestChain100Setup)
|
||||
CBlockIndex* newTip = ::ChainActive().Tip();
|
||||
|
||||
NodeContext node;
|
||||
node.mempool = std::make_unique<CTxMemPool>(&::feeEstimator);
|
||||
node.fee_estimator = std::make_unique<CBlockPolicyEstimator>();
|
||||
node.mempool = std::make_unique<CTxMemPool>(node.fee_estimator.get());
|
||||
auto chain = interfaces::MakeChain(node);
|
||||
|
||||
// Prune the older block file.
|
||||
@ -260,7 +262,8 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
|
||||
m_coinbase_txns.emplace_back(CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
|
||||
|
||||
NodeContext node;
|
||||
node.mempool = std::make_unique<CTxMemPool>(&::feeEstimator);
|
||||
node.fee_estimator = std::make_unique<CBlockPolicyEstimator>();
|
||||
node.mempool = std::make_unique<CTxMemPool>(node.fee_estimator.get());
|
||||
auto chain = interfaces::MakeChain(node);
|
||||
|
||||
std::string backup_file = (GetDataDir() / "wallet.backup").string();
|
||||
@ -393,7 +396,8 @@ BOOST_FIXTURE_TEST_CASE(rpc_getaddressinfo, TestChain100Setup)
|
||||
BOOST_FIXTURE_TEST_CASE(coin_mark_dirty_immature_credit, TestChain100Setup)
|
||||
{
|
||||
NodeContext node;
|
||||
node.mempool = std::make_unique<CTxMemPool>(&::feeEstimator);
|
||||
node.fee_estimator = std::make_unique<CBlockPolicyEstimator>();
|
||||
node.mempool = std::make_unique<CTxMemPool>(node.fee_estimator.get());
|
||||
auto chain = interfaces::MakeChain(node);
|
||||
|
||||
CWallet wallet(chain.get(), "", CreateDummyWalletDatabase());
|
||||
@ -1123,7 +1127,8 @@ BOOST_FIXTURE_TEST_CASE(select_coins_grouped_by_addresses, ListCoinsTestingSetup
|
||||
BOOST_FIXTURE_TEST_CASE(wallet_disableprivkeys, TestChain100Setup)
|
||||
{
|
||||
NodeContext node;
|
||||
node.mempool = std::make_unique<CTxMemPool>(&::feeEstimator);
|
||||
node.fee_estimator = std::make_unique<CBlockPolicyEstimator>();
|
||||
node.mempool = std::make_unique<CTxMemPool>(node.fee_estimator.get());
|
||||
auto chain = interfaces::MakeChain(node);
|
||||
std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(chain.get(), "", CreateDummyWalletDatabase());
|
||||
wallet->SetMinVersion(FEATURE_LATEST);
|
||||
|
@ -13,6 +13,7 @@ from test_framework.util import (
|
||||
assert_equal,
|
||||
assert_greater_than,
|
||||
assert_greater_than_or_equal,
|
||||
assert_raises_rpc_error,
|
||||
satoshi_round,
|
||||
)
|
||||
|
||||
@ -259,5 +260,11 @@ class EstimateFeeTest(BitcoinTestFramework):
|
||||
self.log.info("Final estimates after emptying mempools")
|
||||
check_estimates(self.nodes[1], self.fees_per_kb)
|
||||
|
||||
self.log.info("Testing that fee estimation is disabled in blocksonly.")
|
||||
self.restart_node(0, ["-blocksonly"])
|
||||
assert_raises_rpc_error(-32603, "Fee estimation disabled",
|
||||
self.nodes[0].estimatesmartfee, 2)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
EstimateFeeTest().main()
|
||||
|
@ -255,7 +255,7 @@ class CAddress:
|
||||
self.ip = "0.0.0.0"
|
||||
self.port = 0
|
||||
|
||||
def deserialize(self, f, with_time=True):
|
||||
def deserialize(self, f, *, with_time=True):
|
||||
"""Deserialize from addrv1 format (pre-BIP155)"""
|
||||
if with_time:
|
||||
# VERSION messages serialize CAddress objects without time
|
||||
@ -267,7 +267,7 @@ class CAddress:
|
||||
self.ip = socket.inet_ntoa(f.read(4))
|
||||
self.port = struct.unpack(">H", f.read(2))[0]
|
||||
|
||||
def serialize(self, with_time=True):
|
||||
def serialize(self, *, with_time=True):
|
||||
"""Serialize in addrv1 format (pre-BIP155)"""
|
||||
assert self.net == self.NET_IPV4
|
||||
r = b""
|
||||
@ -1371,10 +1371,10 @@ class msg_version:
|
||||
self.nServices = struct.unpack("<Q", f.read(8))[0]
|
||||
self.nTime = struct.unpack("<q", f.read(8))[0]
|
||||
self.addrTo = CAddress()
|
||||
self.addrTo.deserialize(f, False)
|
||||
self.addrTo.deserialize(f, with_time=False)
|
||||
|
||||
self.addrFrom = CAddress()
|
||||
self.addrFrom.deserialize(f, False)
|
||||
self.addrFrom.deserialize(f, with_time=False)
|
||||
self.nNonce = struct.unpack("<Q", f.read(8))[0]
|
||||
self.strSubVer = deser_string(f)
|
||||
|
||||
@ -1394,8 +1394,8 @@ class msg_version:
|
||||
r += struct.pack("<i", self.nVersion)
|
||||
r += struct.pack("<Q", self.nServices)
|
||||
r += struct.pack("<q", self.nTime)
|
||||
r += self.addrTo.serialize(False)
|
||||
r += self.addrFrom.serialize(False)
|
||||
r += self.addrTo.serialize(with_time=False)
|
||||
r += self.addrFrom.serialize(with_time=False)
|
||||
r += struct.pack("<Q", self.nNonce)
|
||||
r += ser_string(self.strSubVer)
|
||||
r += struct.pack("<i", self.nStartingHeight)
|
||||
|
@ -75,7 +75,6 @@ EXPECTED_CIRCULAR_DEPENDENCIES=(
|
||||
"llmq/chainlocks -> validation -> llmq/chainlocks"
|
||||
"coinjoin/coinjoin -> llmq/chainlocks -> net -> coinjoin/coinjoin"
|
||||
"evo/deterministicmns -> llmq/utils -> net -> evo/deterministicmns"
|
||||
"policy/fees -> txmempool -> validation -> policy/fees"
|
||||
"policy/policy -> policy/settings -> policy/policy"
|
||||
"evo/specialtxman -> validation -> evo/specialtxman"
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user