|
1 | 1 | // Copyright (c) 2012-2020 The Bitcoin Core developers
|
2 | 2 | // Distributed under the MIT software license, see the accompanying
|
3 | 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
| 4 | + |
| 5 | +#include <addrdb.h> |
4 | 6 | #include <addrman.h>
|
| 7 | +#include <chainparams.h> |
5 | 8 | #include <test/data/asmap.raw.h>
|
6 | 9 | #include <test/util/setup_common.h>
|
7 | 10 | #include <util/asmap.h>
|
|
15 | 18 | #include <optional>
|
16 | 19 | #include <string>
|
17 | 20 |
|
| 21 | +using namespace std::literals; |
| 22 | + |
| 23 | +class CAddrManSerializationMock : public CAddrMan |
| 24 | +{ |
| 25 | +public: |
| 26 | + virtual void Serialize(CDataStream& s) const = 0; |
| 27 | + |
| 28 | + CAddrManSerializationMock() |
| 29 | + : CAddrMan(/* deterministic */ true, /* consistency_check_ratio */ 100) |
| 30 | + {} |
| 31 | +}; |
| 32 | + |
| 33 | +class CAddrManUncorrupted : public CAddrManSerializationMock |
| 34 | +{ |
| 35 | +public: |
| 36 | + void Serialize(CDataStream& s) const override |
| 37 | + { |
| 38 | + CAddrMan::Serialize(s); |
| 39 | + } |
| 40 | +}; |
| 41 | + |
| 42 | +class CAddrManCorrupted : public CAddrManSerializationMock |
| 43 | +{ |
| 44 | +public: |
| 45 | + void Serialize(CDataStream& s) const override |
| 46 | + { |
| 47 | + // Produces corrupt output that claims addrman has 20 addrs when it only has one addr. |
| 48 | + unsigned char nVersion = 1; |
| 49 | + s << nVersion; |
| 50 | + s << ((unsigned char)32); |
| 51 | + s << nKey; |
| 52 | + s << 10; // nNew |
| 53 | + s << 10; // nTried |
| 54 | + |
| 55 | + int nUBuckets = ADDRMAN_NEW_BUCKET_COUNT ^ (1 << 30); |
| 56 | + s << nUBuckets; |
| 57 | + |
| 58 | + CService serv; |
| 59 | + BOOST_CHECK(Lookup("252.1.1.1", serv, 7777, false)); |
| 60 | + CAddress addr = CAddress(serv, NODE_NONE); |
| 61 | + CNetAddr resolved; |
| 62 | + BOOST_CHECK(LookupHost("252.2.2.2", resolved, false)); |
| 63 | + CAddrInfo info = CAddrInfo(addr, resolved); |
| 64 | + s << info; |
| 65 | + } |
| 66 | +}; |
| 67 | + |
| 68 | +static CDataStream AddrmanToStream(const CAddrManSerializationMock& _addrman) |
| 69 | +{ |
| 70 | + CDataStream ssPeersIn(SER_DISK, CLIENT_VERSION); |
| 71 | + ssPeersIn << Params().MessageStart(); |
| 72 | + ssPeersIn << _addrman; |
| 73 | + std::string str = ssPeersIn.str(); |
| 74 | + std::vector<unsigned char> vchData(str.begin(), str.end()); |
| 75 | + return CDataStream(vchData, SER_DISK, CLIENT_VERSION); |
| 76 | +} |
| 77 | + |
18 | 78 | class CAddrManTest : public CAddrMan
|
19 | 79 | {
|
20 | 80 | private:
|
@@ -958,5 +1018,79 @@ BOOST_AUTO_TEST_CASE(addrman_evictionworks)
|
958 | 1018 | BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0");
|
959 | 1019 | }
|
960 | 1020 |
|
| 1021 | +BOOST_AUTO_TEST_CASE(caddrdb_read) |
| 1022 | +{ |
| 1023 | + CAddrManUncorrupted addrmanUncorrupted; |
| 1024 | + |
| 1025 | + CService addr1, addr2, addr3; |
| 1026 | + BOOST_CHECK(Lookup("250.7.1.1", addr1, 8333, false)); |
| 1027 | + BOOST_CHECK(Lookup("250.7.2.2", addr2, 9999, false)); |
| 1028 | + BOOST_CHECK(Lookup("250.7.3.3", addr3, 9999, false)); |
| 1029 | + BOOST_CHECK(Lookup("250.7.3.3"s, addr3, 9999, false)); |
| 1030 | + BOOST_CHECK(!Lookup("250.7.3.3\0example.com"s, addr3, 9999, false)); |
| 1031 | + |
| 1032 | + // Add three addresses to new table. |
| 1033 | + CService source; |
| 1034 | + BOOST_CHECK(Lookup("252.5.1.1", source, 8333, false)); |
| 1035 | + std::vector<CAddress> addresses{CAddress(addr1, NODE_NONE), CAddress(addr2, NODE_NONE), CAddress(addr3, NODE_NONE)}; |
| 1036 | + BOOST_CHECK(addrmanUncorrupted.Add(addresses, source)); |
| 1037 | + BOOST_CHECK(addrmanUncorrupted.size() == 3); |
| 1038 | + |
| 1039 | + // Test that the de-serialization does not throw an exception. |
| 1040 | + CDataStream ssPeers1 = AddrmanToStream(addrmanUncorrupted); |
| 1041 | + bool exceptionThrown = false; |
| 1042 | + CAddrMan addrman1(/* deterministic */ false, /* consistency_check_ratio */ 100); |
| 1043 | + |
| 1044 | + BOOST_CHECK(addrman1.size() == 0); |
| 1045 | + try { |
| 1046 | + unsigned char pchMsgTmp[4]; |
| 1047 | + ssPeers1 >> pchMsgTmp; |
| 1048 | + ssPeers1 >> addrman1; |
| 1049 | + } catch (const std::exception&) { |
| 1050 | + exceptionThrown = true; |
| 1051 | + } |
| 1052 | + |
| 1053 | + BOOST_CHECK(addrman1.size() == 3); |
| 1054 | + BOOST_CHECK(exceptionThrown == false); |
| 1055 | + |
| 1056 | + // Test that CAddrDB::Read creates an addrman with the correct number of addrs. |
| 1057 | + CDataStream ssPeers2 = AddrmanToStream(addrmanUncorrupted); |
| 1058 | + |
| 1059 | + CAddrMan addrman2(/* deterministic */ false, /* consistency_check_ratio */ 100); |
| 1060 | + BOOST_CHECK(addrman2.size() == 0); |
| 1061 | + BOOST_CHECK(CAddrDB::Read(addrman2, ssPeers2)); |
| 1062 | + BOOST_CHECK(addrman2.size() == 3); |
| 1063 | +} |
| 1064 | + |
| 1065 | + |
| 1066 | +BOOST_AUTO_TEST_CASE(caddrdb_read_corrupted) |
| 1067 | +{ |
| 1068 | + CAddrManCorrupted addrmanCorrupted; |
| 1069 | + |
| 1070 | + // Test that the de-serialization of corrupted addrman throws an exception. |
| 1071 | + CDataStream ssPeers1 = AddrmanToStream(addrmanCorrupted); |
| 1072 | + bool exceptionThrown = false; |
| 1073 | + CAddrMan addrman1(/* deterministic */ false, /* consistency_check_ratio */ 100); |
| 1074 | + BOOST_CHECK(addrman1.size() == 0); |
| 1075 | + try { |
| 1076 | + unsigned char pchMsgTmp[4]; |
| 1077 | + ssPeers1 >> pchMsgTmp; |
| 1078 | + ssPeers1 >> addrman1; |
| 1079 | + } catch (const std::exception&) { |
| 1080 | + exceptionThrown = true; |
| 1081 | + } |
| 1082 | + // Even through de-serialization failed addrman is not left in a clean state. |
| 1083 | + BOOST_CHECK(addrman1.size() == 1); |
| 1084 | + BOOST_CHECK(exceptionThrown); |
| 1085 | + |
| 1086 | + // Test that CAddrDB::Read leaves addrman in a clean state if de-serialization fails. |
| 1087 | + CDataStream ssPeers2 = AddrmanToStream(addrmanCorrupted); |
| 1088 | + |
| 1089 | + CAddrMan addrman2(/* deterministic */ false, /* consistency_check_ratio */ 100); |
| 1090 | + BOOST_CHECK(addrman2.size() == 0); |
| 1091 | + BOOST_CHECK(!CAddrDB::Read(addrman2, ssPeers2)); |
| 1092 | + BOOST_CHECK(addrman2.size() == 0); |
| 1093 | +} |
| 1094 | + |
961 | 1095 |
|
962 | 1096 | BOOST_AUTO_TEST_SUITE_END()
|
0 commit comments