50fc4df6c4
[mempool] Persist unbroadcast set to mempool.dat (Amiti Uttarwar)297a178536
[test] Integration tests for unbroadcast functionality (Amiti Uttarwar)6851502472
[refactor/test] Extract P2PTxInvStore into test framework (Amiti Uttarwar)dc1da48dc5
[wallet] Update the rebroadcast frequency to be ~1/day. (Amiti Uttarwar)e25e42f20a
[p2p] Reattempt initial send of unbroadcast transactions (Amiti Uttarwar)7e93eecce3
[util] Add method that returns random time in milliseconds (Amiti Uttarwar)89eeb4a333
[mempool] Track "unbroadcast" transactions (Amiti Uttarwar) Pull request description: This PR introduces mempool tracking of unbroadcast transactions and periodic reattempts at initial broadcast. This is a part of the rebroadcast project, and a standalone privacy win. The current rebroadcast logic is terrible for privacy because 1. only the source wallet rebroadcasts transactions and 2. it does so quite frequently. In the current system, if a user submits a transaction that does not immediately get broadcast to the network (eg. they are offline), this "rebroadcast" behavior is the safety net that can actually serve as the initial broadcast. So, keeping the attempts frequent is important for initial delivery within a reasonable timespan. This PR aims to improve # 2 by reducing the wallet rebroadcast frequency to ~1/day from ~1/15 min. It achieves this by separating the notion of initial broadcast from rebroadcasts. With these changes, the mempool tracks locally submitted transactions & periodically reattempts initial broadcast. Transactions submitted via the wallet or RPC are added to an "unbroadcast" set & are removed when a peer sends a `getdata` request, or the transaction is removed from the mempool. Every 10-15 minutes, the node reattempts an initial broadcast. This enables reducing the wallet rebroadcast frequency while ensuring the transactions will be propagated to the network. For privacy improvements around # 1, please see #16698. Thank you to gmaxwell for the idea of how to break out this subset of functionality (https://github.com/bitcoin/bitcoin/pull/16698#issuecomment-571399346) ACKs for top commit: fjahr: Code review ACK50fc4df6c4
MarcoFalke: ACK50fc4df6c4
, I think this is ready for merge now 👻 amitiuttarwar: The current tip `50fc4df` currently has 6 ACKs on it, so I've opened #18807 to address the last bits. jnewbery: utACK50fc4df6c4
. ariard: Code Review ACK50fc4df
(minor points no need to invalid other ACKs) robot-visions: ACK50fc4df6c4
sipa: utACK50fc4df6c4
naumenkogs: utACK50fc4df
Tree-SHA512: 2dd935d645d5e209f8abf87bfaa3ef0e4492705ce7e89ea64279cb27ffd37f4727fa94ad62d41be331177332f8edbebf3c7f4972f8cda10dd951b80a28ab3c0f
99 lines
4.1 KiB
C++
99 lines
4.1 KiB
C++
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
|
// Copyright (c) 2009-2020 The Bitcoin Core developers
|
|
// Distributed under the MIT software license, see the accompanying
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
|
|
#ifndef BITCOIN_NET_PROCESSING_H
|
|
#define BITCOIN_NET_PROCESSING_H
|
|
|
|
#include <consensus/params.h>
|
|
#include <net.h>
|
|
#include <sync.h>
|
|
#include <validationinterface.h>
|
|
|
|
class CTxMemPool;
|
|
|
|
extern RecursiveMutex cs_main;
|
|
extern RecursiveMutex g_cs_orphans;
|
|
|
|
/** 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;
|
|
static const bool DEFAULT_PEERBLOOMFILTERS = false;
|
|
|
|
class PeerLogicValidation final : public CValidationInterface, public NetEventsInterface {
|
|
private:
|
|
CConnman* const connman;
|
|
BanMan* const m_banman;
|
|
CTxMemPool& m_mempool;
|
|
|
|
bool CheckIfBanned(CNode* pnode) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
|
|
|
public:
|
|
PeerLogicValidation(CConnman* connman, BanMan* banman, CScheduler& scheduler, CTxMemPool& pool);
|
|
|
|
/**
|
|
* Overridden from CValidationInterface.
|
|
*/
|
|
void BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex* pindexConnected) override;
|
|
void BlockDisconnected(const std::shared_ptr<const CBlock> &block, const CBlockIndex* pindex) override;
|
|
/**
|
|
* Overridden from CValidationInterface.
|
|
*/
|
|
void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) override;
|
|
/**
|
|
* Overridden from CValidationInterface.
|
|
*/
|
|
void BlockChecked(const CBlock& block, const BlockValidationState& 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);
|
|
|
|
/** Consider evicting an outbound peer based on the amount of time they've been behind our tip */
|
|
void ConsiderEviction(CNode *pto, int64_t time_in_seconds) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
|
/** 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) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
|
/** Retrieve unbroadcast transactions from the mempool and reattempt sending to peers */
|
|
void ReattemptInitialBroadcast(CScheduler& scheduler) const;
|
|
|
|
private:
|
|
int64_t m_stale_tip_check_time; //!< Next time to check for stale tip
|
|
};
|
|
|
|
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);
|
|
|
|
/** Relay transaction to every node */
|
|
void RelayTransaction(const uint256&, const CConnman& connman);
|
|
|
|
#endif // BITCOIN_NET_PROCESSING_H
|