mirror of
https://github.com/dashpay/dash.git
synced 2024-12-25 12:02:48 +01:00
fix(net): Extend blocks-relay-only to also ignore some Dash-specific messages/invs
This commit is contained in:
parent
def2e98d61
commit
678df6318e
@ -1526,7 +1526,7 @@ void CInstantSendManager::AskNodesForLockedTx(const uint256& txid, const CConnma
|
|||||||
if (nodesToAskFor.size() >= 4) {
|
if (nodesToAskFor.size() >= 4) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (pnode->m_tx_relay != nullptr) {
|
if (!pnode->m_block_relay_only_peer) {
|
||||||
LOCK(pnode->m_tx_relay->cs_tx_inventory);
|
LOCK(pnode->m_tx_relay->cs_tx_inventory);
|
||||||
if (pnode->m_tx_relay->filterInventoryKnown.contains(txid)) {
|
if (pnode->m_tx_relay->filterInventoryKnown.contains(txid)) {
|
||||||
pnode->AddRef();
|
pnode->AddRef();
|
||||||
|
@ -200,7 +200,7 @@ void CMasternodeSync::ProcessTick(CConnman& connman)
|
|||||||
// Now that the blockchain is synced request the mempool from the connected outbound nodes if possible
|
// Now that the blockchain is synced request the mempool from the connected outbound nodes if possible
|
||||||
for (auto pNodeTmp : vNodesCopy) {
|
for (auto pNodeTmp : vNodesCopy) {
|
||||||
bool fRequestedEarlier = netfulfilledman.HasFulfilledRequest(pNodeTmp->addr, "mempool-sync");
|
bool fRequestedEarlier = netfulfilledman.HasFulfilledRequest(pNodeTmp->addr, "mempool-sync");
|
||||||
if (pNodeTmp->nVersion >= 70216 && !pNodeTmp->fInbound && !fRequestedEarlier) {
|
if (pNodeTmp->nVersion >= 70216 && !pNodeTmp->fInbound && !fRequestedEarlier && !pNodeTmp->IsBlockRelayOnly()) {
|
||||||
netfulfilledman.AddFulfilledRequest(pNodeTmp->addr, "mempool-sync");
|
netfulfilledman.AddFulfilledRequest(pNodeTmp->addr, "mempool-sync");
|
||||||
connman.PushMessage(pNodeTmp, msgMaker.Make(NetMsgType::MEMPOOL));
|
connman.PushMessage(pNodeTmp, msgMaker.Make(NetMsgType::MEMPOOL));
|
||||||
LogPrint(BCLog::MNSYNC, "CMasternodeSync::ProcessTick -- nTick %d nCurrentAsset %d -- syncing mempool from peer=%d\n", nTick, nCurrentAsset, pNodeTmp->GetId());
|
LogPrint(BCLog::MNSYNC, "CMasternodeSync::ProcessTick -- nTick %d nCurrentAsset %d -- syncing mempool from peer=%d\n", nTick, nCurrentAsset, pNodeTmp->GetId());
|
||||||
|
38
src/net.cpp
38
src/net.cpp
@ -566,7 +566,7 @@ void CNode::copyStats(CNodeStats &stats, const std::vector<bool> &m_asmap)
|
|||||||
X(addr);
|
X(addr);
|
||||||
X(addrBind);
|
X(addrBind);
|
||||||
stats.m_mapped_as = addr.GetMappedAS(m_asmap);
|
stats.m_mapped_as = addr.GetMappedAS(m_asmap);
|
||||||
if (m_tx_relay != nullptr) {
|
if (!m_block_relay_only_peer) {
|
||||||
LOCK(m_tx_relay->cs_filter);
|
LOCK(m_tx_relay->cs_filter);
|
||||||
stats.fRelayTxes = m_tx_relay->fRelayTxes;
|
stats.fRelayTxes = m_tx_relay->fRelayTxes;
|
||||||
} else {
|
} else {
|
||||||
@ -947,7 +947,7 @@ bool CConnman::AttemptToEvictConnection()
|
|||||||
|
|
||||||
bool peer_relay_txes = false;
|
bool peer_relay_txes = false;
|
||||||
bool peer_filter_not_null = false;
|
bool peer_filter_not_null = false;
|
||||||
if (node->m_tx_relay != nullptr) {
|
if (!node->m_block_relay_only_peer) {
|
||||||
LOCK(node->m_tx_relay->cs_filter);
|
LOCK(node->m_tx_relay->cs_filter);
|
||||||
peer_relay_txes = node->m_tx_relay->fRelayTxes;
|
peer_relay_txes = node->m_tx_relay->fRelayTxes;
|
||||||
peer_filter_not_null = node->m_tx_relay->pfilter != nullptr;
|
peer_filter_not_null = node->m_tx_relay->pfilter != nullptr;
|
||||||
@ -2159,7 +2159,7 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
|
|||||||
// also have the added issue that they're attacker controlled and could be used
|
// also have the added issue that they're attacker controlled and could be used
|
||||||
// to prevent us from connecting to particular hosts if we used them here.
|
// to prevent us from connecting to particular hosts if we used them here.
|
||||||
setConnected.insert(pnode->addr.GetGroup(addrman.m_asmap));
|
setConnected.insert(pnode->addr.GetGroup(addrman.m_asmap));
|
||||||
if (pnode->m_tx_relay == nullptr) {
|
if (pnode->m_block_relay_only_peer) {
|
||||||
nOutboundBlockRelay++;
|
nOutboundBlockRelay++;
|
||||||
} else if (!pnode->fFeeler) {
|
} else if (!pnode->fFeeler) {
|
||||||
nOutboundFullRelay++;
|
nOutboundFullRelay++;
|
||||||
@ -3480,12 +3480,17 @@ void CConnman::RelayInvFiltered(CInv &inv, const CTransaction& relatedTx, const
|
|||||||
{
|
{
|
||||||
LOCK(cs_vNodes);
|
LOCK(cs_vNodes);
|
||||||
for (const auto& pnode : vNodes) {
|
for (const auto& pnode : vNodes) {
|
||||||
if (pnode->nVersion < minProtoVersion || !pnode->CanRelay())
|
if (pnode->nVersion < minProtoVersion || !pnode->CanRelay() || pnode->m_block_relay_only_peer) {
|
||||||
continue;
|
continue;
|
||||||
if (pnode->m_tx_relay != nullptr) {
|
}
|
||||||
|
{
|
||||||
LOCK(pnode->m_tx_relay->cs_filter);
|
LOCK(pnode->m_tx_relay->cs_filter);
|
||||||
if(pnode->m_tx_relay->pfilter && !pnode->m_tx_relay->pfilter->IsRelevantAndUpdate(relatedTx))
|
if (!pnode->m_tx_relay->fRelayTxes) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
if (pnode->m_tx_relay->pfilter && !pnode->m_tx_relay->pfilter->IsRelevantAndUpdate(relatedTx)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pnode->PushInventory(inv);
|
pnode->PushInventory(inv);
|
||||||
}
|
}
|
||||||
@ -3495,11 +3500,17 @@ void CConnman::RelayInvFiltered(CInv &inv, const uint256& relatedTxHash, const i
|
|||||||
{
|
{
|
||||||
LOCK(cs_vNodes);
|
LOCK(cs_vNodes);
|
||||||
for (const auto& pnode : vNodes) {
|
for (const auto& pnode : vNodes) {
|
||||||
if (pnode->nVersion < minProtoVersion || !pnode->CanRelay())
|
if (pnode->nVersion < minProtoVersion || !pnode->CanRelay() || pnode->m_block_relay_only_peer) {
|
||||||
continue;
|
continue;
|
||||||
if (pnode->m_tx_relay != nullptr) {
|
}
|
||||||
|
{
|
||||||
LOCK(pnode->m_tx_relay->cs_filter);
|
LOCK(pnode->m_tx_relay->cs_filter);
|
||||||
if(pnode->m_tx_relay->pfilter && !pnode->m_tx_relay->pfilter->contains(relatedTxHash)) continue;
|
if (!pnode->m_tx_relay->fRelayTxes) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (pnode->m_tx_relay->pfilter && !pnode->m_tx_relay->pfilter->contains(relatedTxHash)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pnode->PushInventory(inv);
|
pnode->PushInventory(inv);
|
||||||
}
|
}
|
||||||
@ -3641,10 +3652,7 @@ CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn
|
|||||||
fInbound(fInboundIn),
|
fInbound(fInboundIn),
|
||||||
nKeyedNetGroup(nKeyedNetGroupIn),
|
nKeyedNetGroup(nKeyedNetGroupIn),
|
||||||
addrKnown(5000, 0.001),
|
addrKnown(5000, 0.001),
|
||||||
// Don't relay addr messages to peers that we connect to as block-relay-only
|
m_block_relay_only_peer(block_relay_only),
|
||||||
// peers (to prevent adversaries from inferring these links from addr
|
|
||||||
// traffic).
|
|
||||||
m_addr_relay_peer(!block_relay_only),
|
|
||||||
id(idIn),
|
id(idIn),
|
||||||
nLocalHostNonce(nLocalHostNonceIn),
|
nLocalHostNonce(nLocalHostNonceIn),
|
||||||
nLocalServices(nLocalServicesIn),
|
nLocalServices(nLocalServicesIn),
|
||||||
@ -3653,9 +3661,7 @@ CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn
|
|||||||
hSocket = hSocketIn;
|
hSocket = hSocketIn;
|
||||||
addrName = addrNameIn == "" ? addr.ToStringIPPort() : addrNameIn;
|
addrName = addrNameIn == "" ? addr.ToStringIPPort() : addrNameIn;
|
||||||
hashContinue = uint256();
|
hashContinue = uint256();
|
||||||
if (!block_relay_only) {
|
m_tx_relay = MakeUnique<TxRelay>();
|
||||||
m_tx_relay = MakeUnique<TxRelay>();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const std::string &msg : getAllNetMessageTypes())
|
for (const std::string &msg : getAllNetMessageTypes())
|
||||||
mapRecvBytesPerMsgCmd[msg] = 0;
|
mapRecvBytesPerMsgCmd[msg] = 0;
|
||||||
|
75
src/net.h
75
src/net.h
@ -1028,15 +1028,25 @@ public:
|
|||||||
int64_t nNextAddrSend GUARDED_BY(cs_sendProcessing){0};
|
int64_t nNextAddrSend GUARDED_BY(cs_sendProcessing){0};
|
||||||
int64_t nNextLocalAddrSend GUARDED_BY(cs_sendProcessing){0};
|
int64_t nNextLocalAddrSend GUARDED_BY(cs_sendProcessing){0};
|
||||||
|
|
||||||
const bool m_addr_relay_peer;
|
const bool m_block_relay_only_peer;
|
||||||
bool IsAddrRelayPeer() const { return m_addr_relay_peer; }
|
|
||||||
|
// Don't relay addr messages to peers that we connect to as block-relay-only
|
||||||
|
// peers (to prevent adversaries from inferring these links from addr
|
||||||
|
// traffic).
|
||||||
|
bool IsAddrRelayPeer() const { return !m_block_relay_only_peer; }
|
||||||
|
|
||||||
|
bool IsBlockRelayOnly() const
|
||||||
|
{
|
||||||
|
// Stop processing non-block data early if
|
||||||
|
// 1) We are in blocks only mode and peer has no relay permission
|
||||||
|
// 2) This peer is a block-relay-only peer
|
||||||
|
return (!g_relay_txes && !HasPermission(PF_RELAY)) || m_block_relay_only_peer;
|
||||||
|
}
|
||||||
|
|
||||||
// List of block ids we still have announce.
|
// List of block ids we still have announce.
|
||||||
// There is no final sorting before sending, as they are always sent immediately
|
// There is no final sorting before sending, as they are always sent immediately
|
||||||
// and in the order requested.
|
// and in the order requested.
|
||||||
std::vector<uint256> vInventoryBlockToSend GUARDED_BY(cs_inventory);
|
std::vector<uint256> vInventoryBlockToSend GUARDED_BY(cs_inventory);
|
||||||
// List of non-tx/non-block inventory items
|
|
||||||
std::vector<CInv> vInventoryOtherToSend;
|
|
||||||
CCriticalSection cs_inventory;
|
CCriticalSection cs_inventory;
|
||||||
/** UNIX epoch time of the last block received from this peer that we had
|
/** UNIX epoch time of the last block received from this peer that we had
|
||||||
* not yet seen (e.g. not already received from another peer), that passed
|
* not yet seen (e.g. not already received from another peer), that passed
|
||||||
@ -1066,7 +1076,9 @@ public:
|
|||||||
CRollingBloomFilter filterInventoryKnown GUARDED_BY(cs_tx_inventory){50000, 0.000001};
|
CRollingBloomFilter filterInventoryKnown GUARDED_BY(cs_tx_inventory){50000, 0.000001};
|
||||||
// Set of transaction ids we still have to announce.
|
// Set of transaction ids we still have to announce.
|
||||||
// They are sorted by the mempool before relay, so the order is not important.
|
// They are sorted by the mempool before relay, so the order is not important.
|
||||||
std::set<uint256> setInventoryTxToSend;
|
std::set<uint256> setInventoryTxToSend GUARDED_BY(cs_tx_inventory);
|
||||||
|
// List of non-tx/non-block inventory items
|
||||||
|
std::vector<CInv> vInventoryOtherToSend GUARDED_BY(cs_tx_inventory);
|
||||||
// Used for BIP35 mempool sending, also protected by cs_tx_inventory
|
// Used for BIP35 mempool sending, also protected by cs_tx_inventory
|
||||||
bool fSendMempool GUARDED_BY(cs_tx_inventory){false};
|
bool fSendMempool GUARDED_BY(cs_tx_inventory){false};
|
||||||
// Last time a "MEMPOOL" request was serviced.
|
// Last time a "MEMPOOL" request was serviced.
|
||||||
@ -1074,7 +1086,8 @@ public:
|
|||||||
std::chrono::microseconds nNextInvSend{0};
|
std::chrono::microseconds nNextInvSend{0};
|
||||||
};
|
};
|
||||||
|
|
||||||
// m_tx_relay == nullptr if we're not relaying transactions with this peer
|
// in bitcoin: m_tx_relay == nullptr if we're not relaying transactions with this peer
|
||||||
|
// in dash: m_tx_relay should never be nullptr, use m_block_relay_only_peer == true instead
|
||||||
std::unique_ptr<TxRelay> m_tx_relay;
|
std::unique_ptr<TxRelay> m_tx_relay;
|
||||||
|
|
||||||
// Used for headers announcements - unfiltered blocks to relay
|
// Used for headers announcements - unfiltered blocks to relay
|
||||||
@ -1234,49 +1247,29 @@ public:
|
|||||||
|
|
||||||
void AddInventoryKnown(const uint256& hash)
|
void AddInventoryKnown(const uint256& hash)
|
||||||
{
|
{
|
||||||
if (m_tx_relay != nullptr) {
|
LOCK(m_tx_relay->cs_tx_inventory);
|
||||||
LOCK(m_tx_relay->cs_tx_inventory);
|
m_tx_relay->filterInventoryKnown.insert(hash);
|
||||||
m_tx_relay->filterInventoryKnown.insert(hash);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PushInventory(const CInv& inv)
|
void PushInventory(const CInv& inv)
|
||||||
{
|
{
|
||||||
if (inv.type == MSG_TX || inv.type == MSG_DSTX) {
|
if (inv.type == MSG_BLOCK) {
|
||||||
if (m_tx_relay != nullptr) {
|
|
||||||
LOCK(m_tx_relay->cs_tx_inventory);
|
|
||||||
if (!m_tx_relay->filterInventoryKnown.contains(inv.hash)) {
|
|
||||||
LogPrint(BCLog::NET, "%s -- adding new inv: %s peer=%d\n", __func__, inv.ToString(), id);
|
|
||||||
LOCK(m_tx_relay->cs_filter);
|
|
||||||
m_tx_relay->setInventoryTxToSend.insert(inv.hash);
|
|
||||||
} else {
|
|
||||||
LogPrint(BCLog::NET, "%s -- skipping known inv: %s peer=%d\n", __func__, inv.ToString(), id);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
LogPrint(BCLog::NET, "%s -- skipping unknown inv: %s peer=%d\n", __func__, inv.ToString(), id);
|
|
||||||
}
|
|
||||||
} else if (inv.type == MSG_BLOCK) {
|
|
||||||
LogPrint(BCLog::NET, "%s -- adding new inv: %s peer=%d\n", __func__, inv.ToString(), id);
|
LogPrint(BCLog::NET, "%s -- adding new inv: %s peer=%d\n", __func__, inv.ToString(), id);
|
||||||
LOCK(cs_inventory);
|
LOCK(cs_inventory);
|
||||||
vInventoryBlockToSend.push_back(inv.hash);
|
vInventoryBlockToSend.push_back(inv.hash);
|
||||||
} else {
|
return;
|
||||||
LOCK(cs_inventory);
|
|
||||||
if (m_tx_relay != nullptr) {
|
|
||||||
LOCK(m_tx_relay->cs_tx_inventory);
|
|
||||||
if (!m_tx_relay->filterInventoryKnown.contains(inv.hash)) {
|
|
||||||
LogPrint(BCLog::NET, "%s -- adding new inv: %s peer=%d\n", __func__, inv.ToString(), id);
|
|
||||||
vInventoryOtherToSend.push_back(inv);
|
|
||||||
} else {
|
|
||||||
LogPrint(BCLog::NET, "%s -- skipping known inv: %s peer=%d\n", __func__, inv.ToString(), id);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// TODO KNST for this case we don't use inventory
|
|
||||||
// accordingly #2292 it can increase size of transmitted data.
|
|
||||||
// Should be added dedicated bloom filter
|
|
||||||
LogPrint(BCLog::NET, "%s -- adding new inv: %s peer=%d\n", __func__, inv.ToString(), id);
|
|
||||||
vInventoryOtherToSend.push_back(inv);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
LOCK(m_tx_relay->cs_tx_inventory);
|
||||||
|
if (m_tx_relay->filterInventoryKnown.contains(inv.hash)) {
|
||||||
|
LogPrint(BCLog::NET, "%s -- skipping known inv: %s peer=%d\n", __func__, inv.ToString(), id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LogPrint(BCLog::NET, "%s -- adding new inv: %s peer=%d\n", __func__, inv.ToString(), id);
|
||||||
|
if (inv.type == MSG_TX || inv.type == MSG_DSTX) {
|
||||||
|
m_tx_relay->setInventoryTxToSend.insert(inv.hash);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_tx_relay->vInventoryOtherToSend.push_back(inv);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PushBlockHash(const uint256 &hash)
|
void PushBlockHash(const uint256 &hash)
|
||||||
|
@ -489,7 +489,7 @@ static void PushNodeVersion(CNode *pnode, CConnman* connman, int64_t nTime)
|
|||||||
}
|
}
|
||||||
|
|
||||||
connman->PushMessage(pnode, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::VERSION, nProtocolVersion, (uint64_t)nLocalNodeServices, nTime, addrYou, addrMe,
|
connman->PushMessage(pnode, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::VERSION, nProtocolVersion, (uint64_t)nLocalNodeServices, nTime, addrYou, addrMe,
|
||||||
nonce, strSubVersion, nNodeStartingHeight, ::g_relay_txes && pnode->m_tx_relay != nullptr, mnauthChallenge, pnode->m_masternode_connection.load()));
|
nonce, strSubVersion, nNodeStartingHeight, ::g_relay_txes && !pnode->m_block_relay_only_peer, mnauthChallenge, pnode->m_masternode_connection.load()));
|
||||||
|
|
||||||
if (fLogIPs) {
|
if (fLogIPs) {
|
||||||
LogPrint(BCLog::NET, "send version message: version %d, blocks=%d, us=%s, them=%s, peer=%d\n", nProtocolVersion, nNodeStartingHeight, addrMe.ToString(), addrYou.ToString(), nodeid);
|
LogPrint(BCLog::NET, "send version message: version %d, blocks=%d, us=%s, them=%s, peer=%d\n", nProtocolVersion, nNodeStartingHeight, addrMe.ToString(), addrYou.ToString(), nodeid);
|
||||||
@ -1688,7 +1688,7 @@ void static ProcessGetBlockData(CNode* pfrom, const CChainParams& chainparams, c
|
|||||||
else if (inv.type == MSG_FILTERED_BLOCK) {
|
else if (inv.type == MSG_FILTERED_BLOCK) {
|
||||||
bool sendMerkleBlock = false;
|
bool sendMerkleBlock = false;
|
||||||
CMerkleBlock merkleBlock;
|
CMerkleBlock merkleBlock;
|
||||||
if (pfrom->m_tx_relay != nullptr) {
|
if (!pfrom->m_block_relay_only_peer) {
|
||||||
LOCK(pfrom->m_tx_relay->cs_filter);
|
LOCK(pfrom->m_tx_relay->cs_filter);
|
||||||
if (pfrom->m_tx_relay->pfilter) {
|
if (pfrom->m_tx_relay->pfilter) {
|
||||||
sendMerkleBlock = true;
|
sendMerkleBlock = true;
|
||||||
@ -1757,11 +1757,7 @@ void static ProcessGetData(CNode* pfrom, const CChainParams& chainparams, CConnm
|
|||||||
std::vector<CInv> vNotFound;
|
std::vector<CInv> vNotFound;
|
||||||
const CNetMsgMaker msgMaker(pfrom->GetSendVersion());
|
const CNetMsgMaker msgMaker(pfrom->GetSendVersion());
|
||||||
|
|
||||||
// Note that if we receive a getdata for a MSG_TX or MSG_WITNESS_TX from a
|
{
|
||||||
// block-relay-only outbound peer, we will stop processing further getdata
|
|
||||||
// messages from this peer (likely resulting in our peer eventually
|
|
||||||
// disconnecting us).
|
|
||||||
if (pfrom->m_tx_relay != nullptr) {
|
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
|
|
||||||
while (it != pfrom->vRecvGetData.end() && it->IsKnownType()) {
|
while (it != pfrom->vRecvGetData.end() && it->IsKnownType()) {
|
||||||
@ -1775,6 +1771,13 @@ void static ProcessGetData(CNode* pfrom, const CChainParams& chainparams, CConnm
|
|||||||
if (inv.type == MSG_BLOCK || inv.type == MSG_FILTERED_BLOCK || inv.type == MSG_CMPCT_BLOCK) {
|
if (inv.type == MSG_BLOCK || inv.type == MSG_FILTERED_BLOCK || inv.type == MSG_CMPCT_BLOCK) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (pfrom->m_block_relay_only_peer && NetMessageViolatesBlocksOnly(inv.GetCommand())) {
|
||||||
|
// Note that if we receive a getdata for non-block messages
|
||||||
|
// from a block-relay-only outbound peer that violate the policy,
|
||||||
|
// we will stop processing further getdata messages from this peer
|
||||||
|
// (likely resulting in our peer eventually disconnecting us).
|
||||||
|
break;
|
||||||
|
}
|
||||||
it++;
|
it++;
|
||||||
|
|
||||||
// Send stream from relay memory
|
// Send stream from relay memory
|
||||||
@ -2141,7 +2144,7 @@ bool static ProcessHeadersMessage(CNode *pfrom, CConnman *connman, ChainstateMan
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pfrom->fDisconnect && IsOutboundDisconnectionCandidate(pfrom) && nodestate->pindexBestKnownBlock != nullptr && pfrom->m_tx_relay != nullptr) {
|
if (!pfrom->fDisconnect && IsOutboundDisconnectionCandidate(pfrom) && nodestate->pindexBestKnownBlock != nullptr && !pfrom->m_block_relay_only_peer) {
|
||||||
// If this is an outbound full-relay peer, check to see if we should protect
|
// If this is an outbound full-relay peer, check to see if we should protect
|
||||||
// it from the bad/lagging chain logic.
|
// it from the bad/lagging chain logic.
|
||||||
// Note that block-relay-only peers are already implicitly protected, so we
|
// Note that block-relay-only peers are already implicitly protected, so we
|
||||||
@ -2693,7 +2696,7 @@ bool ProcessMessage(CNode* pfrom, const std::string& msg_type, CDataStream& vRec
|
|||||||
// set nodes not capable of serving the complete blockchain history as "limited nodes"
|
// set nodes not capable of serving the complete blockchain history as "limited nodes"
|
||||||
pfrom->m_limited_node = (!(nServices & NODE_NETWORK) && (nServices & NODE_NETWORK_LIMITED));
|
pfrom->m_limited_node = (!(nServices & NODE_NETWORK) && (nServices & NODE_NETWORK_LIMITED));
|
||||||
|
|
||||||
if (pfrom->m_tx_relay != nullptr) {
|
if (!pfrom->m_block_relay_only_peer) {
|
||||||
LOCK(pfrom->m_tx_relay->cs_filter);
|
LOCK(pfrom->m_tx_relay->cs_filter);
|
||||||
pfrom->m_tx_relay->fRelayTxes = fRelay; // set to true after we get the first filter* message
|
pfrom->m_tx_relay->fRelayTxes = fRelay; // set to true after we get the first filter* message
|
||||||
}
|
}
|
||||||
@ -2766,6 +2769,8 @@ bool ProcessMessage(CNode* pfrom, const std::string& msg_type, CDataStream& vRec
|
|||||||
// At this point, the outgoing message serialization version can't change.
|
// At this point, the outgoing message serialization version can't change.
|
||||||
const CNetMsgMaker msgMaker(pfrom->GetSendVersion());
|
const CNetMsgMaker msgMaker(pfrom->GetSendVersion());
|
||||||
|
|
||||||
|
bool fBlocksOnly = pfrom->IsBlockRelayOnly();
|
||||||
|
|
||||||
if (msg_type == NetMsgType::VERACK)
|
if (msg_type == NetMsgType::VERACK)
|
||||||
{
|
{
|
||||||
pfrom->SetRecvVersion(std::min(pfrom->nVersion.load(), PROTOCOL_VERSION));
|
pfrom->SetRecvVersion(std::min(pfrom->nVersion.load(), PROTOCOL_VERSION));
|
||||||
@ -2777,7 +2782,7 @@ bool ProcessMessage(CNode* pfrom, const std::string& msg_type, CDataStream& vRec
|
|||||||
LogPrintf("New outbound peer connected: version: %d, blocks=%d, peer=%d%s (%s)\n",
|
LogPrintf("New outbound peer connected: version: %d, blocks=%d, peer=%d%s (%s)\n",
|
||||||
pfrom->nVersion.load(), pfrom->nStartingHeight,
|
pfrom->nVersion.load(), pfrom->nStartingHeight,
|
||||||
pfrom->GetId(), (fLogIPs ? strprintf(", peeraddr=%s", pfrom->addr.ToString()) : ""),
|
pfrom->GetId(), (fLogIPs ? strprintf(", peeraddr=%s", pfrom->addr.ToString()) : ""),
|
||||||
pfrom->m_tx_relay == nullptr ? "block-relay" : "full-relay");
|
pfrom->m_block_relay_only_peer ? "block-relay" : "full-relay");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pfrom->m_masternode_probe_connection) {
|
if (!pfrom->m_masternode_probe_connection) {
|
||||||
@ -2802,10 +2807,11 @@ bool ProcessMessage(CNode* pfrom, const std::string& msg_type, CDataStream& vRec
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Tell our peer that he should send us CoinJoin queue messages
|
// Tell our peer that he should send us CoinJoin queue messages
|
||||||
connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::SENDDSQUEUE, true));
|
if (!fBlocksOnly) {
|
||||||
|
connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::SENDDSQUEUE, true));
|
||||||
if (llmq::CLLMQUtils::IsWatchQuorumsEnabled() && !pfrom->m_masternode_connection) {
|
if (llmq::CLLMQUtils::IsWatchQuorumsEnabled() && !pfrom->m_masternode_connection) {
|
||||||
connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::QWATCH));
|
connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::QWATCH));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pfrom->fSuccessfullyConnected = true;
|
pfrom->fSuccessfullyConnected = true;
|
||||||
@ -2847,6 +2853,13 @@ bool ProcessMessage(CNode* pfrom, const std::string& msg_type, CDataStream& vRec
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Stop processing non-block data early in blocks only mode and for block-relay-only peers
|
||||||
|
if (fBlocksOnly && NetMessageViolatesBlocksOnly(msg_type)) {
|
||||||
|
LogPrint(BCLog::NET, "%s sent in violation of protocol peer=%d\n", msg_type, pfrom->GetId());
|
||||||
|
pfrom->fDisconnect = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (msg_type == NetMsgType::ADDR || msg_type == NetMsgType::ADDRV2) {
|
if (msg_type == NetMsgType::ADDR || msg_type == NetMsgType::ADDRV2) {
|
||||||
int stream_version = vRecv.GetVersion();
|
int stream_version = vRecv.GetVersion();
|
||||||
if (msg_type == NetMsgType::ADDRV2) {
|
if (msg_type == NetMsgType::ADDRV2) {
|
||||||
@ -2964,14 +2977,6 @@ bool ProcessMessage(CNode* pfrom, const std::string& msg_type, CDataStream& vRec
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We won't accept tx inv's if we're in blocks-only mode, or this is a
|
|
||||||
// block-relay-only peer
|
|
||||||
bool fBlocksOnly = !g_relay_txes || (pfrom->m_tx_relay == nullptr);
|
|
||||||
|
|
||||||
// Allow whitelisted peers to send data other than blocks in blocks only mode if whitelistrelay is true
|
|
||||||
if (pfrom->HasPermission(PF_RELAY))
|
|
||||||
fBlocksOnly = false;
|
|
||||||
|
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
|
|
||||||
const auto current_time = GetTime<std::chrono::microseconds>();
|
const auto current_time = GetTime<std::chrono::microseconds>();
|
||||||
@ -3027,11 +3032,22 @@ bool ProcessMessage(CNode* pfrom, const std::string& msg_type, CDataStream& vRec
|
|||||||
};
|
};
|
||||||
|
|
||||||
pfrom->AddInventoryKnown(inv);
|
pfrom->AddInventoryKnown(inv);
|
||||||
if (fBlocksOnly) {
|
if (fBlocksOnly && NetMessageViolatesBlocksOnly(inv.GetCommand())) {
|
||||||
LogPrint(BCLog::NET, "transaction (%s) inv sent in violation of protocol, disconnecting peer=%d\n", inv.hash.ToString(), pfrom->GetId());
|
LogPrint(BCLog::NET, "%s (%s) inv sent in violation of protocol, disconnecting peer=%d\n", inv.GetCommand(), inv.hash.ToString(), pfrom->GetId());
|
||||||
pfrom->fDisconnect = true;
|
pfrom->fDisconnect = true;
|
||||||
return true;
|
return true;
|
||||||
} else if (!fAlreadyHave) {
|
} else if (!fAlreadyHave) {
|
||||||
|
if (fBlocksOnly && (inv.type == MSG_ISLOCK || inv.type == MSG_ISDLOCK)) {
|
||||||
|
if (pfrom->GetRecvVersion() <= ADDRV2_PROTO_VERSION) {
|
||||||
|
// It's ok to receive these invs, we just ignore them
|
||||||
|
// and do not request corresponding objects.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Peers with newer versions should never send us these invs when we are in blocks-relay-only mode
|
||||||
|
LogPrint(BCLog::NET, "%s (%s) inv sent in violation of protocol, disconnecting peer=%d\n", inv.GetCommand(), inv.hash.ToString(), pfrom->GetId());
|
||||||
|
pfrom->fDisconnect = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
bool allowWhileInIBD = allowWhileInIBDObjs.count(inv.type);
|
bool allowWhileInIBD = allowWhileInIBDObjs.count(inv.type);
|
||||||
if (allowWhileInIBD || !chainman.ActiveChainstate().IsInitialBlockDownload()) {
|
if (allowWhileInIBD || !chainman.ActiveChainstate().IsInitialBlockDownload()) {
|
||||||
RequestObject(State(pfrom->GetId()), inv, current_time);
|
RequestObject(State(pfrom->GetId()), inv, current_time);
|
||||||
@ -3266,16 +3282,6 @@ bool ProcessMessage(CNode* pfrom, const std::string& msg_type, CDataStream& vRec
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (msg_type == NetMsgType::TX || msg_type == NetMsgType::DSTX || msg_type == NetMsgType::LEGACYTXLOCKREQUEST) {
|
if (msg_type == NetMsgType::TX || msg_type == NetMsgType::DSTX || msg_type == NetMsgType::LEGACYTXLOCKREQUEST) {
|
||||||
// Stop processing the transaction early if
|
|
||||||
// 1) We are in blocks only mode and peer has no relay permission
|
|
||||||
// 2) This peer is a block-relay-only peer
|
|
||||||
if ((!g_relay_txes && !pfrom->HasPermission(PF_RELAY)) || (pfrom->m_tx_relay == nullptr))
|
|
||||||
{
|
|
||||||
LogPrint(BCLog::NET, "transaction sent in violation of protocol peer=%d\n", pfrom->GetId());
|
|
||||||
pfrom->fDisconnect = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
CTransactionRef ptx;
|
CTransactionRef ptx;
|
||||||
CCoinJoinBroadcastTx dstx;
|
CCoinJoinBroadcastTx dstx;
|
||||||
int nInvType = MSG_TX;
|
int nInvType = MSG_TX;
|
||||||
@ -3862,7 +3868,7 @@ bool ProcessMessage(CNode* pfrom, const std::string& msg_type, CDataStream& vRec
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pfrom->m_tx_relay != nullptr) {
|
if (!pfrom->m_block_relay_only_peer) {
|
||||||
LOCK(pfrom->m_tx_relay->cs_tx_inventory);
|
LOCK(pfrom->m_tx_relay->cs_tx_inventory);
|
||||||
pfrom->m_tx_relay->fSendMempool = true;
|
pfrom->m_tx_relay->fSendMempool = true;
|
||||||
}
|
}
|
||||||
@ -3953,7 +3959,7 @@ bool ProcessMessage(CNode* pfrom, const std::string& msg_type, CDataStream& vRec
|
|||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
Misbehaving(pfrom->GetId(), 100);
|
Misbehaving(pfrom->GetId(), 100);
|
||||||
}
|
}
|
||||||
else if (pfrom->m_tx_relay != nullptr)
|
else if (!pfrom->m_block_relay_only_peer)
|
||||||
{
|
{
|
||||||
LOCK(pfrom->m_tx_relay->cs_filter);
|
LOCK(pfrom->m_tx_relay->cs_filter);
|
||||||
pfrom->m_tx_relay->pfilter.reset(new CBloomFilter(filter));
|
pfrom->m_tx_relay->pfilter.reset(new CBloomFilter(filter));
|
||||||
@ -3972,7 +3978,7 @@ bool ProcessMessage(CNode* pfrom, const std::string& msg_type, CDataStream& vRec
|
|||||||
bool bad = false;
|
bool bad = false;
|
||||||
if (vData.size() > MAX_SCRIPT_ELEMENT_SIZE) {
|
if (vData.size() > MAX_SCRIPT_ELEMENT_SIZE) {
|
||||||
bad = true;
|
bad = true;
|
||||||
} else if (pfrom->m_tx_relay != nullptr) {
|
} else if (!pfrom->m_block_relay_only_peer) {
|
||||||
LOCK(pfrom->m_tx_relay->cs_filter);
|
LOCK(pfrom->m_tx_relay->cs_filter);
|
||||||
if (pfrom->m_tx_relay->pfilter) {
|
if (pfrom->m_tx_relay->pfilter) {
|
||||||
pfrom->m_tx_relay->pfilter->insert(vData);
|
pfrom->m_tx_relay->pfilter->insert(vData);
|
||||||
@ -3988,7 +3994,7 @@ bool ProcessMessage(CNode* pfrom, const std::string& msg_type, CDataStream& vRec
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (msg_type == NetMsgType::FILTERCLEAR) {
|
if (msg_type == NetMsgType::FILTERCLEAR) {
|
||||||
if (pfrom->m_tx_relay == nullptr) {
|
if (pfrom->m_block_relay_only_peer) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
LOCK(pfrom->m_tx_relay->cs_filter);
|
LOCK(pfrom->m_tx_relay->cs_filter);
|
||||||
@ -4365,7 +4371,7 @@ void PeerLogicValidation::EvictExtraOutboundPeers(int64_t time_in_seconds)
|
|||||||
// Don't evict our protected peers
|
// Don't evict our protected peers
|
||||||
if (state->m_chain_sync.m_protect) return;
|
if (state->m_chain_sync.m_protect) return;
|
||||||
// Don't evict our block-relay-only peers.
|
// Don't evict our block-relay-only peers.
|
||||||
if (pnode->m_tx_relay == nullptr) return;
|
if (pnode->m_block_relay_only_peer) return;
|
||||||
if (state->m_last_block_announcement < oldest_block_announcement || (state->m_last_block_announcement == oldest_block_announcement && pnode->GetId() > worst_peer)) {
|
if (state->m_last_block_announcement < oldest_block_announcement || (state->m_last_block_announcement == oldest_block_announcement && pnode->GetId() > worst_peer)) {
|
||||||
worst_peer = pnode->GetId();
|
worst_peer = pnode->GetId();
|
||||||
oldest_block_announcement = state->m_last_block_announcement;
|
oldest_block_announcement = state->m_last_block_announcement;
|
||||||
@ -4724,8 +4730,8 @@ bool PeerLogicValidation::SendMessages(CNode* pto)
|
|||||||
LOCK2(m_mempool.cs, pto->cs_inventory);
|
LOCK2(m_mempool.cs, pto->cs_inventory);
|
||||||
|
|
||||||
size_t reserve = INVENTORY_BROADCAST_MAX_PER_1MB_BLOCK * MaxBlockSize() / 1000000;
|
size_t reserve = INVENTORY_BROADCAST_MAX_PER_1MB_BLOCK * MaxBlockSize() / 1000000;
|
||||||
if (pto->m_tx_relay != nullptr) {
|
if (!pto->m_block_relay_only_peer) {
|
||||||
LOCK(pto->m_tx_relay->cs_filter);
|
LOCK(pto->m_tx_relay->cs_tx_inventory);
|
||||||
reserve = std::min<size_t>(pto->m_tx_relay->setInventoryTxToSend.size(), reserve);
|
reserve = std::min<size_t>(pto->m_tx_relay->setInventoryTxToSend.size(), reserve);
|
||||||
}
|
}
|
||||||
reserve = std::max<size_t>(reserve, pto->vInventoryBlockToSend.size());
|
reserve = std::max<size_t>(reserve, pto->vInventoryBlockToSend.size());
|
||||||
@ -4743,10 +4749,8 @@ bool PeerLogicValidation::SendMessages(CNode* pto)
|
|||||||
pto->vInventoryBlockToSend.clear();
|
pto->vInventoryBlockToSend.clear();
|
||||||
|
|
||||||
auto queueAndMaybePushInv = [this, pto, &vInv, &msgMaker](const CInv& invIn) {
|
auto queueAndMaybePushInv = [this, pto, &vInv, &msgMaker](const CInv& invIn) {
|
||||||
if (pto->m_tx_relay != nullptr) {
|
AssertLockHeld(pto->m_tx_relay->cs_tx_inventory);
|
||||||
AssertLockHeld(pto->m_tx_relay->cs_tx_inventory);
|
pto->m_tx_relay->filterInventoryKnown.insert(invIn.hash);
|
||||||
pto->m_tx_relay->filterInventoryKnown.insert(invIn.hash);
|
|
||||||
}
|
|
||||||
LogPrint(BCLog::NET, "SendMessages -- queued inv: %s index=%d peer=%d\n", invIn.ToString(), vInv.size(), pto->GetId());
|
LogPrint(BCLog::NET, "SendMessages -- queued inv: %s index=%d peer=%d\n", invIn.ToString(), vInv.size(), pto->GetId());
|
||||||
vInv.push_back(invIn);
|
vInv.push_back(invIn);
|
||||||
if (vInv.size() == MAX_INV_SZ) {
|
if (vInv.size() == MAX_INV_SZ) {
|
||||||
@ -4756,7 +4760,7 @@ bool PeerLogicValidation::SendMessages(CNode* pto)
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (pto->m_tx_relay != nullptr) {
|
if (!pto->m_block_relay_only_peer) {
|
||||||
LOCK(pto->m_tx_relay->cs_tx_inventory);
|
LOCK(pto->m_tx_relay->cs_tx_inventory);
|
||||||
// Check whether periodic sends should happen
|
// Check whether periodic sends should happen
|
||||||
// Note: If this node is running in a Masternode mode, it makes no sense to delay outgoing txes
|
// Note: If this node is running in a Masternode mode, it makes no sense to delay outgoing txes
|
||||||
@ -4865,21 +4869,27 @@ bool PeerLogicValidation::SendMessages(CNode* pto)
|
|||||||
queueAndMaybePushInv(CInv(nInvType, hash));
|
queueAndMaybePushInv(CInv(nInvType, hash));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
// Send non-tx/non-block inventory items
|
// Send non-tx/non-block inventory items
|
||||||
for (const auto& inv : pto->vInventoryOtherToSend) {
|
LOCK2(pto->m_tx_relay->cs_tx_inventory, pto->m_tx_relay->cs_filter);
|
||||||
|
|
||||||
|
bool fSendIS = pto->m_tx_relay->fRelayTxes && !pto->IsBlockRelayOnly();
|
||||||
|
|
||||||
|
for (const auto& inv : pto->m_tx_relay->vInventoryOtherToSend) {
|
||||||
|
if (!pto->m_tx_relay->fRelayTxes && NetMessageViolatesBlocksOnly(inv.GetCommand())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (pto->m_tx_relay->filterInventoryKnown.contains(inv.hash)) {
|
if (pto->m_tx_relay->filterInventoryKnown.contains(inv.hash)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (!fSendIS && (inv.type == MSG_ISLOCK || inv.type == MSG_ISDLOCK)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
queueAndMaybePushInv(inv);
|
queueAndMaybePushInv(inv);
|
||||||
}
|
}
|
||||||
pto->vInventoryOtherToSend.clear();
|
pto->m_tx_relay->vInventoryOtherToSend.clear();
|
||||||
} else { // m_tx_relay is nullptr but we still need to send items from `vInventoryOtherToSend`
|
|
||||||
// Send non-tx/non-block inventory items
|
|
||||||
for (const auto& inv : pto->vInventoryOtherToSend) {
|
|
||||||
queueAndMaybePushInv(inv);
|
|
||||||
}
|
|
||||||
pto->vInventoryOtherToSend.clear();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!vInv.empty())
|
if (!vInv.empty())
|
||||||
|
@ -174,6 +174,34 @@ const static std::string allNetMessageTypes[] = {
|
|||||||
NetMsgType::HEADERS2};
|
NetMsgType::HEADERS2};
|
||||||
const static std::vector<std::string> allNetMessageTypesVec(allNetMessageTypes, allNetMessageTypes+ARRAYLEN(allNetMessageTypes));
|
const static std::vector<std::string> allNetMessageTypesVec(allNetMessageTypes, allNetMessageTypes+ARRAYLEN(allNetMessageTypes));
|
||||||
|
|
||||||
|
const static std::string netMessageTypesViolateBlocksOnly[] = {
|
||||||
|
NetMsgType::DSACCEPT,
|
||||||
|
NetMsgType::DSCOMPLETE,
|
||||||
|
NetMsgType::DSFINALTX,
|
||||||
|
NetMsgType::DSQUEUE,
|
||||||
|
NetMsgType::DSSIGNFINALTX,
|
||||||
|
NetMsgType::DSSTATUSUPDATE,
|
||||||
|
NetMsgType::DSTX,
|
||||||
|
NetMsgType::DSVIN,
|
||||||
|
NetMsgType::LEGACYTXLOCKREQUEST,
|
||||||
|
NetMsgType::QBSIGSHARES,
|
||||||
|
NetMsgType::QCOMPLAINT,
|
||||||
|
NetMsgType::QCONTRIB,
|
||||||
|
NetMsgType::QDATA,
|
||||||
|
NetMsgType::QGETDATA,
|
||||||
|
NetMsgType::QGETSIGSHARES,
|
||||||
|
NetMsgType::QJUSTIFICATION,
|
||||||
|
NetMsgType::QPCOMMITMENT,
|
||||||
|
NetMsgType::QSENDRECSIGS,
|
||||||
|
NetMsgType::QSIGREC,
|
||||||
|
NetMsgType::QSIGSESANN,
|
||||||
|
NetMsgType::QSIGSHARE,
|
||||||
|
NetMsgType::QSIGSHARESINV,
|
||||||
|
NetMsgType::QWATCH,
|
||||||
|
NetMsgType::TX,
|
||||||
|
};
|
||||||
|
const static std::set<std::string> netMessageTypesViolateBlocksOnlySet(netMessageTypesViolateBlocksOnly, netMessageTypesViolateBlocksOnly+ARRAYLEN(netMessageTypesViolateBlocksOnly));
|
||||||
|
|
||||||
CMessageHeader::CMessageHeader(const MessageStartChars& pchMessageStartIn)
|
CMessageHeader::CMessageHeader(const MessageStartChars& pchMessageStartIn)
|
||||||
{
|
{
|
||||||
memcpy(pchMessageStart, pchMessageStartIn, MESSAGE_START_SIZE);
|
memcpy(pchMessageStart, pchMessageStartIn, MESSAGE_START_SIZE);
|
||||||
@ -337,6 +365,11 @@ const std::vector<std::string> &getAllNetMessageTypes()
|
|||||||
return allNetMessageTypesVec;
|
return allNetMessageTypesVec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool NetMessageViolatesBlocksOnly(const std::string& msg_type)
|
||||||
|
{
|
||||||
|
return netMessageTypesViolateBlocksOnlySet.find(msg_type) != netMessageTypesViolateBlocksOnlySet.end();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert a service flag (NODE_*) to a human readable string.
|
* Convert a service flag (NODE_*) to a human readable string.
|
||||||
* It supports unknown service flags which will be returned as "UNKNOWN[...]".
|
* It supports unknown service flags which will be returned as "UNKNOWN[...]".
|
||||||
|
@ -306,6 +306,9 @@ extern const char *QUORUMROTATIONINFO;
|
|||||||
/* Get a vector of all valid message types (see above) */
|
/* Get a vector of all valid message types (see above) */
|
||||||
const std::vector<std::string> &getAllNetMessageTypes();
|
const std::vector<std::string> &getAllNetMessageTypes();
|
||||||
|
|
||||||
|
/* Whether the message type violates blocks-relay-only policy */
|
||||||
|
bool NetMessageViolatesBlocksOnly(const std::string& msg_type);
|
||||||
|
|
||||||
/** nServices flags */
|
/** nServices flags */
|
||||||
enum ServiceFlags : uint64_t {
|
enum ServiceFlags : uint64_t {
|
||||||
// NOTE: When adding here, be sure to update serviceFlagToStr too
|
// NOTE: When adding here, be sure to update serviceFlagToStr too
|
||||||
|
@ -40,7 +40,7 @@ class P2PBlocksOnly(BitcoinTestFramework):
|
|||||||
}],
|
}],
|
||||||
)['hex']
|
)['hex']
|
||||||
assert_equal(self.nodes[0].getnetworkinfo()['localrelay'], False)
|
assert_equal(self.nodes[0].getnetworkinfo()['localrelay'], False)
|
||||||
with self.nodes[0].assert_debug_log(['transaction sent in violation of protocol peer=0']):
|
with self.nodes[0].assert_debug_log(['tx sent in violation of protocol peer=0']):
|
||||||
self.nodes[0].p2p.send_message(msg_tx(FromHex(CTransaction(), sigtx)))
|
self.nodes[0].p2p.send_message(msg_tx(FromHex(CTransaction(), sigtx)))
|
||||||
self.nodes[0].p2p.wait_for_disconnect()
|
self.nodes[0].p2p.wait_for_disconnect()
|
||||||
assert_equal(self.nodes[0].getmempoolinfo()['size'], 0)
|
assert_equal(self.nodes[0].getmempoolinfo()['size'], 0)
|
||||||
|
Loading…
Reference in New Issue
Block a user