|
|
|
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
|
|
|
// Copyright (c) 2009-2018 The Bitcoin Core developers
|
|
|
|
// Distributed under the MIT software license, see the accompanying
|
|
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
|
|
|
|
|
|
#ifndef BITCOIN_NET_PROCESSING_H
|
|
|
|
#define BITCOIN_NET_PROCESSING_H
|
|
|
|
|
|
|
|
#include <net.h>
|
|
|
|
#include <validationinterface.h>
|
|
|
|
#include <consensus/params.h>
|
|
|
|
|
|
|
|
/** Default for -maxorphantx, maximum number of orphan transactions kept in memory */
|
|
|
|
static const unsigned int DEFAULT_MAX_ORPHAN_TRANSACTIONS = 100;
|
|
|
|
/** Default number of orphan+recently-replaced txn to keep around for block reconstruction */
|
|
|
|
static const unsigned int DEFAULT_BLOCK_RECONSTRUCTION_EXTRA_TXN = 100;
|
|
|
|
/** Default for BIP61 (sending reject messages) */
|
|
|
|
static constexpr bool DEFAULT_ENABLE_BIP61 = true;
|
|
|
|
|
|
|
|
class PeerLogicValidation final : public CValidationInterface, public NetEventsInterface {
|
|
|
|
private:
|
|
|
|
CConnman* const connman;
|
|
|
|
|
|
|
|
public:
|
|
|
|
explicit PeerLogicValidation(CConnman* connman, CScheduler &scheduler, bool enable_bip61);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Overridden from CValidationInterface.
|
|
|
|
*/
|
|
|
|
void BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex* pindexConnected, const std::vector<CTransactionRef>& vtxConflicted) override;
|
|
|
|
/**
|
|
|
|
* Overridden from CValidationInterface.
|
|
|
|
*/
|
|
|
|
void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) override;
|
|
|
|
/**
|
|
|
|
* Overridden from CValidationInterface.
|
|
|
|
*/
|
|
|
|
void BlockChecked(const CBlock& block, const CValidationState& state) override;
|
|
|
|
/**
|
|
|
|
* Overridden from CValidationInterface.
|
|
|
|
*/
|
|
|
|
void NewPoWValidBlock(const CBlockIndex *pindex, const std::shared_ptr<const CBlock>& pblock) override;
|
|
|
|
|
|
|
|
/** 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;
|
|
|
|
/**
|
|
|
|
* Process protocol messages received from a given node
|
|
|
|
*
|
|
|
|
* @param[in] pfrom The node which we have received messages from.
|
|
|
|
* @param[in] interrupt Interrupt condition for processing threads
|
|
|
|
*/
|
|
|
|
bool ProcessMessages(CNode* pfrom, std::atomic<bool>& interrupt) override;
|
|
|
|
/**
|
|
|
|
* Send queued protocol messages to be sent to a give node.
|
|
|
|
*
|
|
|
|
* @param[in] pto The node which we are sending messages to.
|
|
|
|
* @return True if there is more work to be done
|
|
|
|
*/
|
|
|
|
bool SendMessages(CNode* pto) override EXCLUSIVE_LOCKS_REQUIRED(pto->cs_sendProcessing);
|
Permit disconnection of outbound peers on bad/slow chains
Currently we have no rotation of outbound peers. If an outbound peer
stops serving us blocks, or is on a consensus-incompatible chain with
less work than our tip (but otherwise valid headers), then we will never
disconnect that peer, even though that peer is using one of our 8
outbound connection slots. Because we rely on our outbound peers to
find an honest node in order to reach consensus, allowing an
incompatible peer to occupy one of those slots is undesirable,
particularly if it is possible for all such slots to be occupied by such
peers.
Protect against this by always checking to see if a peer's best known
block has less work than our tip, and if so, set a 20 minute timeout --
if the peer is still not known to have caught up to a chain with as much
work as ours after 20 minutes, then send a single getheaders message,
wait 2 more minutes, and if a better header hasn't been received by then,
disconnect that peer.
Note:
- we do not require that our peer sync to the same tip as ours, just an
equal or greater work tip. (Doing otherwise would risk partitioning the
network in the event of a chain split, and is also unnecessary.)
- we pick 4 of our outbound peers and do not subject them to this logic,
to be more conservative. We don't wish to permit temporary network
issues (or an attacker) to excessively disrupt network topology.
7 years ago
|
|
|
|
|
|
|
/** Consider evicting an outbound peer based on the amount of time they've been behind our tip */
|
Permit disconnection of outbound peers on bad/slow chains
Currently we have no rotation of outbound peers. If an outbound peer
stops serving us blocks, or is on a consensus-incompatible chain with
less work than our tip (but otherwise valid headers), then we will never
disconnect that peer, even though that peer is using one of our 8
outbound connection slots. Because we rely on our outbound peers to
find an honest node in order to reach consensus, allowing an
incompatible peer to occupy one of those slots is undesirable,
particularly if it is possible for all such slots to be occupied by such
peers.
Protect against this by always checking to see if a peer's best known
block has less work than our tip, and if so, set a 20 minute timeout --
if the peer is still not known to have caught up to a chain with as much
work as ours after 20 minutes, then send a single getheaders message,
wait 2 more minutes, and if a better header hasn't been received by then,
disconnect that peer.
Note:
- we do not require that our peer sync to the same tip as ours, just an
equal or greater work tip. (Doing otherwise would risk partitioning the
network in the event of a chain split, and is also unnecessary.)
- we pick 4 of our outbound peers and do not subject them to this logic,
to be more conservative. We don't wish to permit temporary network
issues (or an attacker) to excessively disrupt network topology.
7 years ago
|
|
|
void ConsiderEviction(CNode *pto, int64_t time_in_seconds);
|
|
|
|
/** Evict extra outbound peers. If we think our tip may be stale, connect to an extra outbound */
|
|
|
|
void CheckForStaleTipAndEvictPeers(const Consensus::Params &consensusParams);
|
|
|
|
/** If we have extra outbound peers, try to disconnect the one with the oldest block announcement */
|
|
|
|
void EvictExtraOutboundPeers(int64_t time_in_seconds);
|
|
|
|
|
|
|
|
private:
|
|
|
|
int64_t m_stale_tip_check_time; //! Next time to check for stale tip
|
|
|
|
|
|
|
|
/** Enable BIP61 (sending reject messages) */
|
|
|
|
const bool m_enable_bip61;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct CNodeStateStats {
|
|
|
|
int nMisbehavior = 0;
|
|
|
|
int nSyncHeight = -1;
|
|
|
|
int nCommonHeight = -1;
|
|
|
|
std::vector<int> vHeightInFlight;
|
|
|
|
};
|
|
|
|
|
|
|
|
/** Get statistics from node state */
|
|
|
|
bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats);
|
|
|
|
|
|
|
|
#endif // BITCOIN_NET_PROCESSING_H
|