MCPcopy Create free account
hub / github.com/ElementsProject/elements / RequestedTx

Method RequestedTx

src/txrequest.cpp:625–668  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

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

Callers

nothing calls this directly

Calls 5

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

Tested by

no test coverage detected