mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-03-03 02:06:18 +00:00
net: Add PrivateBroadcast::GetBroadcastInfo
Co-authored-by: Daniela Brozzoni <danielabrozzoni@protonmail.com> Co-authored-by: l0rinc <pap.lorinc@gmail.com>
This commit is contained in:
parent
573bb542be
commit
5e64982541
@ -104,6 +104,25 @@ std::vector<CTransactionRef> PrivateBroadcast::GetStale() const
|
||||
return stale;
|
||||
}
|
||||
|
||||
std::vector<PrivateBroadcast::TxBroadcastInfo> PrivateBroadcast::GetBroadcastInfo() const
|
||||
EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
|
||||
{
|
||||
LOCK(m_mutex);
|
||||
std::vector<TxBroadcastInfo> entries;
|
||||
entries.reserve(m_transactions.size());
|
||||
|
||||
for (const auto& [tx, sent_to] : m_transactions) {
|
||||
std::vector<PeerSendInfo> peers;
|
||||
peers.reserve(sent_to.size());
|
||||
for (const auto& status : sent_to) {
|
||||
peers.emplace_back(PeerSendInfo{.address = status.address, .sent = status.picked, .received = status.confirmed});
|
||||
}
|
||||
entries.emplace_back(TxBroadcastInfo{.tx = tx, .peers = std::move(peers)});
|
||||
}
|
||||
|
||||
return entries;
|
||||
}
|
||||
|
||||
PrivateBroadcast::Priority PrivateBroadcast::DerivePriority(const std::vector<SendStatus>& sent_to)
|
||||
{
|
||||
Priority p;
|
||||
|
||||
@ -30,6 +30,17 @@
|
||||
class PrivateBroadcast
|
||||
{
|
||||
public:
|
||||
struct PeerSendInfo {
|
||||
CService address;
|
||||
NodeClock::time_point sent;
|
||||
std::optional<NodeClock::time_point> received;
|
||||
};
|
||||
|
||||
struct TxBroadcastInfo {
|
||||
CTransactionRef tx;
|
||||
std::vector<PeerSendInfo> peers;
|
||||
};
|
||||
|
||||
/**
|
||||
* Add a transaction to the storage.
|
||||
* @param[in] tx The transaction to add.
|
||||
@ -97,6 +108,12 @@ public:
|
||||
std::vector<CTransactionRef> GetStale() const
|
||||
EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);
|
||||
|
||||
/**
|
||||
* Get stats about all transactions currently being privately broadcast.
|
||||
*/
|
||||
std::vector<TxBroadcastInfo> GetBroadcastInfo() const
|
||||
EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);
|
||||
|
||||
private:
|
||||
/// Status of a transaction sent to a given node.
|
||||
struct SendStatus {
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
#include <test/util/setup_common.h>
|
||||
#include <util/time.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
BOOST_FIXTURE_TEST_SUITE(private_broadcast_tests, BasicTestingSetup)
|
||||
@ -29,12 +30,15 @@ BOOST_AUTO_TEST_CASE(basic)
|
||||
|
||||
PrivateBroadcast pb;
|
||||
const NodeId recipient1{1};
|
||||
const CService addr1{};
|
||||
in_addr ipv4Addr;
|
||||
ipv4Addr.s_addr = 0xa0b0c001;
|
||||
const CService addr1{ipv4Addr, 1111};
|
||||
|
||||
// No transactions initially.
|
||||
BOOST_CHECK(!pb.PickTxForSend(/*will_send_to_nodeid=*/recipient1, /*will_send_to_address=*/addr1).has_value());
|
||||
BOOST_CHECK_EQUAL(pb.GetStale().size(), 0);
|
||||
BOOST_CHECK(!pb.HavePendingTransactions());
|
||||
BOOST_CHECK_EQUAL(pb.GetBroadcastInfo().size(), 0);
|
||||
|
||||
// Make a transaction and add it.
|
||||
const auto tx1{MakeDummyTx(/*id=*/1, /*num_witness=*/0)};
|
||||
@ -48,17 +52,32 @@ BOOST_AUTO_TEST_CASE(basic)
|
||||
BOOST_REQUIRE(tx1->GetWitnessHash() != tx2->GetWitnessHash());
|
||||
|
||||
BOOST_CHECK(pb.Add(tx2));
|
||||
const auto find_tx_info{[](auto& infos, const CTransactionRef& tx) -> const PrivateBroadcast::TxBroadcastInfo& {
|
||||
const auto it{std::ranges::find(infos, tx->GetWitnessHash(), [](const auto& info) { return info.tx->GetWitnessHash(); })};
|
||||
BOOST_REQUIRE(it != infos.end());
|
||||
return *it;
|
||||
}};
|
||||
const auto check_peer_counts{[&](size_t tx1_peer_count, size_t tx2_peer_count) {
|
||||
const auto infos{pb.GetBroadcastInfo()};
|
||||
BOOST_CHECK_EQUAL(infos.size(), 2);
|
||||
BOOST_CHECK_EQUAL(find_tx_info(infos, tx1).peers.size(), tx1_peer_count);
|
||||
BOOST_CHECK_EQUAL(find_tx_info(infos, tx2).peers.size(), tx2_peer_count);
|
||||
}};
|
||||
|
||||
check_peer_counts(/*tx1_peer_count=*/0, /*tx2_peer_count=*/0);
|
||||
|
||||
const auto tx_for_recipient1{pb.PickTxForSend(/*will_send_to_nodeid=*/recipient1, /*will_send_to_address=*/addr1).value()};
|
||||
BOOST_CHECK(tx_for_recipient1 == tx1 || tx_for_recipient1 == tx2);
|
||||
|
||||
// A second pick must return the other transaction.
|
||||
const NodeId recipient2{2};
|
||||
const CService addr2{};
|
||||
const CService addr2{ipv4Addr, 2222};
|
||||
const auto tx_for_recipient2{pb.PickTxForSend(/*will_send_to_nodeid=*/recipient2, /*will_send_to_address=*/addr2).value()};
|
||||
BOOST_CHECK(tx_for_recipient2 == tx1 || tx_for_recipient2 == tx2);
|
||||
BOOST_CHECK_NE(tx_for_recipient1, tx_for_recipient2);
|
||||
|
||||
check_peer_counts(/*tx1_peer_count=*/1, /*tx2_peer_count=*/1);
|
||||
|
||||
const NodeId nonexistent_recipient{0};
|
||||
|
||||
// Confirm transactions <-> recipients mapping is correct.
|
||||
@ -80,6 +99,21 @@ BOOST_AUTO_TEST_CASE(basic)
|
||||
BOOST_CHECK(pb.DidNodeConfirmReception(recipient1));
|
||||
BOOST_CHECK(!pb.DidNodeConfirmReception(recipient2));
|
||||
|
||||
const auto infos{pb.GetBroadcastInfo()};
|
||||
BOOST_CHECK_EQUAL(infos.size(), 2);
|
||||
{
|
||||
const auto& [tx, peers]{find_tx_info(infos, tx_for_recipient1)};
|
||||
BOOST_CHECK_EQUAL(peers.size(), 1);
|
||||
BOOST_CHECK_EQUAL(peers[0].address.ToStringAddrPort(), addr1.ToStringAddrPort());
|
||||
BOOST_CHECK(peers[0].received.has_value());
|
||||
}
|
||||
{
|
||||
const auto& [tx, peers]{find_tx_info(infos, tx_for_recipient2)};
|
||||
BOOST_CHECK_EQUAL(peers.size(), 1);
|
||||
BOOST_CHECK_EQUAL(peers[0].address.ToStringAddrPort(), addr2.ToStringAddrPort());
|
||||
BOOST_CHECK(!peers[0].received.has_value());
|
||||
}
|
||||
|
||||
BOOST_CHECK_EQUAL(pb.GetStale().size(), 1);
|
||||
BOOST_CHECK_EQUAL(pb.GetStale()[0], tx_for_recipient2);
|
||||
|
||||
@ -92,7 +126,9 @@ BOOST_AUTO_TEST_CASE(basic)
|
||||
BOOST_CHECK_EQUAL(pb.Remove(tx_for_recipient2).value(), 0);
|
||||
BOOST_CHECK(!pb.Remove(tx_for_recipient2).has_value());
|
||||
|
||||
BOOST_CHECK(!pb.PickTxForSend(/*will_send_to_nodeid=*/nonexistent_recipient, /*will_send_to_address=*/CService{}).has_value());
|
||||
BOOST_CHECK_EQUAL(pb.GetBroadcastInfo().size(), 0);
|
||||
const CService addr_nonexistent{ipv4Addr, 3333};
|
||||
BOOST_CHECK(!pb.PickTxForSend(/*will_send_to_nodeid=*/nonexistent_recipient, /*will_send_to_address=*/addr_nonexistent).has_value());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user