mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-04-29 14:59:39 -04:00
Convert txrequest
to GenTxidVariant
Switch all instances of GenTxid to GenTxid variant in `txrequest` and complete `txdownloadman_impl` by converting `GetRequestsToSend`.
This commit is contained in:
parent
221e60144b
commit
ab739dd4fa
9 changed files with 119 additions and 122 deletions
|
@ -5899,8 +5899,8 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
|
|||
//
|
||||
{
|
||||
LOCK(m_tx_download_mutex);
|
||||
for (const GenTxid& gtxid : m_txdownloadman.GetRequestsToSend(pto->GetId(), current_time)) {
|
||||
vGetData.emplace_back(gtxid.IsWtxid() ? MSG_WTX : (MSG_TX | GetFetchFlags(*peer)), gtxid.GetHash());
|
||||
for (const GenTxidVariant& gtxid : m_txdownloadman.GetRequestsToSend(pto->GetId(), current_time)) {
|
||||
vGetData.emplace_back(std::holds_alternative<Wtxid>(gtxid) ? MSG_WTX : (MSG_TX | GetFetchFlags(*peer)), gtxid.ToUint256());
|
||||
if (vGetData.size() >= MAX_GETDATA_SZ) {
|
||||
MakeAndPushMessage(*pto, NetMsgType::GETDATA, vGetData);
|
||||
vGetData.clear();
|
||||
|
|
|
@ -141,7 +141,7 @@ public:
|
|||
bool AddTxAnnouncement(NodeId peer, const GenTxidVariant& gtxid, std::chrono::microseconds now);
|
||||
|
||||
/** Get getdata requests to send. */
|
||||
std::vector<GenTxid> GetRequestsToSend(NodeId nodeid, std::chrono::microseconds current_time);
|
||||
std::vector<GenTxidVariant> GetRequestsToSend(NodeId nodeid, std::chrono::microseconds current_time);
|
||||
|
||||
/** Should be called when a notfound for a tx has been received. */
|
||||
void ReceivedNotFound(NodeId nodeid, const std::vector<GenTxidVariant>& txhashes);
|
||||
|
|
|
@ -43,7 +43,7 @@ bool TxDownloadManager::AddTxAnnouncement(NodeId peer, const GenTxidVariant& gtx
|
|||
{
|
||||
return m_impl->AddTxAnnouncement(peer, gtxid, now);
|
||||
}
|
||||
std::vector<GenTxid> TxDownloadManager::GetRequestsToSend(NodeId nodeid, std::chrono::microseconds current_time)
|
||||
std::vector<GenTxidVariant> TxDownloadManager::GetRequestsToSend(NodeId nodeid, std::chrono::microseconds current_time)
|
||||
{
|
||||
return m_impl->GetRequestsToSend(nodeid, current_time);
|
||||
}
|
||||
|
@ -224,7 +224,7 @@ bool TxDownloadManagerImpl::AddTxAnnouncement(NodeId peer, const GenTxidVariant&
|
|||
const bool overloaded = !info.m_relay_permissions && m_txrequest.CountInFlight(peer) >= MAX_PEER_TX_REQUEST_IN_FLIGHT;
|
||||
if (overloaded) delay += OVERLOADED_PEER_TX_DELAY;
|
||||
|
||||
m_txrequest.ReceivedInv(peer, GenTxid::FromVariant(gtxid), info.m_preferred, now + delay);
|
||||
m_txrequest.ReceivedInv(peer, gtxid, info.m_preferred, now + delay);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -261,31 +261,31 @@ bool TxDownloadManagerImpl::MaybeAddOrphanResolutionCandidate(const std::vector<
|
|||
// Treat finding orphan resolution candidate as equivalent to the peer announcing all missing parents.
|
||||
// In the future, orphan resolution may include more explicit steps
|
||||
for (const auto& parent_txid : unique_parents) {
|
||||
m_txrequest.ReceivedInv(nodeid, GenTxid::Txid(parent_txid), info.m_preferred, now + delay);
|
||||
m_txrequest.ReceivedInv(nodeid, parent_txid, info.m_preferred, now + delay);
|
||||
}
|
||||
LogDebug(BCLog::TXPACKAGES, "added peer=%d as a candidate for resolving orphan %s\n", nodeid, wtxid.ToString());
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<GenTxid> TxDownloadManagerImpl::GetRequestsToSend(NodeId nodeid, std::chrono::microseconds current_time)
|
||||
std::vector<GenTxidVariant> TxDownloadManagerImpl::GetRequestsToSend(NodeId nodeid, std::chrono::microseconds current_time)
|
||||
{
|
||||
std::vector<GenTxid> requests;
|
||||
std::vector<std::pair<NodeId, GenTxid>> expired;
|
||||
std::vector<GenTxidVariant> requests;
|
||||
std::vector<std::pair<NodeId, GenTxidVariant>> expired;
|
||||
auto requestable = m_txrequest.GetRequestable(nodeid, current_time, &expired);
|
||||
for (const auto& entry : expired) {
|
||||
LogDebug(BCLog::NET, "timeout of inflight %s %s from peer=%d\n", entry.second.IsWtxid() ? "wtx" : "tx",
|
||||
entry.second.GetHash().ToString(), entry.first);
|
||||
LogDebug(BCLog::NET, "timeout of inflight %s %s from peer=%d\n", std::holds_alternative<Wtxid>(entry.second) ? "wtx" : "tx",
|
||||
entry.second.ToUint256().ToString(), entry.first);
|
||||
}
|
||||
for (const GenTxid& gtxid : requestable) {
|
||||
if (!AlreadyHaveTx(gtxid.ToVariant(), /*include_reconsiderable=*/false)) {
|
||||
LogDebug(BCLog::NET, "Requesting %s %s peer=%d\n", gtxid.IsWtxid() ? "wtx" : "tx",
|
||||
gtxid.GetHash().ToString(), nodeid);
|
||||
for (const GenTxidVariant& gtxid : requestable) {
|
||||
if (!AlreadyHaveTx(gtxid, /*include_reconsiderable=*/false)) {
|
||||
LogDebug(BCLog::NET, "Requesting %s %s peer=%d\n", std::holds_alternative<Wtxid>(gtxid) ? "wtx" : "tx",
|
||||
gtxid.ToUint256().ToString(), nodeid);
|
||||
requests.emplace_back(gtxid);
|
||||
m_txrequest.RequestedTx(nodeid, gtxid.GetHash(), current_time + GETDATA_TX_INTERVAL);
|
||||
m_txrequest.RequestedTx(nodeid, gtxid, current_time + GETDATA_TX_INTERVAL);
|
||||
} else {
|
||||
// We have already seen this transaction, no need to download. This is just a belt-and-suspenders, as
|
||||
// this should already be called whenever a transaction becomes AlreadyHaveTx().
|
||||
m_txrequest.ForgetTxHash(gtxid.GetHash());
|
||||
m_txrequest.ForgetTxHash(gtxid);
|
||||
}
|
||||
}
|
||||
return requests;
|
||||
|
@ -296,7 +296,7 @@ void TxDownloadManagerImpl::ReceivedNotFound(NodeId nodeid, const std::vector<Ge
|
|||
for (const auto& txhash : txhashes) {
|
||||
// If we receive a NOTFOUND message for a tx we requested, mark the announcement for it as
|
||||
// completed in TxRequestTracker.
|
||||
m_txrequest.ReceivedResponse(nodeid, txhash.ToUint256());
|
||||
m_txrequest.ReceivedResponse(nodeid, txhash);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -166,7 +166,7 @@ public:
|
|||
bool AddTxAnnouncement(NodeId peer, const GenTxidVariant& gtxid, std::chrono::microseconds now);
|
||||
|
||||
/** Get getdata requests to send. */
|
||||
std::vector<GenTxid> GetRequestsToSend(NodeId nodeid, std::chrono::microseconds current_time);
|
||||
std::vector<GenTxidVariant> GetRequestsToSend(NodeId nodeid, std::chrono::microseconds current_time);
|
||||
|
||||
/** Marks a tx as ReceivedResponse in txrequest. */
|
||||
void ReceivedNotFound(NodeId nodeid, const std::vector<GenTxidVariant>& txhashes);
|
||||
|
|
|
@ -389,7 +389,7 @@ FUZZ_TARGET(txdownloadman_impl, .init = initialize)
|
|||
// TxDownloadManager should not be telling us to request things we already have.
|
||||
// Exclude m_lazy_recent_rejects_reconsiderable because it may request low-feerate parent of orphan.
|
||||
for (const auto& gtxid : getdata_requests) {
|
||||
Assert(!txdownload_impl.AlreadyHaveTx(gtxid.ToVariant(), /*include_reconsiderable=*/false));
|
||||
Assert(!txdownload_impl.AlreadyHaveTx(gtxid, /*include_reconsiderable=*/false));
|
||||
}
|
||||
},
|
||||
[&] {
|
||||
|
|
|
@ -20,7 +20,7 @@ constexpr int MAX_TXHASHES = 16;
|
|||
constexpr int MAX_PEERS = 16;
|
||||
|
||||
//! Randomly generated GenTxids used in this test (length is MAX_TXHASHES).
|
||||
uint256 TXHASHES[MAX_TXHASHES];
|
||||
GenTxidVariant TXHASHES[MAX_TXHASHES];
|
||||
|
||||
//! Precomputed random durations (positive and negative, each ~exponentially distributed).
|
||||
std::chrono::microseconds DELAYS[256];
|
||||
|
@ -30,7 +30,13 @@ struct Initializer
|
|||
Initializer()
|
||||
{
|
||||
for (uint8_t txhash = 0; txhash < MAX_TXHASHES; txhash += 1) {
|
||||
CSHA256().Write(&txhash, 1).Finalize(TXHASHES[txhash].begin());
|
||||
uint256 hash;
|
||||
CSHA256().Write(&txhash, 1).Finalize(hash.begin());
|
||||
if (txhash % 2 == 0) {
|
||||
TXHASHES[txhash] = Txid::FromUint256(hash);
|
||||
} else {
|
||||
TXHASHES[txhash] = Wtxid::FromUint256(hash);
|
||||
}
|
||||
}
|
||||
int i = 0;
|
||||
// DELAYS[N] for N=0..15 is just N microseconds.
|
||||
|
@ -94,7 +100,6 @@ class Tester
|
|||
uint64_t m_sequence;
|
||||
State m_state{State::NOTHING};
|
||||
bool m_preferred;
|
||||
bool m_is_wtxid;
|
||||
uint64_t m_priority; //!< Precomputed priority.
|
||||
};
|
||||
|
||||
|
@ -186,7 +191,7 @@ public:
|
|||
m_tracker.ForgetTxHash(TXHASHES[txhash]);
|
||||
}
|
||||
|
||||
void ReceivedInv(int peer, int txhash, bool is_wtxid, bool preferred, std::chrono::microseconds reqtime)
|
||||
void ReceivedInv(int peer, int txhash, bool preferred, std::chrono::microseconds reqtime)
|
||||
{
|
||||
// Apply to naive structure: if no announcement for txidnum/peer combination
|
||||
// already, create a new CANDIDATE; otherwise do nothing.
|
||||
|
@ -195,7 +200,6 @@ public:
|
|||
ann.m_preferred = preferred;
|
||||
ann.m_state = State::CANDIDATE;
|
||||
ann.m_time = reqtime;
|
||||
ann.m_is_wtxid = is_wtxid;
|
||||
ann.m_sequence = m_current_sequence++;
|
||||
ann.m_priority = m_tracker.ComputePriority(TXHASHES[txhash], peer, ann.m_preferred);
|
||||
|
||||
|
@ -204,7 +208,7 @@ public:
|
|||
}
|
||||
|
||||
// Call TxRequestTracker's implementation.
|
||||
m_tracker.ReceivedInv(peer, is_wtxid ? GenTxid::Wtxid(TXHASHES[txhash]) : GenTxid::Txid(TXHASHES[txhash]), preferred, reqtime);
|
||||
m_tracker.ReceivedInv(peer, TXHASHES[txhash], preferred, reqtime);
|
||||
}
|
||||
|
||||
void RequestedTx(int peer, int txhash, std::chrono::microseconds exptime)
|
||||
|
@ -246,13 +250,13 @@ public:
|
|||
|
||||
//! list of (sequence number, txhash, is_wtxid) tuples.
|
||||
std::vector<std::tuple<uint64_t, int, bool>> result;
|
||||
std::vector<std::pair<NodeId, GenTxid>> expected_expired;
|
||||
std::vector<std::pair<NodeId, GenTxidVariant>> expected_expired;
|
||||
for (int txhash = 0; txhash < MAX_TXHASHES; ++txhash) {
|
||||
// Mark any expired REQUESTED announcements as COMPLETED.
|
||||
for (int peer2 = 0; peer2 < MAX_PEERS; ++peer2) {
|
||||
Announcement& ann2 = m_announcements[txhash][peer2];
|
||||
if (ann2.m_state == State::REQUESTED && ann2.m_time <= m_now) {
|
||||
expected_expired.emplace_back(peer2, ann2.m_is_wtxid ? GenTxid::Wtxid(TXHASHES[txhash]) : GenTxid::Txid(TXHASHES[txhash]));
|
||||
expected_expired.emplace_back(peer2, TXHASHES[txhash]);
|
||||
ann2.m_state = State::COMPLETED;
|
||||
break;
|
||||
}
|
||||
|
@ -262,7 +266,7 @@ public:
|
|||
// CANDIDATEs for which this announcement has the highest priority get returned.
|
||||
const Announcement& ann = m_announcements[txhash][peer];
|
||||
if (ann.m_state == State::CANDIDATE && GetSelected(txhash) == peer) {
|
||||
result.emplace_back(ann.m_sequence, txhash, ann.m_is_wtxid);
|
||||
result.emplace_back(ann.m_sequence, txhash, std::holds_alternative<Wtxid>(TXHASHES[txhash]));
|
||||
}
|
||||
}
|
||||
// Sort the results by sequence number.
|
||||
|
@ -270,7 +274,7 @@ public:
|
|||
std::sort(expected_expired.begin(), expected_expired.end());
|
||||
|
||||
// Compare with TxRequestTracker's implementation.
|
||||
std::vector<std::pair<NodeId, GenTxid>> expired;
|
||||
std::vector<std::pair<NodeId, GenTxidVariant>> expired;
|
||||
const auto actual = m_tracker.GetRequestable(peer, m_now, &expired);
|
||||
std::sort(expired.begin(), expired.end());
|
||||
assert(expired == expected_expired);
|
||||
|
@ -278,8 +282,8 @@ public:
|
|||
m_tracker.PostGetRequestableSanityCheck(m_now);
|
||||
assert(result.size() == actual.size());
|
||||
for (size_t pos = 0; pos < actual.size(); ++pos) {
|
||||
assert(TXHASHES[std::get<1>(result[pos])] == actual[pos].GetHash());
|
||||
assert(std::get<2>(result[pos]) == actual[pos].IsWtxid());
|
||||
assert(TXHASHES[std::get<1>(result[pos])] == actual[pos]);
|
||||
assert(std::get<2>(result[pos]) == std::holds_alternative<Wtxid>(actual[pos]));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -357,16 +361,14 @@ FUZZ_TARGET(txrequest)
|
|||
case 6: // Same, but non-preferred.
|
||||
peer = it == buffer.end() ? 0 : *(it++) % MAX_PEERS;
|
||||
txidnum = it == buffer.end() ? 0 : *(it++);
|
||||
tester.ReceivedInv(peer, txidnum % MAX_TXHASHES, (txidnum / MAX_TXHASHES) & 1, cmd & 1,
|
||||
std::chrono::microseconds::min());
|
||||
tester.ReceivedInv(peer, txidnum % MAX_TXHASHES, cmd & 1, std::chrono::microseconds::min());
|
||||
break;
|
||||
case 7: // Received delayed preferred inv
|
||||
case 8: // Same, but non-preferred.
|
||||
peer = it == buffer.end() ? 0 : *(it++) % MAX_PEERS;
|
||||
txidnum = it == buffer.end() ? 0 : *(it++);
|
||||
delaynum = it == buffer.end() ? 0 : *(it++);
|
||||
tester.ReceivedInv(peer, txidnum % MAX_TXHASHES, (txidnum / MAX_TXHASHES) & 1, cmd & 1,
|
||||
tester.Now() + DELAYS[delaynum]);
|
||||
tester.ReceivedInv(peer, txidnum % MAX_TXHASHES, cmd & 1, tester.Now() + DELAYS[delaynum]);
|
||||
break;
|
||||
case 9: // Requested tx from peer
|
||||
peer = it == buffer.end() ? 0 : *(it++) % MAX_PEERS;
|
||||
|
|
|
@ -56,12 +56,12 @@ struct Runner
|
|||
std::set<NodeId> peerset;
|
||||
|
||||
/** Which txhashes have been assigned already (to prevent reuse). */
|
||||
std::set<uint256> txhashset;
|
||||
std::set<GenTxidVariant> txhashset;
|
||||
|
||||
/** Which (peer, gtxid) combinations are known to be expired. These need to be accumulated here instead of
|
||||
* checked directly in the GetRequestable return value to avoid introducing a dependency between the various
|
||||
* parallel tests. */
|
||||
std::multiset<std::pair<NodeId, GenTxid>> expired;
|
||||
std::multiset<std::pair<NodeId, GenTxidVariant>> expired;
|
||||
};
|
||||
|
||||
std::chrono::microseconds TxRequestTest::RandomTime8s() { return std::chrono::microseconds{1 + m_rng.randbits(23)}; }
|
||||
|
@ -100,7 +100,7 @@ public:
|
|||
}
|
||||
|
||||
/** Schedule a ForgetTxHash call at the Scheduler's current time. */
|
||||
void ForgetTxHash(const uint256& txhash)
|
||||
void ForgetTxHash(const GenTxidVariant& txhash)
|
||||
{
|
||||
auto& runner = m_runner;
|
||||
runner.actions.emplace_back(m_now, [=,&runner]() {
|
||||
|
@ -110,7 +110,7 @@ public:
|
|||
}
|
||||
|
||||
/** Schedule a ReceivedInv call at the Scheduler's current time. */
|
||||
void ReceivedInv(NodeId peer, const GenTxid& gtxid, bool pref, std::chrono::microseconds reqtime)
|
||||
void ReceivedInv(NodeId peer, const GenTxidVariant& gtxid, bool pref, std::chrono::microseconds reqtime)
|
||||
{
|
||||
auto& runner = m_runner;
|
||||
runner.actions.emplace_back(m_now, [=,&runner]() {
|
||||
|
@ -130,7 +130,7 @@ public:
|
|||
}
|
||||
|
||||
/** Schedule a RequestedTx call at the Scheduler's current time. */
|
||||
void RequestedTx(NodeId peer, const uint256& txhash, std::chrono::microseconds exptime)
|
||||
void RequestedTx(NodeId peer, const GenTxidVariant& txhash, std::chrono::microseconds exptime)
|
||||
{
|
||||
auto& runner = m_runner;
|
||||
runner.actions.emplace_back(m_now, [=,&runner]() {
|
||||
|
@ -140,7 +140,7 @@ public:
|
|||
}
|
||||
|
||||
/** Schedule a ReceivedResponse call at the Scheduler's current time. */
|
||||
void ReceivedResponse(NodeId peer, const uint256& txhash)
|
||||
void ReceivedResponse(NodeId peer, const GenTxidVariant& txhash)
|
||||
{
|
||||
auto& runner = m_runner;
|
||||
runner.actions.emplace_back(m_now, [=,&runner]() {
|
||||
|
@ -160,7 +160,7 @@ public:
|
|||
* @param offset Offset with the current time to use (must be <= 0). This allows simulations of time going
|
||||
* backwards (but note that the ordering of this event only follows the scenario's m_now.
|
||||
*/
|
||||
void Check(NodeId peer, const std::vector<GenTxid>& expected, size_t candidates, size_t inflight,
|
||||
void Check(NodeId peer, const std::vector<GenTxidVariant>& expected, size_t candidates, size_t inflight,
|
||||
size_t completed, const std::string& checkname,
|
||||
std::chrono::microseconds offset = std::chrono::microseconds{0})
|
||||
{
|
||||
|
@ -169,7 +169,7 @@ public:
|
|||
const auto now = m_now;
|
||||
assert(offset.count() <= 0);
|
||||
runner.actions.emplace_back(m_now, [=,&runner]() {
|
||||
std::vector<std::pair<NodeId, GenTxid>> expired_now;
|
||||
std::vector<std::pair<NodeId, GenTxidVariant>> expired_now;
|
||||
auto ret = runner.txrequest.GetRequestable(peer, now + offset, &expired_now);
|
||||
for (const auto& entry : expired_now) runner.expired.insert(entry);
|
||||
runner.txrequest.SanityCheck();
|
||||
|
@ -189,12 +189,12 @@ public:
|
|||
*
|
||||
* Every expected expiration should be accounted for through exactly one call to this function.
|
||||
*/
|
||||
void CheckExpired(NodeId peer, GenTxid gtxid)
|
||||
void CheckExpired(NodeId peer, GenTxidVariant gtxid)
|
||||
{
|
||||
const auto& testname = m_testname;
|
||||
auto& runner = m_runner;
|
||||
runner.actions.emplace_back(m_now, [=,&runner]() {
|
||||
auto it = runner.expired.find(std::pair<NodeId, GenTxid>{peer, gtxid});
|
||||
auto it = runner.expired.find(std::pair<NodeId, GenTxidVariant>{peer, gtxid});
|
||||
BOOST_CHECK_MESSAGE(it != runner.expired.end(), "[" + testname + "] missing expiration");
|
||||
if (it != runner.expired.end()) runner.expired.erase(it);
|
||||
});
|
||||
|
@ -208,12 +208,17 @@ public:
|
|||
* where priority is the predicted internal TxRequestTracker's priority, assuming all announcements
|
||||
* are within the same preferredness class.
|
||||
*/
|
||||
uint256 NewTxHash(const std::vector<std::vector<NodeId>>& orders = {})
|
||||
GenTxidVariant NewGTxid(const std::vector<std::vector<NodeId>>& orders = {})
|
||||
{
|
||||
uint256 ret;
|
||||
GenTxidVariant ret;
|
||||
bool ok;
|
||||
do {
|
||||
ret = m_rng.rand256();
|
||||
uint256 hash = m_rng.rand256();
|
||||
if (m_rng.randbool()) {
|
||||
ret = Txid::FromUint256(hash);
|
||||
} else {
|
||||
ret = Wtxid::FromUint256(hash);
|
||||
}
|
||||
ok = true;
|
||||
for (const auto& order : orders) {
|
||||
for (size_t pos = 1; pos < order.size(); ++pos) {
|
||||
|
@ -233,12 +238,6 @@ public:
|
|||
return ret;
|
||||
}
|
||||
|
||||
/** Generate a random GenTxid; the txhash follows NewTxHash; the is_wtxid flag is random. */
|
||||
GenTxid NewGTxid(const std::vector<std::vector<NodeId>>& orders = {})
|
||||
{
|
||||
return m_rng.randbool() ? GenTxid::Wtxid(NewTxHash(orders)) : GenTxid::Txid(NewTxHash(orders));
|
||||
}
|
||||
|
||||
/** Generate a new random NodeId to use as peer. The same NodeId is never returned twice
|
||||
* (across all Scenarios combined). */
|
||||
NodeId NewPeer()
|
||||
|
@ -285,7 +284,7 @@ void TxRequestTest::BuildSingleTest(Scenario& scenario, int config)
|
|||
scenario.AdvanceTime(RandomTime8s());
|
||||
auto expiry = RandomTime8s();
|
||||
scenario.Check(peer, {gtxid}, 1, 0, 0, "s5");
|
||||
scenario.RequestedTx(peer, gtxid.GetHash(), scenario.Now() + expiry);
|
||||
scenario.RequestedTx(peer, gtxid, scenario.Now() + expiry);
|
||||
scenario.Check(peer, {}, 0, 1, 0, "s6");
|
||||
|
||||
if ((config >> 3) == 1) { // The request will time out
|
||||
|
@ -299,7 +298,7 @@ void TxRequestTest::BuildSingleTest(Scenario& scenario, int config)
|
|||
scenario.AdvanceTime(std::chrono::microseconds{m_rng.randrange(expiry.count())});
|
||||
scenario.Check(peer, {}, 0, 1, 0, "s9");
|
||||
if ((config >> 3) == 3) { // A response will arrive for the transaction
|
||||
scenario.ReceivedResponse(peer, gtxid.GetHash());
|
||||
scenario.ReceivedResponse(peer, gtxid);
|
||||
scenario.Check(peer, {}, 0, 0, 0, "s10");
|
||||
return;
|
||||
}
|
||||
|
@ -309,7 +308,7 @@ void TxRequestTest::BuildSingleTest(Scenario& scenario, int config)
|
|||
if (config & 4) { // The peer will go offline
|
||||
scenario.DisconnectedPeer(peer);
|
||||
} else { // The transaction is no longer needed
|
||||
scenario.ForgetTxHash(gtxid.GetHash());
|
||||
scenario.ForgetTxHash(gtxid);
|
||||
}
|
||||
scenario.Check(peer, {}, 0, 0, 0, "s11");
|
||||
}
|
||||
|
@ -355,7 +354,7 @@ void TxRequestTest::BuildPriorityTest(Scenario& scenario, int config)
|
|||
|
||||
// We possibly request from the selected peer.
|
||||
if (config & 8) {
|
||||
scenario.RequestedTx(priopeer, gtxid.GetHash(), MAX_TIME);
|
||||
scenario.RequestedTx(priopeer, gtxid, MAX_TIME);
|
||||
scenario.Check(priopeer, {}, 0, 1, 0, "p7");
|
||||
scenario.Check(otherpeer, {}, 1, 0, 0, "p8");
|
||||
if (m_rng.randbool()) scenario.AdvanceTime(RandomTime8s());
|
||||
|
@ -365,7 +364,7 @@ void TxRequestTest::BuildPriorityTest(Scenario& scenario, int config)
|
|||
if (config & 16) {
|
||||
scenario.DisconnectedPeer(priopeer);
|
||||
} else {
|
||||
scenario.ReceivedResponse(priopeer, gtxid.GetHash());
|
||||
scenario.ReceivedResponse(priopeer, gtxid);
|
||||
}
|
||||
if (m_rng.randbool()) scenario.AdvanceTime(RandomTime8s());
|
||||
scenario.Check(priopeer, {}, 0, 0, !(config & 16), "p8");
|
||||
|
@ -449,7 +448,7 @@ void TxRequestTest::BuildBigPriorityTest(Scenario& scenario, int peers)
|
|||
scenario.DisconnectedPeer(peer);
|
||||
scenario.Check(peer, {}, 0, 0, 0, "b4");
|
||||
} else {
|
||||
scenario.ReceivedResponse(peer, gtxid.GetHash());
|
||||
scenario.ReceivedResponse(peer, gtxid);
|
||||
scenario.Check(peer, {}, 0, 0, request_order.size() > 0, "b5");
|
||||
}
|
||||
if (request_order.size()) {
|
||||
|
@ -509,9 +508,9 @@ void TxRequestTest::BuildWtxidTest(Scenario& scenario, int config)
|
|||
|
||||
auto peerT = scenario.NewPeer();
|
||||
auto peerW = scenario.NewPeer();
|
||||
auto txhash = scenario.NewTxHash();
|
||||
auto txid{GenTxid::Txid(txhash)};
|
||||
auto wtxid{GenTxid::Wtxid(txhash)};
|
||||
auto gtxid = scenario.NewGTxid();
|
||||
auto txid = Txid::FromUint256(gtxid.ToUint256());
|
||||
auto wtxid = Wtxid::FromUint256(gtxid.ToUint256());
|
||||
|
||||
auto reqtimeT = m_rng.randbool() ? MIN_TIME : scenario.Now() + RandomTime8s();
|
||||
auto reqtimeW = m_rng.randbool() ? MIN_TIME : scenario.Now() + RandomTime8s();
|
||||
|
@ -542,11 +541,11 @@ void TxRequestTest::BuildWtxidTest(Scenario& scenario, int config)
|
|||
// Let the preferred announcement be requested. It's not going to be delivered.
|
||||
auto expiry = RandomTime8s();
|
||||
if (config & 2) {
|
||||
scenario.RequestedTx(peerT, txid.GetHash(), scenario.Now() + expiry);
|
||||
scenario.RequestedTx(peerT, txid, scenario.Now() + expiry);
|
||||
scenario.Check(peerT, {}, 0, 1, 0, "w5");
|
||||
scenario.Check(peerW, {}, 1, 0, 0, "w6");
|
||||
} else {
|
||||
scenario.RequestedTx(peerW, wtxid.GetHash(), scenario.Now() + expiry);
|
||||
scenario.RequestedTx(peerW, wtxid, scenario.Now() + expiry);
|
||||
scenario.Check(peerT, {}, 1, 0, 0, "w7");
|
||||
scenario.Check(peerW, {}, 0, 1, 0, "w8");
|
||||
}
|
||||
|
@ -567,7 +566,7 @@ void TxRequestTest::BuildWtxidTest(Scenario& scenario, int config)
|
|||
// If a good transaction with either that hash as wtxid or txid arrives, both
|
||||
// announcements are gone.
|
||||
if (m_rng.randbool()) scenario.AdvanceTime(RandomTime8s());
|
||||
scenario.ForgetTxHash(txhash);
|
||||
scenario.ForgetTxHash(gtxid);
|
||||
scenario.Check(peerT, {}, 0, 0, 0, "w13");
|
||||
scenario.Check(peerW, {}, 0, 0, 0, "w14");
|
||||
}
|
||||
|
@ -599,7 +598,7 @@ void TxRequestTest::BuildTimeBackwardsTest(Scenario& scenario)
|
|||
// Request from peer1.
|
||||
if (m_rng.randbool()) scenario.AdvanceTime(RandomTime8s());
|
||||
auto expiry = scenario.Now() + RandomTime8s();
|
||||
scenario.RequestedTx(peer1, gtxid.GetHash(), expiry);
|
||||
scenario.RequestedTx(peer1, gtxid, expiry);
|
||||
scenario.Check(peer1, {}, 0, 1, 0, "r7");
|
||||
scenario.Check(peer2, {}, 1, 0, 0, "r8");
|
||||
|
||||
|
@ -638,20 +637,20 @@ void TxRequestTest::BuildWeirdRequestsTest(Scenario& scenario)
|
|||
|
||||
// We request gtxid2 from *peer1* - no effect.
|
||||
if (m_rng.randbool()) scenario.AdvanceTime(RandomTime8s());
|
||||
scenario.RequestedTx(peer1, gtxid2.GetHash(), MAX_TIME);
|
||||
scenario.RequestedTx(peer1, gtxid2, MAX_TIME);
|
||||
scenario.Check(peer1, {gtxid1}, 1, 0, 0, "q4");
|
||||
scenario.Check(peer2, {gtxid2}, 1, 0, 0, "q5");
|
||||
|
||||
// Now request gtxid1 from peer1 - marks it as REQUESTED.
|
||||
if (m_rng.randbool()) scenario.AdvanceTime(RandomTime8s());
|
||||
auto expiryA = scenario.Now() + RandomTime8s();
|
||||
scenario.RequestedTx(peer1, gtxid1.GetHash(), expiryA);
|
||||
scenario.RequestedTx(peer1, gtxid1, expiryA);
|
||||
scenario.Check(peer1, {}, 0, 1, 0, "q6");
|
||||
scenario.Check(peer2, {gtxid2}, 1, 0, 0, "q7");
|
||||
|
||||
// Request it a second time - nothing happens, as it's already REQUESTED.
|
||||
auto expiryB = expiryA + RandomTime8s();
|
||||
scenario.RequestedTx(peer1, gtxid1.GetHash(), expiryB);
|
||||
scenario.RequestedTx(peer1, gtxid1, expiryB);
|
||||
scenario.Check(peer1, {}, 0, 1, 0, "q8");
|
||||
scenario.Check(peer2, {gtxid2}, 1, 0, 0, "q9");
|
||||
|
||||
|
@ -668,7 +667,7 @@ void TxRequestTest::BuildWeirdRequestsTest(Scenario& scenario)
|
|||
|
||||
// Requesting it yet again from peer1 doesn't do anything, as it's already COMPLETED.
|
||||
if (m_rng.randbool()) scenario.AdvanceTime(RandomTime8s());
|
||||
scenario.RequestedTx(peer1, gtxid1.GetHash(), MAX_TIME);
|
||||
scenario.RequestedTx(peer1, gtxid1, MAX_TIME);
|
||||
scenario.Check(peer1, {}, 0, 0, 1, "q14");
|
||||
scenario.Check(peer2, {gtxid2, gtxid1}, 2, 0, 0, "q15");
|
||||
|
||||
|
@ -680,13 +679,13 @@ void TxRequestTest::BuildWeirdRequestsTest(Scenario& scenario)
|
|||
|
||||
// And request it from peer1 (weird as peer2 has the preference).
|
||||
if (m_rng.randbool()) scenario.AdvanceTime(RandomTime8s());
|
||||
scenario.RequestedTx(peer1, gtxid2.GetHash(), MAX_TIME);
|
||||
scenario.RequestedTx(peer1, gtxid2, MAX_TIME);
|
||||
scenario.Check(peer1, {}, 0, 1, 1, "q18");
|
||||
scenario.Check(peer2, {gtxid1}, 2, 0, 0, "q19");
|
||||
|
||||
// If peer2 now (normally) requests gtxid2, the existing request by peer1 becomes COMPLETED.
|
||||
if (m_rng.randbool()) scenario.AdvanceTime(RandomTime8s());
|
||||
scenario.RequestedTx(peer2, gtxid2.GetHash(), MAX_TIME);
|
||||
scenario.RequestedTx(peer2, gtxid2, MAX_TIME);
|
||||
scenario.Check(peer1, {}, 0, 0, 2, "q20");
|
||||
scenario.Check(peer2, {gtxid1}, 1, 1, 0, "q21");
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ using SequenceNumber = uint64_t;
|
|||
/** An announcement. This is the data we track for each txid or wtxid that is announced to us by each peer. */
|
||||
struct Announcement {
|
||||
/** Txid or wtxid that was announced. */
|
||||
const uint256 m_txhash;
|
||||
const GenTxidVariant m_txhash;
|
||||
/** For CANDIDATE_{DELAYED,BEST,READY} the reqtime; for REQUESTED the expiry. */
|
||||
std::chrono::microseconds m_time;
|
||||
/** What peer the request was from. */
|
||||
|
@ -70,7 +70,7 @@ struct Announcement {
|
|||
/** Whether the request is preferred. */
|
||||
const bool m_preferred : 1;
|
||||
/** Whether this is a wtxid request. */
|
||||
const bool m_is_wtxid : 1;
|
||||
//const bool m_is_wtxid : 1;
|
||||
|
||||
/** What state this announcement is in. */
|
||||
State m_state : 3 {State::CANDIDATE_DELAYED};
|
||||
|
@ -96,10 +96,9 @@ struct Announcement {
|
|||
}
|
||||
|
||||
/** Construct a new announcement from scratch, initially in CANDIDATE_DELAYED state. */
|
||||
Announcement(const GenTxid& gtxid, NodeId peer, bool preferred, std::chrono::microseconds reqtime,
|
||||
Announcement(const GenTxidVariant& gtxid, NodeId peer, bool preferred, std::chrono::microseconds reqtime,
|
||||
SequenceNumber sequence)
|
||||
: m_txhash(gtxid.GetHash()), m_time(reqtime), m_peer(peer), m_sequence(sequence), m_preferred(preferred),
|
||||
m_is_wtxid{gtxid.IsWtxid()} {}
|
||||
: m_txhash(gtxid), m_time(reqtime), m_peer(peer), m_sequence(sequence), m_preferred(preferred) {}
|
||||
};
|
||||
|
||||
//! Type alias for priorities.
|
||||
|
@ -116,9 +115,9 @@ public:
|
|||
m_k0{deterministic ? 0 : FastRandomContext().rand64()},
|
||||
m_k1{deterministic ? 0 : FastRandomContext().rand64()} {}
|
||||
|
||||
Priority operator()(const uint256& txhash, NodeId peer, bool preferred) const
|
||||
Priority operator()(const GenTxidVariant& txhash, NodeId peer, bool preferred) const
|
||||
{
|
||||
uint64_t low_bits = CSipHasher(m_k0, m_k1).Write(txhash).Write(peer).Finalize() >> 1;
|
||||
uint64_t low_bits = CSipHasher(m_k0, m_k1).Write(txhash.ToUint256()).Write(peer).Finalize() >> 1;
|
||||
return low_bits | uint64_t{preferred} << 63;
|
||||
}
|
||||
|
||||
|
@ -142,7 +141,7 @@ public:
|
|||
// (peer, true, txhash).
|
||||
// * Finding all CANDIDATE_BEST announcements for a given peer in GetRequestable.
|
||||
struct ByPeer {};
|
||||
using ByPeerView = std::tuple<NodeId, bool, const uint256&>;
|
||||
using ByPeerView = std::tuple<NodeId, bool, const GenTxidVariant&>;
|
||||
struct ByPeerViewExtractor
|
||||
{
|
||||
using result_type = ByPeerView;
|
||||
|
@ -163,7 +162,7 @@ struct ByPeerViewExtractor
|
|||
// * Determining when no more non-COMPLETED announcements for a given txhash exist, so the COMPLETED ones can be
|
||||
// deleted.
|
||||
struct ByTxHash {};
|
||||
using ByTxHashView = std::tuple<const uint256&, State, Priority>;
|
||||
using ByTxHashView = std::tuple<const GenTxidVariant&, State, Priority>;
|
||||
class ByTxHashViewExtractor {
|
||||
const PriorityComputer& m_computer;
|
||||
public:
|
||||
|
@ -276,9 +275,9 @@ std::unordered_map<NodeId, PeerInfo> RecomputePeerInfo(const Index& index)
|
|||
}
|
||||
|
||||
/** Compute the TxHashInfo map. Only used for sanity checking. */
|
||||
std::map<uint256, TxHashInfo> ComputeTxHashInfo(const Index& index, const PriorityComputer& computer)
|
||||
std::map<GenTxidVariant, TxHashInfo> ComputeTxHashInfo(const Index& index, const PriorityComputer& computer)
|
||||
{
|
||||
std::map<uint256, TxHashInfo> ret;
|
||||
std::map<GenTxidVariant, TxHashInfo> ret;
|
||||
for (const Announcement& ann : index) {
|
||||
TxHashInfo& info = ret[ann.m_txhash];
|
||||
// Classify how many announcements of each state we have for this txhash.
|
||||
|
@ -299,11 +298,6 @@ std::map<uint256, TxHashInfo> ComputeTxHashInfo(const Index& index, const Priori
|
|||
return ret;
|
||||
}
|
||||
|
||||
GenTxid ToGenTxid(const Announcement& ann)
|
||||
{
|
||||
return ann.m_is_wtxid ? GenTxid::Wtxid(ann.m_txhash) : GenTxid::Txid(ann.m_txhash);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
/** Actual implementation for TxRequestTracker's data structure. */
|
||||
|
@ -472,7 +466,7 @@ private:
|
|||
|
||||
if (IsOnlyNonCompleted(it)) {
|
||||
// This is the last non-COMPLETED announcement for this txhash. Delete all.
|
||||
uint256 txhash = it->m_txhash;
|
||||
GenTxidVariant txhash = it->m_txhash;
|
||||
do {
|
||||
it = Erase<ByTxHash>(it);
|
||||
} while (it != m_index.get<ByTxHash>().end() && it->m_txhash == txhash);
|
||||
|
@ -490,7 +484,7 @@ private:
|
|||
//! - REQUESTED announcements with expiry <= now are turned into COMPLETED.
|
||||
//! - CANDIDATE_DELAYED announcements with reqtime <= now are turned into CANDIDATE_{READY,BEST}.
|
||||
//! - CANDIDATE_{READY,BEST} announcements with reqtime > now are turned into CANDIDATE_DELAYED.
|
||||
void SetTimePoint(std::chrono::microseconds now, std::vector<std::pair<NodeId, GenTxid>>* expired)
|
||||
void SetTimePoint(std::chrono::microseconds now, std::vector<std::pair<NodeId, GenTxidVariant>>* expired)
|
||||
{
|
||||
if (expired) expired->clear();
|
||||
|
||||
|
@ -501,7 +495,7 @@ private:
|
|||
if (it->GetState() == State::CANDIDATE_DELAYED && it->m_time <= now) {
|
||||
PromoteCandidateReady(m_index.project<ByTxHash>(it));
|
||||
} else if (it->GetState() == State::REQUESTED && it->m_time <= now) {
|
||||
if (expired) expired->emplace_back(it->m_peer, ToGenTxid(*it));
|
||||
if (expired) expired->emplace_back(it->m_peer, it->m_txhash);
|
||||
MakeCompleted(m_index.project<ByTxHash>(it));
|
||||
} else {
|
||||
break;
|
||||
|
@ -538,7 +532,8 @@ public:
|
|||
void DisconnectedPeer(NodeId peer)
|
||||
{
|
||||
auto& index = m_index.get<ByPeer>();
|
||||
auto it = index.lower_bound(ByPeerView{peer, false, uint256::ZERO});
|
||||
GenTxidVariant lowerzero = Txid::FromUint256(uint256::ZERO);
|
||||
auto it = index.lower_bound(ByPeerView{peer, false, lowerzero});
|
||||
while (it != index.end() && it->m_peer == peer) {
|
||||
// Check what to continue with after this iteration. 'it' will be deleted in what follows, so we need to
|
||||
// decide what to continue with afterwards. There are a number of cases to consider:
|
||||
|
@ -566,7 +561,7 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void ForgetTxHash(const uint256& txhash)
|
||||
void ForgetTxHash(const GenTxidVariant& txhash)
|
||||
{
|
||||
auto it = m_index.get<ByTxHash>().lower_bound(ByTxHashView{txhash, State::CANDIDATE_DELAYED, 0});
|
||||
while (it != m_index.get<ByTxHash>().end() && it->m_txhash == txhash) {
|
||||
|
@ -574,7 +569,7 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void GetCandidatePeers(const uint256& txhash, std::vector<NodeId>& result_peers) const
|
||||
void GetCandidatePeers(const GenTxidVariant& txhash, std::vector<NodeId>& result_peers) const
|
||||
{
|
||||
auto it = m_index.get<ByTxHash>().lower_bound(ByTxHashView{txhash, State::CANDIDATE_DELAYED, 0});
|
||||
while (it != m_index.get<ByTxHash>().end() && it->m_txhash == txhash && it->GetState() != State::COMPLETED) {
|
||||
|
@ -583,13 +578,13 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void ReceivedInv(NodeId peer, const GenTxid& gtxid, bool preferred,
|
||||
void ReceivedInv(NodeId peer, const GenTxidVariant& gtxid, bool preferred,
|
||||
std::chrono::microseconds reqtime)
|
||||
{
|
||||
// Bail out if we already have a CANDIDATE_BEST announcement for this (txhash, peer) combination. The case
|
||||
// where there is a non-CANDIDATE_BEST announcement already will be caught by the uniqueness property of the
|
||||
// ByPeer index when we try to emplace the new object below.
|
||||
if (m_index.get<ByPeer>().count(ByPeerView{peer, true, gtxid.GetHash()})) return;
|
||||
if (m_index.get<ByPeer>().count(ByPeerView{peer, true, gtxid})) return;
|
||||
|
||||
// Try creating the announcement with CANDIDATE_DELAYED state (which will fail due to the uniqueness
|
||||
// of the ByPeer index if a non-CANDIDATE_BEST announcement already exists with the same txhash and peer).
|
||||
|
@ -603,15 +598,16 @@ public:
|
|||
}
|
||||
|
||||
//! Find the GenTxids to request now from peer.
|
||||
std::vector<GenTxid> GetRequestable(NodeId peer, std::chrono::microseconds now,
|
||||
std::vector<std::pair<NodeId, GenTxid>>* expired)
|
||||
std::vector<GenTxidVariant> GetRequestable(NodeId peer, std::chrono::microseconds now,
|
||||
std::vector<std::pair<NodeId, GenTxidVariant>>* expired)
|
||||
{
|
||||
// Move time.
|
||||
SetTimePoint(now, expired);
|
||||
|
||||
// Find all CANDIDATE_BEST announcements for this peer.
|
||||
std::vector<const Announcement*> selected;
|
||||
auto it_peer = m_index.get<ByPeer>().lower_bound(ByPeerView{peer, true, uint256::ZERO});
|
||||
GenTxidVariant lowerzero = Txid::FromUint256(uint256::ZERO);
|
||||
auto it_peer = m_index.get<ByPeer>().lower_bound(ByPeerView{peer, true, lowerzero});
|
||||
while (it_peer != m_index.get<ByPeer>().end() && it_peer->m_peer == peer &&
|
||||
it_peer->GetState() == State::CANDIDATE_BEST) {
|
||||
selected.emplace_back(&*it_peer);
|
||||
|
@ -624,15 +620,15 @@ public:
|
|||
});
|
||||
|
||||
// Convert to GenTxid and return.
|
||||
std::vector<GenTxid> ret;
|
||||
std::vector<GenTxidVariant> ret;
|
||||
ret.reserve(selected.size());
|
||||
std::transform(selected.begin(), selected.end(), std::back_inserter(ret), [](const Announcement* ann) {
|
||||
return ToGenTxid(*ann);
|
||||
return ann->m_txhash;
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
|
||||
void RequestedTx(NodeId peer, const uint256& txhash, std::chrono::microseconds expiry)
|
||||
void RequestedTx(NodeId peer, const GenTxidVariant& txhash, std::chrono::microseconds expiry)
|
||||
{
|
||||
auto it = m_index.get<ByPeer>().find(ByPeerView{peer, true, txhash});
|
||||
if (it == m_index.get<ByPeer>().end()) {
|
||||
|
@ -677,7 +673,7 @@ public:
|
|||
});
|
||||
}
|
||||
|
||||
void ReceivedResponse(NodeId peer, const uint256& txhash)
|
||||
void ReceivedResponse(NodeId peer, const GenTxidVariant& txhash)
|
||||
{
|
||||
// We need to search the ByPeer index for both (peer, false, txhash) and (peer, true, txhash).
|
||||
auto it = m_index.get<ByPeer>().find(ByPeerView{peer, false, txhash});
|
||||
|
@ -711,7 +707,7 @@ public:
|
|||
//! Count how many announcements are being tracked in total across all peers and transactions.
|
||||
size_t Size() const { return m_index.size(); }
|
||||
|
||||
uint64_t ComputePriority(const uint256& txhash, NodeId peer, bool preferred) const
|
||||
uint64_t ComputePriority(const GenTxidVariant& txhash, NodeId peer, bool preferred) const
|
||||
{
|
||||
// Return Priority as a uint64_t as Priority is internal.
|
||||
return uint64_t{m_computer(txhash, peer, preferred)};
|
||||
|
@ -724,13 +720,13 @@ TxRequestTracker::TxRequestTracker(bool deterministic) :
|
|||
|
||||
TxRequestTracker::~TxRequestTracker() = default;
|
||||
|
||||
void TxRequestTracker::ForgetTxHash(const uint256& txhash) { m_impl->ForgetTxHash(txhash); }
|
||||
void TxRequestTracker::ForgetTxHash(const GenTxidVariant& txhash) { m_impl->ForgetTxHash(txhash); }
|
||||
void TxRequestTracker::DisconnectedPeer(NodeId peer) { m_impl->DisconnectedPeer(peer); }
|
||||
size_t TxRequestTracker::CountInFlight(NodeId peer) const { return m_impl->CountInFlight(peer); }
|
||||
size_t TxRequestTracker::CountCandidates(NodeId peer) const { return m_impl->CountCandidates(peer); }
|
||||
size_t TxRequestTracker::Count(NodeId peer) const { return m_impl->Count(peer); }
|
||||
size_t TxRequestTracker::Size() const { return m_impl->Size(); }
|
||||
void TxRequestTracker::GetCandidatePeers(const uint256& txhash, std::vector<NodeId>& result_peers) const { return m_impl->GetCandidatePeers(txhash, result_peers); }
|
||||
void TxRequestTracker::GetCandidatePeers(const GenTxidVariant& txhash, std::vector<NodeId>& result_peers) const { return m_impl->GetCandidatePeers(txhash, result_peers); }
|
||||
void TxRequestTracker::SanityCheck() const { m_impl->SanityCheck(); }
|
||||
|
||||
void TxRequestTracker::PostGetRequestableSanityCheck(std::chrono::microseconds now) const
|
||||
|
@ -738,29 +734,29 @@ void TxRequestTracker::PostGetRequestableSanityCheck(std::chrono::microseconds n
|
|||
m_impl->PostGetRequestableSanityCheck(now);
|
||||
}
|
||||
|
||||
void TxRequestTracker::ReceivedInv(NodeId peer, const GenTxid& gtxid, bool preferred,
|
||||
void TxRequestTracker::ReceivedInv(NodeId peer, const GenTxidVariant& gtxid, bool preferred,
|
||||
std::chrono::microseconds reqtime)
|
||||
{
|
||||
m_impl->ReceivedInv(peer, gtxid, preferred, reqtime);
|
||||
}
|
||||
|
||||
void TxRequestTracker::RequestedTx(NodeId peer, const uint256& txhash, std::chrono::microseconds expiry)
|
||||
void TxRequestTracker::RequestedTx(NodeId peer, const GenTxidVariant& txhash, std::chrono::microseconds expiry)
|
||||
{
|
||||
m_impl->RequestedTx(peer, txhash, expiry);
|
||||
}
|
||||
|
||||
void TxRequestTracker::ReceivedResponse(NodeId peer, const uint256& txhash)
|
||||
void TxRequestTracker::ReceivedResponse(NodeId peer, const GenTxidVariant& txhash)
|
||||
{
|
||||
m_impl->ReceivedResponse(peer, txhash);
|
||||
}
|
||||
|
||||
std::vector<GenTxid> TxRequestTracker::GetRequestable(NodeId peer, std::chrono::microseconds now,
|
||||
std::vector<std::pair<NodeId, GenTxid>>* expired)
|
||||
std::vector<GenTxidVariant> TxRequestTracker::GetRequestable(NodeId peer, std::chrono::microseconds now,
|
||||
std::vector<std::pair<NodeId, GenTxidVariant>>* expired)
|
||||
{
|
||||
return m_impl->GetRequestable(peer, now, expired);
|
||||
}
|
||||
|
||||
uint64_t TxRequestTracker::ComputePriority(const uint256& txhash, NodeId peer, bool preferred) const
|
||||
uint64_t TxRequestTracker::ComputePriority(const GenTxidVariant& txhash, NodeId peer, bool preferred) const
|
||||
{
|
||||
return m_impl->ComputePriority(txhash, peer, preferred);
|
||||
}
|
||||
|
|
|
@ -132,7 +132,7 @@ public:
|
|||
* fetched. The new announcement is given the specified preferred and reqtime values, and takes its is_wtxid
|
||||
* from the specified gtxid.
|
||||
*/
|
||||
void ReceivedInv(NodeId peer, const GenTxid& gtxid, bool preferred,
|
||||
void ReceivedInv(NodeId peer, const GenTxidVariant& gtxid, bool preferred,
|
||||
std::chrono::microseconds reqtime);
|
||||
|
||||
/** Deletes all announcements for a given peer.
|
||||
|
@ -146,7 +146,7 @@ public:
|
|||
* This should be called when a transaction is no longer needed. The caller should ensure that new announcements
|
||||
* for the same txhash will not trigger new ReceivedInv calls, at least in the short term after this call.
|
||||
*/
|
||||
void ForgetTxHash(const uint256& txhash);
|
||||
void ForgetTxHash(const GenTxidVariant& txhash);
|
||||
|
||||
/** Find the txids to request now from peer.
|
||||
*
|
||||
|
@ -164,8 +164,8 @@ public:
|
|||
* out of order: if multiple dependent transactions are announced simultaneously by one peer, and end up
|
||||
* being requested from them, the requests will happen in announcement order.
|
||||
*/
|
||||
std::vector<GenTxid> GetRequestable(NodeId peer, std::chrono::microseconds now,
|
||||
std::vector<std::pair<NodeId, GenTxid>>* expired = nullptr);
|
||||
std::vector<GenTxidVariant> GetRequestable(NodeId peer, std::chrono::microseconds now,
|
||||
std::vector<std::pair<NodeId, GenTxidVariant>>* expired = nullptr);
|
||||
|
||||
/** Marks a transaction as requested, with a specified expiry.
|
||||
*
|
||||
|
@ -175,7 +175,7 @@ public:
|
|||
* was made (GetRequestable will never advise doing so). In this case it is converted to COMPLETED, as we're
|
||||
* no longer waiting for a response to it.
|
||||
*/
|
||||
void RequestedTx(NodeId peer, const uint256& txhash, std::chrono::microseconds expiry);
|
||||
void RequestedTx(NodeId peer, const GenTxidVariant& txhash, std::chrono::microseconds expiry);
|
||||
|
||||
/** Converts a CANDIDATE or REQUESTED announcement to a COMPLETED one. If no such announcement exists for the
|
||||
* provided peer and txhash, nothing happens.
|
||||
|
@ -183,7 +183,7 @@ public:
|
|||
* It should be called whenever a transaction or NOTFOUND was received from a peer. When the transaction is
|
||||
* not needed entirely anymore, ForgetTxhash should be called instead of, or in addition to, this call.
|
||||
*/
|
||||
void ReceivedResponse(NodeId peer, const uint256& txhash);
|
||||
void ReceivedResponse(NodeId peer, const GenTxidVariant& txhash);
|
||||
|
||||
// The operations below inspect the data structure.
|
||||
|
||||
|
@ -201,10 +201,10 @@ public:
|
|||
|
||||
/** For some txhash (txid or wtxid), finds all peers with non-COMPLETED announcements and appends them to
|
||||
* result_peers. Does not try to ensure that result_peers contains no duplicates. */
|
||||
void GetCandidatePeers(const uint256& txhash, std::vector<NodeId>& result_peers) const;
|
||||
void GetCandidatePeers(const GenTxidVariant& txhash, std::vector<NodeId>& result_peers) const;
|
||||
|
||||
/** Access to the internal priority computation (testing only) */
|
||||
uint64_t ComputePriority(const uint256& txhash, NodeId peer, bool preferred) const;
|
||||
uint64_t ComputePriority(const GenTxidVariant& txhash, NodeId peer, bool preferred) const;
|
||||
|
||||
/** Run internal consistency check (testing only). */
|
||||
void SanityCheck() const;
|
||||
|
|
Loading…
Add table
Reference in a new issue