diff options
Diffstat (limited to 'src/test/net_tests.cpp')
-rw-r--r-- | src/test/net_tests.cpp | 88 |
1 files changed, 52 insertions, 36 deletions
diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp index 34d7867079..5976aa3713 100644 --- a/src/test/net_tests.cpp +++ b/src/test/net_tests.cpp @@ -850,7 +850,7 @@ BOOST_AUTO_TEST_CASE(initial_advertise_from_version_message) std::chrono::microseconds time_received_dummy{0}; const auto msg_version = - msg_maker.Make(NetMsgType::VERSION, PROTOCOL_VERSION, services, time, services, WithParams(CAddress::V1_NETWORK, peer_us)); + msg_maker.Make(NetMsgType::VERSION, PROTOCOL_VERSION, services, time, services, CAddress::V1_NETWORK(peer_us)); CDataStream msg_version_stream{msg_version.data, SER_NETWORK, PROTOCOL_VERSION}; m_node.peerman->ProcessMessage( @@ -876,7 +876,7 @@ BOOST_AUTO_TEST_CASE(initial_advertise_from_version_message) DataStream s{data}; std::vector<CAddress> addresses; - s >> WithParams(CAddress::V1_NETWORK, addresses); + s >> CAddress::V1_NETWORK(addresses); for (const auto& addr : addresses) { if (addr == expected) { @@ -1031,9 +1031,11 @@ class V2TransportTester bool m_test_initiator; //!< Whether m_transport is the initiator (true) or responder (false) std::vector<uint8_t> m_sent_garbage; //!< The garbage we've sent to m_transport. + std::vector<uint8_t> m_recv_garbage; //!< The garbage we've received from m_transport. std::vector<uint8_t> m_to_send; //!< Bytes we have queued up to send to m_transport. std::vector<uint8_t> m_received; //!< Bytes we have received from m_transport. std::deque<CSerializedNetMsg> m_msg_to_send; //!< Messages to be sent *by* m_transport to us. + bool m_sent_aad{false}; public: /** Construct a tester object. test_initiator: whether the tested transport is initiator. */ @@ -1131,8 +1133,7 @@ public: /** Schedule specified garbage to be sent to the transport. */ void SendGarbage(Span<const uint8_t> garbage) { - // Remember the specified garbage (so we can use it for constructing the garbage - // authentication packet). + // Remember the specified garbage (so we can use it as AAD). m_sent_garbage.assign(garbage.begin(), garbage.end()); // Schedule it for sending. Send(m_sent_garbage); @@ -1191,27 +1192,27 @@ public: Send(ciphertext); } - /** Schedule garbage terminator and authentication packet to be sent to the transport (only - * after ReceiveKey). */ - void SendGarbageTermAuth(size_t garb_auth_data_len = 0, bool garb_auth_ignore = false) + /** Schedule garbage terminator to be sent to the transport (only after ReceiveKey). */ + void SendGarbageTerm() { - // Generate random data to include in the garbage authentication packet (ignored by peer). - auto garb_auth_data = g_insecure_rand_ctx.randbytes<uint8_t>(garb_auth_data_len); // Schedule the garbage terminator to be sent. Send(m_cipher.GetSendGarbageTerminator()); - // Schedule the garbage authentication packet to be sent. - SendPacket(/*content=*/garb_auth_data, /*aad=*/m_sent_garbage, /*ignore=*/garb_auth_ignore); } /** Schedule version packet to be sent to the transport (only after ReceiveKey). */ void SendVersion(Span<const uint8_t> version_data = {}, bool vers_ignore = false) { - SendPacket(/*content=*/version_data, /*aad=*/{}, /*ignore=*/vers_ignore); + Span<const std::uint8_t> aad; + // Set AAD to garbage only for first packet. + if (!m_sent_aad) aad = m_sent_garbage; + SendPacket(/*content=*/version_data, /*aad=*/aad, /*ignore=*/vers_ignore); + m_sent_aad = true; } /** Expect a packet to have been received from transport, process it, and return its contents - * (only after ReceiveKey). By default, decoys are skipped. */ - std::vector<uint8_t> ReceivePacket(Span<const std::byte> aad = {}, bool skip_decoy = true) + * (only after ReceiveKey). Decoys are skipped. Optional associated authenticated data (AAD) is + * expected in the first received packet, no matter if that is a decoy or not. */ + std::vector<uint8_t> ReceivePacket(Span<const std::byte> aad = {}) { std::vector<uint8_t> contents; // Loop as long as there are ignored packets that are to be skipped. @@ -1232,16 +1233,18 @@ public: /*ignore=*/ignore, /*contents=*/MakeWritableByteSpan(contents)); BOOST_CHECK(ret); + // Don't expect AAD in further packets. + aad = {}; // Strip the processed packet's bytes off the front of the receive buffer. m_received.erase(m_received.begin(), m_received.begin() + size + BIP324Cipher::EXPANSION); - // Stop if the ignore bit is not set on this packet, or if we choose to not honor it. - if (!ignore || !skip_decoy) break; + // Stop if the ignore bit is not set on this packet. + if (!ignore) break; } return contents; } - /** Expect garbage, garbage terminator, and garbage auth packet to have been received, and - * process them (only after ReceiveKey). */ + /** Expect garbage and garbage terminator to have been received, and process them (only after + * ReceiveKey). */ void ReceiveGarbage() { // Figure out the garbage length. @@ -1252,18 +1255,15 @@ public: if (term_span == m_cipher.GetReceiveGarbageTerminator()) break; } // Copy the garbage to a buffer. - std::vector<uint8_t> garbage(m_received.begin(), m_received.begin() + garblen); + m_recv_garbage.assign(m_received.begin(), m_received.begin() + garblen); // Strip garbage + garbage terminator off the front of the receive buffer. m_received.erase(m_received.begin(), m_received.begin() + garblen + BIP324Cipher::GARBAGE_TERMINATOR_LEN); - // Process the expected garbage authentication packet. Such a packet still functions as one - // even when its ignore bit is set to true, so we do not skip decoy packets here. - ReceivePacket(/*aad=*/MakeByteSpan(garbage), /*skip_decoy=*/false); } /** Expect version packet to have been received, and process it (only after ReceiveKey). */ void ReceiveVersion() { - auto contents = ReceivePacket(); + auto contents = ReceivePacket(/*aad=*/MakeByteSpan(m_recv_garbage)); // Version packets from real BIP324 peers are expected to be empty, despite the fact that // this class supports *sending* non-empty version packets (to test that BIP324 peers // correctly ignore version packet contents). @@ -1321,6 +1321,14 @@ public: SendPacket(contents); } + /** Test whether the transport's session ID matches the session ID we expect. */ + void CompareSessionIDs() const + { + auto info = m_transport.GetInfo(); + BOOST_CHECK(info.session_id); + BOOST_CHECK(uint256(MakeUCharSpan(m_cipher.GetSessionID())) == *info.session_id); + } + /** Introduce a bit error in the data scheduled to be sent. */ void Damage() { @@ -1340,12 +1348,13 @@ BOOST_AUTO_TEST_CASE(v2transport_test) tester.SendKey(); tester.SendGarbage(); tester.ReceiveKey(); - tester.SendGarbageTermAuth(); + tester.SendGarbageTerm(); tester.SendVersion(); ret = tester.Interact(); BOOST_REQUIRE(ret && ret->empty()); tester.ReceiveGarbage(); tester.ReceiveVersion(); + tester.CompareSessionIDs(); auto msg_data_1 = g_insecure_rand_ctx.randbytes<uint8_t>(InsecureRandRange(100000)); auto msg_data_2 = g_insecure_rand_ctx.randbytes<uint8_t>(InsecureRandRange(1000)); tester.SendMessage(uint8_t(4), msg_data_1); // cmpctblock short id @@ -1357,11 +1366,19 @@ BOOST_AUTO_TEST_CASE(v2transport_test) BOOST_CHECK(!(*ret)[1]); BOOST_CHECK((*ret)[2] && (*ret)[2]->m_type == "tx" && Span{(*ret)[2]->m_recv} == MakeByteSpan(msg_data_2)); - // Then send a message with a bit error, expecting failure. + // Then send a message with a bit error, expecting failure. It's possible this failure does + // not occur immediately (when the length descriptor was modified), but it should come + // eventually, and no messages can be delivered anymore. tester.SendMessage("bad", msg_data_1); tester.Damage(); - ret = tester.Interact(); - BOOST_CHECK(!ret); + while (true) { + ret = tester.Interact(); + if (!ret) break; // failure + BOOST_CHECK(ret->size() == 0); // no message can be delivered + // Send another message. + auto msg_data_3 = g_insecure_rand_ctx.randbytes<uint8_t>(InsecureRandRange(10000)); + tester.SendMessage(uint8_t(12), msg_data_3); // getheaders short id + } } // Normal scenario, with a transport in responder node. @@ -1372,12 +1389,13 @@ BOOST_AUTO_TEST_CASE(v2transport_test) auto ret = tester.Interact(); BOOST_REQUIRE(ret && ret->empty()); tester.ReceiveKey(); - tester.SendGarbageTermAuth(); + tester.SendGarbageTerm(); tester.SendVersion(); ret = tester.Interact(); BOOST_REQUIRE(ret && ret->empty()); tester.ReceiveGarbage(); tester.ReceiveVersion(); + tester.CompareSessionIDs(); auto msg_data_1 = g_insecure_rand_ctx.randbytes<uint8_t>(InsecureRandRange(100000)); auto msg_data_2 = g_insecure_rand_ctx.randbytes<uint8_t>(InsecureRandRange(1000)); tester.SendMessage(uint8_t(14), msg_data_1); // inv short id @@ -1400,10 +1418,6 @@ BOOST_AUTO_TEST_CASE(v2transport_test) bool initiator = InsecureRandBool(); /** Use either 0 bytes or the maximum possible (4095 bytes) garbage length. */ size_t garb_len = InsecureRandBool() ? 0 : V2Transport::MAX_GARBAGE_LEN; - /** Sometimes, use non-empty contents in the garbage authentication packet (which is to be ignored). */ - size_t garb_auth_data_len = InsecureRandBool() ? 0 : InsecureRandRange(100000); - /** Whether to set the ignore bit on the garbage authentication packet (it still functions as garbage authentication). */ - bool garb_ignore = InsecureRandBool(); /** How many decoy packets to send before the version packet. */ unsigned num_ignore_version = InsecureRandRange(10); /** What data to send in the version packet (ignored by BIP324 peers, but reserved for future extensions). */ @@ -1424,7 +1438,7 @@ BOOST_AUTO_TEST_CASE(v2transport_test) tester.SendGarbage(garb_len); } tester.ReceiveKey(); - tester.SendGarbageTermAuth(garb_auth_data_len, garb_ignore); + tester.SendGarbageTerm(); for (unsigned v = 0; v < num_ignore_version; ++v) { size_t ver_ign_data_len = InsecureRandBool() ? 0 : InsecureRandRange(1000); auto ver_ign_data = g_insecure_rand_ctx.randbytes<uint8_t>(ver_ign_data_len); @@ -1435,6 +1449,7 @@ BOOST_AUTO_TEST_CASE(v2transport_test) BOOST_REQUIRE(ret && ret->empty()); tester.ReceiveGarbage(); tester.ReceiveVersion(); + tester.CompareSessionIDs(); for (unsigned d = 0; d < num_decoys_1; ++d) { auto decoy_data = g_insecure_rand_ctx.randbytes<uint8_t>(InsecureRandRange(1000)); tester.SendPacket(/*content=*/decoy_data, /*aad=*/{}, /*ignore=*/true); @@ -1468,7 +1483,7 @@ BOOST_AUTO_TEST_CASE(v2transport_test) tester.SendKey(); tester.SendGarbage(V2Transport::MAX_GARBAGE_LEN + 1); tester.ReceiveKey(); - tester.SendGarbageTermAuth(); + tester.SendGarbageTerm(); ret = tester.Interact(); BOOST_CHECK(!ret); } @@ -1481,7 +1496,7 @@ BOOST_AUTO_TEST_CASE(v2transport_test) auto ret = tester.Interact(); BOOST_REQUIRE(ret && ret->empty()); tester.ReceiveKey(); - tester.SendGarbageTermAuth(); + tester.SendGarbageTerm(); ret = tester.Interact(); BOOST_CHECK(!ret); } @@ -1506,12 +1521,13 @@ BOOST_AUTO_TEST_CASE(v2transport_test) // the first 15 of them match. garbage[len_before + 15] ^= (uint8_t(1) << InsecureRandRange(8)); tester.SendGarbage(garbage); - tester.SendGarbageTermAuth(); + tester.SendGarbageTerm(); tester.SendVersion(); ret = tester.Interact(); BOOST_REQUIRE(ret && ret->empty()); tester.ReceiveGarbage(); tester.ReceiveVersion(); + tester.CompareSessionIDs(); auto msg_data_1 = g_insecure_rand_ctx.randbytes<uint8_t>(4000000); // test that receiving 4M payload works auto msg_data_2 = g_insecure_rand_ctx.randbytes<uint8_t>(4000000); // test that sending 4M payload works tester.SendMessage(uint8_t(InsecureRandRange(223) + 33), {}); // unknown short id |