26std::chrono::microseconds
DELAYS[256];
38 DELAYS[i] = std::chrono::microseconds{i};
42 for (; i < 128; ++i) {
48 for (; i < 256; ++i) {
87 std::priority_queue<std::chrono::microseconds, std::vector<std::chrono::microseconds>,
88 std::greater<std::chrono::microseconds>> m_events;
93 std::chrono::microseconds m_time;
95 State m_state{State::NOTHING};
105 std::chrono::microseconds m_now{244466666};
111 for (
int peer = 0; peer <
MAX_PEERS; ++peer) {
112 const Announcement&
ann = m_announcements[
txhash][peer];
113 if (
ann.m_state != State::NOTHING) {
114 if (
ann.m_state != State::COMPLETED)
return;
119 for (
int peer = 0; peer <
MAX_PEERS; ++peer) {
120 m_announcements[
txhash][peer].m_state = State::NOTHING;
129 for (
int peer = 0; peer <
MAX_PEERS; ++peer) {
130 const Announcement&
ann = m_announcements[
txhash][peer];
132 if (
ann.m_state == State::REQUESTED)
return -1;
134 if (
ann.m_state == State::CANDIDATE &&
ann.m_time <= m_now) {
144 Tester() : m_tracker(
true) {}
146 std::chrono::microseconds
Now()
const {
return m_now; }
151 while (!m_events.empty() && m_events.top() <= m_now) m_events.pop();
156 while (!m_events.empty() && m_events.top() <= m_now) m_events.pop();
157 if (!m_events.empty()) {
158 m_now = m_events.top();
163 void DisconnectedPeer(
int peer)
167 if (m_announcements[
txhash][peer].m_state != State::NOTHING) {
168 m_announcements[
txhash][peer].m_state = State::NOTHING;
177 void ForgetTxHash(
int txhash)
180 for (
int peer = 0; peer <
MAX_PEERS; ++peer) {
181 m_announcements[
txhash][peer].m_state = State::NOTHING;
193 Announcement&
ann = m_announcements[
txhash][peer];
194 if (
ann.m_state == State::NOTHING) {
196 ann.m_state = State::CANDIDATE;
199 ann.m_sequence = m_current_sequence++;
211 void RequestedTx(
int peer,
int txhash, std::chrono::microseconds
exptime)
215 if (m_announcements[
txhash][peer].m_state == State::CANDIDATE) {
217 if (m_announcements[
txhash][
peer2].m_state == State::REQUESTED) {
218 m_announcements[
txhash][
peer2].m_state = State::COMPLETED;
221 m_announcements[
txhash][peer].m_state = State::REQUESTED;
232 void ReceivedResponse(
int peer,
int txhash)
235 if (m_announcements[
txhash][peer].m_state != State::NOTHING) {
236 m_announcements[
txhash][peer].m_state = State::COMPLETED;
244 void GetRequestable(
int peer)
249 std::vector<std::tuple<uint64_t, int, bool>> result;
255 if (
ann2.m_state == State::REQUESTED &&
ann2.m_time <= m_now) {
258 ann2.m_state = State::COMPLETED;
265 const Announcement&
ann = m_announcements[
txhash][peer];
267 result.emplace_back(
ann.m_sequence,
txhash,
ann.m_is_wtxid);
271 std::sort(result.begin(), result.end());
275 std::vector<std::pair<NodeId, GenTxid>> expired;
277 std::sort(expired.begin(), expired.end());
282 for (
size_t pos = 0; pos <
actual.size(); ++pos) {
284 assert(std::get<2>(result[pos]) ==
actual[pos].IsWtxid());
292 for (
int peer = 0; peer <
MAX_PEERS; ++peer) {
297 tracked += m_announcements[
txhash][peer].m_state != State::NOTHING;
298 inflight += m_announcements[
txhash][peer].m_state == State::REQUESTED;
302 for (
int peer = 0; peer <
MAX_PEERS; ++peer) {
303 if (m_announcements[
txhash][peer].m_state == State::CANDIDATE || m_announcements[
txhash][peer].m_state == State::REQUESTED) {
334 auto it = buffer.begin();
335 while (it != buffer.end()) {
336 int cmd = *(it++) % 11;
343 delaynum = it == buffer.end() ? 0 : *(it++);
347 peer = it == buffer.end() ? 0 : *(it++) %
MAX_PEERS;
348 tester.GetRequestable(peer);
351 peer = it == buffer.end() ? 0 : *(it++) %
MAX_PEERS;
352 tester.DisconnectedPeer(peer);
355 txidnum = it == buffer.end() ? 0 : *(it++);
360 peer = it == buffer.end() ? 0 : *(it++) %
MAX_PEERS;
361 txidnum = it == buffer.end() ? 0 : *(it++);
363 std::chrono::microseconds::min());
367 peer = it == buffer.end() ? 0 : *(it++) %
MAX_PEERS;
368 txidnum = it == buffer.end() ? 0 : *(it++);
369 delaynum = it == buffer.end() ? 0 : *(it++);
374 peer = it == buffer.end() ? 0 : *(it++) %
MAX_PEERS;
375 txidnum = it == buffer.end() ? 0 : *(it++);
376 delaynum = it == buffer.end() ? 0 : *(it++);
380 peer = it == buffer.end() ? 0 : *(it++) %
MAX_PEERS;
381 txidnum = it == buffer.end() ? 0 : *(it++);
A hasher class for SHA-256.
void Finalize(unsigned char hash[OUTPUT_SIZE])
CSHA256 & Write(const unsigned char *data, size_t len)
General SipHash-2-4 implementation.
uint64_t Finalize() const
Compute the 64-bit SipHash-2-4 of the data written so far.
CSipHasher & Write(uint64_t data)
Hash a 64-bit integer worth of data.
Data structure to keep track of, and schedule, transaction downloads from peers.
void ReceivedInv(NodeId peer, const GenTxid >xid, bool preferred, std::chrono::microseconds reqtime)
Adds a new CANDIDATE announcement.
void SanityCheck() const
Run internal consistency check (testing only).
size_t CountInFlight(NodeId peer) const
Count how many REQUESTED announcements a peer has.
void GetCandidatePeers(const uint256 &txhash, std::vector< NodeId > &result_peers) const
For some txhash (txid or wtxid), finds all peers with non-COMPLETED announcements and appends them to...
size_t CountCandidates(NodeId peer) const
Count how many CANDIDATE announcements a peer has.
void DisconnectedPeer(NodeId peer)
Deletes all announcements for a given peer.
void ReceivedResponse(NodeId peer, const uint256 &txhash)
Converts a CANDIDATE or REQUESTED announcement to a COMPLETED one.
uint64_t ComputePriority(const uint256 &txhash, NodeId peer, bool preferred) const
Access to the internal priority computation (testing only)
void PostGetRequestableSanityCheck(std::chrono::microseconds now) const
Run a time-dependent internal consistency check (testing only).
void RequestedTx(NodeId peer, const uint256 &txhash, std::chrono::microseconds expiry)
Marks a transaction as requested, with a specified expiry.
size_t Count(NodeId peer) const
Count how many announcements a peer has (REQUESTED, CANDIDATE, and COMPLETED combined).
size_t Size() const
Count how many announcements are being tracked in total across all peers and transaction hashes.
std::vector< GenTxid > GetRequestable(NodeId peer, std::chrono::microseconds now, std::vector< std::pair< NodeId, GenTxid > > *expired=nullptr)
Find the txids to request now from peer.
void ForgetTxHash(const uint256 &txhash)
Deletes all announcements for a given txhash (both txid and wtxid ones).
static transaction_identifier FromUint256(const uint256 &id)
T Now()
Return the current time point cast to the given precision.
constexpr auto Ticks(Dur2 d)
Helper to count the seconds of a duration/time_point.