NodeStore_test_disabled.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456
  1. /* vim: set expandtab ts=4 sw=4: */
  2. /*
  3. * You may redistribute this program and/or modify it under the terms of
  4. * the GNU General Public License as published by the Free Software Foundation,
  5. * either version 3 of the License, or (at your option) any later version.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. *
  12. * You should have received a copy of the GNU General Public License
  13. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. #include "memory/MallocAllocator.h"
  16. #include "crypto/random/Random.h"
  17. #include "crypto/AddressCalc.h"
  18. #include "dht/Address.h"
  19. #include "dht/dhtcore/Node.h"
  20. #include "dht/dhtcore/NodeList.h"
  21. #include "dht/dhtcore/NodeStore.h"
  22. #include "io/FileWriter.h"
  23. #include "switch/LabelSplicer.h"
  24. #include "util/Assert.h"
  25. #include "util/Endian.h"
  26. #include "util/log/WriterLog.h"
  27. #include "util/version/Version.h"
  28. #include "crypto_scalarmult_curve25519.h"
  29. #include <stddef.h>
  30. #include <stdio.h>
  31. static struct Allocator* alloc = NULL;
  32. static struct Random* rand = NULL;
  33. static struct Log* logger = NULL;
  34. static bool genKeys = 0;
  35. static int nextKey = 0;
  36. static char* KEYS[] = {
  37. #include "dht/dhtcore/test/TestKeys.data"
  38. };
  39. static struct NodeStore* setUp(struct Address* myAddress, uint32_t capacity)
  40. {
  41. return NodeStore_new(myAddress, capacity, alloc, logger, rand);
  42. }
  43. static void missingKey()
  44. {
  45. printf("mismatching key, run this:\n"
  46. "head ./dht/dhtcore/NodeStore.c -n 14 > ./TestKeys.data && "
  47. "./build_linux/testcjdroute NodeStore_test --genkeys | sed -ne "
  48. "'s/^created new key: \\[\\(.\\{32\\}\\)\\(.\\{32\\}\\)\\]$/\"\\1\"\\n\"\\2\",/p' "
  49. "| sed 's/\\([0-9a-f]\\{2\\}\\)/\\\\x\\1/g' >> TestKeys.data && "
  50. "mv ./TestKeys.data ./dht/dhtcore/test/\n");
  51. Assert_true(false);
  52. }
  53. static uint64_t getPath(int* hops)
  54. {
  55. int i;
  56. uint64_t out = 0;
  57. for (i = 0; hops[i] != 1; i++) ;
  58. for (; i >= 0; i--) {
  59. int bits = NumberCompress_bitsUsedForNumber(hops[i]);
  60. out <<= bits;
  61. out |= NumberCompress_getCompressed(hops[i], bits);
  62. }
  63. return out;
  64. }
  65. static struct Address* createAddress(int mostSignificantAddressSpaceByte, int* hops)
  66. {
  67. uint64_t path = getPath(hops);
  68. struct Address address = { .path = 0 };
  69. if (!genKeys) {
  70. if ((int)(sizeof(KEYS) / sizeof(*KEYS)) < (nextKey + 1)) {
  71. missingKey();
  72. }
  73. Bits_memcpyConst(address.key, KEYS[nextKey], 32);
  74. if (AddressCalc_addressForPublicKey(address.ip6.bytes, address.key)
  75. && (mostSignificantAddressSpaceByte == -1
  76. || address.ip6.bytes[8] == mostSignificantAddressSpaceByte))
  77. {
  78. nextKey++;
  79. uint8_t publicKeyHex[65];
  80. Hex_encode(publicKeyHex, 65, address.key, 32);
  81. printf("created new key: [%s]\n", publicKeyHex);
  82. address.path = path;
  83. return Allocator_clone(alloc, &address);
  84. } else {
  85. uint8_t publicKeyHex[65];
  86. Hex_encode(publicKeyHex, 65, address.key, 32);
  87. printf("bad key: [%s]\n", publicKeyHex);
  88. if (address.ip6.ints.three) {
  89. uint8_t printedAddr[40];
  90. AddrTools_printIp(printedAddr, address.ip6.bytes);
  91. printf("addr: [%s]\n", printedAddr);
  92. }
  93. missingKey();
  94. }
  95. }
  96. for (;;) {
  97. Random_bytes(rand, address.key, 32);
  98. // Brute force for keys until one matches FC00:/8
  99. if (AddressCalc_addressForPublicKey(address.ip6.bytes, address.key)
  100. && (mostSignificantAddressSpaceByte == -1
  101. || address.ip6.bytes[8] == mostSignificantAddressSpaceByte))
  102. {
  103. uint8_t publicKeyHex[65];
  104. Hex_encode(publicKeyHex, 65, address.key, 32);
  105. printf("created new key: [%s]\n", publicKeyHex);
  106. address.path = path;
  107. return Allocator_clone(alloc, &address);
  108. }
  109. }
  110. }
  111. static struct Address* randomIp(int* hops)
  112. {
  113. return createAddress(-1, hops);
  114. }
  115. // This creates a random address which is a peer
  116. static struct Address* randomAddress()
  117. {
  118. return randomIp((int[]){0,1}/*0x13*/);
  119. }
  120. static void test_addNode()
  121. {
  122. struct Address* myAddr = randomAddress();
  123. struct NodeStore* store = setUp(myAddr, 2);
  124. // adding ourselves should be null
  125. Assert_true(NodeStore_addNode(store, myAddr, 1, Version_CURRENT_PROTOCOL) == NULL);
  126. // adding a random node with no peer should be null
  127. Assert_true(
  128. !NodeStore_addNode(store, randomIp((int[]){2,2,1}/*0x155*/), 1, Version_CURRENT_PROTOCOL)
  129. );
  130. // adding a peer should be non-null
  131. Assert_true(
  132. NodeStore_addNode(store, randomIp((int[]){2,1}/*0x15*/), 1, Version_CURRENT_PROTOCOL)
  133. );
  134. // adding a node behind our peer should also be non-null
  135. Assert_true(
  136. NodeStore_addNode(store, randomIp((int[]){2,2,1}/*0x155*/), 1, Version_CURRENT_PROTOCOL)
  137. );
  138. // test at capacity and verify worst path is replaced
  139. NodeStore_addNode(store, randomIp((int[]){3,2,1}/*0x157*/), 1, Version_CURRENT_PROTOCOL);
  140. struct Node* node =
  141. NodeStore_addNode(store, randomIp((int[]){0,1}/*0x13*/), 1, Version_CURRENT_PROTOCOL);
  142. Assert_true( Address_isSameIp(&node->address, &NodeStore_dumpTable(store,1)->address) );
  143. }
  144. static void test_getNodesByAddr()
  145. {
  146. struct Address* myAddr = randomAddress();
  147. struct NodeStore* store = setUp(myAddr, 8);
  148. struct Address* otherAddr = randomIp((int[]){0,1}/*0x13*/);
  149. // make sure we can add an addr and get it back
  150. NodeStore_addNode(store, otherAddr, 1, Version_CURRENT_PROTOCOL);
  151. struct NodeList* list = NodeStore_getNodesByAddr(otherAddr, 1, alloc, store);
  152. Assert_true(list->size == 1);
  153. Assert_true(Address_isSameIp(&list->nodes[0]->address, otherAddr));
  154. // try for two
  155. otherAddr->path = getPath((int[]){2,1}) /*0x15*/;
  156. NodeStore_addNode(store, otherAddr, 1, Version_CURRENT_PROTOCOL);
  157. list = NodeStore_getNodesByAddr(otherAddr, 2, alloc, store);
  158. Assert_true(list->size == 2);
  159. Assert_true(Address_isSameIp(&list->nodes[0]->address, otherAddr));
  160. Assert_true(Address_isSameIp(&list->nodes[1]->address, otherAddr));
  161. // make sure 1 still works
  162. list = NodeStore_getNodesByAddr(otherAddr, 1, alloc, store);
  163. Assert_true(list->size == 1);
  164. }
  165. static void test_getPeers()
  166. {
  167. // mucking around with switch labels...
  168. // see switch/NumberCompress.h
  169. struct Address* myAddr = createAddress(0x99, (int[]){1}/*0x01*/); // 0001
  170. struct NodeStore* store = setUp(myAddr, 8);
  171. uint64_t target = getPath((int[]){7,1})/*0x1f*/;
  172. struct Address* oneHop1 = createAddress(0x02, (int[]){3,1}/*0x17*/);
  173. struct Address* oneHop2 = createAddress(0x01, (int[]){2,1}/*0x15*/);
  174. struct Address* oneHop3 = createAddress(0x04, (int[]){6,1}/*0x1d*/);
  175. struct Address* twoHop = createAddress(0x03, (int[]){2,2,1}/*0x155*/);
  176. // using variable scheme, 4 bits (suffix 1).
  177. /* specific to v3x5x8
  178. Assert_true(NumberCompress_bitsUsedForLabel(target) == 4);
  179. Assert_true(NumberCompress_bitsUsedForLabel(oneHop1->path) == 4);
  180. Assert_true(NumberCompress_bitsUsedForLabel(oneHop2->path) == 4);
  181. Assert_true(NumberCompress_bitsUsedForLabel(oneHop3->path) == 4);
  182. Assert_true(NumberCompress_bitsUsedForLabel(twoHop->path) == 4);
  183. */
  184. // verify we setup our test data correctly.
  185. Assert_true(LabelSplicer_isOneHop(oneHop1->path));
  186. Assert_true(LabelSplicer_isOneHop(oneHop2->path));
  187. Assert_true(LabelSplicer_isOneHop(oneHop3->path));
  188. Assert_true(!LabelSplicer_isOneHop(twoHop->path));
  189. // verify empty case, should always return a NodeList
  190. struct NodeList* list = NodeStore_getPeers(target, 1, alloc, store);
  191. Assert_true(list != NULL);
  192. Assert_true(list->size == 0);
  193. // add test nodes
  194. NodeStore_addNode(store, oneHop1, 1, Version_CURRENT_PROTOCOL);
  195. NodeStore_addNode(store, oneHop2, 1, Version_CURRENT_PROTOCOL);
  196. NodeStore_addNode(store, oneHop3, 1, Version_CURRENT_PROTOCOL);
  197. NodeStore_addNode(store, twoHop, 1, Version_CURRENT_PROTOCOL);
  198. // verify we only get nodes with 1 hop labels
  199. list = NodeStore_getPeers(target, 10, alloc, store);
  200. Assert_true(list->size == 3);
  201. for (uint32_t i=0; i < list->size; i++) {
  202. Assert_true(LabelSplicer_isOneHop(list->nodes[i]->address.path));
  203. }
  204. // verify max parameter works
  205. list = NodeStore_getPeers(target, 1, alloc, store);
  206. Assert_true(list->size == 1);
  207. }
  208. static void test_getBest()
  209. {
  210. struct Address* myAddr = createAddress(0x99, (int[]){1}/*0x1*/);
  211. struct NodeStore* store = setUp(myAddr, 8);
  212. struct Address* target = createAddress(0x01, (int[]){2,1}/*0x15*/);
  213. struct Address* a = createAddress(0x05, (int[]){3,1}/*0x17*/); // 1 hop
  214. struct Address* b = createAddress(0xff, (int[]){3,3,1}/*0x177*/); // 2 hops (behind 0x17)
  215. struct Node* best = NULL;
  216. // exact address match should be best
  217. NodeStore_addNode(store, a, 1, Version_CURRENT_PROTOCOL);
  218. NodeStore_addNode(store, b, 1, Version_CURRENT_PROTOCOL);
  219. best = NodeStore_getBest(b, store);
  220. Assert_true(best != NULL);
  221. Assert_true(Address_isSameIp(&best->address, b));
  222. // shortest label should be used if no exact match
  223. best = NodeStore_getBest(target, store);
  224. Assert_true(best != NULL);
  225. Assert_true(Address_isSameIp(&best->address, a));
  226. }
  227. static void test_getClosestNodes()
  228. {
  229. // gets nodes that are "close" as in log2(path) aka # hops away
  230. struct Address* myAddr = createAddress(0x99, (int[]){1} /*0x1*/);
  231. struct NodeStore* store = setUp(myAddr, 8);
  232. struct Address* target = createAddress(0x06, (int[]){0,1}/*0x13*/);
  233. struct Address* oneHop = createAddress(0x05, (int[]){2,1}/*0x15*/);
  234. struct Address* twoHop = createAddress(0x08, (int[]){2,2,1}/*0x155*/);
  235. struct NodeList* closest = NULL;
  236. NodeStore_addNode(store, oneHop, 1, Version_CURRENT_PROTOCOL);
  237. NodeStore_addNode(store, twoHop, 1, Version_CURRENT_PROTOCOL);
  238. NodeStore_addNode(
  239. store, randomIp((int[]){3,3,3,3,1}/*0x17777*/), 1, Version_CURRENT_PROTOCOL);
  240. NodeStore_addNode(
  241. store, randomIp((int[]){2,3,2,3,2,1}/*0x157575*/), 1, Version_CURRENT_PROTOCOL);
  242. // check basic case returns in reverse order (of hops)
  243. closest = NodeStore_getClosestNodes(store, target, NULL, 2,
  244. Version_CURRENT_PROTOCOL, alloc);
  245. Assert_true(closest != NULL);
  246. Assert_true(closest->size == 2);
  247. Assert_true(Address_isSameIp(&closest->nodes[0]->address, twoHop));
  248. Assert_true(Address_isSameIp(&closest->nodes[1]->address, oneHop));
  249. }
  250. static void test_updateReach()
  251. {
  252. struct NodeStore* store = setUp(randomAddress(), 8);
  253. struct Address* a = randomIp((int[]){3,1} /*0x17*/); // 00010111 iface #3,#1
  254. struct Address* b = randomIp((int[]){2,1} /*0x15*/); // 00010101 iface #2,#1
  255. struct Address* c = randomIp((int[]){2,2,1} /*0x155*/); // 000111011101 iface #2,#2,#1
  256. // verify c routes through b
  257. Assert_true(LabelSplicer_routesThrough(c->path, b->path));
  258. NodeStore_addNode(store, a, 1, Version_CURRENT_PROTOCOL);
  259. struct Node* node = NodeStore_addNode(store, b, 15, Version_CURRENT_PROTOCOL);
  260. NodeStore_addNode(store, c, 20, Version_CURRENT_PROTOCOL);
  261. // update reach of b, and verify reach of c is changed as well
  262. node->reach = 10;
  263. NodeStore_updateReach(node, store);
  264. Assert_true(NodeStore_dumpTable(store, 2)->reach == 10);
  265. }
  266. static void test_nonZeroNodes()
  267. {
  268. struct NodeStore* store = setUp(randomAddress(), 8);
  269. struct Node* node =
  270. NodeStore_addNode(store, randomIp((int[]){0,1}), 1, Version_CURRENT_PROTOCOL);
  271. NodeStore_addNode(store, randomIp((int[]){2,1}), 1, Version_CURRENT_PROTOCOL);
  272. NodeStore_addNode(store, randomIp((int[]){3,1}), 1, Version_CURRENT_PROTOCOL);
  273. NodeStore_addNode(store, randomIp((int[]){4,1}), 1, Version_CURRENT_PROTOCOL);
  274. Assert_true(store->size == 4);
  275. Assert_true(NodeStore_nonZeroNodes(store)==4);
  276. // zero a node and make sure we get one less.
  277. node->reach = 0;
  278. NodeStore_updateReach(node, store);
  279. Assert_true(NodeStore_nonZeroNodes(store)==3);
  280. }
  281. static void test_size()
  282. {
  283. struct NodeStore* store = setUp(randomAddress(), 8);
  284. Assert_true(NodeStore_size(store) == 0);
  285. NodeStore_addNode(store, randomAddress(), 0, Version_CURRENT_PROTOCOL);
  286. Assert_true(NodeStore_size(store) == 1);
  287. }
  288. static void test_getNodeByNetworkAddr()
  289. {
  290. struct NodeStore* store = setUp(randomAddress(), 8);
  291. // empty case should be null
  292. Assert_true(NodeStore_getNodeByNetworkAddr(getPath((int[]){2,1}),store)==NULL);
  293. // happy case
  294. NodeStore_addNode(store, randomIp((int[]){0,1}), 1, Version_CURRENT_PROTOCOL);
  295. NodeStore_addNode(store, randomIp((int[]){3,1}), 1, Version_CURRENT_PROTOCOL);
  296. Assert_true(
  297. NodeStore_getNodeByNetworkAddr(getPath((int[]){3,1}),store)->address.path ==
  298. getPath((int[]){3,1})
  299. );
  300. }
  301. static void test_brokenPath()
  302. {
  303. struct Address* myAddr = randomIp((int[]){1});
  304. struct NodeStore* store = setUp(myAddr, 8);
  305. struct Address* a = randomIp((int[]){3,1});
  306. struct Address* b = randomIp((int[]){2,1});
  307. struct Address* c = randomIp((int[]){2,2,1});
  308. // verify c routes through b
  309. Assert_true(LabelSplicer_routesThrough(c->path, b->path));
  310. // verify removing b should invalidate c
  311. NodeStore_addNode(store, a, 1, Version_CURRENT_PROTOCOL);
  312. NodeStore_addNode(store, b, 1, Version_CURRENT_PROTOCOL);
  313. NodeStore_addNode(store, c, 1, Version_CURRENT_PROTOCOL);
  314. // calling brokenPath on B directly should remove it
  315. Assert_true(NodeStore_brokenPath(b->path, store)==2);
  316. // should only have 1 valid route now...
  317. Assert_true(NodeStore_nonZeroNodes(store)==1);
  318. }
  319. static void test_dumpTable()
  320. {
  321. struct NodeStore* store = setUp(randomAddress(), 8);
  322. NodeStore_addNode(store, randomIp((int[]){0,1}), 1, Version_CURRENT_PROTOCOL);
  323. struct Node* orig =
  324. NodeStore_addNode(store, randomIp((int[]){5,1}), 1, Version_CURRENT_PROTOCOL);
  325. NodeStore_addNode(store, randomIp((int[]){3,1}), 1, Version_CURRENT_PROTOCOL);
  326. // verify happy case
  327. struct Node* test = NodeStore_dumpTable(store, 1);
  328. Assert_true(Address_isSameIp(&orig->address, &test->address));
  329. // verify out of bounds index gets NULL
  330. Assert_true(NodeStore_dumpTable(store, -1) == NULL);
  331. Assert_true(NodeStore_dumpTable(store, 3) == NULL);
  332. }
  333. static void test_pathfinderTwo_splitLink()
  334. {
  335. #ifndef EXPERIMENTAL_PATHFINDER
  336. return;
  337. #endif
  338. struct NodeStore* store = setUp(randomAddress(), 8);
  339. struct EncodingScheme* scheme = NumberCompress_defineScheme(alloc);
  340. // always linked to self
  341. Assert_true(NodeStore_linkCount(store->selfNode) == 1);
  342. // fcfe:15a1:15f1:ba25:ec32:4507:8d78:efef 0000.0000.0000.0031 --> 0000.0000.0000.0031
  343. NodeStore_discoverNode(store, randomIp((int[]){8,1}), 0,
  344. Version_CURRENT_PROTOCOL, scheme, 0);
  345. // should be just efef in the table.
  346. Assert_true(NodeStore_linkCount(store->selfNode) == 2);
  347. // fc98:0c83:e1be:0bdc:e177:49c6:2f96:39ee 0000.0000.0000.a629 --> 0000.0000.0014.c531
  348. NodeStore_discoverNode(store, randomIp((int[]){8,4,8,4,1}), 0,
  349. Version_CURRENT_PROTOCOL, scheme, 0);
  350. // Now should be efef->39ee
  351. Assert_true(NodeStore_linkCount(store->selfNode) == 2);
  352. struct Node_Link* linkSelfEfef = NodeStore_getLink(store->selfNode, 0);
  353. Assert_true(NodeStore_linkCount(linkSelfEfef->child) == 1);
  354. struct Node_Link* linkEfEf39ee = NodeStore_getLink(linkSelfEfef->child, 0);
  355. struct Node_Two* node39ee = linkEfEf39ee->child;
  356. Assert_true(NodeStore_linkCount(linkEfEf39ee->child) == 0);
  357. // fc1e:7c83:c316:11e3:2b3b:0b25:e667:2765 0000.0000.0000.0029 --> 0000.0000.0000.0531
  358. NodeStore_discoverNode(store, randomIp((int[]){8,4,1}), 0,
  359. Version_CURRENT_PROTOCOL, scheme, 0);
  360. // This split efef->39ee resulting in: efef->2765->39ee
  361. Assert_true(NodeStore_linkCount(linkSelfEfef->child) == 1);
  362. struct Node_Link* linkEfef2765 = NodeStore_getLink(linkSelfEfef->child, 0);
  363. Assert_true(linkEfef2765->child != node39ee);
  364. Assert_true(NodeStore_linkCount(linkEfef2765->child) == 1);
  365. struct Node_Link* link276539ee = NodeStore_getLink(linkEfef2765->child, 0);
  366. Assert_true(link276539ee->child == node39ee);
  367. Assert_true(NodeStore_linkCount(node39ee) == 0);
  368. }
  369. int main(int argc, char** argv)
  370. {
  371. if (argc > 1 && !CString_strcmp(argv[argc-1], "--genkeys")) {
  372. genKeys = 1;
  373. }
  374. alloc = MallocAllocator_new(1<<20);
  375. struct Writer* writer = FileWriter_new(stdout, alloc);
  376. logger = WriterLog_new(writer, alloc);
  377. rand = Random_new(alloc, NULL, NULL);
  378. test_addNode();
  379. test_getBest();
  380. test_getNodesByAddr();
  381. test_getPeers();
  382. test_getClosestNodes();
  383. test_updateReach();
  384. test_nonZeroNodes();
  385. test_size();
  386. test_getNodeByNetworkAddr();
  387. test_brokenPath();
  388. test_dumpTable();
  389. test_pathfinderTwo_splitLink();
  390. Allocator_free(alloc);
  391. return 0;
  392. }