MCPcopy Create free account
hub / github.com/bitcoin/bitcoin / RequestedTx

Method RequestedTx

src/txrequest.cpp:624–667  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

622 }
623
624 void RequestedTx(NodeId peer, const uint256& txhash, std::chrono::microseconds expiry)
625 {
626 auto it = m_index.get<ByPeer>().find(ByPeerView{peer, true, txhash});
627 if (it == m_index.get<ByPeer>().end()) {
628 // There is no CANDIDATE_BEST announcement, look for a _READY or _DELAYED instead. If the caller only
629 // ever invokes RequestedTx with the values returned by GetRequestable, and no other non-const functions
630 // other than ForgetTxHash and GetRequestable in between, this branch will never execute (as txhashes
631 // returned by GetRequestable always correspond to CANDIDATE_BEST announcements).
632
633 it = m_index.get<ByPeer>().find(ByPeerView{peer, false, txhash});
634 if (it == m_index.get<ByPeer>().end() || (it->GetState() != State::CANDIDATE_DELAYED &&
635 it->GetState() != State::CANDIDATE_READY)) {
636 // There is no CANDIDATE announcement tracked for this peer, so we have nothing to do. Either this
637 // txhash wasn't tracked at all (and the caller should have called ReceivedInv), or it was already
638 // requested and/or completed for other reasons and this is just a superfluous RequestedTx call.
639 return;
640 }
641
642 // Look for an existing CANDIDATE_BEST or REQUESTED with the same txhash. We only need to do this if the
643 // found announcement had a different state than CANDIDATE_BEST. If it did, invariants guarantee that no
644 // other CANDIDATE_BEST or REQUESTED can exist.
645 auto it_old = m_index.get<ByTxHash>().lower_bound(ByTxHashView{txhash, State::CANDIDATE_BEST, 0});
646 if (it_old != m_index.get<ByTxHash>().end() && it_old->m_gtxid.ToUint256() == txhash) {
647 if (it_old->GetState() == State::CANDIDATE_BEST) {
648 // The data structure's invariants require that there can be at most one CANDIDATE_BEST or one
649 // REQUESTED announcement per txhash (but not both simultaneously), so we have to convert any
650 // existing CANDIDATE_BEST to another CANDIDATE_* when constructing another REQUESTED.
651 // It doesn't matter whether we pick CANDIDATE_READY or _DELAYED here, as SetTimePoint()
652 // will correct it at GetRequestable() time. If time only goes forward, it will always be
653 // _READY, so pick that to avoid extra work in SetTimePoint().
654 Modify<ByTxHash>(it_old, [](Announcement& ann) { ann.SetState(State::CANDIDATE_READY); });
655 } else if (it_old->GetState() == State::REQUESTED) {
656 // As we're no longer waiting for a response to the previous REQUESTED announcement, convert it
657 // to COMPLETED. This also helps guaranteeing progress.
658 Modify<ByTxHash>(it_old, [](Announcement& ann) { ann.SetState(State::COMPLETED); });
659 }
660 }
661 }
662
663 Modify<ByPeer>(it, [expiry](Announcement& ann) {
664 ann.SetState(State::REQUESTED);
665 ann.m_time = expiry;
666 });
667 }
668
669 void ReceivedResponse(NodeId peer, const uint256& txhash)
670 {

Callers

nothing calls this directly

Calls 5

findMethod · 0.80
lower_boundMethod · 0.80
SetStateMethod · 0.80
endMethod · 0.45
GetStateMethod · 0.45

Tested by

no test coverage detected