| 648 | } |
| 649 | |
| 650 | std::vector<CTransactionRef> TxOrphanageImpl::GetChildrenFromSamePeer(const CTransactionRef& parent, NodeId peer) const |
| 651 | { |
| 652 | std::vector<CTransactionRef> children_found; |
| 653 | const auto& parent_txid{parent->GetHash()}; |
| 654 | |
| 655 | // Iterate through all orphans from this peer, in reverse order, so that more recent |
| 656 | // transactions are added first. Doing so helps avoid work when one of the orphans replaced |
| 657 | // an earlier one. Since we require the NodeId to match, one peer's announcement order does |
| 658 | // not bias how we process other peer's orphans. |
| 659 | auto& index_by_peer = m_orphans.get<ByPeer>(); |
| 660 | auto it_upper = index_by_peer.upper_bound(ByPeerView{peer, true, std::numeric_limits<uint64_t>::max()}); |
| 661 | auto it_lower = index_by_peer.lower_bound(ByPeerView{peer, false, 0}); |
| 662 | |
| 663 | while (it_upper != it_lower) { |
| 664 | --it_upper; |
| 665 | if (!Assume(it_upper->m_announcer == peer)) break; |
| 666 | // Check if this tx spends from parent. |
| 667 | for (const auto& input : it_upper->m_tx->vin) { |
| 668 | if (input.prevout.hash == parent_txid) { |
| 669 | children_found.emplace_back(it_upper->m_tx); |
| 670 | break; |
| 671 | } |
| 672 | } |
| 673 | } |
| 674 | return children_found; |
| 675 | } |
| 676 | |
| 677 | std::vector<TxOrphanage::OrphanInfo> TxOrphanageImpl::GetOrphanTransactions() const |
| 678 | { |