Branch data Line data Source code
1 : : // Copyright (c) 2025-present The Bitcoin Core developers
2 : : // Distributed under the MIT software license, see the accompanying
3 : : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 : :
5 : : #include <primitives/transaction.h>
6 : : #include <private_broadcast.h>
7 : : #include <test/util/setup_common.h>
8 : : #include <util/time.h>
9 : :
10 : : #include <algorithm>
11 : : #include <boost/test/unit_test.hpp>
12 : :
13 : : BOOST_FIXTURE_TEST_SUITE(private_broadcast_tests, BasicTestingSetup)
14 : :
15 : 2 : static CTransactionRef MakeDummyTx(uint32_t id, size_t num_witness)
16 : : {
17 : 2 : CMutableTransaction mtx;
18 [ + - ]: 2 : mtx.vin.resize(1);
19 [ + + ]: 2 : mtx.vin[0].nSequence = id;
20 [ + + ]: 2 : if (num_witness > 0) {
21 : 1 : mtx.vin[0].scriptWitness = CScriptWitness{};
22 [ + - ]: 1 : mtx.vin[0].scriptWitness.stack.resize(num_witness);
23 : : }
24 [ + - ]: 4 : return MakeTransactionRef(mtx);
25 : 2 : }
26 : :
27 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(basic)
+ - + - -
+ + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- ]
28 : : {
29 : 1 : SetMockTime(Now<NodeSeconds>());
30 : :
31 [ + - ]: 1 : PrivateBroadcast pb;
32 : 1 : const NodeId recipient1{1};
33 : 1 : in_addr ipv4Addr;
34 : 1 : ipv4Addr.s_addr = 0xa0b0c001;
35 [ + - ]: 1 : const CService addr1{ipv4Addr, 1111};
36 : :
37 : : // No transactions initially.
38 [ + - + - : 2 : BOOST_CHECK(!pb.PickTxForSend(/*will_send_to_nodeid=*/recipient1, /*will_send_to_address=*/addr1).has_value());
+ - + - ]
39 [ + - + - : 2 : BOOST_CHECK_EQUAL(pb.GetStale().size(), 0);
+ - ]
40 [ + - + - : 2 : BOOST_CHECK(!pb.HavePendingTransactions());
+ - + - ]
41 [ + - + - : 2 : BOOST_CHECK_EQUAL(pb.GetBroadcastInfo().size(), 0);
+ - ]
42 : :
43 : : // Make a transaction and add it.
44 [ + - ]: 1 : const auto tx1{MakeDummyTx(/*id=*/1, /*num_witness=*/0)};
45 : :
46 [ + - + - : 2 : BOOST_CHECK(pb.Add(tx1));
+ - + - ]
47 [ + - + - : 2 : BOOST_CHECK(!pb.Add(tx1));
+ - + - ]
48 : :
49 : : // Make another transaction with same txid, different wtxid and add it.
50 [ + - ]: 1 : const auto tx2{MakeDummyTx(/*id=*/1, /*num_witness=*/1)};
51 [ + - + - : 2 : BOOST_REQUIRE(tx1->GetHash() == tx2->GetHash());
+ - ]
52 [ + - + - : 2 : BOOST_REQUIRE(tx1->GetWitnessHash() != tx2->GetWitnessHash());
+ - ]
53 : :
54 [ + - + - : 2 : BOOST_CHECK(pb.Add(tx2));
+ - + - ]
55 : 7 : const auto find_tx_info{[](auto& infos, const CTransactionRef& tx) -> const PrivateBroadcast::TxBroadcastInfo& {
56 [ + + ]: 15 : const auto it{std::ranges::find(infos, tx->GetWitnessHash(), [](const auto& info) { return info.tx->GetWitnessHash(); })};
57 [ + - ]: 12 : BOOST_REQUIRE(it != infos.end());
58 : 6 : return *it;
59 : : }};
60 : 3 : const auto check_peer_counts{[&](size_t tx1_peer_count, size_t tx2_peer_count) {
61 : 2 : const auto infos{pb.GetBroadcastInfo()};
62 [ + - - + : 2 : BOOST_CHECK_EQUAL(infos.size(), 2);
+ - ]
63 [ + - + - : 2 : BOOST_CHECK_EQUAL(find_tx_info(infos, tx1).peers.size(), tx1_peer_count);
- + + - ]
64 [ + - + - : 2 : BOOST_CHECK_EQUAL(find_tx_info(infos, tx2).peers.size(), tx2_peer_count);
- + + - ]
65 : 3 : }};
66 : :
67 [ + - ]: 1 : check_peer_counts(/*tx1_peer_count=*/0, /*tx2_peer_count=*/0);
68 : :
69 [ + - ]: 2 : const auto tx_for_recipient1{pb.PickTxForSend(/*will_send_to_nodeid=*/recipient1, /*will_send_to_address=*/addr1).value()};
70 [ + - + - : 3 : BOOST_CHECK(tx_for_recipient1 == tx1 || tx_for_recipient1 == tx2);
+ - + - +
- ]
71 : :
72 : : // A second pick must return the other transaction.
73 : 1 : const NodeId recipient2{2};
74 [ + - ]: 1 : const CService addr2{ipv4Addr, 2222};
75 [ + - ]: 2 : const auto tx_for_recipient2{pb.PickTxForSend(/*will_send_to_nodeid=*/recipient2, /*will_send_to_address=*/addr2).value()};
76 [ + - - + : 2 : BOOST_CHECK(tx_for_recipient2 == tx1 || tx_for_recipient2 == tx2);
- - + - +
- ]
77 [ + - + - ]: 1 : BOOST_CHECK_NE(tx_for_recipient1, tx_for_recipient2);
78 : :
79 [ + - ]: 1 : check_peer_counts(/*tx1_peer_count=*/1, /*tx2_peer_count=*/1);
80 : :
81 : 1 : const NodeId nonexistent_recipient{0};
82 : :
83 : : // Confirm transactions <-> recipients mapping is correct.
84 [ + - + - : 2 : BOOST_CHECK(!pb.GetTxForNode(nonexistent_recipient).has_value());
+ - + - ]
85 [ + - + - : 2 : BOOST_CHECK_EQUAL(pb.GetTxForNode(recipient1).value(), tx_for_recipient1);
+ - ]
86 [ + - + - : 2 : BOOST_CHECK_EQUAL(pb.GetTxForNode(recipient2).value(), tx_for_recipient2);
+ - ]
87 : :
88 : : // Confirm none of the transactions' reception have been confirmed.
89 [ + - + - : 2 : BOOST_CHECK(!pb.DidNodeConfirmReception(recipient1));
+ - + - ]
90 [ + - + - : 2 : BOOST_CHECK(!pb.DidNodeConfirmReception(recipient2));
+ - + - ]
91 [ + - + - : 2 : BOOST_CHECK(!pb.DidNodeConfirmReception(nonexistent_recipient));
+ - + - ]
92 : :
93 [ + - + - : 2 : BOOST_CHECK_EQUAL(pb.GetStale().size(), 2);
+ - ]
94 : :
95 : : // Confirm reception by recipient1.
96 [ + - ]: 1 : pb.NodeConfirmedReception(nonexistent_recipient); // Dummy call.
97 [ + - ]: 1 : pb.NodeConfirmedReception(recipient1);
98 : :
99 [ + - + - : 2 : BOOST_CHECK(pb.DidNodeConfirmReception(recipient1));
+ - + - ]
100 [ + - + - : 2 : BOOST_CHECK(!pb.DidNodeConfirmReception(recipient2));
+ - + - ]
101 : :
102 [ + - ]: 1 : const auto infos{pb.GetBroadcastInfo()};
103 [ + - - + : 1 : BOOST_CHECK_EQUAL(infos.size(), 2);
+ - ]
104 : 1 : {
105 [ + - ]: 1 : const auto& [tx, peers]{find_tx_info(infos, tx_for_recipient1)};
106 [ + - - + : 1 : BOOST_CHECK_EQUAL(peers.size(), 1);
+ - ]
107 [ + - + - : 1 : BOOST_CHECK_EQUAL(peers[0].address.ToStringAddrPort(), addr1.ToStringAddrPort());
+ - + - ]
108 [ + - + - : 2 : BOOST_CHECK(peers[0].received.has_value());
+ - ]
109 : : }
110 : 1 : {
111 [ + - ]: 1 : const auto& [tx, peers]{find_tx_info(infos, tx_for_recipient2)};
112 [ + - - + : 1 : BOOST_CHECK_EQUAL(peers.size(), 1);
+ - ]
113 [ + - + - : 1 : BOOST_CHECK_EQUAL(peers[0].address.ToStringAddrPort(), addr2.ToStringAddrPort());
+ - + - ]
114 [ + - + - : 2 : BOOST_CHECK(!peers[0].received.has_value());
+ - ]
115 : : }
116 : :
117 [ + - + - : 2 : BOOST_CHECK_EQUAL(pb.GetStale().size(), 1);
+ - ]
118 [ + - + - : 1 : BOOST_CHECK_EQUAL(pb.GetStale()[0], tx_for_recipient2);
+ - ]
119 : :
120 [ + - ]: 1 : SetMockTime(Now<NodeSeconds>() + 10h);
121 : :
122 [ + - + - : 2 : BOOST_CHECK_EQUAL(pb.GetStale().size(), 2);
+ - ]
123 : :
124 [ + - + - : 2 : BOOST_CHECK_EQUAL(pb.Remove(tx_for_recipient1).value(), 1);
+ - ]
125 [ + - + - : 2 : BOOST_CHECK(!pb.Remove(tx_for_recipient1).has_value());
+ - + - ]
126 [ + - + - : 2 : BOOST_CHECK_EQUAL(pb.Remove(tx_for_recipient2).value(), 0);
+ - ]
127 [ + - + - : 2 : BOOST_CHECK(!pb.Remove(tx_for_recipient2).has_value());
+ - + - ]
128 : :
129 [ + - + - : 2 : BOOST_CHECK_EQUAL(pb.GetBroadcastInfo().size(), 0);
+ - ]
130 [ + - ]: 1 : const CService addr_nonexistent{ipv4Addr, 3333};
131 [ + - + - : 2 : BOOST_CHECK(!pb.PickTxForSend(/*will_send_to_nodeid=*/nonexistent_recipient, /*will_send_to_address=*/addr_nonexistent).has_value());
+ - ]
132 [ + - + - : 5 : }
+ - + - ]
133 : :
134 : : BOOST_AUTO_TEST_SUITE_END()
|