mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-04 10:07:27 -05:00
c3fad1f29d
Before this commit, there are only two possibly outcomes for the "more" prediction in Transport::GetBytesToSend(): * true: the transport itself has more to send, so the answer is certainly yes. * false: the transport has nothing further to send, but if vSendMsg has more message(s) left, that still will result in more wire bytes after the next SetMessageToSend(). For the BIP324 v2 transport, there will arguably be a third state: * definitely not: the transport has nothing further to send, but even if vSendMsg has more messages left, they can't be sent (right now). This happens before the handshake is complete. To implement this, we move the entire decision logic to the Transport, by adding a boolean to GetBytesToSend(), called have_next_message, which informs the transport whether more messages are available. The return values are still true and false, but they mean "definitely yes" and "definitely no", rather than "yes" and "maybe".
124 lines
5 KiB
C++
124 lines
5 KiB
C++
// Copyright (c) 2020-2022 The Bitcoin Core developers
|
|
// Distributed under the MIT software license, see the accompanying
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
|
|
#include <test/util/net.h>
|
|
|
|
#include <chainparams.h>
|
|
#include <node/eviction.h>
|
|
#include <net.h>
|
|
#include <net_processing.h>
|
|
#include <netmessagemaker.h>
|
|
#include <span.h>
|
|
|
|
#include <vector>
|
|
|
|
void ConnmanTestMsg::Handshake(CNode& node,
|
|
bool successfully_connected,
|
|
ServiceFlags remote_services,
|
|
ServiceFlags local_services,
|
|
int32_t version,
|
|
bool relay_txs)
|
|
{
|
|
auto& peerman{static_cast<PeerManager&>(*m_msgproc)};
|
|
auto& connman{*this};
|
|
const CNetMsgMaker mm{0};
|
|
|
|
peerman.InitializeNode(node, local_services);
|
|
FlushSendBuffer(node); // Drop the version message added by InitializeNode.
|
|
|
|
CSerializedNetMsg msg_version{
|
|
mm.Make(NetMsgType::VERSION,
|
|
version, //
|
|
Using<CustomUintFormatter<8>>(remote_services), //
|
|
int64_t{}, // dummy time
|
|
int64_t{}, // ignored service bits
|
|
WithParams(CNetAddr::V1, CService{}), // dummy
|
|
int64_t{}, // ignored service bits
|
|
WithParams(CNetAddr::V1, CService{}), // ignored
|
|
uint64_t{1}, // dummy nonce
|
|
std::string{}, // dummy subver
|
|
int32_t{}, // dummy starting_height
|
|
relay_txs),
|
|
};
|
|
|
|
(void)connman.ReceiveMsgFrom(node, std::move(msg_version));
|
|
node.fPauseSend = false;
|
|
connman.ProcessMessagesOnce(node);
|
|
peerman.SendMessages(&node);
|
|
FlushSendBuffer(node); // Drop the verack message added by SendMessages.
|
|
if (node.fDisconnect) return;
|
|
assert(node.nVersion == version);
|
|
assert(node.GetCommonVersion() == std::min(version, PROTOCOL_VERSION));
|
|
CNodeStateStats statestats;
|
|
assert(peerman.GetNodeStateStats(node.GetId(), statestats));
|
|
assert(statestats.m_relay_txs == (relay_txs && !node.IsBlockOnlyConn()));
|
|
assert(statestats.their_services == remote_services);
|
|
if (successfully_connected) {
|
|
CSerializedNetMsg msg_verack{mm.Make(NetMsgType::VERACK)};
|
|
(void)connman.ReceiveMsgFrom(node, std::move(msg_verack));
|
|
node.fPauseSend = false;
|
|
connman.ProcessMessagesOnce(node);
|
|
peerman.SendMessages(&node);
|
|
assert(node.fSuccessfullyConnected == true);
|
|
}
|
|
}
|
|
|
|
void ConnmanTestMsg::NodeReceiveMsgBytes(CNode& node, Span<const uint8_t> msg_bytes, bool& complete) const
|
|
{
|
|
assert(node.ReceiveMsgBytes(msg_bytes, complete));
|
|
if (complete) {
|
|
node.MarkReceivedMsgsForProcessing();
|
|
}
|
|
}
|
|
|
|
void ConnmanTestMsg::FlushSendBuffer(CNode& node) const
|
|
{
|
|
LOCK(node.cs_vSend);
|
|
node.vSendMsg.clear();
|
|
node.m_send_memusage = 0;
|
|
while (true) {
|
|
const auto& [to_send, _more, _msg_type] = node.m_transport->GetBytesToSend(false);
|
|
if (to_send.empty()) break;
|
|
node.m_transport->MarkBytesSent(to_send.size());
|
|
}
|
|
}
|
|
|
|
bool ConnmanTestMsg::ReceiveMsgFrom(CNode& node, CSerializedNetMsg&& ser_msg) const
|
|
{
|
|
bool queued = node.m_transport->SetMessageToSend(ser_msg);
|
|
assert(queued);
|
|
bool complete{false};
|
|
while (true) {
|
|
const auto& [to_send, _more, _msg_type] = node.m_transport->GetBytesToSend(false);
|
|
if (to_send.empty()) break;
|
|
NodeReceiveMsgBytes(node, to_send, complete);
|
|
node.m_transport->MarkBytesSent(to_send.size());
|
|
}
|
|
return complete;
|
|
}
|
|
|
|
std::vector<NodeEvictionCandidate> GetRandomNodeEvictionCandidates(int n_candidates, FastRandomContext& random_context)
|
|
{
|
|
std::vector<NodeEvictionCandidate> candidates;
|
|
candidates.reserve(n_candidates);
|
|
for (int id = 0; id < n_candidates; ++id) {
|
|
candidates.push_back({
|
|
/*id=*/id,
|
|
/*m_connected=*/std::chrono::seconds{random_context.randrange(100)},
|
|
/*m_min_ping_time=*/std::chrono::microseconds{random_context.randrange(100)},
|
|
/*m_last_block_time=*/std::chrono::seconds{random_context.randrange(100)},
|
|
/*m_last_tx_time=*/std::chrono::seconds{random_context.randrange(100)},
|
|
/*fRelevantServices=*/random_context.randbool(),
|
|
/*m_relay_txs=*/random_context.randbool(),
|
|
/*fBloomFilter=*/random_context.randbool(),
|
|
/*nKeyedNetGroup=*/random_context.randrange(100),
|
|
/*prefer_evict=*/random_context.randbool(),
|
|
/*m_is_local=*/random_context.randbool(),
|
|
/*m_network=*/ALL_NETWORKS[random_context.randrange(ALL_NETWORKS.size())],
|
|
/*m_noban=*/false,
|
|
/*m_conn_type=*/ConnectionType::INBOUND,
|
|
});
|
|
}
|
|
return candidates;
|
|
}
|