Compare commits
662 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a2c473e9d3 | |||
| 962684ff56 | |||
| 7b3804c078 | |||
| 170f1823e1 | |||
| dc2020559a | |||
| 2b9444cce3 | |||
| 68c1c068ac | |||
| 3d0b70a237 | |||
| 65a6edc78c | |||
| 2ec8349897 | |||
| 38a2d94f80 | |||
| c7fa910516 | |||
| 2fe08274dd | |||
| be89d848dc | |||
| a230a9b8b9 | |||
| 72eae7cdf3 | |||
| 7cae195370 | |||
| dfb16e385c | |||
| 660e1cad0a | |||
| 7c1aa57a7e | |||
| a06e496f78 | |||
| 70599b97b9 | |||
| 02b194bde0 | |||
| 20ec049db5 | |||
| ebac4e8564 | |||
| da81664729 | |||
| fec3d46b33 | |||
| a4eb3a7dbf | |||
| 28d15f2c4f | |||
| 6078787daa | |||
| 6d93f36c82 | |||
| c6f93e38f5 | |||
| 2159f71888 | |||
| a9abea3446 | |||
| 8e2713c9ba | |||
| 2ba0ef0e35 | |||
| d3713cbc79 | |||
| 4d3fb2b585 | |||
| e65e611859 | |||
| ebfb9c4bc1 | |||
| 8e7918cc45 | |||
| c465eb3efc | |||
| b90136ac4e | |||
| ae5373168d | |||
| 6f3942f6b7 | |||
| 4a25725a11 | |||
| 13f38343aa | |||
| d34c829174 | |||
| f75b4843e8 | |||
| 6963ead65a | |||
| 0425cdeaf0 | |||
| 789914b096 | |||
| 8acd3a0975 | |||
| fa1519ec6a | |||
| da94b7e8df | |||
| 4aa8cb4647 | |||
| 5d13538508 | |||
| 4bbbcf629d | |||
| 34ef970fd8 | |||
| fec570613c | |||
| 14a904eff0 | |||
| 24ffb8fe8c | |||
| d1bf1f2005 | |||
| c42b3f7617 | |||
| 606144dd87 | |||
| a5bcbcc1f5 | |||
| 31cd62b676 | |||
| b43844bd7a | |||
| 53366c4151 | |||
| 2ca63a6fd5 | |||
| d33baec79b | |||
| 0626e54b6a | |||
| 2a260d46f8 | |||
| 7cb5afdeab | |||
| d18f4c0380 | |||
| c9c4059c90 | |||
| cd89feb57e | |||
| 17553d606e | |||
| 3fe33dec8b | |||
| 589074360d | |||
| 2e5406692c | |||
| b6d9ed960b | |||
| 1920177b2f | |||
| 1d89a887fb | |||
| f562433519 | |||
| 2affa76304 | |||
| d6aeb9142f | |||
| 70af84b6b1 | |||
| fc397053c8 | |||
| 3092c8e68e | |||
| 4a1efab5c8 | |||
| a2d57f269d | |||
| 38c4cc3345 | |||
| 06ebe56914 | |||
| 1c3140898f | |||
| 6005bf6101 | |||
| 78b9ebb463 | |||
| ad7f993f0f | |||
| 9be8a53ea2 | |||
| a89f8cf2ab | |||
| a2dab0e64d | |||
| 52459f6545 | |||
| a82bc3356e | |||
| 9ebe8310a1 | |||
| cf5c5f1df4 | |||
| 8585a68d7f | |||
| e8540c13a5 | |||
| 5a24a8fafc | |||
| 1195b120ff | |||
| f30cfc0be7 | |||
| 9460a9941c | |||
| eeffc0db51 | |||
| b7d6e0e1e3 | |||
| 45e0b406ac | |||
| 405d4653df | |||
| 579527b480 | |||
| 70360196f0 | |||
| b777adeda6 | |||
| 6a6505c9d7 | |||
| b10119d339 | |||
| 3a4bd4ffd6 | |||
| 9769387730 | |||
| 71747e3c82 | |||
| 5cbbeee0d5 | |||
| 57187be113 | |||
| fbd634a866 | |||
| 8d4eba858e | |||
| f1486fb989 | |||
| c50c30ae76 | |||
| 5745cb4d7a | |||
| 00c978c864 | |||
| 9e4c58efdf | |||
| 13e6fcaa85 | |||
| 9bd095ec18 | |||
| 60d50ff17a | |||
| 03f3f0285a | |||
| 3e87063ab4 | |||
| a32cbd44b0 | |||
| 962070a33c | |||
| 55f11a5433 | |||
| 48332a1069 | |||
| f43a2a1e42 | |||
| 205c887686 | |||
| 4666e91820 | |||
| 7d0a25d570 | |||
| bb46235b54 | |||
| 464041f9e1 | |||
| 433748521c | |||
| 3cbcd001f4 | |||
| 282b27646f | |||
| 5cc3ee32e9 | |||
| f412f45b50 | |||
| 9c19452758 | |||
| bf34d00478 | |||
| 70fa41c165 | |||
| 065d416305 | |||
| 3e93d2a250 | |||
| 8bc85191d5 | |||
| 7d714a22f0 | |||
| 102a8a0d8b | |||
| ae28a45915 | |||
| cffb8d98af | |||
| a40c2239d7 | |||
| 5a990a58ff | |||
| 2a1d37dd22 | |||
| be79042a23 | |||
| 7019dcc11f | |||
| bab842d277 | |||
| a374bca601 | |||
| d4d3041816 | |||
| 3acf521fc1 | |||
| 70766b6d3e | |||
| 437c66ad0b | |||
| 1afcfb0842 | |||
| 759e2fa2c5 | |||
| 489914fb42 | |||
| bca8992115 | |||
| f94d900d18 | |||
| dab55a12c7 | |||
| 82f722936f | |||
| 7f08020d4f | |||
| 579e41d57e | |||
| 06953298eb | |||
| 1d78f8747f | |||
| a6e9414cb8 | |||
| 23d7230d33 | |||
| 496f172070 | |||
| 76953df4bb | |||
| ce2449f86a | |||
| 598014bf30 | |||
| 73fe7618db | |||
| 7a416f8cf5 | |||
| 3077c2ea8d | |||
| be6c63723c | |||
| c5a3cb7707 | |||
| cce9f0b183 | |||
| 84b74703b2 | |||
| 9bf3600e5b | |||
| 9f20c8ed1f | |||
| 84e66c34f2 | |||
| e04df37988 | |||
| b617729873 | |||
| 0eb6eb855b | |||
| c91412f949 | |||
| 0a89f31a29 | |||
| 9badeac832 | |||
| b59c41d9cd | |||
| 8f083ff91e | |||
| 0f44836025 | |||
| 68ee2d747d | |||
| e29c76678d | |||
| a4005c7d81 | |||
| efe6d916e2 | |||
| a06ae48e2f | |||
| c5e1ea289c | |||
| 266c98a80e | |||
| 4540b3b41a | |||
| a9beb13189 | |||
| ebc30ec248 | |||
| 3cd9c6ad13 | |||
| b83d4e964b | |||
| bceb59a832 | |||
| 50a48603e3 | |||
| 1ae718c345 | |||
| 12c4450527 | |||
| 5bf34950ab | |||
| 910b6a1369 | |||
| 7818658ee8 | |||
| 89e34b4fd3 | |||
| 2f5a00dbda | |||
| 7f87d42f9a | |||
| e5f41731ae | |||
| a6fda391ae | |||
| 1ded24dcfc | |||
| 8c42640853 | |||
| 38aabc7983 | |||
| 4324845d29 | |||
| 93b12bccca | |||
| 89fb4ef03f | |||
| b8ab187db0 | |||
| a9790c1f66 | |||
| b46634b8f7 | |||
| 633e7ffb46 | |||
| dd2077bf12 | |||
| 0323ba2bb9 | |||
| b9524a0f58 | |||
| e7cd417894 | |||
| 07cc47a0ff | |||
| ca25db845a | |||
| 64a0ce31a8 | |||
| a8fe8d9bfb | |||
| c346f145d1 | |||
| 45dd6f2632 | |||
| 22d28759ab | |||
| 890d0f7440 | |||
| b342eb870e | |||
| fc71e0cafd | |||
| 1ecb57fda0 | |||
| 3c1ec82289 | |||
| 089e403d87 | |||
| dd2b477cda | |||
| 0902539332 | |||
| 0783c532de | |||
| 8817ae7805 | |||
| 6a900c3c42 | |||
| 0ba80c9a86 | |||
| d712b65ec5 | |||
| 383b2c1351 | |||
| fe7484f0f4 | |||
| f0a4350e83 | |||
| b63d04b10c | |||
| 5a35068c87 | |||
| 4899773e61 | |||
| 996f4afaf7 | |||
| d5c2a01a34 | |||
| b1c58b36fe | |||
| dfbcc781db | |||
| 5026960169 | |||
| 7c2710b61a | |||
| 0af807ac92 | |||
| bf9fc2d537 | |||
| 4182af9199 | |||
| 408d803344 | |||
| c2a5d6c035 | |||
| 1136901daf | |||
| 593a1da0ff | |||
| 9c17b7c269 | |||
| df398dbe05 | |||
| effd03b2f5 | |||
| e00db6adb9 | |||
| fd207d4699 | |||
| b9126dfc0e | |||
| 7bbe153b8f | |||
| 36e1e73ed2 | |||
| 6e23322ac4 | |||
| 729eedc960 | |||
| 025cbf5231 | |||
| 3db3959a74 | |||
| 3ba83795d4 | |||
| 39b01d10bd | |||
| f99bedd7e8 | |||
| 7717bf5cf9 | |||
| 6060ce5fb8 | |||
| 8fbad9cad8 | |||
| 650865e59a | |||
| 08e580ec8b | |||
| ad86ec9315 | |||
| 53ab4c8ec9 | |||
| f827eb4242 | |||
| 6f4b00b5c2 | |||
| d681ad20cf | |||
| 5818d58caf | |||
| da4eab8fdb | |||
| 9323ca9339 | |||
| f34c9d5d28 | |||
| b93afe7756 | |||
| 140cd7d940 | |||
| 7d233a4a2f | |||
| 5f60344c2b | |||
| c53b46ee1d | |||
| 7fc9eca46f | |||
| 4e5c765a0d | |||
| e1abbc0b5b | |||
| ce067db401 | |||
| 373cc54f3f | |||
| a276608fd0 | |||
| b332a6b556 | |||
| c610389198 | |||
| d283ecae22 | |||
| 2120acfdad | |||
| b613775551 | |||
| 73d4896b0b | |||
| b8b66fa4ad | |||
| ba59022160 | |||
| 8e2c64a867 | |||
| 73ae09cb76 | |||
| fd238b1d1b | |||
| 1f2d888626 | |||
| 9f47b05ed6 | |||
| f559a03732 | |||
| 3e12766afd | |||
| 1c93cc8a68 | |||
| 4865f7f205 | |||
| a785950d76 | |||
| 328d1c25b7 | |||
| 862a248902 | |||
| f826904407 | |||
| 67467ca76d | |||
| a53ae5b6b5 | |||
| bfc495ef29 | |||
| 9d74c22f9b | |||
| f978552a3a | |||
| b2477dd81b | |||
| dcd712430e | |||
| 5dcad5ffd4 | |||
| 210269cb9c | |||
| 8c59106add | |||
| 264771f8cf | |||
| 28d27eb84e | |||
| d57757584c | |||
| 6da00513a7 | |||
| 035faf70e4 | |||
| b238d108e6 | |||
| 5581b15094 | |||
| af19c4ecfd | |||
| 1855423981 | |||
| 229561bab9 | |||
| 7d2044c177 | |||
| 7885d3c986 | |||
| 78fb3c2293 | |||
| 0ed43d2439 | |||
| 69c1a32392 | |||
| 30ffea19a1 | |||
| 9e3bd8588d | |||
| ac7b821782 | |||
| bb372fb35c | |||
| 5f4220867a | |||
| bfa029f284 | |||
| 4c5351ba60 | |||
| 3a6058be60 | |||
| 7fcc8cdd19 | |||
| 098bd4eb3c | |||
| fa1e9988b3 | |||
| 999b4f743e | |||
| cc55abf7fb | |||
| 020edb8f84 | |||
| ae2079272b | |||
| a656429376 | |||
| 2086946e16 | |||
| 08e0892327 | |||
| d28783cb2a | |||
| 1815a2d3a5 | |||
| 1429f63d9d | |||
| 1ed087e801 | |||
| 7fce0a9692 | |||
| bef0a537b2 | |||
| fb2b2c963b | |||
| 2aa5e25532 | |||
| 588ed7dead | |||
| 519d419bbf | |||
| f5e72cefcc | |||
| a5a9b5128f | |||
| 94cfac0bae | |||
| 6fc4a06b3b | |||
| 91b790accc | |||
| c585753d02 | |||
| 0b46d64869 | |||
| 4c43935862 | |||
| 1804c66a96 | |||
| 8fa213502d | |||
| b869c30909 | |||
| f012a1a069 | |||
| 74d03bfb3b | |||
| ff499869d3 | |||
| b8ab07020c | |||
| dcd3d80b24 | |||
| ebd1eeb38d | |||
| 36f84ca18f | |||
| 6259106b6b | |||
| 73d6e704c4 | |||
| c95e424981 | |||
| 06abe53399 | |||
| 7c14a92baa | |||
| c07b782afa | |||
| 062f4517d6 | |||
| 28b02c83db | |||
| 1b5a0f8cf2 | |||
| 6c0573cb01 | |||
| b59487cfb0 | |||
| 0ac8098dad | |||
| 9b10871efb | |||
| e48af11e8f | |||
| a4e5b2af93 | |||
| 67c5a36894 | |||
| 765ac715c1 | |||
| c4bc156cac | |||
| 40f08dcbb2 | |||
| b4e45ef3ef | |||
| fc43cb590b | |||
| 6e1b869c99 | |||
| 35d84b6e42 | |||
| d31fddf940 | |||
| 14ee279ec8 | |||
| a3b1a7337d | |||
| c7f7e77099 | |||
| 5bb96bf42c | |||
| c0ae924c58 | |||
| daa5f01683 | |||
| 337d53b2ec | |||
| cdc49e0749 | |||
| 1916adedcc | |||
| a3132b907a | |||
| 0e09826140 | |||
| bf4f16c7b9 | |||
| 6915fef99f | |||
| c80c0b88bf | |||
| fe2edd56a8 | |||
| 84a36c00b4 | |||
| 4c9de843c5 | |||
| f7edc223e9 | |||
| f0072ce828 | |||
| 1223f50fe8 | |||
| 297cde513b | |||
| 7e6feb0cd2 | |||
| 0a213990a7 | |||
| a44cd1cca9 | |||
| 5fe6a2c63d | |||
| 8d46bba8eb | |||
| 90ff36afe8 | |||
| d2f482c743 | |||
| ebf9a98a1e | |||
| 578ae7f267 | |||
| deb5054357 | |||
| 089143cb3e | |||
| fa1a05886f | |||
| bec2cc951a | |||
| 400f248e83 | |||
| 7554d0ac02 | |||
| 74556ffb0f | |||
| 91893ac44c | |||
| 033246268a | |||
| 3866a9a40d | |||
| f56b62baa2 | |||
| 8782de7679 | |||
| 05f0fad7d1 | |||
| a04c5c7e92 | |||
| 5b4daa23b6 | |||
| 658b635509 | |||
| b73cc165ae | |||
| c40e69415f | |||
| 54906756db | |||
| 7ea139b624 | |||
| 3082cd5d32 | |||
| ce08de28b5 | |||
| e352c25b32 | |||
| f5378e8a86 | |||
| 9bc3a1d431 | |||
| f68ce457f7 | |||
| 22b3ff6bec | |||
| 2fae46d19e | |||
| bd7779ec63 | |||
| f3be91741a | |||
| bda9f03b21 | |||
| 635ae1118a | |||
| 6c0ea49185 | |||
| 8fe3070b85 | |||
| d11cf0823d | |||
| fb5d775857 | |||
| d020fb0a0b | |||
| f66132fcef | |||
| 821865cb62 | |||
| 68e0dd1f29 | |||
| cf201cba53 | |||
| c1e67cdc15 | |||
| 6ebe71c8a2 | |||
| e51283f9d3 | |||
| bad74928a1 | |||
| 467dc6cf4a | |||
| ef22cb9fcd | |||
| efe952fdf2 | |||
| 6d2e761319 | |||
| 3c8c51e1c9 | |||
| 480799bad1 | |||
| e699f1ad79 | |||
| 0b4a1833ec | |||
| 78b00302c8 | |||
| eb914463dc | |||
| 9a5d6103d6 | |||
| 7ccba11d82 | |||
| e67d3d816c | |||
| e2aa7aa31c | |||
| 7ecac4a7b4 | |||
| 0b82109e3c | |||
| 46a319bd7a | |||
| af68da9406 | |||
| 27978908d0 | |||
| 72cffc71cc | |||
| 5753c30973 | |||
| 7cbba823f8 | |||
| c89273ab37 | |||
| 6d66d769de | |||
| 70d37576f4 | |||
| 01e4abc95f | |||
| 2195310d06 | |||
| 5f98364e6f | |||
| b6cd9b2bae | |||
| 682db85268 | |||
| 78930d82b2 | |||
| 1ebb0c7daa | |||
| ae6c80f0cd | |||
| 0b49c74ac9 | |||
| 34be5abaf3 | |||
| 7f3c53e196 | |||
| b710fbe524 | |||
| 4c125792b2 | |||
| 8e6215ecf4 | |||
| 7132e2dae5 | |||
| 79852d9dcd | |||
| 30413d7877 | |||
| 08ed7b42de | |||
| 6e8c0ad90e | |||
| 8f1f61e247 | |||
| 8044ad5445 | |||
| 9a4737acd0 | |||
| 8231bc1c73 | |||
| c3af84a952 | |||
| 2172644f98 | |||
| 393b67873d | |||
| 70b15c9226 | |||
| f7e6677878 | |||
| 73e87b2deb | |||
| 2cf65b3694 | |||
| 7bc1b0dbcf | |||
| 68bc4a59f7 | |||
| 2bc8a76899 | |||
| 25053e5e8a | |||
| 6735c1ae58 | |||
| b037c8fbeb | |||
| 3fcfbad4c0 | |||
| da14947227 | |||
| 5e40e480bc | |||
| 490319d961 | |||
| 810adb82cc | |||
| 0e11cf92fc | |||
| 43e4cabb85 | |||
| 496a1bc97d | |||
| 7db4ddff56 | |||
| 6b25f83ee3 | |||
| 7602f4b130 | |||
| f762062f9f | |||
| a0958cddb4 | |||
| 5bb9e36842 | |||
| 0282251016 | |||
| 9b78409fdc | |||
| f26d4ab882 | |||
| ca86bbc3a5 | |||
| 1f41eca0b2 | |||
| 0e56d8c2f7 | |||
| c13297d18d | |||
| fe3c6bdad4 | |||
| 57b9372050 | |||
| 8371bf898f | |||
| aa5691447d | |||
| fa8e81d9dd | |||
| bc19fa7a78 | |||
| df1b648fa0 | |||
| 846fd6aeaa | |||
| fbba59f001 | |||
| b94c81a784 | |||
| 67b893175f | |||
| a9ff4ccb10 | |||
| 2f4f303223 | |||
| 3265d58052 | |||
| 30facbcec4 | |||
| 0f5157f7d1 | |||
| 3369aa51bc | |||
| 9e5890a0d7 | |||
| 3bda5f59a3 | |||
| 154dfa089b | |||
| bd0cbbc18a | |||
| ed0e7a7a25 | |||
| 5b35cfcfb2 | |||
| d3ba008b88 | |||
| a04a782dbf | |||
| f5d9fda0b1 | |||
| aebd386382 | |||
| 9a6f96b5e0 | |||
| 5a3ff0f9f7 | |||
| 160db34651 | |||
| ae20d2afb8 | |||
| 41b7a2a20d | |||
| 208ec4574b | |||
| 2bff66e2c7 | |||
| 28a0c3eb17 | |||
| 1aad5fc1bf | |||
| a3d7b541e2 | |||
| 7861a0081a | |||
| c8b911d5d0 | |||
| 22979ce245 | |||
| b5a3a720a4 | |||
| 0ec5fb37c2 | |||
| 2817c68e2e | |||
| c3050e5d02 | |||
| 8f1901b6e0 | |||
| 96a42fa03d | |||
| 718de1f102 | |||
| cb9d730c16 | |||
| 0e17fe5581 | |||
| b25747dd60 | |||
| b16349f2e9 | |||
| f4b5693bcb | |||
| 42a53a1c49 | |||
| 081fec72e5 | |||
| f2223dddca | |||
| 9be7b8ab56 | |||
| 40dc0d2cc7 | |||
| 19de5cb792 | |||
| 377e06daab | |||
| b54d82a01a | |||
| ad052ef498 | |||
| a3bc4af8fe | |||
| b6d57e2862 |
@@ -1,9 +0,0 @@
|
||||
# Description
|
||||
|
||||
Closes: #XXXX
|
||||
|
||||
<!-- If appropriate, insert relevant description here -->
|
||||
|
||||
# Checklist:
|
||||
|
||||
- [ ] added a changelog entry to `CHANGELOG.md`
|
||||
@@ -14,12 +14,20 @@ inputs:
|
||||
description: 'The tag/release to process. Uses the release id when trigger from a release.'
|
||||
required: false
|
||||
default: ''
|
||||
repo:
|
||||
description: 'The repo to use. Defaults to "nym".'
|
||||
required: false
|
||||
default: 'nym'
|
||||
owner:
|
||||
description: 'The repo owner to use. Defaults to "nymtech".'
|
||||
required: false
|
||||
default: 'nymtech'
|
||||
outputs:
|
||||
hashes:
|
||||
description: 'A string containing JSON with the release asset hashes and signatures'
|
||||
runs:
|
||||
using: 'node16'
|
||||
main: 'index.js'
|
||||
using: 'node20'
|
||||
main: 'dist/index.js'
|
||||
branding:
|
||||
icon: 'hash'
|
||||
color: 'green'
|
||||
|
||||
@@ -0,0 +1,450 @@
|
||||
export const id = 37;
|
||||
export const ids = [37];
|
||||
export const modules = {
|
||||
|
||||
/***/ 4037:
|
||||
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
|
||||
|
||||
__webpack_require__.r(__webpack_exports__);
|
||||
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
||||
/* harmony export */ "toFormData": () => (/* binding */ toFormData)
|
||||
/* harmony export */ });
|
||||
/* harmony import */ var fetch_blob_from_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2777);
|
||||
/* harmony import */ var formdata_polyfill_esm_min_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(8010);
|
||||
|
||||
|
||||
|
||||
let s = 0;
|
||||
const S = {
|
||||
START_BOUNDARY: s++,
|
||||
HEADER_FIELD_START: s++,
|
||||
HEADER_FIELD: s++,
|
||||
HEADER_VALUE_START: s++,
|
||||
HEADER_VALUE: s++,
|
||||
HEADER_VALUE_ALMOST_DONE: s++,
|
||||
HEADERS_ALMOST_DONE: s++,
|
||||
PART_DATA_START: s++,
|
||||
PART_DATA: s++,
|
||||
END: s++
|
||||
};
|
||||
|
||||
let f = 1;
|
||||
const F = {
|
||||
PART_BOUNDARY: f,
|
||||
LAST_BOUNDARY: f *= 2
|
||||
};
|
||||
|
||||
const LF = 10;
|
||||
const CR = 13;
|
||||
const SPACE = 32;
|
||||
const HYPHEN = 45;
|
||||
const COLON = 58;
|
||||
const A = 97;
|
||||
const Z = 122;
|
||||
|
||||
const lower = c => c | 0x20;
|
||||
|
||||
const noop = () => {};
|
||||
|
||||
class MultipartParser {
|
||||
/**
|
||||
* @param {string} boundary
|
||||
*/
|
||||
constructor(boundary) {
|
||||
this.index = 0;
|
||||
this.flags = 0;
|
||||
|
||||
this.onHeaderEnd = noop;
|
||||
this.onHeaderField = noop;
|
||||
this.onHeadersEnd = noop;
|
||||
this.onHeaderValue = noop;
|
||||
this.onPartBegin = noop;
|
||||
this.onPartData = noop;
|
||||
this.onPartEnd = noop;
|
||||
|
||||
this.boundaryChars = {};
|
||||
|
||||
boundary = '\r\n--' + boundary;
|
||||
const ui8a = new Uint8Array(boundary.length);
|
||||
for (let i = 0; i < boundary.length; i++) {
|
||||
ui8a[i] = boundary.charCodeAt(i);
|
||||
this.boundaryChars[ui8a[i]] = true;
|
||||
}
|
||||
|
||||
this.boundary = ui8a;
|
||||
this.lookbehind = new Uint8Array(this.boundary.length + 8);
|
||||
this.state = S.START_BOUNDARY;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Uint8Array} data
|
||||
*/
|
||||
write(data) {
|
||||
let i = 0;
|
||||
const length_ = data.length;
|
||||
let previousIndex = this.index;
|
||||
let {lookbehind, boundary, boundaryChars, index, state, flags} = this;
|
||||
const boundaryLength = this.boundary.length;
|
||||
const boundaryEnd = boundaryLength - 1;
|
||||
const bufferLength = data.length;
|
||||
let c;
|
||||
let cl;
|
||||
|
||||
const mark = name => {
|
||||
this[name + 'Mark'] = i;
|
||||
};
|
||||
|
||||
const clear = name => {
|
||||
delete this[name + 'Mark'];
|
||||
};
|
||||
|
||||
const callback = (callbackSymbol, start, end, ui8a) => {
|
||||
if (start === undefined || start !== end) {
|
||||
this[callbackSymbol](ui8a && ui8a.subarray(start, end));
|
||||
}
|
||||
};
|
||||
|
||||
const dataCallback = (name, clear) => {
|
||||
const markSymbol = name + 'Mark';
|
||||
if (!(markSymbol in this)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (clear) {
|
||||
callback(name, this[markSymbol], i, data);
|
||||
delete this[markSymbol];
|
||||
} else {
|
||||
callback(name, this[markSymbol], data.length, data);
|
||||
this[markSymbol] = 0;
|
||||
}
|
||||
};
|
||||
|
||||
for (i = 0; i < length_; i++) {
|
||||
c = data[i];
|
||||
|
||||
switch (state) {
|
||||
case S.START_BOUNDARY:
|
||||
if (index === boundary.length - 2) {
|
||||
if (c === HYPHEN) {
|
||||
flags |= F.LAST_BOUNDARY;
|
||||
} else if (c !== CR) {
|
||||
return;
|
||||
}
|
||||
|
||||
index++;
|
||||
break;
|
||||
} else if (index - 1 === boundary.length - 2) {
|
||||
if (flags & F.LAST_BOUNDARY && c === HYPHEN) {
|
||||
state = S.END;
|
||||
flags = 0;
|
||||
} else if (!(flags & F.LAST_BOUNDARY) && c === LF) {
|
||||
index = 0;
|
||||
callback('onPartBegin');
|
||||
state = S.HEADER_FIELD_START;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (c !== boundary[index + 2]) {
|
||||
index = -2;
|
||||
}
|
||||
|
||||
if (c === boundary[index + 2]) {
|
||||
index++;
|
||||
}
|
||||
|
||||
break;
|
||||
case S.HEADER_FIELD_START:
|
||||
state = S.HEADER_FIELD;
|
||||
mark('onHeaderField');
|
||||
index = 0;
|
||||
// falls through
|
||||
case S.HEADER_FIELD:
|
||||
if (c === CR) {
|
||||
clear('onHeaderField');
|
||||
state = S.HEADERS_ALMOST_DONE;
|
||||
break;
|
||||
}
|
||||
|
||||
index++;
|
||||
if (c === HYPHEN) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (c === COLON) {
|
||||
if (index === 1) {
|
||||
// empty header field
|
||||
return;
|
||||
}
|
||||
|
||||
dataCallback('onHeaderField', true);
|
||||
state = S.HEADER_VALUE_START;
|
||||
break;
|
||||
}
|
||||
|
||||
cl = lower(c);
|
||||
if (cl < A || cl > Z) {
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
case S.HEADER_VALUE_START:
|
||||
if (c === SPACE) {
|
||||
break;
|
||||
}
|
||||
|
||||
mark('onHeaderValue');
|
||||
state = S.HEADER_VALUE;
|
||||
// falls through
|
||||
case S.HEADER_VALUE:
|
||||
if (c === CR) {
|
||||
dataCallback('onHeaderValue', true);
|
||||
callback('onHeaderEnd');
|
||||
state = S.HEADER_VALUE_ALMOST_DONE;
|
||||
}
|
||||
|
||||
break;
|
||||
case S.HEADER_VALUE_ALMOST_DONE:
|
||||
if (c !== LF) {
|
||||
return;
|
||||
}
|
||||
|
||||
state = S.HEADER_FIELD_START;
|
||||
break;
|
||||
case S.HEADERS_ALMOST_DONE:
|
||||
if (c !== LF) {
|
||||
return;
|
||||
}
|
||||
|
||||
callback('onHeadersEnd');
|
||||
state = S.PART_DATA_START;
|
||||
break;
|
||||
case S.PART_DATA_START:
|
||||
state = S.PART_DATA;
|
||||
mark('onPartData');
|
||||
// falls through
|
||||
case S.PART_DATA:
|
||||
previousIndex = index;
|
||||
|
||||
if (index === 0) {
|
||||
// boyer-moore derrived algorithm to safely skip non-boundary data
|
||||
i += boundaryEnd;
|
||||
while (i < bufferLength && !(data[i] in boundaryChars)) {
|
||||
i += boundaryLength;
|
||||
}
|
||||
|
||||
i -= boundaryEnd;
|
||||
c = data[i];
|
||||
}
|
||||
|
||||
if (index < boundary.length) {
|
||||
if (boundary[index] === c) {
|
||||
if (index === 0) {
|
||||
dataCallback('onPartData', true);
|
||||
}
|
||||
|
||||
index++;
|
||||
} else {
|
||||
index = 0;
|
||||
}
|
||||
} else if (index === boundary.length) {
|
||||
index++;
|
||||
if (c === CR) {
|
||||
// CR = part boundary
|
||||
flags |= F.PART_BOUNDARY;
|
||||
} else if (c === HYPHEN) {
|
||||
// HYPHEN = end boundary
|
||||
flags |= F.LAST_BOUNDARY;
|
||||
} else {
|
||||
index = 0;
|
||||
}
|
||||
} else if (index - 1 === boundary.length) {
|
||||
if (flags & F.PART_BOUNDARY) {
|
||||
index = 0;
|
||||
if (c === LF) {
|
||||
// unset the PART_BOUNDARY flag
|
||||
flags &= ~F.PART_BOUNDARY;
|
||||
callback('onPartEnd');
|
||||
callback('onPartBegin');
|
||||
state = S.HEADER_FIELD_START;
|
||||
break;
|
||||
}
|
||||
} else if (flags & F.LAST_BOUNDARY) {
|
||||
if (c === HYPHEN) {
|
||||
callback('onPartEnd');
|
||||
state = S.END;
|
||||
flags = 0;
|
||||
} else {
|
||||
index = 0;
|
||||
}
|
||||
} else {
|
||||
index = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (index > 0) {
|
||||
// when matching a possible boundary, keep a lookbehind reference
|
||||
// in case it turns out to be a false lead
|
||||
lookbehind[index - 1] = c;
|
||||
} else if (previousIndex > 0) {
|
||||
// if our boundary turned out to be rubbish, the captured lookbehind
|
||||
// belongs to partData
|
||||
const _lookbehind = new Uint8Array(lookbehind.buffer, lookbehind.byteOffset, lookbehind.byteLength);
|
||||
callback('onPartData', 0, previousIndex, _lookbehind);
|
||||
previousIndex = 0;
|
||||
mark('onPartData');
|
||||
|
||||
// reconsider the current character even so it interrupted the sequence
|
||||
// it could be the beginning of a new sequence
|
||||
i--;
|
||||
}
|
||||
|
||||
break;
|
||||
case S.END:
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unexpected state entered: ${state}`);
|
||||
}
|
||||
}
|
||||
|
||||
dataCallback('onHeaderField');
|
||||
dataCallback('onHeaderValue');
|
||||
dataCallback('onPartData');
|
||||
|
||||
// Update properties for the next call
|
||||
this.index = index;
|
||||
this.state = state;
|
||||
this.flags = flags;
|
||||
}
|
||||
|
||||
end() {
|
||||
if ((this.state === S.HEADER_FIELD_START && this.index === 0) ||
|
||||
(this.state === S.PART_DATA && this.index === this.boundary.length)) {
|
||||
this.onPartEnd();
|
||||
} else if (this.state !== S.END) {
|
||||
throw new Error('MultipartParser.end(): stream ended unexpectedly');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function _fileName(headerValue) {
|
||||
// matches either a quoted-string or a token (RFC 2616 section 19.5.1)
|
||||
const m = headerValue.match(/\bfilename=("(.*?)"|([^()<>@,;:\\"/[\]?={}\s\t]+))($|;\s)/i);
|
||||
if (!m) {
|
||||
return;
|
||||
}
|
||||
|
||||
const match = m[2] || m[3] || '';
|
||||
let filename = match.slice(match.lastIndexOf('\\') + 1);
|
||||
filename = filename.replace(/%22/g, '"');
|
||||
filename = filename.replace(/&#(\d{4});/g, (m, code) => {
|
||||
return String.fromCharCode(code);
|
||||
});
|
||||
return filename;
|
||||
}
|
||||
|
||||
async function toFormData(Body, ct) {
|
||||
if (!/multipart/i.test(ct)) {
|
||||
throw new TypeError('Failed to fetch');
|
||||
}
|
||||
|
||||
const m = ct.match(/boundary=(?:"([^"]+)"|([^;]+))/i);
|
||||
|
||||
if (!m) {
|
||||
throw new TypeError('no or bad content-type header, no multipart boundary');
|
||||
}
|
||||
|
||||
const parser = new MultipartParser(m[1] || m[2]);
|
||||
|
||||
let headerField;
|
||||
let headerValue;
|
||||
let entryValue;
|
||||
let entryName;
|
||||
let contentType;
|
||||
let filename;
|
||||
const entryChunks = [];
|
||||
const formData = new formdata_polyfill_esm_min_js__WEBPACK_IMPORTED_MODULE_1__/* .FormData */ .Ct();
|
||||
|
||||
const onPartData = ui8a => {
|
||||
entryValue += decoder.decode(ui8a, {stream: true});
|
||||
};
|
||||
|
||||
const appendToFile = ui8a => {
|
||||
entryChunks.push(ui8a);
|
||||
};
|
||||
|
||||
const appendFileToFormData = () => {
|
||||
const file = new fetch_blob_from_js__WEBPACK_IMPORTED_MODULE_0__/* .File */ .$B(entryChunks, filename, {type: contentType});
|
||||
formData.append(entryName, file);
|
||||
};
|
||||
|
||||
const appendEntryToFormData = () => {
|
||||
formData.append(entryName, entryValue);
|
||||
};
|
||||
|
||||
const decoder = new TextDecoder('utf-8');
|
||||
decoder.decode();
|
||||
|
||||
parser.onPartBegin = function () {
|
||||
parser.onPartData = onPartData;
|
||||
parser.onPartEnd = appendEntryToFormData;
|
||||
|
||||
headerField = '';
|
||||
headerValue = '';
|
||||
entryValue = '';
|
||||
entryName = '';
|
||||
contentType = '';
|
||||
filename = null;
|
||||
entryChunks.length = 0;
|
||||
};
|
||||
|
||||
parser.onHeaderField = function (ui8a) {
|
||||
headerField += decoder.decode(ui8a, {stream: true});
|
||||
};
|
||||
|
||||
parser.onHeaderValue = function (ui8a) {
|
||||
headerValue += decoder.decode(ui8a, {stream: true});
|
||||
};
|
||||
|
||||
parser.onHeaderEnd = function () {
|
||||
headerValue += decoder.decode();
|
||||
headerField = headerField.toLowerCase();
|
||||
|
||||
if (headerField === 'content-disposition') {
|
||||
// matches either a quoted-string or a token (RFC 2616 section 19.5.1)
|
||||
const m = headerValue.match(/\bname=("([^"]*)"|([^()<>@,;:\\"/[\]?={}\s\t]+))/i);
|
||||
|
||||
if (m) {
|
||||
entryName = m[2] || m[3] || '';
|
||||
}
|
||||
|
||||
filename = _fileName(headerValue);
|
||||
|
||||
if (filename) {
|
||||
parser.onPartData = appendToFile;
|
||||
parser.onPartEnd = appendFileToFormData;
|
||||
}
|
||||
} else if (headerField === 'content-type') {
|
||||
contentType = headerValue;
|
||||
}
|
||||
|
||||
headerValue = '';
|
||||
headerField = '';
|
||||
};
|
||||
|
||||
for await (const chunk of Body) {
|
||||
parser.write(chunk);
|
||||
}
|
||||
|
||||
parser.end();
|
||||
|
||||
return formData;
|
||||
}
|
||||
|
||||
|
||||
/***/ })
|
||||
|
||||
};
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,57 @@
|
||||
'use strict';
|
||||
const fs = require('fs');
|
||||
const crypto = require('crypto');
|
||||
const {parentPort} = require('worker_threads');
|
||||
|
||||
const handlers = {
|
||||
hashFile: (algorithm, filePath) => new Promise((resolve, reject) => {
|
||||
const hasher = crypto.createHash(algorithm);
|
||||
fs.createReadStream(filePath)
|
||||
// TODO: Use `Stream.pipeline` when targeting Node.js 12.
|
||||
.on('error', reject)
|
||||
.pipe(hasher)
|
||||
.on('error', reject)
|
||||
.on('finish', () => {
|
||||
const {buffer} = new Uint8Array(hasher.read());
|
||||
resolve({value: buffer, transferList: [buffer]});
|
||||
});
|
||||
}),
|
||||
hash: async (algorithm, input) => {
|
||||
const hasher = crypto.createHash(algorithm);
|
||||
|
||||
if (Array.isArray(input)) {
|
||||
for (const part of input) {
|
||||
hasher.update(part);
|
||||
}
|
||||
} else {
|
||||
hasher.update(input);
|
||||
}
|
||||
|
||||
const {buffer} = new Uint8Array(hasher.digest());
|
||||
return {value: buffer, transferList: [buffer]};
|
||||
}
|
||||
};
|
||||
|
||||
parentPort.on('message', async message => {
|
||||
try {
|
||||
const {method, args} = message;
|
||||
const handler = handlers[method];
|
||||
|
||||
if (handler === undefined) {
|
||||
throw new Error(`Unknown method '${method}'`);
|
||||
}
|
||||
|
||||
const {value, transferList} = await handler(...args);
|
||||
parentPort.postMessage({id: message.id, value}, transferList);
|
||||
} catch (error) {
|
||||
const newError = {message: error.message, stack: error.stack};
|
||||
|
||||
for (const [key, value] of Object.entries(error)) {
|
||||
if (typeof value !== 'object') {
|
||||
newError[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
parentPort.postMessage({id: message.id, error: newError});
|
||||
}
|
||||
});
|
||||
@@ -1,15 +0,0 @@
|
||||
import core from "@actions/core";
|
||||
import github from "@actions/github";
|
||||
import { createHashesFromReleaseTagOrNameOrId } from './create-hashes.mjs';
|
||||
|
||||
const algorithm = core.getInput('hash-type');
|
||||
const filename = core.getInput("file-name");
|
||||
|
||||
// use the release id from the payload if it is set
|
||||
const releaseTagOrNameOrId = core.getInput("release-tag-or-name-or-id") || github.context.payload.release?.id;
|
||||
|
||||
try {
|
||||
await createHashesFromReleaseTagOrNameOrId({ releaseTagOrNameOrId, algorithm, filename })
|
||||
} catch (error) {
|
||||
core.setFailed(error.message);
|
||||
}
|
||||
@@ -2,17 +2,6 @@
|
||||
"name": "nym-hash-release",
|
||||
"version": "1.0.0",
|
||||
"description": "Generate hashes and signatures for assets in Nym releases",
|
||||
"main": "index.js",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"local": "node run-local.mjs"
|
||||
},
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.10.0",
|
||||
"@actions/github": "^5.1.1",
|
||||
"@octokit/auth-action": "^4.0.0",
|
||||
"@octokit/rest": "^20.0.1",
|
||||
"hasha": "^5.2.0",
|
||||
"node-fetch": "^3.2.10"
|
||||
}
|
||||
"main": "dist/index.js",
|
||||
"type": "module"
|
||||
}
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
import {createHashesFromReleaseTagOrNameOrId} from './create-hashes.mjs';
|
||||
|
||||
await createHashesFromReleaseTagOrNameOrId({releaseTagOrNameOrId: 119065724, cache: true, upload: false});
|
||||
await createHashesFromReleaseTagOrNameOrId({releaseTagOrNameOrId: '119065724', cache: true, upload: false});
|
||||
await createHashesFromReleaseTagOrNameOrId({releaseTagOrNameOrId: 'nym-connect-v1.1.19-snickers', cache: true, upload: false});
|
||||
await createHashesFromReleaseTagOrNameOrId({releaseTagOrNameOrId: 'Nym Connect v1.1.19-snickers', cache: true, upload: false});
|
||||
@@ -0,0 +1,14 @@
|
||||
# nym-hash-release
|
||||
|
||||
This is the source code for the custom GitHub Action to calculate hashes.
|
||||
|
||||
It is in a subdirectory to avoid issues with `package.json`.
|
||||
|
||||
## Build
|
||||
|
||||
The following will bundle all code and dependencies into the `dist` folder, and copy it into place for GitHub Actions.
|
||||
|
||||
```
|
||||
npm run build
|
||||
npm run dist:copy
|
||||
```
|
||||
+22
-9
@@ -11,10 +11,14 @@ function getBinInfo(path) {
|
||||
let mode = fs.statSync(path).mode
|
||||
fs.chmodSync(path, mode | 0o111)
|
||||
|
||||
const raw = execSync(`${path} build-info --output=json`, { stdio: 'pipe', encoding: "utf8" });
|
||||
const cmd = `${path} build-info --output=json`;
|
||||
console.log(`🚚 Running ${cmd}... (for max of 3 seconds, then SIGTERM)`);
|
||||
const raw = execSync(cmd, { stdio: 'pipe', encoding: "utf8", timeout: 3000 });
|
||||
const parsed = JSON.parse(raw)
|
||||
console.log(` ✅ ok`);
|
||||
return parsed
|
||||
} catch (_) {
|
||||
console.log(` ❌ failed`);
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
@@ -24,8 +28,11 @@ async function run(assets, algorithm, filename, cache) {
|
||||
console.warn("cache is set to 'false', but we we no longer support it")
|
||||
}
|
||||
|
||||
const directory = path.join(process.env.RUNNER_TEMP || '.tmp', process.env.GITHUB_RUN_ID || '');
|
||||
console.log('Temporary directory: ', directory);
|
||||
|
||||
try {
|
||||
fs.mkdirSync('.tmp');
|
||||
fs.mkdirSync(directory, { recursive: true });
|
||||
} catch(e) {
|
||||
// ignore
|
||||
}
|
||||
@@ -40,13 +47,13 @@ async function run(assets, algorithm, filename, cache) {
|
||||
let sig = null;
|
||||
|
||||
// cache in `${WORKING_DIR}/.tmp/`
|
||||
const cacheFilename = path.resolve(`.tmp/${asset.name}`);
|
||||
const cacheFilename = path.join(directory, `${asset.name}`);
|
||||
if(!fs.existsSync(cacheFilename)) {
|
||||
console.log(`Downloading ${asset.browser_download_url}... to ${cacheFilename}`);
|
||||
console.log(`⬇️ Downloading ${asset.browser_download_url}... to ${cacheFilename} [${numAwaiting} of ${assets.length}]`);
|
||||
buffer = Buffer.from(await fetch(asset.browser_download_url).then(res => res.arrayBuffer()));
|
||||
fs.writeFileSync(cacheFilename, buffer);
|
||||
} else {
|
||||
console.log(`Loading from ${cacheFilename}`);
|
||||
console.log(`💾 Loading from ${cacheFilename}`);
|
||||
buffer = Buffer.from(fs.readFileSync(cacheFilename));
|
||||
|
||||
// console.log('Reading signature from content');
|
||||
@@ -131,6 +138,7 @@ async function run(assets, algorithm, filename, cache) {
|
||||
}
|
||||
}
|
||||
}
|
||||
console.log(`Completed hashing ${assets.length} files`);
|
||||
return hashes;
|
||||
}
|
||||
|
||||
@@ -142,7 +150,7 @@ export async function createHashes({ assets, algorithm, filename, cache }) {
|
||||
return output;
|
||||
}
|
||||
|
||||
export async function createHashesFromReleaseTagOrNameOrId({ releaseTagOrNameOrId, algorithm = 'sha256', filename = 'hashes.json', cache = false, upload = true }) {
|
||||
export async function createHashesFromReleaseTagOrNameOrId({ releaseTagOrNameOrId, algorithm = 'sha256', filename = 'hashes.json', cache = false, upload = true, owner = 'nymtech', repo = 'nym' }) {
|
||||
console.log("🚀🚀🚀 Getting releases");
|
||||
|
||||
let auth;
|
||||
@@ -157,8 +165,6 @@ export async function createHashesFromReleaseTagOrNameOrId({ releaseTagOrNameOrI
|
||||
auth: process.env.GITHUB_TOKEN,
|
||||
request: { fetch }
|
||||
});
|
||||
const owner = "nymtech";
|
||||
const repo = "nym";
|
||||
|
||||
let releases;
|
||||
if(cache) {
|
||||
@@ -212,7 +218,14 @@ export async function createHashesFromReleaseTagOrNameOrId({ releaseTagOrNameOrI
|
||||
|
||||
releasesToProcess.forEach(release => {
|
||||
const {tag_name, name} = release;
|
||||
const tagComponents = tag_name.split('-v');
|
||||
const matches = tag_name.match(/(\S+)-v([0-9]+\.[0-9]+(\.\S+)?)/);
|
||||
|
||||
if(!matches || matches.length < 2) {
|
||||
console.warn('Could not match version structure in tag name = ', tag_name);
|
||||
return;
|
||||
}
|
||||
|
||||
const tagComponents = matches.slice(1);
|
||||
const componentName = tagComponents[0];
|
||||
const componentVersion = 'v' + tagComponents[1];
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
import core from "@actions/core";
|
||||
import github from "@actions/github";
|
||||
import { createHashesFromReleaseTagOrNameOrId } from './create-hashes.mjs';
|
||||
|
||||
const algorithm = core.getInput('hash-type');
|
||||
const filename = core.getInput("file-name");
|
||||
const owner = core.getInput("owner");
|
||||
const repo = core.getInput("repo");
|
||||
|
||||
async function main() {
|
||||
// use the release id from the payload if it is set
|
||||
const releaseTagOrNameOrId = core.getInput("release-tag-or-name-or-id") || github.context.payload.release?.id;
|
||||
|
||||
try {
|
||||
await createHashesFromReleaseTagOrNameOrId({releaseTagOrNameOrId, algorithm, filename, owner, repo})
|
||||
} catch (error) {
|
||||
core.setFailed(error.message);
|
||||
}
|
||||
}
|
||||
|
||||
main().catch(error => core.setFailed(error.message));
|
||||
+72
-35
@@ -1,26 +1,28 @@
|
||||
{
|
||||
"name": "ghaction-generate-release-hashes",
|
||||
"name": "nym-hash-release",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "ghaction-generate-release-hashes",
|
||||
"name": "nym-hash-release",
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.10.0",
|
||||
"@actions/core": "^1.10.1",
|
||||
"@actions/github": "^5.1.1",
|
||||
"@octokit/auth-action": "^4.0.0",
|
||||
"@octokit/rest": "^20.0.1",
|
||||
"@octokit/auth-action": "^4.0.1",
|
||||
"@octokit/rest": "^20.0.2",
|
||||
"hasha": "^5.2.0",
|
||||
"node-fetch": "^3.2.10"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vercel/ncc": "^0.38.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/core": {
|
||||
"version": "1.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.10.0.tgz",
|
||||
"integrity": "sha512-2aZDDa3zrrZbP5ZYg159sNoLRb61nQ7awl5pSvIq5Qpj81vwDzdMRKzkWJGJuwVvWpvZKx7vspJALyvaaIQyug==",
|
||||
"version": "1.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.10.1.tgz",
|
||||
"integrity": "sha512-3lBR9EDAY+iYIpTnTIXmWcNbX3T2kCkAEQGIQx4NVQ0575nk2k3GRZDTPQG+vVtS2izSLmINlxXf0uLtnrTP+g==",
|
||||
"dependencies": {
|
||||
"@actions/http-client": "^2.0.1",
|
||||
"uuid": "^8.3.2"
|
||||
@@ -46,12 +48,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/auth-action": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/auth-action/-/auth-action-4.0.0.tgz",
|
||||
"integrity": "sha512-sMm9lWZdiX6e89YFaLrgE9EFs94k58BwIkvjOtozNWUqyTmsrnWFr/M5LolaRzZ7Kmb5FbhF9hi7FEeE274SoQ==",
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/auth-action/-/auth-action-4.0.1.tgz",
|
||||
"integrity": "sha512-mJLOcFFafIivLZ7BEkGDCTFoHPJv7BeL5Zwy7j5qMDU0b/DKshhi6GCU9tw3vmKhOxTNquYfvwqsEfPpemaaxg==",
|
||||
"dependencies": {
|
||||
"@octokit/auth-token": "^4.0.0",
|
||||
"@octokit/types": "^11.0.0"
|
||||
"@octokit/types": "^12.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
@@ -66,16 +68,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/auth-action/node_modules/@octokit/openapi-types": {
|
||||
"version": "18.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-18.0.0.tgz",
|
||||
"integrity": "sha512-V8GImKs3TeQRxRtXFpG2wl19V7444NIOTDF24AWuIbmNaNYOQMWRbjcGDXV5B+0n887fgDcuMNOmlul+k+oJtw=="
|
||||
"version": "20.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz",
|
||||
"integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA=="
|
||||
},
|
||||
"node_modules/@octokit/auth-action/node_modules/@octokit/types": {
|
||||
"version": "11.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-11.1.0.tgz",
|
||||
"integrity": "sha512-Fz0+7GyLm/bHt8fwEqgvRBWwIV1S6wRRyq+V6exRKLVWaKGsuy6H9QFYeBVDV7rK6fO3XwHgQOPxv+cLj2zpXQ==",
|
||||
"version": "12.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz",
|
||||
"integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==",
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": "^18.0.0"
|
||||
"@octokit/openapi-types": "^20.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/auth-token": {
|
||||
@@ -191,14 +193,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/rest": {
|
||||
"version": "20.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-20.0.1.tgz",
|
||||
"integrity": "sha512-wROV21RwHQIMNb2Dgd4+pY+dVy1Dwmp85pBrgr6YRRDYRBu9Gb+D73f4Bl2EukZSj5hInq2Tui9o7gAQpc2k2Q==",
|
||||
"version": "20.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-20.0.2.tgz",
|
||||
"integrity": "sha512-Ux8NDgEraQ/DMAU1PlAohyfBBXDwhnX2j33Z1nJNziqAfHi70PuxkFYIcIt8aIAxtRE7KVuKp8lSR8pA0J5iOQ==",
|
||||
"dependencies": {
|
||||
"@octokit/core": "^5.0.0",
|
||||
"@octokit/plugin-paginate-rest": "^8.0.0",
|
||||
"@octokit/plugin-paginate-rest": "^9.0.0",
|
||||
"@octokit/plugin-request-log": "^4.0.0",
|
||||
"@octokit/plugin-rest-endpoint-methods": "^9.0.0"
|
||||
"@octokit/plugin-rest-endpoint-methods": "^10.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
@@ -261,17 +263,30 @@
|
||||
"integrity": "sha512-V8GImKs3TeQRxRtXFpG2wl19V7444NIOTDF24AWuIbmNaNYOQMWRbjcGDXV5B+0n887fgDcuMNOmlul+k+oJtw=="
|
||||
},
|
||||
"node_modules/@octokit/rest/node_modules/@octokit/plugin-paginate-rest": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-8.0.0.tgz",
|
||||
"integrity": "sha512-2xZ+baZWUg+qudVXnnvXz7qfrTmDeYPCzangBVq/1gXxii/OiS//4shJp9dnCCvj1x+JAm9ji1Egwm1BA47lPQ==",
|
||||
"version": "9.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.2.1.tgz",
|
||||
"integrity": "sha512-wfGhE/TAkXZRLjksFXuDZdmGnJQHvtU/joFQdweXUgzo1XwvBCD4o4+75NtFfjfLK5IwLf9vHTfSiU3sLRYpRw==",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^11.0.0"
|
||||
"@octokit/types": "^12.6.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@octokit/core": ">=5"
|
||||
"@octokit/core": "5"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/rest/node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/openapi-types": {
|
||||
"version": "20.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz",
|
||||
"integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA=="
|
||||
},
|
||||
"node_modules/@octokit/rest/node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/types": {
|
||||
"version": "12.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz",
|
||||
"integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==",
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": "^20.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/rest/node_modules/@octokit/plugin-request-log": {
|
||||
@@ -286,17 +301,30 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/rest/node_modules/@octokit/plugin-rest-endpoint-methods": {
|
||||
"version": "9.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-9.0.0.tgz",
|
||||
"integrity": "sha512-KquMF/VB1IkKNiVnzJKspY5mFgGyLd7HzdJfVEGTJFzqu9BRFNWt+nwTCMuUiWc72gLQhRWYubTwOkQj+w/1PA==",
|
||||
"version": "10.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-10.4.1.tgz",
|
||||
"integrity": "sha512-xV1b+ceKV9KytQe3zCVqjg+8GTGfDYwaT1ATU5isiUyVtlVAO3HNdzpS4sr4GBx4hxQ46s7ITtZrAsxG22+rVg==",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^11.0.0"
|
||||
"@octokit/types": "^12.6.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@octokit/core": ">=5"
|
||||
"@octokit/core": "5"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/rest/node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/openapi-types": {
|
||||
"version": "20.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz",
|
||||
"integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA=="
|
||||
},
|
||||
"node_modules/@octokit/rest/node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/types": {
|
||||
"version": "12.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz",
|
||||
"integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==",
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": "^20.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/rest/node_modules/@octokit/request": {
|
||||
@@ -343,6 +371,15 @@
|
||||
"@octokit/openapi-types": "^12.11.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@vercel/ncc": {
|
||||
"version": "0.38.1",
|
||||
"resolved": "https://registry.npmjs.org/@vercel/ncc/-/ncc-0.38.1.tgz",
|
||||
"integrity": "sha512-IBBb+iI2NLu4VQn3Vwldyi2QwaXt5+hTyh58ggAMoCGE6DJmPvwL3KPBWcJl1m9LYPChBLE980Jw+CS4Wokqxw==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"ncc": "dist/ncc/cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/before-after-hook": {
|
||||
"version": "2.2.3",
|
||||
"resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz",
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"name": "nym-hash-release",
|
||||
"version": "1.0.0",
|
||||
"description": "Generate hashes and signatures for assets in Nym releases",
|
||||
"main": "index.js",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"local": "node run-local.mjs",
|
||||
"build": "ncc build index.js -o dist",
|
||||
"dist:copy": "mkdir -p ../dist && cp dist/*.js ../dist"
|
||||
},
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.10.1",
|
||||
"@actions/github": "^5.1.1",
|
||||
"@octokit/auth-action": "^4.0.1",
|
||||
"@octokit/rest": "^20.0.2",
|
||||
"hasha": "^5.2.0",
|
||||
"node-fetch": "^3.2.10"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vercel/ncc": "^0.38.1"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import {createHashesFromReleaseTagOrNameOrId} from './create-hashes.mjs';
|
||||
|
||||
const cache = true;
|
||||
|
||||
await createHashesFromReleaseTagOrNameOrId({releaseTagOrNameOrId: 'nym-binaries-v2024.1-marabou', cache, upload: false});
|
||||
await createHashesFromReleaseTagOrNameOrId({releaseTagOrNameOrId: 'nym-vpn-desktop-v0.0.8', cache, upload: false, repo: 'nym-vpn-client'});
|
||||
|
||||
// await createHashesFromReleaseTagOrNameOrId({releaseTagOrNameOrId: 119065724, cache: true, upload: false});
|
||||
// await createHashesFromReleaseTagOrNameOrId({releaseTagOrNameOrId: '119065724', cache: true, upload: false});
|
||||
// await createHashesFromReleaseTagOrNameOrId({releaseTagOrNameOrId: 'nym-connect-v1.1.19-snickers', cache: true, upload: false});
|
||||
// await createHashesFromReleaseTagOrNameOrId({releaseTagOrNameOrId: 'Nym Connect v1.1.19-snickers', cache: true, upload: false});
|
||||
@@ -9,7 +9,11 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Install Dependencies (Linux)
|
||||
run: sudo apt-get update && sudo apt-get install -y build-essential curl wget libssl-dev libudev-dev squashfs-tools protobuf-compiler
|
||||
run: sudo apt-get update && sudo apt-get install -y build-essential curl wget libssl-dev libudev-dev squashfs-tools protobuf-compiler git python3 && sudo apt-get update --fix-missing
|
||||
- name: Install pip3
|
||||
run: sudo apt install -y python3-pip
|
||||
- name: Install Python3 modules
|
||||
run: sudo pip3 install pandas tabulate
|
||||
- name: Install rsync
|
||||
run: sudo apt-get install rsync
|
||||
- uses: rlespinasse/github-slug-action@v3.x
|
||||
@@ -30,9 +34,24 @@ jobs:
|
||||
- name: Remove existing Nym config directory (`~/.nym/`)
|
||||
run: cd documentation && ./remove_existing_config.sh
|
||||
continue-on-error: false
|
||||
- name: Build all projects in documentation/ & move to ~/dist/docs/
|
||||
# This is the original flow
|
||||
# - name: Build all projects in documentation/ & move to ~/dist/docs/
|
||||
# run: cd documentation && ./build_all_to_dist.sh
|
||||
|
||||
# This is a workaround replacement which builds on the last working commit b332a6b55668f60988e36961f3f62a794ba82ddb and then on current branch
|
||||
- name: Save current branch to ~/current_branch
|
||||
run: git rev-parse --abbrev-ref HEAD > ~/current_branch
|
||||
- name: Git pull, reset & switch to b332a6b55668f60988e36961f3f62a794ba82ddb
|
||||
run: git pull && git reset --hard && git checkout b332a6b55668f60988e36961f3f62a794ba82ddb
|
||||
- name: Build all projects in documentation/ & move to ~/dist/docs/ from b332a6b55668f60988e36961f3f62a794ba82ddb
|
||||
run: cd documentation && ./build_all_to_dist.sh
|
||||
continue-on-error: false
|
||||
|
||||
- name: Switch to current branch
|
||||
run: git checkout $echo "$(cat ~/current_branch)"
|
||||
- name: Build all projects in documentation/ & move to ~/dist/docs/ on current branch
|
||||
run: cd documentation && ./build_all_to_dist.sh && rm ~/current_branch
|
||||
|
||||
# End of replacemet
|
||||
|
||||
- name: Post process
|
||||
run: cd documentation && ./post_process.sh
|
||||
|
||||
@@ -104,14 +104,12 @@ jobs:
|
||||
name: nym-binaries-artifacts
|
||||
path: |
|
||||
target/release/nym-client
|
||||
target/release/nym-gateway
|
||||
target/release/nym-mixnode
|
||||
target/release/nym-socks5-client
|
||||
target/release/nym-api
|
||||
target/release/nym-network-requester
|
||||
target/release/nym-network-statistics
|
||||
target/release/nym-cli
|
||||
target/release/nymvisor
|
||||
target/release/nym-node
|
||||
retention-days: 30
|
||||
|
||||
# If this was a pull_request or nightly, upload to build server
|
||||
@@ -123,13 +121,11 @@ jobs:
|
||||
OUTPUT_DIR: ci-builds/${{ github.ref_name }}
|
||||
run: |
|
||||
cp target/release/nym-client $OUTPUT_DIR
|
||||
cp target/release/nym-gateway $OUTPUT_DIR
|
||||
cp target/release/nym-mixnode $OUTPUT_DIR
|
||||
cp target/release/nym-socks5-client $OUTPUT_DIR
|
||||
cp target/release/nym-api $OUTPUT_DIR
|
||||
cp target/release/nym-network-requester $OUTPUT_DIR
|
||||
cp target/release/nym-network-statistics $OUTPUT_DIR
|
||||
cp target/release/nymvisor $OUTPUT_DIR
|
||||
cp target/release/nym-node $OUTPUT_DIR
|
||||
cp target/release/nym-cli $OUTPUT_DIR
|
||||
cp target/release/explorer-api $OUTPUT_DIR
|
||||
if [ ${{ github.event_name == 'workflow_dispatch' && inputs.enable_deb == true }} = true ]; then
|
||||
|
||||
@@ -6,7 +6,6 @@ on:
|
||||
- 'clients/**'
|
||||
- 'common/**'
|
||||
- 'explorer-api/**'
|
||||
- 'ephemera/**'
|
||||
- 'gateway/**'
|
||||
- 'integrations/**'
|
||||
- 'mixnode/**'
|
||||
@@ -24,7 +23,6 @@ on:
|
||||
- 'clients/**'
|
||||
- 'common/**'
|
||||
- 'explorer-api/**'
|
||||
- 'ephemera/**'
|
||||
- 'gateway/**'
|
||||
- 'integrations/**'
|
||||
- 'mixnode/**'
|
||||
|
||||
@@ -35,7 +35,7 @@ jobs:
|
||||
- name: Install Rust stable
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
toolchain: 1.77
|
||||
target: wasm32-unknown-unknown
|
||||
override: true
|
||||
|
||||
@@ -58,9 +58,6 @@ jobs:
|
||||
cp contracts/target/wasm32-unknown-unknown/release/nym_coconut_dkg.wasm $OUTPUT_DIR
|
||||
cp contracts/target/wasm32-unknown-unknown/release/cw3_flex_multisig.wasm $OUTPUT_DIR
|
||||
cp contracts/target/wasm32-unknown-unknown/release/cw4_group.wasm $OUTPUT_DIR
|
||||
cp contracts/target/wasm32-unknown-unknown/release/nym_service_provider_directory.wasm $OUTPUT_DIR
|
||||
cp contracts/target/wasm32-unknown-unknown/release/nym_name_service.wasm $OUTPUT_DIR
|
||||
cp contracts/target/wasm32-unknown-unknown/release/nym_ephemera.wasm $OUTPUT_DIR
|
||||
|
||||
- name: Deploy branch to CI www
|
||||
continue-on-error: true
|
||||
|
||||
@@ -13,7 +13,11 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Install Dependencies (Linux)
|
||||
run: sudo apt-get update && sudo apt-get install -y build-essential curl wget libssl-dev libudev-dev squashfs-tools protobuf-compiler
|
||||
run: sudo apt-get update && sudo apt-get install -y build-essential curl wget libssl-dev libudev-dev squashfs-tools protobuf-compiler git python3 && sudo apt-get update --fix-missing
|
||||
- name: Install pip3
|
||||
run: sudo apt install -y python3-pip
|
||||
- name: Install Python3 modules
|
||||
run: sudo pip3 install pandas tabulate
|
||||
- name: Install rsync
|
||||
run: sudo apt-get install rsync
|
||||
- uses: rlespinasse/github-slug-action@v3.x
|
||||
@@ -34,9 +38,25 @@ jobs:
|
||||
- name: Remove existing Nym config directory (`~/.nym/`)
|
||||
run: cd documentation && ./remove_existing_config.sh
|
||||
continue-on-error: false
|
||||
- name: Build all projects in documentation/ & move to ~/dist/docs/
|
||||
|
||||
# This is the original flow
|
||||
# - name: Build all projects in documentation/ & move to ~/dist/docs/
|
||||
# run: cd documentation && ./build_all_to_dist.sh
|
||||
|
||||
# This is a workaround replacement which builds on the last working commit b332a6b55668f60988e36961f3f62a794ba82ddb and then on current branch
|
||||
- name: Save current branch to ~/current_branch
|
||||
run: git rev-parse --abbrev-ref HEAD > ~/current_branch
|
||||
- name: Git pull, reset & switch to b332a6b55668f60988e36961f3f62a794ba82ddb
|
||||
run: git pull && git reset --hard && git checkout b332a6b55668f60988e36961f3f62a794ba82ddb
|
||||
- name: Build all projects in documentation/ & move to ~/dist/docs/ from b332a6b55668f60988e36961f3f62a794ba82ddb
|
||||
run: cd documentation && ./build_all_to_dist.sh
|
||||
continue-on-error: false
|
||||
|
||||
- name: Switch to current branch
|
||||
run: git checkout $echo "$(cat ~/current_branch)"
|
||||
- name: Build all projects in documentation/ & move to ~/dist/docs/ on current branch
|
||||
run: cd documentation && ./build_all_to_dist.sh && rm ~/current_branch
|
||||
|
||||
# End of replacemet
|
||||
|
||||
- name: Deploy branch to CI www
|
||||
continue-on-error: true
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
name: ci-nym-connect-desktop-rust
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- "nym-connect/desktop/src-tauri/**"
|
||||
- "nym-connect/desktop/src-tauri/Cargo.toml"
|
||||
- "clients/client-core/**"
|
||||
- "clients/socks5/**"
|
||||
- "common/**"
|
||||
- "gateway/gateway-requests/**"
|
||||
- "contracts/vesting/**"
|
||||
- "nym-api/nym-api-requests/**"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: [self-hosted, custom-linux]
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
steps:
|
||||
- name: Install Dependencies (Linux)
|
||||
run: sudo apt-get update && sudo apt-get -y install libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev squashfs-tools libayatana-appindicator3-dev
|
||||
continue-on-error: true
|
||||
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Install rust toolchain
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: stable
|
||||
override: true
|
||||
components: rustfmt, clippy
|
||||
|
||||
- name: Check formatting
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: fmt
|
||||
args: --manifest-path nym-connect/desktop/Cargo.toml --all -- --check
|
||||
|
||||
- name: Build all binaries
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: build
|
||||
args: --manifest-path nym-connect/desktop/Cargo.toml --workspace
|
||||
|
||||
- name: Run all tests
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: test
|
||||
args: --manifest-path nym-connect/desktop/Cargo.toml --workspace
|
||||
|
||||
- uses: actions-rs/clippy-check@v1
|
||||
name: Clippy checks
|
||||
continue-on-error: true
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
args: --manifest-path nym-connect/desktop/Cargo.toml --workspace --all-features
|
||||
|
||||
- name: Run clippy
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: clippy
|
||||
args: --manifest-path nym-connect/desktop/Cargo.toml --workspace --all-features -- -D warnings
|
||||
@@ -1,72 +0,0 @@
|
||||
name: ci-nym-connect-desktop
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'nym-connect/desktop/**'
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: nym-connect/desktop
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: custom-linux
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install rsync
|
||||
run: sudo apt-get install rsync
|
||||
continue-on-error: true
|
||||
- uses: rlespinasse/github-slug-action@v3.x
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
- name: Install Yarn
|
||||
run: npm install -g yarn
|
||||
- name: Install Rust stable
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
- name: Install wasm-pack
|
||||
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
|
||||
- name: Install project dependencies
|
||||
run: cd ../.. && yarn --network-timeout 100000
|
||||
|
||||
- name: Install app dependencies
|
||||
run: yarn
|
||||
continue-on-error: true
|
||||
|
||||
- name: Set environment from the example
|
||||
run: cp .env.sample .env
|
||||
- run: yarn storybook:build
|
||||
- name: Deploy branch to CI www
|
||||
continue-on-error: true
|
||||
uses: easingthemes/ssh-deploy@main
|
||||
env:
|
||||
SSH_PRIVATE_KEY: ${{ secrets.CI_WWW_SSH_PRIVATE_KEY }}
|
||||
ARGS: "-rltgoDzvO --delete"
|
||||
SOURCE: "nym-connect/desktop/storybook-static/"
|
||||
REMOTE_HOST: ${{ secrets.CI_WWW_REMOTE_HOST }}
|
||||
REMOTE_USER: ${{ secrets.CI_WWW_REMOTE_USER }}
|
||||
TARGET: ${{ secrets.CI_WWW_REMOTE_TARGET }}/nym-connect-${{ env.GITHUB_REF_SLUG }}
|
||||
EXCLUDE: "/dist/, /node_modules/"
|
||||
- name: Matrix - Node Install
|
||||
run: npm install
|
||||
working-directory: .github/workflows/support-files
|
||||
- name: Matrix - Send Notification
|
||||
env:
|
||||
NYM_NOTIFICATION_KIND: nym-connect
|
||||
NYM_PROJECT_NAME: "nym-connect"
|
||||
NYM_CI_WWW_BASE: "${{ secrets.NYM_CI_WWW_BASE }}"
|
||||
NYM_CI_WWW_LOCATION: "nym-connect-${{ env.GITHUB_REF_SLUG }}"
|
||||
GIT_COMMIT_MESSAGE: "${{ github.event.head_commit.message }}"
|
||||
GIT_BRANCH: "${GITHUB_REF##*/}"
|
||||
IS_SUCCESS: "${{ job.status == 'success' }}"
|
||||
MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}"
|
||||
MATRIX_ROOM: "${{ secrets.MATRIX_ROOM }}"
|
||||
MATRIX_USER_ID: "${{ secrets.MATRIX_USER_ID }}"
|
||||
MATRIX_TOKEN: "${{ secrets.MATRIX_TOKEN }}"
|
||||
MATRIX_DEVICE_ID: "${{ secrets.MATRIX_DEVICE_ID }}"
|
||||
uses: docker://keybaseio/client:stable-node
|
||||
with:
|
||||
args: .github/workflows/support-files/notifications/entry_point.sh
|
||||
@@ -17,7 +17,7 @@ jobs:
|
||||
- uses: rlespinasse/github-slug-action@v3.x
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
node-version: 18.17
|
||||
- name: Install Rust stable
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
|
||||
@@ -6,11 +6,10 @@ on:
|
||||
- 'wasm/**'
|
||||
- 'clients/client-core/**'
|
||||
- 'common/**'
|
||||
- '.github/workflows/ci-sdk-wasm.yml'
|
||||
|
||||
jobs:
|
||||
wasm:
|
||||
runs-on: [ custom-linux ]
|
||||
runs-on: [custom-linux]
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
steps:
|
||||
@@ -44,9 +43,6 @@ jobs:
|
||||
- name: Install wasm-bindgen-cli
|
||||
run: cargo install wasm-bindgen-cli
|
||||
|
||||
- name: Install clang
|
||||
run: sudo apt update && sudo apt install -y clang
|
||||
|
||||
- name: "Build"
|
||||
run: make sdk-wasm-build
|
||||
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
name: nightly-nym-connect-desktop-build
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '14 1 * * *'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-20.04, macos-latest, windows-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
MANIFEST_PATH: --manifest-path nym-connect/desktop/Cargo.toml
|
||||
continue-on-error: true
|
||||
steps:
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Install Dependencies (Linux)
|
||||
run: sudo apt-get update && sudo apt-get install -y libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev squashfs-tools
|
||||
if: matrix.os == 'ubuntu-20.04'
|
||||
|
||||
- name: Install rust toolchain
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: stable
|
||||
override: true
|
||||
components: rustfmt, clippy
|
||||
|
||||
- name: Check formatting
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: fmt
|
||||
args: ${{ env.MANIFEST_PATH }} --all -- --check
|
||||
|
||||
- name: Build
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: build
|
||||
args: ${{ env.MANIFEST_PATH }} --release --workspace
|
||||
|
||||
- name: Unit tests
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: test
|
||||
args: ${{ env.MANIFEST_PATH }} --workspace
|
||||
|
||||
- name: Clippy
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: clippy
|
||||
args: ${{ env.MANIFEST_PATH }} --workspace --all-targets -- -D warnings
|
||||
|
||||
notification:
|
||||
needs: build
|
||||
runs-on: custom-linux
|
||||
steps:
|
||||
- name: Collect jobs status
|
||||
uses: technote-space/workflow-conclusion-action@v2
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v3
|
||||
- name: install npm
|
||||
uses: actions/setup-node@v3
|
||||
if: env.WORKFLOW_CONCLUSION == 'failure'
|
||||
with:
|
||||
node-version: 18
|
||||
- name: Matrix - Node Install
|
||||
if: env.WORKFLOW_CONCLUSION == 'failure'
|
||||
run: npm install
|
||||
working-directory: .github/workflows/support-files
|
||||
- name: Matrix - Send Notification
|
||||
if: env.WORKFLOW_CONCLUSION == 'failure'
|
||||
env:
|
||||
NYM_NOTIFICATION_KIND: nightly
|
||||
NYM_PROJECT_NAME: "nym-connect-desktop-nightly-build"
|
||||
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
|
||||
GIT_COMMIT_MESSAGE: "${{ github.event.head_commit.message }}"
|
||||
GIT_BRANCH: "${GITHUB_REF##*/}"
|
||||
IS_SUCCESS: "${{ env.WORKFLOW_CONCLUSION == 'success' }}"
|
||||
MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}"
|
||||
MATRIX_ROOM: "${{ secrets.MATRIX_ROOM_NIGHTLY }}"
|
||||
MATRIX_USER_ID: "${{ secrets.MATRIX_USER_ID }}"
|
||||
MATRIX_TOKEN: "${{ secrets.MATRIX_TOKEN }}"
|
||||
MATRIX_DEVICE_ID: "${{ secrets.MATRIX_DEVICE_ID }}"
|
||||
uses: docker://keybaseio/client:stable-node
|
||||
with:
|
||||
args: .github/workflows/support-files/notifications/entry_point.sh
|
||||
@@ -0,0 +1,27 @@
|
||||
name: pr-validation
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- develop
|
||||
- 'release/**'
|
||||
types:
|
||||
- labeled
|
||||
- unlabeled
|
||||
- opened
|
||||
- reopened
|
||||
- synchronize
|
||||
- edited
|
||||
- milestoned
|
||||
- demilestoned
|
||||
|
||||
env:
|
||||
LABELS: ${{ join( github.event.pull_request.labels.*.name, ' ' ) }}
|
||||
|
||||
jobs:
|
||||
check-milestone:
|
||||
name: Check Milestone
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- if: github.event.pull_request.milestone == null && contains( env.LABELS, 'no-milestone' ) == false
|
||||
run: exit 1
|
||||
@@ -27,21 +27,17 @@ jobs:
|
||||
release_id: ${{ steps.create-release.outputs.id }}
|
||||
release_date: ${{ fromJSON(steps.create-release.outputs.assets)[0].published_at }}
|
||||
client_hash: ${{ steps.binary-hashes.outputs.client_hash }}
|
||||
mixnode_hash: ${{ steps.binary-hashes.outputs.mixnode_hash }}
|
||||
gateway_hash: ${{ steps.binary-hashes.outputs.gateway_hash }}
|
||||
nymvisor_hash: ${{ steps.binary-hashes.outputs.nymvisor_hash }}
|
||||
nymnode_hash: ${{ steps.binary-hashes.outputs.nymnode_hash }}
|
||||
socks5_hash: ${{ steps.binary-hashes.outputs.socks5_hash }}
|
||||
netreq_hash: ${{ steps.binary-hashes.outputs.netreq_hash }}
|
||||
cli_hash: ${{ steps.binary-hashes.outputs.cli_hash }}
|
||||
netstat_hash: ${{ steps.binary-hashes.outputs.netstat_hash }}
|
||||
client_version: ${{ steps.binary-versions.outputs.client_version }}
|
||||
mixnode_version: ${{ steps.binary-versions.outputs.mixnode_version }}
|
||||
gateway_version: ${{ steps.binary-versions.outputs.gateway_version }}
|
||||
nymvisor_version: ${{ steps.binary-versions.outputs.nymvisor_version }}
|
||||
nymnode_version: ${{ steps.binary-versions.outputs.nymnode_version }}
|
||||
socks5_version: ${{ steps.binary-versions.outputs.socks5_version }}
|
||||
netreq_version: ${{ steps.binary-versions.outputs.netreq_version }}
|
||||
cli_version: ${{ steps.binary-versions.outputs.cli_version }}
|
||||
netstat_version: ${{ steps.binary-versions.outputs.netstat_version }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
@@ -73,14 +69,12 @@ jobs:
|
||||
path: |
|
||||
target/release/explorer-api
|
||||
target/release/nym-client
|
||||
target/release/nym-gateway
|
||||
target/release/nym-mixnode
|
||||
target/release/nym-socks5-client
|
||||
target/release/nym-api
|
||||
target/release/nym-network-requester
|
||||
target/release/nym-network-statistics
|
||||
target/release/nym-cli
|
||||
target/release/nymvisor
|
||||
target/release/nym-node
|
||||
retention-days: 30
|
||||
|
||||
- id: create-release
|
||||
@@ -91,14 +85,12 @@ jobs:
|
||||
files: |
|
||||
target/release/explorer-api
|
||||
target/release/nym-client
|
||||
target/release/nym-gateway
|
||||
target/release/nym-mixnode
|
||||
target/release/nym-socks5-client
|
||||
target/release/nym-api
|
||||
target/release/nym-network-requester
|
||||
target/release/nym-network-statistics
|
||||
target/release/nym-cli
|
||||
target/release/nymvisor
|
||||
target/release/nym-node
|
||||
|
||||
push-release-data-client:
|
||||
if: ${{ (startsWith(github.ref, 'refs/tags/nym-binaries-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
||||
|
||||
@@ -1,122 +0,0 @@
|
||||
name: publish-nym-connect-macos
|
||||
on:
|
||||
workflow_dispatch:
|
||||
release:
|
||||
types: [created]
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: nym-connect/desktop
|
||||
|
||||
jobs:
|
||||
publish-tauri:
|
||||
if: ${{ (startsWith(github.ref, 'refs/tags/nym-connect-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
platform: [macos-12-large]
|
||||
runs-on: ${{ matrix.platform }}
|
||||
|
||||
outputs:
|
||||
release_id: ${{ steps.create-release.outputs.id }}
|
||||
release_date: ${{ fromJSON(steps.create-release.outputs.assets)[0].created_at }}
|
||||
version: ${{ steps.release-info.outputs.version }}
|
||||
filename: ${{ steps.release-info.outputs.filename }}
|
||||
file_hash: ${{ steps.release-info.outputs.file_hash }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
|
||||
- name: Install Rust stable
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
target: wasm32-unknown-unknown
|
||||
|
||||
- name: Install wasm-pack
|
||||
run: |
|
||||
export WASM_PACK_VERSION="v0.12.1"
|
||||
curl -LO https://github.com/rustwasm/wasm-pack/releases/download/${WASM_PACK_VERSION}/wasm-pack-${WASM_PACK_VERSION}-x86_64-apple-darwin.tar.gz
|
||||
tar xvzf wasm-pack-${WASM_PACK_VERSION}-x86_64-apple-darwin.tar.gz -C $HOME/.cargo/bin --strip-components=1
|
||||
rm wasm-pack-${WASM_PACK_VERSION}-x86_64-apple-darwin.tar.gz
|
||||
|
||||
- name: Install the Apple developer certificate for code signing
|
||||
env:
|
||||
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
|
||||
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
|
||||
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
|
||||
run: |
|
||||
# create variables
|
||||
CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12
|
||||
KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db
|
||||
|
||||
# import certificate and provisioning profile from secrets
|
||||
echo -n "$APPLE_CERTIFICATE" | base64 --decode --output $CERTIFICATE_PATH
|
||||
|
||||
# create temporary keychain
|
||||
security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
|
||||
security set-keychain-settings -lut 21600 $KEYCHAIN_PATH
|
||||
security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
|
||||
|
||||
# import certificate to keychain
|
||||
security import $CERTIFICATE_PATH -P "$APPLE_CERTIFICATE_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
|
||||
security list-keychain -d user -s $KEYCHAIN_PATH
|
||||
|
||||
- name: Create env file
|
||||
uses: timheuer/base64-to-file@v1.2
|
||||
with:
|
||||
fileName: '.env'
|
||||
encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }}
|
||||
|
||||
- name: Install project dependencies
|
||||
shell: bash
|
||||
run: cd .. && yarn --network-timeout 100000
|
||||
|
||||
- name: Install app dependencies and build it
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
ENABLE_CODE_SIGNING: ${{ secrets.APPLE_CERTIFICATE }}
|
||||
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
|
||||
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
|
||||
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_IDENTITY_ID }}
|
||||
APPLE_ID: ${{ secrets.APPLE_ID }}
|
||||
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
|
||||
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
||||
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
||||
SENTRY_DSN_RUST: ${{ secrets.SENTRY_DSN_RUST }}
|
||||
SENTRY_DSN_JS: ${{ secrets.SENTRY_DSN_JS }}
|
||||
run: yarn && yarn build
|
||||
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: nym-connect_1.0.0_x64.dmg
|
||||
path: nym-connect/desktop/target/release/bundle/dmg/nym-connect_1*_x64.dmg
|
||||
retention-days: 30
|
||||
|
||||
- name: Clean up keychain
|
||||
if: ${{ always() }}
|
||||
run: |
|
||||
security delete-keychain $RUNNER_TEMP/app-signing.keychain-db
|
||||
|
||||
- id: create-release
|
||||
name: Upload to release based on tag name
|
||||
uses: softprops/action-gh-release@v1
|
||||
if: github.event_name == 'release'
|
||||
with:
|
||||
files: |
|
||||
nym-connect/desktop/target/release/bundle/dmg/*.dmg
|
||||
nym-connect/desktop/target/release/bundle/macos/*.app.tar.gz*
|
||||
|
||||
push-release-data:
|
||||
if: ${{ (startsWith(github.ref, 'refs/tags/nym-connect-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
||||
uses: ./.github/workflows/release-calculate-hash.yml
|
||||
needs: publish-tauri
|
||||
with:
|
||||
release_tag: ${{ github.ref_name }}
|
||||
secrets: inherit
|
||||
@@ -1,89 +0,0 @@
|
||||
name: publish-nym-connect-ubuntu
|
||||
on:
|
||||
workflow_dispatch:
|
||||
release:
|
||||
types: [created]
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: nym-connect/desktop
|
||||
|
||||
jobs:
|
||||
publish-tauri:
|
||||
if: ${{ (startsWith(github.ref, 'refs/tags/nym-connect-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
platform: [custom-ubuntu-20.04]
|
||||
runs-on: ${{ matrix.platform }}
|
||||
|
||||
outputs:
|
||||
release_id: ${{ steps.create-release.outputs.id }}
|
||||
release_date: ${{ fromJSON(steps.create-release.outputs.assets)[0].created_at }}
|
||||
version: ${{ steps.release-info.outputs.version }}
|
||||
filename: ${{ steps.release-info.outputs.filename }}
|
||||
file_hash: ${{ steps.release-info.outputs.file_hash }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Tauri dependencies
|
||||
run: >
|
||||
sudo apt-get update &&
|
||||
sudo apt-get install -y webkit2gtk-4.0 libayatana-appindicator3-dev
|
||||
continue-on-error: true
|
||||
|
||||
- name: Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
|
||||
- name: Install Rust stable
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
|
||||
- name: Install project dependencies
|
||||
shell: bash
|
||||
run: cd .. && yarn --network-timeout 100000
|
||||
|
||||
- name: Install app dependencies
|
||||
run: yarn
|
||||
|
||||
- name: Create env file
|
||||
uses: timheuer/base64-to-file@v1.2
|
||||
with:
|
||||
fileName: '.env'
|
||||
encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }}
|
||||
|
||||
- name: Build app
|
||||
run: yarn build
|
||||
env:
|
||||
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
||||
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
||||
SENTRY_DSN_RUST: ${{ secrets.SENTRY_DSN_RUST }}
|
||||
SENTRY_DSN_JS: ${{ secrets.SENTRY_DSN_JS }}
|
||||
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: nym-connect.AppImage.tar.gz
|
||||
path: nym-connect/desktop/target/release/bundle/appimage/nym-connect_1*_amd64.AppImage
|
||||
retention-days: 30
|
||||
|
||||
- id: create-release
|
||||
name: Upload to release based on tag name
|
||||
uses: softprops/action-gh-release@v1
|
||||
if: github.event_name == 'release'
|
||||
with:
|
||||
files: |
|
||||
nym-connect/desktop/target/release/bundle/appimage/*.AppImage
|
||||
nym-connect/desktop/target/release/bundle/appimage/*.AppImage.tar.gz*
|
||||
|
||||
push-release-data:
|
||||
if: ${{ (startsWith(github.ref, 'refs/tags/nym-connect-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
||||
uses: ./.github/workflows/release-calculate-hash.yml
|
||||
needs: publish-tauri
|
||||
with:
|
||||
release_tag: ${{ github.ref_name }}
|
||||
secrets: inherit
|
||||
@@ -1,108 +0,0 @@
|
||||
name: publish-nym-connect-win10
|
||||
on:
|
||||
workflow_dispatch:
|
||||
release:
|
||||
types: [created]
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: nym-connect/desktop
|
||||
|
||||
jobs:
|
||||
publish-tauri:
|
||||
if: ${{ (startsWith(github.ref, 'refs/tags/nym-connect-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
platform: [windows10]
|
||||
runs-on: ${{ matrix.platform }}
|
||||
|
||||
outputs:
|
||||
release_id: ${{ steps.create-release.outputs.id }}
|
||||
release_date: ${{ fromJSON(steps.create-release.outputs.assets)[0].created_at }}
|
||||
version: ${{ steps.release-info.outputs.version }}
|
||||
filename: ${{ steps.release-info.outputs.filename }}
|
||||
file_hash: ${{ steps.release-info.outputs.file_hash }}
|
||||
|
||||
steps:
|
||||
- name: Clean up first
|
||||
continue-on-error: true
|
||||
working-directory: .
|
||||
run: |
|
||||
cd ..
|
||||
del /s /q /A:H nym
|
||||
rmdir /s /q nym
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Import signing certificate
|
||||
env:
|
||||
WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }}
|
||||
WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
|
||||
run: |
|
||||
New-Item -ItemType directory -Path certificate
|
||||
Set-Content -Path certificate/tempCert.txt -Value $env:WINDOWS_CERTIFICATE
|
||||
certutil -decode certificate/tempCert.txt certificate/certificate.pfx
|
||||
Remove-Item -path certificate -include tempCert.txt
|
||||
Import-PfxCertificate -FilePath certificate/certificate.pfx -CertStoreLocation Cert:\CurrentUser\My -Password (ConvertTo-SecureString -String $env:WINDOWS_CERTIFICATE_PASSWORD -Force -AsPlainText)
|
||||
|
||||
- name: Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
|
||||
- name: Install Rust stable
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
|
||||
- name: Create env file
|
||||
uses: timheuer/base64-to-file@v1.2
|
||||
with:
|
||||
fileName: '.env'
|
||||
encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }}
|
||||
|
||||
- name: Install project dependencies
|
||||
shell: bash
|
||||
run: cd .. && yarn --network-timeout 100000
|
||||
|
||||
- name: Install app dependencies
|
||||
shell: bash
|
||||
run: yarn --network-timeout 100000
|
||||
|
||||
- name: Build and sign it
|
||||
shell: bash
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
ENABLE_CODE_SIGNING: ${{ secrets.WINDOWS_CERTIFICATE }}
|
||||
WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }}
|
||||
WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
|
||||
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
||||
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
||||
SENTRY_DSN_RUST: ${{ secrets.SENTRY_DSN_RUST }}
|
||||
SENTRY_DSN_JS: ${{ secrets.SENTRY_DSN_JS }}
|
||||
run: yarn build
|
||||
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: nym-connect_1.0.0_x64_en-US.msi
|
||||
path: nym-connect/desktop/target/release/bundle/msi/nym-connect_1*_x64_en-US.msi
|
||||
retention-days: 30
|
||||
|
||||
- id: create-release
|
||||
name: Upload to release based on tag name
|
||||
uses: softprops/action-gh-release@v1
|
||||
if: github.event_name == 'release'
|
||||
with:
|
||||
files: |
|
||||
nym-connect/desktop/target/release/bundle/msi/*.msi
|
||||
nym-connect/desktop/target/release/bundle/msi/*.msi.zip*
|
||||
|
||||
push-release-data:
|
||||
if: ${{ (startsWith(github.ref, 'refs/tags/nym-connect-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
||||
uses: ./.github/workflows/release-calculate-hash.yml
|
||||
needs: publish-tauri
|
||||
with:
|
||||
release_tag: ${{ github.ref_name }}
|
||||
secrets: inherit
|
||||
@@ -102,6 +102,18 @@ jobs:
|
||||
nym-wallet/target/release/bundle/dmg/*.dmg
|
||||
nym-wallet/target/release/bundle/macos/*.app.tar.gz*
|
||||
|
||||
- name: Deploy artifacts to CI www
|
||||
continue-on-error: true
|
||||
uses: easingthemes/ssh-deploy@main
|
||||
env:
|
||||
SSH_PRIVATE_KEY: ${{ secrets.CI_WWW_SSH_PRIVATE_KEY }}
|
||||
ARGS: "-avzr"
|
||||
SOURCE: "nym-wallet/target/release/bundle/macos/nym-wallet.app.tar.gz"
|
||||
REMOTE_HOST: ${{ secrets.CI_WWW_REMOTE_HOST }}
|
||||
REMOTE_USER: ${{ secrets.CI_WWW_REMOTE_USER }}
|
||||
TARGET: ${{ secrets.CI_WWW_REMOTE_TARGET }}/builds/${{ github.ref_name }}/nym-wallet
|
||||
EXCLUDE: "/dist/, /node_modules/"
|
||||
|
||||
push-release-data:
|
||||
if: ${{ (startsWith(github.ref, 'refs/tags/nym-wallet-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
||||
uses: ./.github/workflows/release-calculate-hash.yml
|
||||
|
||||
@@ -77,6 +77,18 @@ jobs:
|
||||
nym-wallet/target/release/bundle/appimage/*.AppImage
|
||||
nym-wallet/target/release/bundle/appimage/*.AppImage.tar.gz*
|
||||
|
||||
- name: Deploy artifacts to CI www
|
||||
continue-on-error: true
|
||||
uses: easingthemes/ssh-deploy@main
|
||||
env:
|
||||
SSH_PRIVATE_KEY: ${{ secrets.CI_WWW_SSH_PRIVATE_KEY }}
|
||||
ARGS: "-avzr"
|
||||
SOURCE: "nym-wallet/target/release/bundle/appimage/nym-wallet*.AppImage.tar.gz"
|
||||
REMOTE_HOST: ${{ secrets.CI_WWW_REMOTE_HOST }}
|
||||
REMOTE_USER: ${{ secrets.CI_WWW_REMOTE_USER }}
|
||||
TARGET: ${{ secrets.CI_WWW_REMOTE_TARGET }}/builds/${{ github.ref_name }}/nym-wallet
|
||||
EXCLUDE: "/dist/, /node_modules/"
|
||||
|
||||
push-release-data:
|
||||
if: ${{ (startsWith(github.ref, 'refs/tags/nym-wallet-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
||||
uses: ./.github/workflows/release-calculate-hash.yml
|
||||
|
||||
@@ -97,6 +97,18 @@ jobs:
|
||||
nym-wallet/target/release/bundle/msi/*.msi
|
||||
nym-wallet/target/release/bundle/msi/*.msi.zip*
|
||||
|
||||
- name: Deploy artifacts to CI www
|
||||
continue-on-error: true
|
||||
uses: easingthemes/ssh-deploy@main
|
||||
env:
|
||||
SSH_PRIVATE_KEY: ${{ secrets.CI_WWW_SSH_PRIVATE_KEY }}
|
||||
ARGS: "-avzr"
|
||||
SOURCE: "nym-wallet/target/release/bundle/msi/nym-wallet_1.*.msi"
|
||||
REMOTE_HOST: ${{ secrets.CI_WWW_REMOTE_HOST }}
|
||||
REMOTE_USER: ${{ secrets.CI_WWW_REMOTE_USER }}
|
||||
TARGET: ${{ secrets.CI_WWW_REMOTE_TARGET }}/builds/${{ github.ref_name }}/nym-wallet
|
||||
EXCLUDE: "/dist/, /node_modules/"
|
||||
|
||||
push-release-data:
|
||||
if: ${{ (startsWith(github.ref, 'refs/tags/nym-wallet-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }}
|
||||
uses: ./.github/workflows/release-calculate-hash.yml
|
||||
|
||||
@@ -8,8 +8,8 @@ on:
|
||||
required: true
|
||||
type: string
|
||||
workflow_dispatch:
|
||||
release_tag:
|
||||
tag:
|
||||
inputs:
|
||||
release_tag:
|
||||
description: 'Release tag'
|
||||
required: true
|
||||
type: string
|
||||
@@ -24,10 +24,7 @@ jobs:
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
- name: Install packages
|
||||
run: cd ./.github/actions/nym-hash-releases && npm i
|
||||
|
||||
- uses: ./.github/actions/nym-hash-releases
|
||||
- uses: nymtech/nym/.github/actions/nym-hash-releases@develop
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
const Handlebars = require('handlebars');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
async function addToContextAndValidate(context) {
|
||||
if (!context.env.NYM_CI_WWW_LOCATION) {
|
||||
throw new Error('Please ensure the env var NYM_CI_WWW_LOCATION is set');
|
||||
}
|
||||
if (!context.env.NYM_CI_WWW_BASE) {
|
||||
throw new Error('Please ensure the env var NYM_CI_WWW_BASE is set');
|
||||
}
|
||||
}
|
||||
|
||||
async function getMessageBody(context) {
|
||||
const source = fs
|
||||
.readFileSync(
|
||||
context.env.IS_SUCCESS === 'true'
|
||||
? path.resolve(__dirname, 'templates', 'success')
|
||||
: path.resolve(__dirname, 'templates', 'failure'),
|
||||
)
|
||||
.toString();
|
||||
const template = Handlebars.compile(source);
|
||||
return template(context);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
addToContextAndValidate,
|
||||
getMessageBody,
|
||||
};
|
||||
@@ -1,16 +0,0 @@
|
||||
🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥
|
||||
> :rocket: {{ env.NYM_PROJECT_NAME }}
|
||||
>
|
||||
> 🔴 **FAILURE** :cry:
|
||||
>
|
||||
> `branch` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/tree/{{ env.GIT_BRANCH_NAME }}
|
||||
>
|
||||
> `commit` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/commit/{{ env.GITHUB_SHA }}
|
||||
>
|
||||
> `build ` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/actions/runs/{{ env.GITHUB_RUN_ID }}
|
||||
>
|
||||
|
||||
Commit message:
|
||||
```
|
||||
{{ env.GIT_COMMIT_MESSAGE }}
|
||||
```
|
||||
@@ -1,16 +0,0 @@
|
||||
🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩
|
||||
> :rocket: {{ env.NYM_PROJECT_NAME }} ➡️➡️➡️➡️➡️ **View storybook:** https://{{ env.NYM_CI_WWW_LOCATION }}.{{ env.NYM_CI_WWW_BASE }}/
|
||||
>
|
||||
> ✅ **SUCCESS**
|
||||
>
|
||||
> `branch` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/tree/{{ env.GIT_BRANCH_NAME }}
|
||||
>
|
||||
> `commit` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/commit/{{ env.GITHUB_SHA }}
|
||||
>
|
||||
> `build ` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/actions/runs/{{ env.GITHUB_RUN_ID }}
|
||||
>
|
||||
|
||||
Commit message by `{{ env.GITHUB_ACTOR }}` at {{ timestamp }}:
|
||||
```
|
||||
{{ env.GIT_COMMIT_MESSAGE }}
|
||||
```
|
||||
+135
@@ -4,6 +4,141 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [2024.7-doubledecker] (2024-07-04)
|
||||
|
||||
- Add an early return in `parse_raw_str_logs` for empty raw log strings. ([#4686])
|
||||
- Bump braces from 3.0.2 to 3.0.3 in /wasm/mix-fetch/internal-dev ([#4672])
|
||||
- add expiry returned on import ([#4670])
|
||||
- [bugfix] missing rustls feature ([#4666])
|
||||
- Bump ws from 8.13.0 to 8.17.1 in /wasm/client/internal-dev-node ([#4665])
|
||||
- Bump braces from 3.0.2 to 3.0.3 in /clients/native/examples/js-examples/websocket ([#4663])
|
||||
- Bump ws from 8.14.2 to 8.17.1 in /sdk/typescript/packages/nodejs-client ([#4662])
|
||||
- Update setup.md ([#4661])
|
||||
- New clippy lints ([#4660])
|
||||
- Bump braces from 3.0.2 to 3.0.3 in /nym-api/tests ([#4659])
|
||||
- Bump braces from 3.0.2 to 3.0.3 in /docker/typescript_client/upload_contract ([#4658])
|
||||
- Update vps-setup.md ([#4656])
|
||||
- Update configuration.md ([#4655])
|
||||
- Remove old PR template ([#4639])
|
||||
|
||||
[#4686]: https://github.com/nymtech/nym/pull/4686
|
||||
[#4672]: https://github.com/nymtech/nym/pull/4672
|
||||
[#4670]: https://github.com/nymtech/nym/pull/4670
|
||||
[#4666]: https://github.com/nymtech/nym/pull/4666
|
||||
[#4665]: https://github.com/nymtech/nym/pull/4665
|
||||
[#4663]: https://github.com/nymtech/nym/pull/4663
|
||||
[#4662]: https://github.com/nymtech/nym/pull/4662
|
||||
[#4661]: https://github.com/nymtech/nym/pull/4661
|
||||
[#4660]: https://github.com/nymtech/nym/pull/4660
|
||||
[#4659]: https://github.com/nymtech/nym/pull/4659
|
||||
[#4658]: https://github.com/nymtech/nym/pull/4658
|
||||
[#4656]: https://github.com/nymtech/nym/pull/4656
|
||||
[#4655]: https://github.com/nymtech/nym/pull/4655
|
||||
[#4639]: https://github.com/nymtech/nym/pull/4639
|
||||
|
||||
## [2024.6-chomp] (2024-06-25)
|
||||
|
||||
- Remove additional code as part of Ephemera Purge and SP and contracts ([#4650])
|
||||
- bugfix: make sure nym-api can handle non-cw2 (or without detailed build info) compliant contracts ([#4648])
|
||||
- introduced a flag to accept toc and exposed it via self-described API ([#4647])
|
||||
- bugfix: make sure to return an error on invalid public ip ([#4646])
|
||||
- Add ci check for PR having an assigned milestone ([#4644])
|
||||
- Removed ephemera code ([#4642])
|
||||
- Remove stale peers ([#4640])
|
||||
- Add generic wg private network routing ([#4636])
|
||||
- Feature/new node endpoints ([#4635])
|
||||
- standarised ContractBuildInformation and added it to all contracts ([#4631])
|
||||
- validate nym-node public ips on startup ([#4630])
|
||||
- Bump defguard wg ([#4625])
|
||||
- Fix cargo warnings ([#4624])
|
||||
- Update kernel peers on peer modification ([#4622])
|
||||
- Handle v6 and v7 requests in the IPR, but reply with v6 ([#4620])
|
||||
- fix typo ([#4619])
|
||||
- Update crypto and rand crates ([#4607])
|
||||
- Purge name service and service provider directory contracts ([#4603])
|
||||
|
||||
[#4650]: https://github.com/nymtech/nym/pull/4650
|
||||
[#4648]: https://github.com/nymtech/nym/pull/4648
|
||||
[#4647]: https://github.com/nymtech/nym/pull/4647
|
||||
[#4646]: https://github.com/nymtech/nym/pull/4646
|
||||
[#4644]: https://github.com/nymtech/nym/pull/4644
|
||||
[#4642]: https://github.com/nymtech/nym/pull/4642
|
||||
[#4640]: https://github.com/nymtech/nym/pull/4640
|
||||
[#4636]: https://github.com/nymtech/nym/pull/4636
|
||||
[#4635]: https://github.com/nymtech/nym/pull/4635
|
||||
[#4631]: https://github.com/nymtech/nym/pull/4631
|
||||
[#4630]: https://github.com/nymtech/nym/pull/4630
|
||||
[#4625]: https://github.com/nymtech/nym/pull/4625
|
||||
[#4624]: https://github.com/nymtech/nym/pull/4624
|
||||
[#4622]: https://github.com/nymtech/nym/pull/4622
|
||||
[#4620]: https://github.com/nymtech/nym/pull/4620
|
||||
[#4619]: https://github.com/nymtech/nym/pull/4619
|
||||
[#4607]: https://github.com/nymtech/nym/pull/4607
|
||||
[#4603]: https://github.com/nymtech/nym/pull/4603
|
||||
|
||||
## [2024.5-ragusa] (2024-05-22)
|
||||
|
||||
- Feature/nym node api location ([#4605])
|
||||
- Add optional signature to IPR request/response ([#4604])
|
||||
- Feature/unstable tested nodes endpoint ([#4601])
|
||||
- nym-api: make report/avg_uptime endpoints ignore blacklist ([#4599])
|
||||
- removed blocking for coconut in the final epoch state ([#4598])
|
||||
- allow using explicit admin address for issuing freepasses ([#4595])
|
||||
- Use rfc3339 for last_polled in described nym-api endpoint ([#4591])
|
||||
- Explicitly handle constraint unique violation when importing credential ([#4588])
|
||||
- [bugfix] noop flag for nym-api for nymvisor compatibility ([#4586])
|
||||
- Chore/additional helpers ([#4585])
|
||||
- Feature/wasm coconut ([#4584])
|
||||
- upgraded axum and related deps to the most recent version ([#4573])
|
||||
- Feature/nyxd scraper pruning ([#4564])
|
||||
- Run cargo autoinherit on the main workspace ([#4553])
|
||||
- Add rustls-tls to reqwest in validator-client ([#4552])
|
||||
- Feature/rewarder voucher issuance ([#4548])
|
||||
- make sure 'OffsetDateTimeJsonSchemaWrapper' is serialised with legacy format ([#4613])
|
||||
|
||||
|
||||
[#4613]: https://github.com/nymtech/nym/pull/4613
|
||||
[#4605]: https://github.com/nymtech/nym/pull/4605
|
||||
[#4604]: https://github.com/nymtech/nym/pull/4604
|
||||
[#4601]: https://github.com/nymtech/nym/pull/4601
|
||||
[#4599]: https://github.com/nymtech/nym/pull/4599
|
||||
[#4598]: https://github.com/nymtech/nym/pull/4598
|
||||
[#4595]: https://github.com/nymtech/nym/pull/4595
|
||||
[#4591]: https://github.com/nymtech/nym/pull/4591
|
||||
[#4588]: https://github.com/nymtech/nym/pull/4588
|
||||
[#4586]: https://github.com/nymtech/nym/pull/4586
|
||||
[#4585]: https://github.com/nymtech/nym/pull/4585
|
||||
[#4584]: https://github.com/nymtech/nym/pull/4584
|
||||
[#4573]: https://github.com/nymtech/nym/pull/4573
|
||||
[#4564]: https://github.com/nymtech/nym/pull/4564
|
||||
[#4553]: https://github.com/nymtech/nym/pull/4553
|
||||
[#4552]: https://github.com/nymtech/nym/pull/4552
|
||||
[#4548]: https://github.com/nymtech/nym/pull/4548
|
||||
|
||||
## [2024.4-nutella] (2024-05-08)
|
||||
|
||||
- [fix] apply disable_poisson_rate from internal NR/IPR cfgs ([#4579])
|
||||
- updating sign commands to include nym-node ([#4578])
|
||||
- changed nym-node redirects from 308 'Permanent Redirect' to 303: 'See Other' ([#4572])
|
||||
|
||||
[#4579]: https://github.com/nymtech/nym/pull/4579
|
||||
[#4578]: https://github.com/nymtech/nym/pull/4578
|
||||
[#4572]: https://github.com/nymtech/nym/pull/4572
|
||||
|
||||
## [2024.3-eclipse] (2024-04-22)
|
||||
|
||||
- Initial release of the first iteration of the Nym Node
|
||||
- Improvements to gateway functionality
|
||||
- IPR development
|
||||
- Removal of allow list in favour of implementing an exit policy
|
||||
- Explorer delegation: enables direct delegation to nodes via the Nym Explorer
|
||||
|
||||
|
||||
## [2024.2-fast-and-furious] (2024-03-25)
|
||||
|
||||
- Internal testing pre-release
|
||||
|
||||
|
||||
## [2024.1-marabou] (2024-02-15)
|
||||
|
||||
**New Features:**
|
||||
|
||||
Generated
+1939
-3412
File diff suppressed because it is too large
Load Diff
+173
-44
@@ -20,10 +20,14 @@ members = [
|
||||
"clients/native",
|
||||
"clients/native/websocket-requests",
|
||||
"clients/socks5",
|
||||
"common/authenticator-requests",
|
||||
"common/async-file-watcher",
|
||||
"common/bandwidth-controller",
|
||||
"common/bin-common",
|
||||
"common/client-core",
|
||||
"common/client-core/config-types",
|
||||
"common/client-core/surb-storage",
|
||||
"common/client-core/gateways-storage",
|
||||
"common/client-libs/gateway-client",
|
||||
"common/client-libs/mixnet-client",
|
||||
"common/client-libs/validator-client",
|
||||
@@ -32,13 +36,11 @@ members = [
|
||||
"common/cosmwasm-smart-contracts/coconut-bandwidth-contract",
|
||||
"common/cosmwasm-smart-contracts/coconut-dkg",
|
||||
"common/cosmwasm-smart-contracts/contracts-common",
|
||||
# "common/cosmwasm-smart-contracts/ephemera",
|
||||
"common/cosmwasm-smart-contracts/group-contract",
|
||||
"common/cosmwasm-smart-contracts/mixnet-contract",
|
||||
"common/cosmwasm-smart-contracts/multisig-contract",
|
||||
"common/cosmwasm-smart-contracts/name-service",
|
||||
"common/cosmwasm-smart-contracts/service-provider-directory",
|
||||
"common/cosmwasm-smart-contracts/vesting-contract",
|
||||
"common/country-group",
|
||||
"common/credential-storage",
|
||||
"common/credentials",
|
||||
"common/credential-utils",
|
||||
@@ -48,6 +50,7 @@ members = [
|
||||
"common/execute",
|
||||
"common/exit-policy",
|
||||
"common/http-api-client",
|
||||
"common/http-api-common",
|
||||
"common/inclusion-probability",
|
||||
"common/ip-packet-requests",
|
||||
"common/ledger",
|
||||
@@ -56,6 +59,8 @@ members = [
|
||||
"common/node-tester-utils",
|
||||
"common/nonexhaustive-delayqueue",
|
||||
"common/nymcoconut",
|
||||
"common/nym-id",
|
||||
"common/nym-metrics",
|
||||
"common/nymsphinx",
|
||||
"common/nymsphinx/acknowledgements",
|
||||
"common/nymsphinx/addressing",
|
||||
@@ -72,7 +77,6 @@ members = [
|
||||
"common/socks5-client-core",
|
||||
"common/socks5/proxy-helpers",
|
||||
"common/socks5/requests",
|
||||
"common/statistics",
|
||||
"common/store-cipher",
|
||||
"common/task",
|
||||
"common/topology",
|
||||
@@ -92,27 +96,30 @@ members = [
|
||||
"mixnode",
|
||||
"sdk/lib/socks5-listener",
|
||||
"sdk/rust/nym-sdk",
|
||||
"service-providers/authenticator",
|
||||
"service-providers/common",
|
||||
"service-providers/ip-packet-router",
|
||||
"service-providers/network-requester",
|
||||
"service-providers/network-statistics",
|
||||
"nym-api",
|
||||
"nym-browser-extension/storage",
|
||||
"nym-api/nym-api-requests",
|
||||
"nym-node",
|
||||
"nym-node/nym-node-http-api",
|
||||
"nym-node/nym-node-requests",
|
||||
"nym-outfox",
|
||||
"nym-validator-rewarder",
|
||||
"tools/internal/ssl-inject",
|
||||
# "tools/internal/sdk-version-bump",
|
||||
"tools/nym-cli",
|
||||
"tools/nym-id-cli",
|
||||
"tools/nym-nr-query",
|
||||
"tools/nymvisor",
|
||||
"tools/ts-rs-cli",
|
||||
"wasm/client",
|
||||
# "wasm/full-nym-wasm",
|
||||
# "wasm/full-nym-wasm", # If we uncomment this again, remember to also uncomment the profile settings below
|
||||
"wasm/mix-fetch",
|
||||
"wasm/node-tester",
|
||||
"wasm/zknym-lib",
|
||||
]
|
||||
|
||||
default-members = [
|
||||
@@ -120,15 +127,21 @@ default-members = [
|
||||
"clients/socks5",
|
||||
"gateway",
|
||||
"service-providers/network-requester",
|
||||
"service-providers/network-statistics",
|
||||
"mixnode",
|
||||
"nym-api",
|
||||
"tools/nymvisor",
|
||||
"explorer-api",
|
||||
"nym-validator-rewarder",
|
||||
"nym-node"
|
||||
]
|
||||
|
||||
exclude = ["explorer", "contracts", "nym-wallet", "nym-connect/mobile/src-tauri", "nym-connect/desktop", "nym-vpn/ui/src-tauri", "cpu-cycles", "sdk/ffi/cpp"]
|
||||
exclude = [
|
||||
"explorer",
|
||||
"contracts",
|
||||
"nym-wallet",
|
||||
"cpu-cycles",
|
||||
"sdk/ffi/cpp",
|
||||
]
|
||||
|
||||
[workspace.package]
|
||||
authors = ["Nym Technologies SA"]
|
||||
@@ -139,88 +152,201 @@ edition = "2021"
|
||||
license = "Apache-2.0"
|
||||
|
||||
[workspace.dependencies]
|
||||
addr = "0.15.6"
|
||||
aes = "0.8.1"
|
||||
aes-gcm = "0.10.1"
|
||||
anyhow = "1.0.71"
|
||||
argon2 = "0.5.0"
|
||||
async-trait = "0.1.68"
|
||||
axum = "0.6.20"
|
||||
axum = "0.7.5"
|
||||
axum-extra = "0.9.3"
|
||||
base64 = "0.21.4"
|
||||
bs58 = "0.5.0"
|
||||
bincode = "1.3.3"
|
||||
bip39 = { version = "2.0.0", features = ["zeroize"] }
|
||||
clap = "4.4.7"
|
||||
bitvec = "1.0.0"
|
||||
blake3 = "1.3.1"
|
||||
bs58 = "0.5.1"
|
||||
bytecodec = "0.4.15"
|
||||
bytes = "1.5.0"
|
||||
cargo_metadata = "0.18.1"
|
||||
celes = "2.4.0"
|
||||
cfg-if = "1.0.0"
|
||||
chacha20 = "0.9.0"
|
||||
chacha20poly1305 = "0.10.1"
|
||||
chrono = "0.4.31"
|
||||
cipher = "0.4.3"
|
||||
clap = "4.4.7"
|
||||
clap_complete = "4.0"
|
||||
clap_complete_fig = "4.0"
|
||||
colored = "2.0"
|
||||
comfy-table = "6.0.0"
|
||||
console-subscriber = "0.1.1"
|
||||
console_error_panic_hook = "0.1"
|
||||
const-str = "0.5.6"
|
||||
const_format = "0.2.32"
|
||||
criterion = "0.4"
|
||||
csv = "1.3.0"
|
||||
ctr = "0.9.1"
|
||||
cupid = "0.6.1"
|
||||
curve25519-dalek = "4.1"
|
||||
dashmap = "5.5.3"
|
||||
defguard_wireguard_rs = "0.4.2"
|
||||
digest = "0.10.7"
|
||||
dirs = "4.0"
|
||||
doc-comment = "0.3"
|
||||
dotenvy = "0.15.6"
|
||||
ecdsa = "0.16"
|
||||
ed25519-dalek = "2.1"
|
||||
etherparse = "0.13.0"
|
||||
eyre = "0.6.9"
|
||||
fastrand = "2.1.0"
|
||||
flate2 = "1.0.28"
|
||||
futures = "0.3.28"
|
||||
generic-array = "0.14.7"
|
||||
getrandom = "0.2.10"
|
||||
hyper = "0.14.27"
|
||||
getset = "0.1.1"
|
||||
handlebars = "3.5.5"
|
||||
headers = "0.4.0"
|
||||
hex = "0.4.3"
|
||||
hex-literal = "0.3.3"
|
||||
hkdf = "0.12.3"
|
||||
hmac = "0.12.1"
|
||||
http = "1"
|
||||
httpcodec = "0.2.3"
|
||||
humantime = "2.1.0"
|
||||
humantime-serde = "1.1.1"
|
||||
hyper = "1.3.1"
|
||||
indexed_db_futures = "0.3.0"
|
||||
inquire = "0.6.2"
|
||||
ip_network = "0.4.1"
|
||||
ipnetwork = "0.16"
|
||||
isocountry = "0.3.2"
|
||||
k256 = "0.13"
|
||||
lazy_static = "1.4.0"
|
||||
ledger-transport = "0.10.0"
|
||||
ledger-transport-hid = "0.10.0"
|
||||
log = "0.4"
|
||||
maxminddb = "0.23.0"
|
||||
mime = "0.3.17"
|
||||
nix = "0.27.1"
|
||||
notify = "5.1.0"
|
||||
okapi = "0.7.0"
|
||||
once_cell = "1.7.2"
|
||||
opentelemetry = "0.19.0"
|
||||
opentelemetry-jaeger = "0.18.0"
|
||||
parking_lot = "0.12.1"
|
||||
pem = "0.8"
|
||||
pin-project = "1.0"
|
||||
pretty_env_logger = "0.4.0"
|
||||
publicsuffix = "2.2.3"
|
||||
quote = "1"
|
||||
rand = "0.8.5"
|
||||
reqwest = { version = "0.11.22", default_features = false, features = ["rustls-tls"] }
|
||||
rand-07 = "0.7.3"
|
||||
rand_chacha = "0.3"
|
||||
rand_chacha_02 = "0.2"
|
||||
rand_core = "0.6.3"
|
||||
rand_distr = "0.4"
|
||||
rand_pcg = "0.3.1"
|
||||
rand_seeder = "0.2.3"
|
||||
rayon = "1.5.1"
|
||||
regex = "1.8.4"
|
||||
reqwest = { version = "0.12.4", default-features = false }
|
||||
rocket = "0.5.0"
|
||||
rocket_cors = "0.6.0"
|
||||
rocket_okapi = "0.8.0"
|
||||
safer-ffi = "0.1.4"
|
||||
schemars = "0.8.1"
|
||||
semver = "1.0.23"
|
||||
serde = "1.0.152"
|
||||
serde_bytes = "0.11.6"
|
||||
serde_derive = "1.0"
|
||||
serde_json = "1.0.91"
|
||||
serde_repr = "0.1"
|
||||
serde_with = "3.4.0"
|
||||
serde_yaml = "0.9.25"
|
||||
sha2 = "0.10.8"
|
||||
si-scale = "0.2.2"
|
||||
sphinx-packet = "0.1.1"
|
||||
sqlx = "0.6.3"
|
||||
strum = "0.25"
|
||||
subtle-encoding = "0.5"
|
||||
syn = "1"
|
||||
sysinfo = "0.30.12"
|
||||
tap = "1.0.1"
|
||||
time = "0.3.30"
|
||||
tar = "0.4.40"
|
||||
tempfile = "3.5.0"
|
||||
thiserror = "1.0.48"
|
||||
time = "0.3.30"
|
||||
tokio = "1.33.0"
|
||||
tokio-stream = "0.1.14"
|
||||
tokio-test = "0.4.2"
|
||||
tokio-tungstenite = { version = "0.20.1" }
|
||||
tokio-util = "0.7.10"
|
||||
tokio-tungstenite = { version = "0.20.1", features = ["rustls"] }
|
||||
toml = "0.8.14"
|
||||
tower = "0.4.13"
|
||||
tower-http = "0.5.2"
|
||||
tracing = "0.1.37"
|
||||
tungstenite = { version = "0.20.1", default-features = false, features = ["rustls"] }
|
||||
tracing-opentelemetry = "0.19.0"
|
||||
tracing-subscriber = "0.3.16"
|
||||
tracing-tree = "0.2.2"
|
||||
ts-rs = "7.0.0"
|
||||
utoipa = "3.5.0"
|
||||
utoipa-swagger-ui = "3.1.5"
|
||||
tungstenite = { version = "0.20.1", default-features = false }
|
||||
url = "2.4"
|
||||
utoipa = "4.2.0"
|
||||
utoipa-swagger-ui = "6.0.0"
|
||||
vergen = { version = "=8.3.1", default-features = false }
|
||||
walkdir = "2"
|
||||
wasm-bindgen-test = "0.3.36"
|
||||
x25519-dalek = "2.0.0"
|
||||
zeroize = "1.6.0"
|
||||
|
||||
prometheus = { version = "0.13.0" }
|
||||
|
||||
# coconut/DKG related
|
||||
# unfortunately until https://github.com/zkcrypto/bls12_381/issues/10 is resolved, we have to rely on the fork
|
||||
# as we need to be able to serialize Gt so that we could create the lookup table for baby-step-giant-step algorithm
|
||||
bls12_381 = { git = "https://github.com/jstuczyn/bls12_381", branch ="feature/gt-serialization-0.8.0" }
|
||||
group = "0.13.0"
|
||||
ff = "0.13.0"
|
||||
|
||||
bls12_381 = { git = "https://github.com/jstuczyn/bls12_381", default-features = false, branch = "feature/gt-serialization-0.8.0" }
|
||||
group = { version = "0.13.0", default-features = false }
|
||||
ff = { version = "0.13.0", default-features = false }
|
||||
|
||||
# cosmwasm-related
|
||||
cosmwasm-derive = "=1.3.0"
|
||||
cosmwasm-schema = "=1.3.0"
|
||||
cosmwasm-std = "=1.3.0"
|
||||
# use 0.5.0 as that's the version used by cosmwasm-std 1.3.0
|
||||
cosmwasm-derive = "=1.4.3"
|
||||
cosmwasm-schema = "=1.4.3"
|
||||
cosmwasm-std = "=1.4.3"
|
||||
# use 0.5.0 as that's the version used by cosmwasm-std 1.4.3
|
||||
# (and ideally we don't want to pull the same dependency twice)
|
||||
serde-json-wasm = "=0.5.0"
|
||||
cosmwasm-storage = "=1.3.0"
|
||||
cosmwasm-storage = "=1.4.3"
|
||||
# same version as used by cosmwasm
|
||||
cw-utils = "=1.0.1"
|
||||
cw-storage-plus = "=1.1.0"
|
||||
cw2 = { version = "=1.1.0" }
|
||||
cw3 = { version = "=1.1.0" }
|
||||
cw4 = { version = "=1.1.0" }
|
||||
cw-storage-plus = "=1.2.0"
|
||||
cw2 = { version = "=1.1.2" }
|
||||
cw3 = { version = "=1.1.2" }
|
||||
cw4 = { version = "=1.1.2" }
|
||||
cw-controllers = { version = "=1.1.0" }
|
||||
|
||||
# cosmrs-related
|
||||
bip32 = "0.5.1"
|
||||
bip32 = { version = "0.5.1", default-features = false }
|
||||
|
||||
# temporarily using a fork again (yay.) because we need staking and slashing support
|
||||
cosmrs = { git = "https://github.com/jstuczyn/cosmos-rust", branch ="nym-temp/all-validator-features" }
|
||||
cosmrs = { git = "https://github.com/jstuczyn/cosmos-rust", branch = "nym-temp/all-validator-features" }
|
||||
#cosmrs = { git = "https://github.com/jstuczyn/cosmos-rust", branch = "nym-temp/all-validator-features" } # unfortuntely we need a fork by yours truly to get the staking support
|
||||
tendermint = "0.34" # same version as used by cosmrs
|
||||
tendermint = "0.34" # same version as used by cosmrs
|
||||
tendermint-rpc = "0.34" # same version as used by cosmrs
|
||||
prost = "0.12"
|
||||
prost = { version = "0.12", default-features = false }
|
||||
|
||||
# wasm-related dependencies
|
||||
gloo-utils = "0.1.7"
|
||||
js-sys = "0.3.63"
|
||||
serde-wasm-bindgen = "0.5.0"
|
||||
gloo-utils = "0.2.0"
|
||||
gloo-net = "0.5.0"
|
||||
js-sys = "0.3.69"
|
||||
serde-wasm-bindgen = "0.6.5"
|
||||
tsify = "0.4.5"
|
||||
wasm-bindgen = "0.2.86"
|
||||
wasm-bindgen-futures = "0.4.37"
|
||||
wasm-bindgen = "0.2.92"
|
||||
wasm-bindgen-futures = "0.4.39"
|
||||
wasmtimer = "0.2.0"
|
||||
web-sys = "0.3.63"
|
||||
web-sys = "0.3.69"
|
||||
itertools = "0.12.0"
|
||||
|
||||
|
||||
# Profile settings for individual crates
|
||||
|
||||
@@ -236,9 +362,12 @@ opt-level = 'z'
|
||||
# lto = true
|
||||
opt-level = 'z'
|
||||
|
||||
[profile.release.package.nym-wasm-sdk]
|
||||
# lto = true
|
||||
opt-level = 'z'
|
||||
# Commented out since the crate is also commented out from the inclusion in the
|
||||
# workspace above. We should uncomment this if we re-include it in the
|
||||
# workspace
|
||||
#[profile.release.package.nym-wasm-sdk]
|
||||
## lto = true
|
||||
#opt-level = 'z'
|
||||
|
||||
[profile.release.package.mix-fetch-wasm]
|
||||
# lto = true
|
||||
|
||||
@@ -92,7 +92,6 @@ endef
|
||||
$(eval $(call add_cargo_workspace,main,.))
|
||||
$(eval $(call add_cargo_workspace,contracts,contracts,--lib --target wasm32-unknown-unknown,RUSTFLAGS='-C link-arg=-s'))
|
||||
$(eval $(call add_cargo_workspace,wallet,nym-wallet))
|
||||
$(eval $(call add_cargo_workspace,connect,nym-connect/desktop))
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# SDK
|
||||
@@ -105,6 +104,7 @@ sdk-wasm-build:
|
||||
$(MAKE) -C wasm/client
|
||||
$(MAKE) -C wasm/node-tester
|
||||
$(MAKE) -C wasm/mix-fetch
|
||||
$(MAKE) -C wasm/zknym-lib
|
||||
#$(MAKE) -C wasm/full-nym-wasm
|
||||
|
||||
# run this from npm/yarn to ensure tools are in the path, e.g. yarn build:sdk from root of repo
|
||||
@@ -115,7 +115,7 @@ sdk-typescript-build:
|
||||
yarn --cwd sdk/typescript/codegen/contract-clients build
|
||||
|
||||
# NOTE: These targets are part of the main workspace (but not as wasm32-unknown-unknown)
|
||||
WASM_CRATES = extension-storage nym-client-wasm nym-node-tester-wasm
|
||||
WASM_CRATES = extension-storage nym-client-wasm nym-node-tester-wasm zknym-lib
|
||||
|
||||
sdk-wasm-test:
|
||||
#cargo test $(addprefix -p , $(WASM_CRATES)) --target wasm32-unknown-unknown -- -Dwarnings
|
||||
@@ -133,7 +133,7 @@ clippy: sdk-wasm-lint
|
||||
# Build contracts ready for deploy
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
CONTRACTS=vesting_contract mixnet_contract nym_service_provider_directory nym_name_service
|
||||
CONTRACTS=vesting_contract mixnet_contract
|
||||
CONTRACTS_WASM=$(addsuffix .wasm, $(CONTRACTS))
|
||||
CONTRACTS_OUT_DIR=contracts/target/wasm32-unknown-unknown/release
|
||||
|
||||
@@ -185,4 +185,4 @@ deb-gateway: build-nym-gateway
|
||||
deb-cli: build-nym-cli
|
||||
cargo deb -p nym-cli
|
||||
|
||||
deb: deb-mixnode deb-gateway deb-cli
|
||||
deb: deb-mixnode deb-gateway deb-cli
|
||||
|
||||
@@ -7,86 +7,66 @@ SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
The platform is composed of multiple Rust crates. Top-level executable binary crates include:
|
||||
|
||||
* nym-mixnode - shuffles [Sphinx](https://github.com/nymtech/sphinx) packets together to provide privacy against network-level attackers.
|
||||
* nym-client - an executable which you can build into your own applications. Use it for interacting with Nym nodes.
|
||||
* nym-socks5-client - a Socks5 proxy you can run on your machine and use with existing applications.
|
||||
* nym-gateway - acts sort of like a mailbox for mixnet messages, which removes the need for direct delivery to potentially offline or firewalled devices.
|
||||
* nym-network-monitor - sends packets through the full system to check that they are working as expected, and stores node uptime histories as the basis of a rewards system ("mixmining" or "proof-of-mixing").
|
||||
* nym-explorer - a (projected) block explorer and (existing) mixnet viewer.
|
||||
* nym-wallet - a desktop wallet implemented using the [Tauri](https://tauri.studio/en/docs/about/intro) framework.
|
||||
* `nym-node` - a tool for running a node within the Nym network. Nym Nodes containing functionality such as `mixnode`, `entry-gateway` and `exit-gateway` are fundamental components of Nym Mixnet architecture. Nym Nodes are ran by decentralised node operators. Read more about `nym-node` in [Operators Guide documentation](https://nymtech.net/operators/nodes/nym-node.html). Network functionality of `nym-node` (labeled with `--mode` flag) can be:
|
||||
- `mixnode` - shuffles [Sphinx](https://github.com/nymtech/sphinx) packets together to provide privacy against network-level attackers.
|
||||
- `gateway` - acts sort of like a mailbox for mixnet messages, which removes the need for direct delivery to potentially offline or firewalled devices. Gateways can be further categorized as `entry-gateway` and `exit-gateway`. The latter has an extra embedded IP packet router and Network requester to route data to the internet.
|
||||
* `nym-client` - an executable which you can build into your own applications. Use it for interacting with Nym nodes.
|
||||
* `nym-socks5-client` - a Socks5 proxy you can run on your machine and use with existing applications.
|
||||
* `nym-explorer` - a (projected) block explorer and (existing) mixnet viewer.
|
||||
* `nym-wallet` - a desktop wallet implemented using the [Tauri](https://tauri.studio/en/docs/about/intro) framework.
|
||||
<!-- coming soon
|
||||
* `nym-network-monitor` - sends packets through the full system to check that they are working as expected, and stores node uptime histories as the basis of a rewards system ("mixmining" or "proof-of-mixing").
|
||||
-->
|
||||
|
||||
```ascii
|
||||
┌─►mix──┐ mix mix
|
||||
│ │
|
||||
Entry │ │ Exit
|
||||
client ───► Gateway ──┘ mix │ mix ┌─►mix ───► Gateway ───► internet
|
||||
│ │
|
||||
│ │
|
||||
mix └─►mix──┘ mix
|
||||
|
||||
```
|
||||
|
||||
[](https://github.com/nymtech/nym/actions?query=branch%3Adevelop)
|
||||
|
||||
|
||||
### Building
|
||||
|
||||
Platform build instructions are available on [our docs site](https://nymtech.net/docs/binaries/pre-built-binaries.html).
|
||||
Wallet build instructions are also available on [our docs site](https://nymtech.net/docs/wallet/desktop-wallet.html).
|
||||
* Platform build instructions are available on Nym [Operators Guide documentation](https://nymtech.net/operators/binaries/building-nym.html).
|
||||
* Wallet build instructions are available on Nym [Technical docs](https://nymtech.net/docs/wallet/desktop-wallet.html).
|
||||
|
||||
### Developing
|
||||
|
||||
There's a `.env.sample-dev` file provided which you can rename to `.env` if you want convenient logging, backtrace, or other environment variables pre-set. The `.env` file is ignored so you don't need to worry about checking it in.
|
||||
There's a [`sandbox.env`](https://github.com/nymtech/nym/envs/sandbox.env) file provided which you can rename to `.env` if you want convenient testing environment. Read more about sandbox environment in our [Operators Guide page](https://nymtech.net/operators/sandbox.html).
|
||||
|
||||
For Typescript components, please see [ts-packages](./ts-packages).
|
||||
References for developers:
|
||||
|
||||
* [Developers Portal](https://nymtech.net/developers)
|
||||
* [Typescript SDKs](https://sdk.nymtech.net/)
|
||||
* [Technical Documentation - Nym network overview](https://nymtech.net/docs/)
|
||||
* [Release Cycle - git flow](https://nymtech.net/operators/release-cycle.html)
|
||||
|
||||
### Developer chat
|
||||
|
||||
> We used to use Keybase for developer chats, but we have since migrated to Matrix and Discord. We no longer check the old **nymtech.friends** Keybase team.
|
||||
|
||||
You can chat to us in two places:
|
||||
* The #dev channel on [Matrix](https://matrix.to/#/#dev:nymtech.chat)
|
||||
* The various developer channels on [Discord](https://discord.gg/nym)
|
||||
* The various developer channels on [Discord](https://discord.gg/FaTJb8q8)
|
||||
|
||||
### Rewards
|
||||
### Tokenomics & Rewards
|
||||
|
||||
Node, node operator and delegator rewards are determined according to the principles laid out in the section 6 of [Nym Whitepaper](https://nymtech.net/nym-whitepaper.pdf). Below is a TLDR of the variables and formulas involved in calculating the epoch rewards. Initial reward pool is set to 250 million Nym, making the circulating supply 750 million Nym.
|
||||
|
||||
|Symbol|Definition|
|
||||
|---|---|
|
||||
|<img src="https://render.githubusercontent.com/render/math?math=R#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}R#gh-dark-mode-only">|global share of rewards available, starts at 2% of the reward pool.
|
||||
|<img src="https://render.githubusercontent.com/render/math?math=R_{i}#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}R_{i}#gh-dark-mode-only">|node reward for mixnode `i`.
|
||||
|<img src="https://render.githubusercontent.com/render/math?math=\sigma_{i}#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}\sigma_{i}#gh-dark-mode-only">|ratio of total node stake (node bond + all delegations) to the token circulating supply.
|
||||
|<img src="https://render.githubusercontent.com/render/math?math=\lambda_{i}#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}\lambda_{i}#gh-dark-mode-only">|ratio of stake operator has pledged to their node to the token circulating supply.
|
||||
|<img src="https://render.githubusercontent.com/render/math?math=\omega_{i}#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}\omega_{i}#gh-dark-mode-only">|fraction of total effort undertaken by node `i`, set to `1/k`.
|
||||
|<img src="https://render.githubusercontent.com/render/math?math=k#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}k#gh-dark-mode-only">|number of nodes stakeholders are incentivised to create, set by the validators, a matter of governance. Currently determined by the `reward set` size, and set to 720 in testnet Sandbox.
|
||||
|<img src="https://render.githubusercontent.com/render/math?math=\alpha#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}\alpha#gh-dark-mode-only">|A Sybil attack resistance parameter - the higher this parameter is set, the stronger the reduction in competitiveness for a Sybil attacker.
|
||||
|<img src="https://render.githubusercontent.com/render/math?math=PM_{i}#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}PM_{i}#gh-dark-mode-only">|declared profit margin of operator `i`, defaults to 10%.
|
||||
|<img src="https://render.githubusercontent.com/render/math?math=PF_{i}#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}PF_{i}#gh-dark-mode-only">|uptime of node `i`, scaled to 0 - 1, for the rewarding epoch
|
||||
|<img src="https://render.githubusercontent.com/render/math?math=PP_{i}#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}PP_{i}#gh-dark-mode-only">|cost of operating node `i` for the duration of the rewarding epoch, set to 40 NYMs.
|
||||
|
||||
Node reward for node `i` is determined as:
|
||||
|
||||
<img src="https://render.githubusercontent.com/render/math?math=R_{i}=PF_{i} \cdot R \cdot (\sigma^'_{i} \cdot \omega_{i} \cdot k %2b \alpha \cdot \lambda^'_{i} \cdot \sigma^'_{i} \cdot k)/(1 %2b \alpha)#gh-light-mode-only">
|
||||
<img src="https://render.githubusercontent.com/render/math?math=\color{white}R_{i}=PF_{i} \cdot R \cdot (\sigma^'_{i} \cdot \omega_{i} \cdot k %2b \alpha \cdot \lambda^'_{i} \cdot \sigma^'_{i} \cdot k)/(1 %2b \alpha)#gh-dark-mode-only">
|
||||
where:
|
||||
|
||||
<img src="https://render.githubusercontent.com/render/math?math=\sigma^'_{i} = min\{\sigma_{i}, 1/k\}#gh-light-mode-only">
|
||||
<img src="https://render.githubusercontent.com/render/math?math=\color{white}\sigma^'_{i} = min\{\sigma_{i}, 1/k\}#gh-dark-mode-only">
|
||||
|
||||
and
|
||||
|
||||
<img src="https://render.githubusercontent.com/render/math?math=\lambda^'_{i} = min\{\lambda_{i}, 1/k\}#gh-light-mode-only">
|
||||
<img src="https://render.githubusercontent.com/render/math?math=\color{white}\lambda^'_{i} = min\{\lambda_{i}, 1/k\}#gh-dark-mode-only">
|
||||
|
||||
Operator of node `i` is credited with the following amount:
|
||||
|
||||
<img src="https://render.githubusercontent.com/render/math?math=min\{PP_{i},R_{i})\} %2b max\{0, (PM_{i} %2b (1 - PM_{i}) \cdot \lambda_{i}/\delta_{i}) \cdot (R_{i} - PP_{i})\}#gh-light-mode-only">
|
||||
<img src="https://render.githubusercontent.com/render/math?math=\color{white}min\{PP_{i},R_{i})\} %2b max\{0, (PM_{i} %2b (1 - PM_{i}) \cdot \lambda_{i}/\delta_{i}) \cdot (R_{i} - PP_{i})\}#gh-dark-mode-only">
|
||||
|
||||
Delegate with stake `s` receives:
|
||||
|
||||
<img src="https://render.githubusercontent.com/render/math?math=max\{0, (1-PM_{i}) \cdot (s^'/\sigma_{i}) \cdot (R_{i} - PP_{i})\}#gh-light-mode-only">
|
||||
<img src="https://render.githubusercontent.com/render/math?math=\color{white}max\{0, (1-PM_{i}) \cdot (s^'/\sigma_{i}) \cdot (R_{i} - PP_{i})\}#gh-dark-mode-only">
|
||||
|
||||
where `s'` is stake `s` scaled over total token circulating supply.
|
||||
Nym network economic incentives, operator and validator rewards, and scalability of the network are determined according to the principles laid out in the section 6 of [Nym Whitepaper](https://nymtech.net/nym-whitepaper.pdf).
|
||||
Initial reward pool is set to 250 million Nym, making the circulating supply 750 million Nym.
|
||||
|
||||
### Licensing and copyright information
|
||||
|
||||
This is a monorepo and components that make up Nym as a system are licensed individually, so for accurate information, please check individual files.
|
||||
|
||||
As a general approach, licensing is as follows this pattern:
|
||||
|
||||
- applications and binaries are GPLv3
|
||||
- libraries and components are Apache 2.0 or MIT
|
||||
- documentation is Apache 2.0 or CC0-1.0
|
||||
|
||||
Again, for accurate information, please check individual files.
|
||||
Nym Node Operators and Validators Temrs and Conditions can be found [here](https://nymtech.net/terms-and-conditions/operators/v1.0.0).
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
[package]
|
||||
name = "nym-client"
|
||||
version = "1.1.33"
|
||||
version = "1.1.37"
|
||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
|
||||
description = "Implementation of the Nym Client"
|
||||
edition = "2021"
|
||||
rust-version = "1.65"
|
||||
rust-version = "1.70"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
@@ -23,13 +23,13 @@ url = { workspace = true }
|
||||
|
||||
bs58 = { workspace = true }
|
||||
clap = { workspace = true, features = ["cargo", "derive"] }
|
||||
dirs = "4.0"
|
||||
dirs = { workspace = true }
|
||||
log = { workspace = true } # self explanatory
|
||||
rand = { version = "0.7.3", features = ["wasm-bindgen"] } # rng-related traits + some rng implementation to use
|
||||
rand = { workspace = true }
|
||||
serde = { workspace = true, features = ["derive"] } # for config serialization/deserialization
|
||||
serde_json = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
tap = "1.0.1"
|
||||
tap = { workspace = true }
|
||||
time = { workspace = true }
|
||||
tokio = { workspace = true, features = ["rt-multi-thread", "net", "signal"] } # async runtime
|
||||
tokio-tungstenite = { workspace = true }
|
||||
@@ -37,8 +37,8 @@ zeroize = { workspace = true }
|
||||
|
||||
## internal
|
||||
nym-bandwidth-controller = { path = "../../common/bandwidth-controller" }
|
||||
nym-bin-common = { path = "../../common/bin-common", features = ["output_format"] }
|
||||
nym-client-core = { path = "../../common/client-core", features = ["fs-surb-storage", "cli"] }
|
||||
nym-bin-common = { path = "../../common/bin-common", features = ["output_format", "clap"] }
|
||||
nym-client-core = { path = "../../common/client-core", features = ["fs-surb-storage", "fs-gateways-storage", "cli"] }
|
||||
nym-config = { path = "../../common/config" }
|
||||
nym-credential-storage = { path = "../../common/credential-storage" }
|
||||
nym-credentials = { path = "../../common/credentials" }
|
||||
@@ -51,5 +51,6 @@ nym-task = { path = "../../common/task" }
|
||||
nym-topology = { path = "../../common/topology" }
|
||||
nym-validator-client = { path = "../../common/client-libs/validator-client", features = ["http-client"] }
|
||||
nym-client-websocket-requests = { path = "websocket-requests" }
|
||||
nym-id = { path = "../../common/nym-id" }
|
||||
|
||||
[dev-dependencies]
|
||||
|
||||
+403
-361
File diff suppressed because it is too large
Load Diff
@@ -4,7 +4,7 @@
|
||||
use crate::client::config::persistence::ClientPaths;
|
||||
use crate::client::config::template::CONFIG_TEMPLATE;
|
||||
use nym_bin_common::logging::LoggingSettings;
|
||||
use nym_client_core::cli_helpers::client_init::ClientConfig;
|
||||
use nym_client_core::cli_helpers::CliClientConfig;
|
||||
use nym_client_core::config::disk_persistence::CommonClientPaths;
|
||||
use nym_config::defaults::DEFAULT_WEBSOCKET_LISTENING_PORT;
|
||||
use nym_config::{
|
||||
@@ -19,11 +19,12 @@ use std::path::{Path, PathBuf};
|
||||
use std::str::FromStr;
|
||||
|
||||
pub use nym_client_core::config::Config as BaseClientConfig;
|
||||
pub use nym_client_core::config::{DebugConfig, GatewayEndpointConfig};
|
||||
pub use nym_client_core::config::DebugConfig;
|
||||
|
||||
pub mod old_config_v1_1_13;
|
||||
pub mod old_config_v1_1_20;
|
||||
pub mod old_config_v1_1_20_2;
|
||||
pub mod old_config_v1_1_33;
|
||||
mod persistence;
|
||||
mod template;
|
||||
|
||||
@@ -74,7 +75,7 @@ impl NymConfigTemplate for Config {
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientConfig for Config {
|
||||
impl CliClientConfig for Config {
|
||||
fn common_paths(&self) -> &CommonClientPaths {
|
||||
&self.storage_paths.common_paths
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@ use crate::client::config::old_config_v1_1_20_2::{
|
||||
ClientPathsV1_1_20_2, ConfigV1_1_20_2, SocketTypeV1_1_20_2, SocketV1_1_20_2,
|
||||
};
|
||||
use nym_bin_common::logging::LoggingSettings;
|
||||
use nym_client_core::config::disk_persistence::keys_paths::ClientKeysPaths;
|
||||
use nym_client_core::config::disk_persistence::old_v1_1_20_2::CommonClientPathsV1_1_20_2;
|
||||
use nym_client_core::config::disk_persistence::old_v1_1_33::ClientKeysPathsV1_1_33;
|
||||
use nym_client_core::config::old_config_v1_1_20::ConfigV1_1_20 as BaseConfigV1_1_20;
|
||||
use nym_client_core::config::old_config_v1_1_20_2::{
|
||||
ClientV1_1_20_2, ConfigV1_1_20_2 as BaseConfigV1_1_20_2,
|
||||
@@ -60,7 +60,7 @@ impl From<ConfigV1_1_20> for ConfigV1_1_20_2 {
|
||||
socket: value.socket.into(),
|
||||
storage_paths: ClientPathsV1_1_20_2 {
|
||||
common_paths: CommonClientPathsV1_1_20_2 {
|
||||
keys: ClientKeysPaths {
|
||||
keys: ClientKeysPathsV1_1_33 {
|
||||
private_identity_key_file: value.base.client.private_identity_key_file,
|
||||
public_identity_key_file: value.base.client.public_identity_key_file,
|
||||
private_encryption_key_file: value.base.client.private_encryption_key_file,
|
||||
|
||||
@@ -1,18 +1,15 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::{
|
||||
client::config::{
|
||||
default_config_filepath, persistence::ClientPaths, Config, Socket, SocketType,
|
||||
},
|
||||
error::ClientError,
|
||||
use crate::client::config::old_config_v1_1_33::{
|
||||
ClientPathsV1_1_33, ConfigV1_1_33, SocketTypeV1_1_33, SocketV1_1_33,
|
||||
};
|
||||
|
||||
use crate::{client::config::default_config_filepath, error::ClientError};
|
||||
use nym_bin_common::logging::LoggingSettings;
|
||||
use nym_client_core::config::disk_persistence::old_v1_1_20_2::CommonClientPathsV1_1_20_2;
|
||||
use nym_client_core::config::old_config_v1_1_20_2::ConfigV1_1_20_2 as BaseConfigV1_1_20_2;
|
||||
use nym_client_core::config::old_config_v1_1_30::ConfigV1_1_30 as BaseConfigV1_1_30;
|
||||
use nym_client_core::config::GatewayEndpointConfig;
|
||||
use nym_client_core::config::old_config_v1_1_33::OldGatewayEndpointConfigV1_1_33;
|
||||
use nym_config::read_config_from_toml_file;
|
||||
use nym_network_defaults::DEFAULT_WEBSOCKET_LISTENING_PORT;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -49,12 +46,12 @@ impl ConfigV1_1_20_2 {
|
||||
|
||||
// in this upgrade, gateway endpoint configuration was moved out of the config file,
|
||||
// so its returned to be stored elsewhere.
|
||||
pub fn upgrade(self) -> Result<(Config, GatewayEndpointConfig), ClientError> {
|
||||
pub fn upgrade(self) -> Result<(ConfigV1_1_33, OldGatewayEndpointConfigV1_1_33), ClientError> {
|
||||
let gateway_details = self.base.client.gateway_endpoint.clone().into();
|
||||
let config = Config {
|
||||
let config = ConfigV1_1_33 {
|
||||
base: BaseConfigV1_1_30::from(self.base).into(),
|
||||
socket: self.socket.into(),
|
||||
storage_paths: ClientPaths {
|
||||
storage_paths: ClientPathsV1_1_33 {
|
||||
common_paths: self.storage_paths.common_paths.upgrade_default()?,
|
||||
},
|
||||
logging: self.logging,
|
||||
@@ -71,11 +68,11 @@ pub enum SocketTypeV1_1_20_2 {
|
||||
None,
|
||||
}
|
||||
|
||||
impl From<SocketTypeV1_1_20_2> for SocketType {
|
||||
impl From<SocketTypeV1_1_20_2> for SocketTypeV1_1_33 {
|
||||
fn from(value: SocketTypeV1_1_20_2) -> Self {
|
||||
match value {
|
||||
SocketTypeV1_1_20_2::WebSocket => SocketType::WebSocket,
|
||||
SocketTypeV1_1_20_2::None => SocketType::None,
|
||||
SocketTypeV1_1_20_2::WebSocket => SocketTypeV1_1_33::WebSocket,
|
||||
SocketTypeV1_1_20_2::None => SocketTypeV1_1_33::None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -88,9 +85,9 @@ pub struct SocketV1_1_20_2 {
|
||||
pub listening_port: u16,
|
||||
}
|
||||
|
||||
impl From<SocketV1_1_20_2> for Socket {
|
||||
impl From<SocketV1_1_20_2> for SocketV1_1_33 {
|
||||
fn from(value: SocketV1_1_20_2) -> Self {
|
||||
Socket {
|
||||
SocketV1_1_33 {
|
||||
socket_type: value.socket_type.into(),
|
||||
host: value.host,
|
||||
listening_port: value.listening_port,
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::client::config::persistence::ClientPaths;
|
||||
use crate::client::config::{default_config_filepath, Config, Socket, SocketType};
|
||||
use crate::error::ClientError;
|
||||
use nym_bin_common::logging::LoggingSettings;
|
||||
use nym_client_core::config::disk_persistence::old_v1_1_33::CommonClientPathsV1_1_33;
|
||||
use nym_client_core::config::old_config_v1_1_33::ConfigV1_1_33 as BaseConfigV1_1_33;
|
||||
use nym_config::read_config_from_toml_file;
|
||||
use nym_network_defaults::DEFAULT_WEBSOCKET_LISTENING_PORT;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::io;
|
||||
use std::net::{IpAddr, Ipv4Addr};
|
||||
use std::path::Path;
|
||||
|
||||
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize, Clone)]
|
||||
pub struct ClientPathsV1_1_33 {
|
||||
#[serde(flatten)]
|
||||
pub common_paths: CommonClientPathsV1_1_33,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct ConfigV1_1_33 {
|
||||
#[serde(flatten)]
|
||||
pub base: BaseConfigV1_1_33,
|
||||
|
||||
pub socket: SocketV1_1_33,
|
||||
|
||||
// \/ CHANGED
|
||||
pub storage_paths: ClientPathsV1_1_33,
|
||||
// /\ CHANGED
|
||||
pub logging: LoggingSettings,
|
||||
}
|
||||
|
||||
impl ConfigV1_1_33 {
|
||||
pub fn read_from_toml_file<P: AsRef<Path>>(path: P) -> io::Result<Self> {
|
||||
read_config_from_toml_file(path)
|
||||
}
|
||||
|
||||
pub fn read_from_default_path<P: AsRef<Path>>(id: P) -> io::Result<Self> {
|
||||
Self::read_from_toml_file(default_config_filepath(id))
|
||||
}
|
||||
|
||||
pub fn try_upgrade(self) -> Result<Config, ClientError> {
|
||||
Ok(Config {
|
||||
base: self.base.into(),
|
||||
socket: self.socket.into(),
|
||||
storage_paths: ClientPaths {
|
||||
common_paths: self.storage_paths.common_paths.upgrade_default()?,
|
||||
},
|
||||
logging: self.logging,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize, Clone, Copy)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub enum SocketTypeV1_1_33 {
|
||||
WebSocket,
|
||||
None,
|
||||
}
|
||||
|
||||
impl From<SocketTypeV1_1_33> for SocketType {
|
||||
fn from(value: SocketTypeV1_1_33) -> Self {
|
||||
match value {
|
||||
SocketTypeV1_1_33::WebSocket => SocketType::WebSocket,
|
||||
SocketTypeV1_1_33::None => SocketType::None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct SocketV1_1_33 {
|
||||
pub socket_type: SocketTypeV1_1_33,
|
||||
pub host: IpAddr,
|
||||
pub listening_port: u16,
|
||||
}
|
||||
|
||||
impl From<SocketV1_1_33> for Socket {
|
||||
fn from(value: SocketV1_1_33) -> Self {
|
||||
Socket {
|
||||
socket_type: value.socket_type.into(),
|
||||
host: value.host,
|
||||
listening_port: value.listening_port,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for SocketV1_1_33 {
|
||||
fn default() -> Self {
|
||||
SocketV1_1_33 {
|
||||
socket_type: SocketTypeV1_1_33::WebSocket,
|
||||
host: IpAddr::V4(Ipv4Addr::LOCALHOST),
|
||||
listening_port: DEFAULT_WEBSOCKET_LISTENING_PORT,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -50,10 +50,6 @@ keys.private_encryption_key_file = '{{ storage_paths.keys.private_encryption_key
|
||||
# Path to file containing public encryption key.
|
||||
keys.public_encryption_key_file = '{{ storage_paths.keys.public_encryption_key_file }}'
|
||||
|
||||
# A gateway specific, optional, base58 stringified shared key used for
|
||||
# communication with particular gateway.
|
||||
keys.gateway_shared_key_file = '{{ storage_paths.keys.gateway_shared_key_file }}'
|
||||
|
||||
# Path to file containing key used for encrypting and decrypting the content of an
|
||||
# acknowledgement so that nobody besides the client knows which packet it refers to.
|
||||
keys.ack_key_file = '{{ storage_paths.keys.ack_key_file }}'
|
||||
@@ -64,9 +60,9 @@ credentials_database = '{{ storage_paths.credentials_database }}'
|
||||
# Path to the persistent store for received reply surbs, unused encryption keys and used sender tags.
|
||||
reply_surb_database = '{{ storage_paths.reply_surb_database }}'
|
||||
|
||||
# Path to the file containing information about gateway used by this client,
|
||||
# i.e. details such as its public key, owner address or the network information.
|
||||
gateway_details = '{{ storage_paths.gateway_details }}'
|
||||
# Path to the file containing information about gateways used by this client,
|
||||
# i.e. details such as their public keys, owner addresses or the network information.
|
||||
gateway_registrations = '{{ storage_paths.gateway_registrations }}'
|
||||
|
||||
##### socket config options #####
|
||||
|
||||
|
||||
@@ -106,8 +106,10 @@ impl SocketClient {
|
||||
};
|
||||
|
||||
let storage = self.initialise_storage().await?;
|
||||
let user_agent = nym_bin_common::bin_info!().into();
|
||||
|
||||
let mut base_client = BaseClientBuilder::new(&self.config.base, storage, dkg_query_client);
|
||||
let mut base_client = BaseClientBuilder::new(&self.config.base, storage, dkg_query_client)
|
||||
.with_user_agent(user_agent);
|
||||
|
||||
if let Some(custom_mixnet) = &self.custom_mixnet {
|
||||
base_client = base_client.with_stored_topology(custom_mixnet)?;
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::commands::CliNativeClient;
|
||||
use crate::error::ClientError;
|
||||
use nym_bin_common::output_format::OutputFormat;
|
||||
use nym_client_core::cli_helpers::client_add_gateway::{add_gateway, CommonClientAddGatewayArgs};
|
||||
|
||||
#[derive(clap::Args)]
|
||||
pub(crate) struct Args {
|
||||
#[command(flatten)]
|
||||
common_args: CommonClientAddGatewayArgs,
|
||||
|
||||
#[arg(short, long, default_value_t = OutputFormat::default())]
|
||||
output: OutputFormat,
|
||||
}
|
||||
|
||||
impl AsRef<CommonClientAddGatewayArgs> for Args {
|
||||
fn as_ref(&self) -> &CommonClientAddGatewayArgs {
|
||||
&self.common_args
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn execute(args: Args) -> Result<(), ClientError> {
|
||||
let user_agent = nym_bin_common::bin_info!().into();
|
||||
let output = args.output;
|
||||
let res = add_gateway::<CliNativeClient, _>(args, Some(user_agent)).await?;
|
||||
|
||||
println!("{}", output.format(&res));
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,101 +1,14 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::commands::try_load_current_config;
|
||||
use crate::commands::CliNativeClient;
|
||||
use crate::error::ClientError;
|
||||
use clap::ArgGroup;
|
||||
use log::{error, info};
|
||||
use nym_credential_storage::models::StorableIssuedCredential;
|
||||
use nym_credential_storage::storage::Storage;
|
||||
use nym_credentials::coconut::bandwidth::issued::BandwidthCredentialIssuedDataVariant;
|
||||
use nym_credentials::IssuedBandwidthCredential;
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
use zeroize::Zeroizing;
|
||||
use nym_client_core::cli_helpers::client_import_credential::{
|
||||
import_credential, CommonClientImportCredentialArgs,
|
||||
};
|
||||
|
||||
fn parse_encoded_credential_data(raw: &str) -> bs58::decode::Result<Vec<u8>> {
|
||||
bs58::decode(raw).into_vec()
|
||||
}
|
||||
|
||||
#[derive(clap::Args)]
|
||||
#[clap(group(ArgGroup::new("cred_data").required(true)))]
|
||||
pub(crate) struct Args {
|
||||
/// Id of client that is going to import the credential
|
||||
#[clap(long)]
|
||||
pub id: String,
|
||||
|
||||
/// Explicitly provide the encoded credential data (as base58)
|
||||
#[clap(long, group = "cred_data", value_parser = parse_encoded_credential_data)]
|
||||
pub(crate) credential_data: Option<Vec<u8>>,
|
||||
|
||||
/// Specifies the path to file containing binary credential data
|
||||
#[clap(long, group = "cred_data")]
|
||||
pub(crate) credential_path: Option<PathBuf>,
|
||||
|
||||
// currently hidden as there exists only a single serialization standard
|
||||
#[clap(long, hide = true, default_value_t = 1)]
|
||||
pub(crate) version: u8,
|
||||
}
|
||||
|
||||
pub(crate) async fn execute(args: Args) -> Result<(), ClientError> {
|
||||
let config = try_load_current_config(&args.id)?;
|
||||
|
||||
let credentials_store = nym_credential_storage::initialise_persistent_storage(
|
||||
&config.storage_paths.common_paths.credentials_database,
|
||||
)
|
||||
.await;
|
||||
|
||||
let raw_credential = match args.credential_data {
|
||||
Some(data) => data,
|
||||
None => {
|
||||
// SAFETY: one of those arguments must have been set
|
||||
fs::read(args.credential_path.unwrap())?
|
||||
}
|
||||
};
|
||||
let raw_credential = Zeroizing::new(raw_credential);
|
||||
|
||||
// we're unpacking the data in order to make sure it's valid
|
||||
// and to extract relevant metadata for storage purposes
|
||||
let credential = match args.version {
|
||||
1 => Zeroizing::new(
|
||||
IssuedBandwidthCredential::unpack_v1(&raw_credential).map_err(|source| {
|
||||
ClientError::CredentialDeserializationFailure {
|
||||
storage_revision: 1,
|
||||
source,
|
||||
}
|
||||
})?,
|
||||
),
|
||||
other => panic!("unknown credential serialization version {other}"),
|
||||
};
|
||||
|
||||
info!("importing {}", credential.typ());
|
||||
match credential.variant_data() {
|
||||
BandwidthCredentialIssuedDataVariant::Voucher(voucher_info) => {
|
||||
info!("with value of {}", voucher_info.value())
|
||||
}
|
||||
BandwidthCredentialIssuedDataVariant::FreePass(freepass_info) => {
|
||||
info!("with expiry at {}", freepass_info.expiry_date());
|
||||
if freepass_info.expired() {
|
||||
error!("the free pass has already expired!");
|
||||
|
||||
// technically we can import it, but the gateway will just reject it so what's the point
|
||||
return Err(ClientError::ExpiredCredentialImport {
|
||||
expiration: freepass_info.expiry_date(),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let storable = StorableIssuedCredential {
|
||||
serialization_revision: args.version,
|
||||
credential_data: &raw_credential,
|
||||
credential_type: credential.typ().to_string(),
|
||||
epoch_id: credential
|
||||
.epoch_id()
|
||||
.try_into()
|
||||
.expect("our epoch is has run over u32::MAX!"),
|
||||
};
|
||||
|
||||
credentials_store.insert_issued_credential(storable).await?;
|
||||
pub(crate) async fn execute(args: CommonClientImportCredentialArgs) -> Result<(), ClientError> {
|
||||
import_credential::<CliNativeClient, _>(args).await?;
|
||||
println!("successfully imported credential!");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
use crate::client::config::{
|
||||
default_config_directory, default_config_filepath, default_data_directory,
|
||||
};
|
||||
use crate::commands::try_upgrade_config;
|
||||
use crate::commands::CliNativeClient;
|
||||
use crate::{
|
||||
client::config::Config,
|
||||
commands::{override_config, OverrideConfig},
|
||||
@@ -21,17 +21,8 @@ use std::fs;
|
||||
use std::net::IpAddr;
|
||||
use std::path::PathBuf;
|
||||
|
||||
struct NativeClientInit;
|
||||
|
||||
impl InitialisableClient for NativeClientInit {
|
||||
const NAME: &'static str = "native";
|
||||
type Error = ClientError;
|
||||
impl InitialisableClient for CliNativeClient {
|
||||
type InitArgs = Init;
|
||||
type Config = Config;
|
||||
|
||||
fn try_upgrade_outdated_config(id: &str) -> Result<(), Self::Error> {
|
||||
try_upgrade_config(id)
|
||||
}
|
||||
|
||||
fn initialise_storage_paths(id: &str) -> Result<(), Self::Error> {
|
||||
fs::create_dir_all(default_data_directory(id))?;
|
||||
@@ -123,8 +114,9 @@ impl Display for InitResults {
|
||||
pub(crate) async fn execute(args: Init) -> Result<(), ClientError> {
|
||||
eprintln!("Initialising client...");
|
||||
|
||||
let user_agent = nym_bin_common::bin_info!().into();
|
||||
let output = args.output;
|
||||
let res = initialise_client::<NativeClientInit>(args).await?;
|
||||
let res = initialise_client::<CliNativeClient>(args, Some(user_agent)).await?;
|
||||
|
||||
let init_results = InitResults::new(res);
|
||||
println!("{}", output.format(&init_results));
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::commands::CliNativeClient;
|
||||
use crate::error::ClientError;
|
||||
use nym_bin_common::output_format::OutputFormat;
|
||||
use nym_client_core::cli_helpers::client_list_gateways::{
|
||||
list_gateways, CommonClientListGatewaysArgs,
|
||||
};
|
||||
|
||||
#[derive(clap::Args)]
|
||||
pub(crate) struct Args {
|
||||
#[command(flatten)]
|
||||
common_args: CommonClientListGatewaysArgs,
|
||||
|
||||
#[arg(short, long, default_value_t = OutputFormat::default())]
|
||||
output: OutputFormat,
|
||||
}
|
||||
|
||||
impl AsRef<CommonClientListGatewaysArgs> for Args {
|
||||
fn as_ref(&self) -> &CommonClientListGatewaysArgs {
|
||||
&self.common_args
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn execute(args: Args) -> Result<(), ClientError> {
|
||||
let output = args.output;
|
||||
let res = list_gateways::<CliNativeClient, _>(args).await?;
|
||||
|
||||
println!("{}", output.format(&res));
|
||||
Ok(())
|
||||
}
|
||||
@@ -4,6 +4,7 @@
|
||||
use crate::client::config::old_config_v1_1_13::OldConfigV1_1_13;
|
||||
use crate::client::config::old_config_v1_1_20::ConfigV1_1_20;
|
||||
use crate::client::config::old_config_v1_1_20_2::ConfigV1_1_20_2;
|
||||
use crate::client::config::old_config_v1_1_33::ConfigV1_1_33;
|
||||
use crate::client::config::{BaseClientConfig, Config};
|
||||
use crate::error::ClientError;
|
||||
use clap::CommandFactory;
|
||||
@@ -11,21 +12,37 @@ use clap::{Parser, Subcommand};
|
||||
use log::{error, info};
|
||||
use nym_bin_common::bin_info;
|
||||
use nym_bin_common::completions::{fig_generate, ArgShell};
|
||||
use nym_client_core::client::base_client::storage::gateway_details::{
|
||||
OnDiskGatewayDetails, PersistedGatewayDetails,
|
||||
};
|
||||
use nym_client_core::client::key_manager::persistence::OnDiskKeys;
|
||||
use nym_client_core::config::GatewayEndpointConfig;
|
||||
use nym_client_core::error::ClientCoreError;
|
||||
use nym_client_core::cli_helpers::client_import_credential::CommonClientImportCredentialArgs;
|
||||
use nym_client_core::cli_helpers::CliClient;
|
||||
use nym_client_core::client::base_client::storage::migration_helpers::v1_1_33;
|
||||
use nym_config::OptionalSet;
|
||||
use std::error::Error;
|
||||
use std::net::IpAddr;
|
||||
use std::sync::OnceLock;
|
||||
|
||||
mod add_gateway;
|
||||
pub(crate) mod build_info;
|
||||
pub(crate) mod import_credential;
|
||||
pub(crate) mod init;
|
||||
mod list_gateways;
|
||||
pub(crate) mod run;
|
||||
mod switch_gateway;
|
||||
|
||||
pub(crate) struct CliNativeClient;
|
||||
|
||||
impl CliClient for CliNativeClient {
|
||||
const NAME: &'static str = "native";
|
||||
type Error = ClientError;
|
||||
type Config = Config;
|
||||
|
||||
async fn try_upgrade_outdated_config(id: &str) -> Result<(), Self::Error> {
|
||||
try_upgrade_config(id).await
|
||||
}
|
||||
|
||||
async fn try_load_current_config(id: &str) -> Result<Self::Config, Self::Error> {
|
||||
try_load_current_config(id).await
|
||||
}
|
||||
}
|
||||
|
||||
fn pretty_build_info_static() -> &'static str {
|
||||
static PRETTY_BUILD_INFORMATION: OnceLock<String> = OnceLock::new();
|
||||
@@ -56,7 +73,16 @@ pub(crate) enum Commands {
|
||||
Run(run::Run),
|
||||
|
||||
/// Import a pre-generated credential
|
||||
ImportCredential(import_credential::Args),
|
||||
ImportCredential(CommonClientImportCredentialArgs),
|
||||
|
||||
/// List all registered with gateways
|
||||
ListGateways(list_gateways::Args),
|
||||
|
||||
/// Add new gateway to this client
|
||||
AddGateway(add_gateway::Args),
|
||||
|
||||
/// Change the currently active gateway. Note that you must have already registered with the new gateway!
|
||||
SwitchGateway(switch_gateway::Args),
|
||||
|
||||
/// Show build information of this binary
|
||||
BuildInfo(build_info::BuildInfo),
|
||||
@@ -87,6 +113,9 @@ pub(crate) async fn execute(args: Cli) -> Result<(), Box<dyn Error + Send + Sync
|
||||
Commands::Init(m) => init::execute(m).await?,
|
||||
Commands::Run(m) => run::execute(m).await?,
|
||||
Commands::ImportCredential(m) => import_credential::execute(m).await?,
|
||||
Commands::ListGateways(args) => list_gateways::execute(args).await?,
|
||||
Commands::AddGateway(args) => add_gateway::execute(args).await?,
|
||||
Commands::SwitchGateway(args) => switch_gateway::execute(args).await?,
|
||||
Commands::BuildInfo(m) => build_info::execute(m),
|
||||
Commands::Completions(s) => s.generate(&mut Cli::command(), bin_name),
|
||||
Commands::GenerateFigSpec => fig_generate(&mut Cli::command(), bin_name),
|
||||
@@ -122,29 +151,7 @@ pub(crate) fn override_config(config: Config, args: OverrideConfig) -> Config {
|
||||
)
|
||||
}
|
||||
|
||||
fn persist_gateway_details(
|
||||
config: &Config,
|
||||
details: GatewayEndpointConfig,
|
||||
) -> Result<(), ClientError> {
|
||||
let details_store =
|
||||
OnDiskGatewayDetails::new(&config.storage_paths.common_paths.gateway_details);
|
||||
let keys_store = OnDiskKeys::new(config.storage_paths.common_paths.keys.clone());
|
||||
let shared_keys = keys_store.ephemeral_load_gateway_keys().map_err(|source| {
|
||||
ClientError::ClientCoreError(ClientCoreError::KeyStoreError {
|
||||
source: Box::new(source),
|
||||
})
|
||||
})?;
|
||||
let persisted_details = PersistedGatewayDetails::new(details.into(), Some(&shared_keys))?;
|
||||
details_store
|
||||
.store_to_disk(&persisted_details)
|
||||
.map_err(|source| {
|
||||
ClientError::ClientCoreError(ClientCoreError::GatewayDetailsStoreError {
|
||||
source: Box::new(source),
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
fn try_upgrade_v1_1_13_config(id: &str) -> Result<bool, ClientError> {
|
||||
async fn try_upgrade_v1_1_13_config(id: &str) -> Result<bool, ClientError> {
|
||||
use nym_config::legacy_helpers::nym_config::MigrationNymConfig;
|
||||
|
||||
// explicitly load it as v1.1.13 (which is incompatible with the next step, i.e. 1.1.19)
|
||||
@@ -158,14 +165,22 @@ fn try_upgrade_v1_1_13_config(id: &str) -> Result<bool, ClientError> {
|
||||
|
||||
let updated_step1: ConfigV1_1_20 = old_config.into();
|
||||
let updated_step2: ConfigV1_1_20_2 = updated_step1.into();
|
||||
let (updated, gateway_config) = updated_step2.upgrade()?;
|
||||
persist_gateway_details(&updated, gateway_config)?;
|
||||
let (updated_step3, gateway_config) = updated_step2.upgrade()?;
|
||||
let old_paths = updated_step3.storage_paths.clone();
|
||||
let updated = updated_step3.try_upgrade()?;
|
||||
|
||||
v1_1_33::migrate_gateway_details(
|
||||
&old_paths.common_paths,
|
||||
&updated.storage_paths.common_paths,
|
||||
Some(gateway_config),
|
||||
)
|
||||
.await?;
|
||||
|
||||
updated.save_to_default_location()?;
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
fn try_upgrade_v1_1_20_config(id: &str) -> Result<bool, ClientError> {
|
||||
async fn try_upgrade_v1_1_20_config(id: &str) -> Result<bool, ClientError> {
|
||||
use nym_config::legacy_helpers::nym_config::MigrationNymConfig;
|
||||
|
||||
// explicitly load it as v1.1.20 (which is incompatible with the current one, i.e. +1.1.21)
|
||||
@@ -178,14 +193,21 @@ fn try_upgrade_v1_1_20_config(id: &str) -> Result<bool, ClientError> {
|
||||
info!("It is going to get updated to the current specification.");
|
||||
|
||||
let updated_step1: ConfigV1_1_20_2 = old_config.into();
|
||||
let (updated, gateway_config) = updated_step1.upgrade()?;
|
||||
persist_gateway_details(&updated, gateway_config)?;
|
||||
let (updated_step2, gateway_config) = updated_step1.upgrade()?;
|
||||
let old_paths = updated_step2.storage_paths.clone();
|
||||
let updated = updated_step2.try_upgrade()?;
|
||||
|
||||
v1_1_33::migrate_gateway_details(
|
||||
&old_paths.common_paths,
|
||||
&updated.storage_paths.common_paths,
|
||||
Some(gateway_config),
|
||||
)
|
||||
.await?;
|
||||
updated.save_to_default_location()?;
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
fn try_upgrade_v1_1_20_2_config(id: &str) -> Result<bool, ClientError> {
|
||||
async fn try_upgrade_v1_1_20_2_config(id: &str) -> Result<bool, ClientError> {
|
||||
// explicitly load it as v1.1.20_2 (which is incompatible with the current one, i.e. +1.1.21)
|
||||
let Ok(old_config) = ConfigV1_1_20_2::read_from_default_path(id) else {
|
||||
// if we failed to load it, there might have been nothing to upgrade
|
||||
@@ -195,28 +217,62 @@ fn try_upgrade_v1_1_20_2_config(id: &str) -> Result<bool, ClientError> {
|
||||
info!("It seems the client is using <= v1.1.20_2 config template.");
|
||||
info!("It is going to get updated to the current specification.");
|
||||
|
||||
let (updated, gateway_config) = old_config.upgrade()?;
|
||||
persist_gateway_details(&updated, gateway_config)?;
|
||||
let (updated_step1, gateway_config) = old_config.upgrade()?;
|
||||
let old_paths = updated_step1.storage_paths.clone();
|
||||
let updated = updated_step1.try_upgrade()?;
|
||||
|
||||
v1_1_33::migrate_gateway_details(
|
||||
&old_paths.common_paths,
|
||||
&updated.storage_paths.common_paths,
|
||||
Some(gateway_config),
|
||||
)
|
||||
.await?;
|
||||
updated.save_to_default_location()?;
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
async fn try_upgrade_v1_1_33_config(id: &str) -> Result<bool, ClientError> {
|
||||
// explicitly load it as v1.1.33 (which is incompatible with the current one, i.e. +1.1.34)
|
||||
let Ok(old_config) = ConfigV1_1_33::read_from_default_path(id) else {
|
||||
// if we failed to load it, there might have been nothing to upgrade
|
||||
// or maybe it was an even older file. in either way. just ignore it and carry on with our day
|
||||
return Ok(false);
|
||||
};
|
||||
info!("It seems the client is using <= v1.1.33 config template.");
|
||||
info!("It is going to get updated to the current specification.");
|
||||
|
||||
let old_paths = old_config.storage_paths.clone();
|
||||
let updated = old_config.try_upgrade()?;
|
||||
|
||||
v1_1_33::migrate_gateway_details(
|
||||
&old_paths.common_paths,
|
||||
&updated.storage_paths.common_paths,
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
|
||||
updated.save_to_default_location()?;
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
fn try_upgrade_config(id: &str) -> Result<(), ClientError> {
|
||||
if try_upgrade_v1_1_13_config(id)? {
|
||||
async fn try_upgrade_config(id: &str) -> Result<(), ClientError> {
|
||||
if try_upgrade_v1_1_13_config(id).await? {
|
||||
return Ok(());
|
||||
}
|
||||
if try_upgrade_v1_1_20_config(id)? {
|
||||
if try_upgrade_v1_1_20_config(id).await? {
|
||||
return Ok(());
|
||||
}
|
||||
if try_upgrade_v1_1_20_2_config(id)? {
|
||||
if try_upgrade_v1_1_20_2_config(id).await? {
|
||||
return Ok(());
|
||||
}
|
||||
if try_upgrade_v1_1_33_config(id).await? {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn try_load_current_config(id: &str) -> Result<Config, ClientError> {
|
||||
async fn try_load_current_config(id: &str) -> Result<Config, ClientError> {
|
||||
// try to load the config as is
|
||||
if let Ok(cfg) = Config::read_from_default_path(id) {
|
||||
return if !cfg.validate() {
|
||||
@@ -227,7 +283,7 @@ fn try_load_current_config(id: &str) -> Result<Config, ClientError> {
|
||||
}
|
||||
|
||||
// we couldn't load it - try upgrading it from older revisions
|
||||
try_upgrade_config(id)?;
|
||||
try_upgrade_config(id).await?;
|
||||
|
||||
let config = match Config::read_from_default_path(id) {
|
||||
Ok(cfg) => cfg,
|
||||
@@ -247,7 +303,6 @@ fn try_load_current_config(id: &str) -> Result<Config, ClientError> {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use clap::CommandFactory;
|
||||
|
||||
#[test]
|
||||
fn verify_cli() {
|
||||
|
||||
@@ -69,7 +69,7 @@ fn version_check(cfg: &Config) -> bool {
|
||||
pub(crate) async fn execute(args: Run) -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||
eprintln!("Starting client {}...", args.common_args.id);
|
||||
|
||||
let mut config = try_load_current_config(&args.common_args.id)?;
|
||||
let mut config = try_load_current_config(&args.common_args.id).await?;
|
||||
config = override_config(config, OverrideConfig::from(args.clone()));
|
||||
|
||||
if !version_check(&config) {
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::commands::CliNativeClient;
|
||||
use crate::error::ClientError;
|
||||
use nym_client_core::cli_helpers::client_switch_gateway::{
|
||||
switch_gateway, CommonClientSwitchGatewaysArgs,
|
||||
};
|
||||
|
||||
#[derive(clap::Args, Clone, Debug)]
|
||||
pub struct Args {
|
||||
#[command(flatten)]
|
||||
common_args: CommonClientSwitchGatewaysArgs,
|
||||
}
|
||||
|
||||
impl AsRef<CommonClientSwitchGatewaysArgs> for Args {
|
||||
fn as_ref(&self) -> &CommonClientSwitchGatewaysArgs {
|
||||
&self.common_args
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn execute(args: Args) -> Result<(), ClientError> {
|
||||
switch_gateway::<CliNativeClient, _>(args).await
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
use nym_client_core::error::ClientCoreError;
|
||||
use nym_credential_storage::error::StorageError;
|
||||
use time::OffsetDateTime;
|
||||
|
||||
use nym_id::NymIdError;
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum ClientError {
|
||||
@@ -23,21 +23,9 @@ pub enum ClientError {
|
||||
#[error("Attempted to start the client in invalid socket mode")]
|
||||
InvalidSocketMode,
|
||||
|
||||
#[error("failed to store credential: {source}")]
|
||||
CredentialStorageFailure {
|
||||
#[from]
|
||||
source: StorageError,
|
||||
},
|
||||
#[error(transparent)]
|
||||
ConfigUpgradeFailure(#[from] nym_client_core::config::ConfigUpgradeFailure),
|
||||
|
||||
#[error(
|
||||
"failed to deserialize provided credential using revision {storage_revision}: {source}"
|
||||
)]
|
||||
CredentialDeserializationFailure {
|
||||
storage_revision: u8,
|
||||
#[source]
|
||||
source: nym_credentials::error::Error,
|
||||
},
|
||||
|
||||
#[error("attempted to import an expired credential (it expired on {expiration})")]
|
||||
ExpiredCredentialImport { expiration: OffsetDateTime },
|
||||
#[error(transparent)]
|
||||
NymIdError(#[from] NymIdError),
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ use crate::error::{self, ErrorKind};
|
||||
use crate::text::ClientRequestText;
|
||||
use nym_sphinx::addressing::clients::Recipient;
|
||||
use nym_sphinx::anonymous_replies::requests::{AnonymousSenderTag, SENDER_TAG_SIZE};
|
||||
use std::convert::{TryFrom, TryInto};
|
||||
|
||||
use std::mem::size_of;
|
||||
|
||||
#[repr(u8)]
|
||||
|
||||
@@ -9,7 +9,7 @@ use crate::text::ServerResponseText;
|
||||
use nym_sphinx::addressing::clients::Recipient;
|
||||
use nym_sphinx::anonymous_replies::requests::{AnonymousSenderTag, SENDER_TAG_SIZE};
|
||||
use nym_sphinx::receiver::ReconstructedMessage;
|
||||
use std::convert::TryInto;
|
||||
|
||||
use std::mem::size_of;
|
||||
|
||||
#[repr(u8)]
|
||||
|
||||
@@ -7,7 +7,6 @@ use crate::responses::ServerResponse;
|
||||
use nym_sphinx::addressing::clients::Recipient;
|
||||
use nym_sphinx::anonymous_replies::requests::AnonymousSenderTag;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::convert::{TryFrom, TryInto};
|
||||
|
||||
// local text equivalent of `ClientRequest` for easier serialization + deserialization with serde
|
||||
// TODO: figure out if there's an easy way to avoid defining it
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
[package]
|
||||
name = "nym-socks5-client"
|
||||
version = "1.1.33"
|
||||
version = "1.1.37"
|
||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
|
||||
description = "A SOCKS5 localhost proxy that converts incoming messages to Sphinx and sends them to a Nym address"
|
||||
edition = "2021"
|
||||
rust-version = "1.56"
|
||||
rust-version = "1.70"
|
||||
license.workspace = true
|
||||
|
||||
[dependencies]
|
||||
@@ -13,28 +13,30 @@ clap = { workspace = true, features = ["cargo", "derive"] }
|
||||
log = { workspace = true }
|
||||
serde = { workspace = true, features = ["derive"] } # for config serialization/deserialization
|
||||
serde_json = { workspace = true }
|
||||
tap = "1.0.1"
|
||||
tap = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
tokio = { version = "1.24.1", features = ["rt-multi-thread", "net", "signal"] }
|
||||
rand = "0.7.3"
|
||||
tokio = { workspace = true, features = ["rt-multi-thread", "net", "signal"] }
|
||||
rand = { workspace = true }
|
||||
time = { workspace = true }
|
||||
url = { workspace = true }
|
||||
zeroize = { workspace = true }
|
||||
|
||||
# internal
|
||||
nym-bin-common = { path = "../../common/bin-common", features = ["output_format"] }
|
||||
nym-client-core = { path = "../../common/client-core", features = ["fs-surb-storage", "cli"] }
|
||||
nym-client-core = { path = "../../common/client-core", features = ["fs-surb-storage", "fs-gateways-storage", "cli"] }
|
||||
nym-config = { path = "../../common/config" }
|
||||
nym-credential-storage = { path = "../../common/credential-storage" }
|
||||
nym-credentials = { path = "../../common/credentials" }
|
||||
nym-crypto = { path = "../../common/crypto" }
|
||||
nym-gateway-requests = { path = "../../gateway/gateway-requests" }
|
||||
nym-credential-storage = { path = "../../common/credential-storage" }
|
||||
nym-id = { path = "../../common/nym-id" }
|
||||
nym-network-defaults = { path = "../../common/network-defaults" }
|
||||
nym-sphinx = { path = "../../common/nymsphinx" }
|
||||
nym-ordered-buffer = { path = "../../common/socks5/ordered-buffer" }
|
||||
nym-pemstore = { path = "../../common/pemstore" }
|
||||
nym-topology = { path = "../../common/topology" }
|
||||
nym-socks5-client-core = { path = "../../common/socks5-client-core" }
|
||||
nym-sphinx = { path = "../../common/nymsphinx" }
|
||||
nym-topology = { path = "../../common/topology" }
|
||||
nym-validator-client = { path = "../../common/client-libs/validator-client", features = ["http-client"] }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::commands::CliSocks5Client;
|
||||
use crate::error::Socks5ClientError;
|
||||
use nym_bin_common::output_format::OutputFormat;
|
||||
use nym_client_core::cli_helpers::client_add_gateway::{add_gateway, CommonClientAddGatewayArgs};
|
||||
|
||||
#[derive(clap::Args)]
|
||||
pub(crate) struct Args {
|
||||
#[command(flatten)]
|
||||
common_args: CommonClientAddGatewayArgs,
|
||||
|
||||
#[arg(short, long, default_value_t = OutputFormat::default())]
|
||||
output: OutputFormat,
|
||||
}
|
||||
|
||||
impl AsRef<CommonClientAddGatewayArgs> for Args {
|
||||
fn as_ref(&self) -> &CommonClientAddGatewayArgs {
|
||||
&self.common_args
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn execute(args: Args) -> Result<(), Socks5ClientError> {
|
||||
let user_agent = nym_bin_common::bin_info!().into();
|
||||
let output = args.output;
|
||||
let res = add_gateway::<CliSocks5Client, _>(args, Some(user_agent)).await?;
|
||||
|
||||
println!("{}", output.format(&res));
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,101 +1,16 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::commands::try_load_current_config;
|
||||
use crate::commands::CliSocks5Client;
|
||||
use crate::error::Socks5ClientError;
|
||||
use clap::ArgGroup;
|
||||
use log::{error, info};
|
||||
use nym_credential_storage::models::StorableIssuedCredential;
|
||||
use nym_credential_storage::storage::Storage;
|
||||
use nym_credentials::coconut::bandwidth::issued::BandwidthCredentialIssuedDataVariant;
|
||||
use nym_credentials::IssuedBandwidthCredential;
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
use zeroize::Zeroizing;
|
||||
use nym_client_core::cli_helpers::client_import_credential::{
|
||||
import_credential, CommonClientImportCredentialArgs,
|
||||
};
|
||||
|
||||
fn parse_encoded_credential_data(raw: &str) -> bs58::decode::Result<Vec<u8>> {
|
||||
bs58::decode(raw).into_vec()
|
||||
}
|
||||
|
||||
#[derive(clap::Args)]
|
||||
#[clap(group(ArgGroup::new("cred_data").required(true)))]
|
||||
pub(crate) struct Args {
|
||||
/// Id of client that is going to import the credential
|
||||
#[clap(long)]
|
||||
pub id: String,
|
||||
|
||||
/// Explicitly provide the encoded credential data (as base58)
|
||||
#[clap(long, group = "cred_data", value_parser = parse_encoded_credential_data)]
|
||||
pub(crate) credential_data: Option<Vec<u8>>,
|
||||
|
||||
/// Specifies the path to file containing binary credential data
|
||||
#[clap(long, group = "cred_data")]
|
||||
pub(crate) credential_path: Option<PathBuf>,
|
||||
|
||||
// currently hidden as there exists only a single serialization standard
|
||||
#[clap(long, hide = true, default_value_t = 1)]
|
||||
pub(crate) version: u8,
|
||||
}
|
||||
|
||||
pub(crate) async fn execute(args: Args) -> Result<(), Socks5ClientError> {
|
||||
let config = try_load_current_config(&args.id)?;
|
||||
|
||||
let credentials_store = nym_credential_storage::initialise_persistent_storage(
|
||||
&config.storage_paths.common_paths.credentials_database,
|
||||
)
|
||||
.await;
|
||||
|
||||
let raw_credential = match args.credential_data {
|
||||
Some(data) => data,
|
||||
None => {
|
||||
// SAFETY: one of those arguments must have been set
|
||||
fs::read(args.credential_path.unwrap())?
|
||||
}
|
||||
};
|
||||
let raw_credential = Zeroizing::new(raw_credential);
|
||||
|
||||
// we're unpacking the data in order to make sure it's valid
|
||||
// and to extract relevant metadata for storage purposes
|
||||
let credential = match args.version {
|
||||
1 => Zeroizing::new(
|
||||
IssuedBandwidthCredential::unpack_v1(&raw_credential).map_err(|source| {
|
||||
Socks5ClientError::CredentialDeserializationFailure {
|
||||
storage_revision: 1,
|
||||
source,
|
||||
}
|
||||
})?,
|
||||
),
|
||||
other => panic!("unknown credential serialization version {other}"),
|
||||
};
|
||||
|
||||
info!("importing {}", credential.typ());
|
||||
match credential.variant_data() {
|
||||
BandwidthCredentialIssuedDataVariant::Voucher(voucher_info) => {
|
||||
info!("with value of {}", voucher_info.value())
|
||||
}
|
||||
BandwidthCredentialIssuedDataVariant::FreePass(freepass_info) => {
|
||||
info!("with expiry at {}", freepass_info.expiry_date());
|
||||
if freepass_info.expired() {
|
||||
error!("the free pass has already expired!");
|
||||
|
||||
// technically we can import it, but the gateway will just reject it so what's the point
|
||||
return Err(Socks5ClientError::ExpiredCredentialImport {
|
||||
expiration: freepass_info.expiry_date(),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let storable = StorableIssuedCredential {
|
||||
serialization_revision: args.version,
|
||||
credential_data: &raw_credential,
|
||||
credential_type: credential.typ().to_string(),
|
||||
epoch_id: credential
|
||||
.epoch_id()
|
||||
.try_into()
|
||||
.expect("our epoch is has run over u32::MAX!"),
|
||||
};
|
||||
|
||||
credentials_store.insert_issued_credential(storable).await?;
|
||||
pub(crate) async fn execute(
|
||||
args: CommonClientImportCredentialArgs,
|
||||
) -> Result<(), Socks5ClientError> {
|
||||
import_credential::<CliSocks5Client, _>(args).await?;
|
||||
println!("successfully imported credential!");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::commands::try_upgrade_config;
|
||||
use crate::commands::CliSocks5Client;
|
||||
use crate::config::{
|
||||
default_config_directory, default_config_filepath, default_data_directory, Config,
|
||||
};
|
||||
@@ -21,17 +21,8 @@ use std::fs;
|
||||
use std::net::{IpAddr, SocketAddr};
|
||||
use std::path::PathBuf;
|
||||
|
||||
struct Socks5ClientInit;
|
||||
|
||||
impl InitialisableClient for Socks5ClientInit {
|
||||
const NAME: &'static str = "socks5";
|
||||
type Error = Socks5ClientError;
|
||||
impl InitialisableClient for CliSocks5Client {
|
||||
type InitArgs = Init;
|
||||
type Config = Config;
|
||||
|
||||
fn try_upgrade_outdated_config(id: &str) -> Result<(), Self::Error> {
|
||||
try_upgrade_config(id)
|
||||
}
|
||||
|
||||
fn initialise_storage_paths(id: &str) -> Result<(), Self::Error> {
|
||||
fs::create_dir_all(default_data_directory(id))?;
|
||||
@@ -118,7 +109,7 @@ impl InitResults {
|
||||
Self {
|
||||
client_address: res.init_results.address.to_string(),
|
||||
client_core: res.init_results,
|
||||
socks5_listening_address: res.config.core.socks5.bind_adddress,
|
||||
socks5_listening_address: res.config.core.socks5.bind_address,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -138,8 +129,9 @@ impl Display for InitResults {
|
||||
pub(crate) async fn execute(args: Init) -> Result<(), Socks5ClientError> {
|
||||
eprintln!("Initialising client...");
|
||||
|
||||
let user_agent = nym_bin_common::bin_info!().into();
|
||||
let output = args.output;
|
||||
let res = initialise_client::<Socks5ClientInit>(args).await?;
|
||||
let res = initialise_client::<CliSocks5Client>(args, Some(user_agent)).await?;
|
||||
|
||||
let init_results = InitResults::new(res);
|
||||
println!("{}", output.format(&init_results));
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::commands::CliSocks5Client;
|
||||
use crate::error::Socks5ClientError;
|
||||
use nym_bin_common::output_format::OutputFormat;
|
||||
use nym_client_core::cli_helpers::client_list_gateways::{
|
||||
list_gateways, CommonClientListGatewaysArgs,
|
||||
};
|
||||
|
||||
#[derive(clap::Args)]
|
||||
pub(crate) struct Args {
|
||||
#[command(flatten)]
|
||||
common_args: CommonClientListGatewaysArgs,
|
||||
|
||||
#[arg(short, long, default_value_t = OutputFormat::default())]
|
||||
output: OutputFormat,
|
||||
}
|
||||
|
||||
impl AsRef<CommonClientListGatewaysArgs> for Args {
|
||||
fn as_ref(&self) -> &CommonClientListGatewaysArgs {
|
||||
&self.common_args
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn execute(args: Args) -> Result<(), Socks5ClientError> {
|
||||
let output = args.output;
|
||||
let res = list_gateways::<CliSocks5Client, _>(args).await?;
|
||||
|
||||
println!("{}", output.format(&res));
|
||||
Ok(())
|
||||
}
|
||||
@@ -5,30 +5,48 @@ use crate::config::old_config_v1_1_13::OldConfigV1_1_13;
|
||||
use crate::config::old_config_v1_1_20::ConfigV1_1_20;
|
||||
use crate::config::old_config_v1_1_20_2::ConfigV1_1_20_2;
|
||||
use crate::config::old_config_v1_1_30::ConfigV1_1_30;
|
||||
use crate::config::{BaseClientConfig, Config, SocksClientPaths};
|
||||
use crate::config::old_config_v1_1_33::ConfigV1_1_33;
|
||||
use crate::config::{BaseClientConfig, Config};
|
||||
use crate::error::Socks5ClientError;
|
||||
use clap::CommandFactory;
|
||||
use clap::{Parser, Subcommand};
|
||||
use log::{error, info};
|
||||
use nym_bin_common::bin_info;
|
||||
use nym_bin_common::completions::{fig_generate, ArgShell};
|
||||
use nym_client_core::client::base_client::storage::gateway_details::{
|
||||
OnDiskGatewayDetails, PersistedGatewayDetails,
|
||||
};
|
||||
use nym_client_core::client::key_manager::persistence::OnDiskKeys;
|
||||
use nym_client_core::cli_helpers::client_import_credential::CommonClientImportCredentialArgs;
|
||||
use nym_client_core::cli_helpers::CliClient;
|
||||
use nym_client_core::client::base_client::storage::migration_helpers::v1_1_33;
|
||||
use nym_client_core::client::topology_control::geo_aware_provider::CountryGroup;
|
||||
use nym_client_core::config::{GatewayEndpointConfig, GroupBy, TopologyStructure};
|
||||
use nym_client_core::error::ClientCoreError;
|
||||
use nym_client_core::config::{GroupBy, TopologyStructure};
|
||||
use nym_config::OptionalSet;
|
||||
use nym_sphinx::params::{PacketSize, PacketType};
|
||||
use std::error::Error;
|
||||
use std::net::IpAddr;
|
||||
use std::sync::OnceLock;
|
||||
|
||||
mod add_gateway;
|
||||
pub(crate) mod build_info;
|
||||
mod import_credential;
|
||||
pub mod init;
|
||||
mod list_gateways;
|
||||
pub(crate) mod run;
|
||||
mod switch_gateway;
|
||||
|
||||
pub(crate) struct CliSocks5Client;
|
||||
|
||||
impl CliClient for CliSocks5Client {
|
||||
const NAME: &'static str = "socks5";
|
||||
type Error = Socks5ClientError;
|
||||
type Config = Config;
|
||||
|
||||
async fn try_upgrade_outdated_config(id: &str) -> Result<(), Self::Error> {
|
||||
try_upgrade_config(id).await
|
||||
}
|
||||
|
||||
async fn try_load_current_config(id: &str) -> Result<Self::Config, Self::Error> {
|
||||
try_load_current_config(id).await
|
||||
}
|
||||
}
|
||||
|
||||
fn pretty_build_info_static() -> &'static str {
|
||||
static PRETTY_BUILD_INFORMATION: OnceLock<String> = OnceLock::new();
|
||||
@@ -59,7 +77,16 @@ pub(crate) enum Commands {
|
||||
Run(run::Run),
|
||||
|
||||
/// Import a pre-generated credential
|
||||
ImportCredential(import_credential::Args),
|
||||
ImportCredential(CommonClientImportCredentialArgs),
|
||||
|
||||
/// List all registered with gateways
|
||||
ListGateways(list_gateways::Args),
|
||||
|
||||
/// Add new gateway to this client
|
||||
AddGateway(add_gateway::Args),
|
||||
|
||||
/// Change the currently active gateway. Note that you must have already registered with the new gateway!
|
||||
SwitchGateway(switch_gateway::Args),
|
||||
|
||||
/// Show build information of this binary
|
||||
BuildInfo(build_info::BuildInfo),
|
||||
@@ -93,6 +120,9 @@ pub(crate) async fn execute(args: Cli) -> Result<(), Box<dyn Error + Send + Sync
|
||||
Commands::Init(m) => init::execute(m).await?,
|
||||
Commands::Run(m) => run::execute(m).await?,
|
||||
Commands::ImportCredential(m) => import_credential::execute(m).await?,
|
||||
Commands::ListGateways(args) => list_gateways::execute(args).await?,
|
||||
Commands::AddGateway(args) => add_gateway::execute(args).await?,
|
||||
Commands::SwitchGateway(args) => switch_gateway::execute(args).await?,
|
||||
Commands::BuildInfo(m) => build_info::execute(m),
|
||||
Commands::Completions(s) => s.generate(&mut Cli::command(), bin_name),
|
||||
Commands::GenerateFigSpec => fig_generate(&mut Cli::command(), bin_name),
|
||||
@@ -168,28 +198,7 @@ pub(crate) fn override_config(config: Config, args: OverrideConfig) -> Config {
|
||||
)
|
||||
}
|
||||
|
||||
fn persist_gateway_details(
|
||||
storage_paths: &SocksClientPaths,
|
||||
details: GatewayEndpointConfig,
|
||||
) -> Result<(), Socks5ClientError> {
|
||||
let details_store = OnDiskGatewayDetails::new(&storage_paths.common_paths.gateway_details);
|
||||
let keys_store = OnDiskKeys::new(storage_paths.common_paths.keys.clone());
|
||||
let shared_keys = keys_store.ephemeral_load_gateway_keys().map_err(|source| {
|
||||
Socks5ClientError::ClientCoreError(ClientCoreError::KeyStoreError {
|
||||
source: Box::new(source),
|
||||
})
|
||||
})?;
|
||||
let persisted_details = PersistedGatewayDetails::new(details.into(), Some(&shared_keys))?;
|
||||
details_store
|
||||
.store_to_disk(&persisted_details)
|
||||
.map_err(|source| {
|
||||
Socks5ClientError::ClientCoreError(ClientCoreError::GatewayDetailsStoreError {
|
||||
source: Box::new(source),
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
fn try_upgrade_v1_1_13_config(id: &str) -> Result<bool, Socks5ClientError> {
|
||||
async fn try_upgrade_v1_1_13_config(id: &str) -> Result<bool, Socks5ClientError> {
|
||||
use nym_config::legacy_helpers::nym_config::MigrationNymConfig;
|
||||
|
||||
// explicitly load it as v1.1.13 (which is incompatible with the next step, i.e. 1.1.19)
|
||||
@@ -204,14 +213,23 @@ fn try_upgrade_v1_1_13_config(id: &str) -> Result<bool, Socks5ClientError> {
|
||||
let updated_step1: ConfigV1_1_20 = old_config.into();
|
||||
let updated_step2: ConfigV1_1_20_2 = updated_step1.into();
|
||||
let (updated_step3, gateway_config) = updated_step2.upgrade()?;
|
||||
persist_gateway_details(&updated_step3.storage_paths, gateway_config)?;
|
||||
let old_paths = updated_step3.storage_paths.clone();
|
||||
|
||||
let updated_step4: ConfigV1_1_33 = updated_step3.into();
|
||||
let updated = updated_step4.try_upgrade()?;
|
||||
|
||||
v1_1_33::migrate_gateway_details(
|
||||
&old_paths.common_paths,
|
||||
&updated.storage_paths.common_paths,
|
||||
Some(gateway_config),
|
||||
)
|
||||
.await?;
|
||||
|
||||
let updated: Config = updated_step3.into();
|
||||
updated.save_to_default_location()?;
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
fn try_upgrade_v1_1_20_config(id: &str) -> Result<bool, Socks5ClientError> {
|
||||
async fn try_upgrade_v1_1_20_config(id: &str) -> Result<bool, Socks5ClientError> {
|
||||
use nym_config::legacy_helpers::nym_config::MigrationNymConfig;
|
||||
|
||||
// explicitly load it as v1.1.20 (which is incompatible with the current one, i.e. +1.1.21)
|
||||
@@ -225,14 +243,23 @@ fn try_upgrade_v1_1_20_config(id: &str) -> Result<bool, Socks5ClientError> {
|
||||
|
||||
let updated_step1: ConfigV1_1_20_2 = old_config.into();
|
||||
let (updated_step2, gateway_config) = updated_step1.upgrade()?;
|
||||
persist_gateway_details(&updated_step2.storage_paths, gateway_config)?;
|
||||
let old_paths = updated_step2.storage_paths.clone();
|
||||
|
||||
let updated_step3: ConfigV1_1_33 = updated_step2.into();
|
||||
let updated = updated_step3.try_upgrade()?;
|
||||
|
||||
v1_1_33::migrate_gateway_details(
|
||||
&old_paths.common_paths,
|
||||
&updated.storage_paths.common_paths,
|
||||
Some(gateway_config),
|
||||
)
|
||||
.await?;
|
||||
|
||||
let updated: Config = updated_step2.into();
|
||||
updated.save_to_default_location()?;
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
fn try_upgrade_v1_1_20_2_config(id: &str) -> Result<bool, Socks5ClientError> {
|
||||
async fn try_upgrade_v1_1_20_2_config(id: &str) -> Result<bool, Socks5ClientError> {
|
||||
// explicitly load it as v1.1.20_2 (which is incompatible with the current one, i.e. +1.1.21)
|
||||
let Ok(old_config) = ConfigV1_1_20_2::read_from_default_path(id) else {
|
||||
// if we failed to load it, there might have been nothing to upgrade
|
||||
@@ -243,14 +270,23 @@ fn try_upgrade_v1_1_20_2_config(id: &str) -> Result<bool, Socks5ClientError> {
|
||||
info!("It is going to get updated to the current specification.");
|
||||
|
||||
let (updated_step1, gateway_config) = old_config.upgrade()?;
|
||||
persist_gateway_details(&updated_step1.storage_paths, gateway_config)?;
|
||||
let old_paths = updated_step1.storage_paths.clone();
|
||||
|
||||
let updated_step2: ConfigV1_1_33 = updated_step1.into();
|
||||
let updated = updated_step2.try_upgrade()?;
|
||||
|
||||
v1_1_33::migrate_gateway_details(
|
||||
&old_paths.common_paths,
|
||||
&updated.storage_paths.common_paths,
|
||||
Some(gateway_config),
|
||||
)
|
||||
.await?;
|
||||
|
||||
let updated: Config = updated_step1.into();
|
||||
updated.save_to_default_location()?;
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
fn try_upgrade_v1_1_30_config(id: &str) -> Result<bool, Socks5ClientError> {
|
||||
async fn try_upgrade_v1_1_30_config(id: &str) -> Result<bool, Socks5ClientError> {
|
||||
// explicitly load it as v1.1.30 (which is incompatible with the current one, i.e. +1.1.31)
|
||||
let Ok(old_config) = ConfigV1_1_30::read_from_default_path(id) else {
|
||||
// if we failed to load it, there might have been nothing to upgrade
|
||||
@@ -260,29 +296,68 @@ fn try_upgrade_v1_1_30_config(id: &str) -> Result<bool, Socks5ClientError> {
|
||||
info!("It seems the client is using <= v1.1.30 config template.");
|
||||
info!("It is going to get updated to the current specification.");
|
||||
|
||||
let updated: Config = old_config.into();
|
||||
let old_paths = old_config.storage_paths.clone();
|
||||
|
||||
let updated_step1: ConfigV1_1_33 = old_config.into();
|
||||
let updated = updated_step1.try_upgrade()?;
|
||||
|
||||
v1_1_33::migrate_gateway_details(
|
||||
&old_paths.common_paths,
|
||||
&updated.storage_paths.common_paths,
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
|
||||
updated.save_to_default_location()?;
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
fn try_upgrade_config(id: &str) -> Result<(), Socks5ClientError> {
|
||||
if try_upgrade_v1_1_13_config(id)? {
|
||||
async fn try_upgrade_v1_1_33_config(id: &str) -> Result<bool, Socks5ClientError> {
|
||||
// explicitly load it as v1.1.33 (which is incompatible with the current one, i.e. +1.1.34)
|
||||
let Ok(old_config) = ConfigV1_1_33::read_from_default_path(id) else {
|
||||
// if we failed to load it, there might have been nothing to upgrade
|
||||
// or maybe it was an even older file. in either way. just ignore it and carry on with our day
|
||||
return Ok(false);
|
||||
};
|
||||
info!("It seems the client is using <= v1.1.33 config template.");
|
||||
info!("It is going to get updated to the current specification.");
|
||||
|
||||
let old_paths = old_config.storage_paths.clone();
|
||||
|
||||
let updated = old_config.try_upgrade()?;
|
||||
|
||||
v1_1_33::migrate_gateway_details(
|
||||
&old_paths.common_paths,
|
||||
&updated.storage_paths.common_paths,
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
|
||||
updated.save_to_default_location()?;
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
async fn try_upgrade_config(id: &str) -> Result<(), Socks5ClientError> {
|
||||
if try_upgrade_v1_1_13_config(id).await? {
|
||||
return Ok(());
|
||||
}
|
||||
if try_upgrade_v1_1_20_config(id)? {
|
||||
if try_upgrade_v1_1_20_config(id).await? {
|
||||
return Ok(());
|
||||
}
|
||||
if try_upgrade_v1_1_20_2_config(id)? {
|
||||
if try_upgrade_v1_1_20_2_config(id).await? {
|
||||
return Ok(());
|
||||
}
|
||||
if try_upgrade_v1_1_30_config(id)? {
|
||||
if try_upgrade_v1_1_30_config(id).await? {
|
||||
return Ok(());
|
||||
}
|
||||
if try_upgrade_v1_1_33_config(id).await? {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn try_load_current_config(id: &str) -> Result<Config, Socks5ClientError> {
|
||||
async fn try_load_current_config(id: &str) -> Result<Config, Socks5ClientError> {
|
||||
// try to load the config as is
|
||||
if let Ok(cfg) = Config::read_from_default_path(id) {
|
||||
return if !cfg.validate() {
|
||||
@@ -293,7 +368,7 @@ fn try_load_current_config(id: &str) -> Result<Config, Socks5ClientError> {
|
||||
}
|
||||
|
||||
// we couldn't load it - try upgrading it from older revisions
|
||||
try_upgrade_config(id)?;
|
||||
try_upgrade_config(id).await?;
|
||||
|
||||
let config = match Config::read_from_default_path(id) {
|
||||
Ok(cfg) => cfg,
|
||||
@@ -313,7 +388,6 @@ fn try_load_current_config(id: &str) -> Result<Config, Socks5ClientError> {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use clap::CommandFactory;
|
||||
|
||||
#[test]
|
||||
fn verify_cli() {
|
||||
|
||||
@@ -105,7 +105,7 @@ fn version_check(cfg: &Config) -> bool {
|
||||
pub(crate) async fn execute(args: Run) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||
eprintln!("Starting client {}...", args.common_args.id);
|
||||
|
||||
let mut config = try_load_current_config(&args.common_args.id)?;
|
||||
let mut config = try_load_current_config(&args.common_args.id).await?;
|
||||
config = override_config(config, OverrideConfig::from(args.clone()));
|
||||
|
||||
if !version_check(&config) {
|
||||
@@ -116,7 +116,13 @@ pub(crate) async fn execute(args: Run) -> Result<(), Box<dyn std::error::Error +
|
||||
let storage =
|
||||
OnDiskPersistent::from_paths(config.storage_paths.common_paths, &config.core.base.debug)
|
||||
.await?;
|
||||
NymClient::new(config.core, storage, args.common_args.custom_mixnet)
|
||||
.run_forever()
|
||||
.await
|
||||
let user_agent = nym_bin_common::bin_info!().into();
|
||||
NymClient::new(
|
||||
config.core,
|
||||
storage,
|
||||
user_agent,
|
||||
args.common_args.custom_mixnet,
|
||||
)
|
||||
.run_forever()
|
||||
.await
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::commands::CliSocks5Client;
|
||||
use crate::error::Socks5ClientError;
|
||||
use nym_client_core::cli_helpers::client_switch_gateway::{
|
||||
switch_gateway, CommonClientSwitchGatewaysArgs,
|
||||
};
|
||||
|
||||
#[derive(clap::Args, Clone, Debug)]
|
||||
pub struct Args {
|
||||
#[command(flatten)]
|
||||
common_args: CommonClientSwitchGatewaysArgs,
|
||||
}
|
||||
|
||||
impl AsRef<CommonClientSwitchGatewaysArgs> for Args {
|
||||
fn as_ref(&self) -> &CommonClientSwitchGatewaysArgs {
|
||||
&self.common_args
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn execute(args: Args) -> Result<(), Socks5ClientError> {
|
||||
switch_gateway::<CliSocks5Client, _>(args).await
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
use crate::config::template::CONFIG_TEMPLATE;
|
||||
use nym_bin_common::logging::LoggingSettings;
|
||||
use nym_client_core::cli_helpers::client_init::ClientConfig;
|
||||
use nym_client_core::cli_helpers::CliClientConfig;
|
||||
use nym_client_core::config::disk_persistence::CommonClientPaths;
|
||||
use nym_config::{
|
||||
must_get_home, read_config_from_toml_file, save_formatted_config_to_file, NymConfigTemplate,
|
||||
@@ -24,6 +24,7 @@ pub mod old_config_v1_1_13;
|
||||
pub mod old_config_v1_1_20;
|
||||
pub mod old_config_v1_1_20_2;
|
||||
pub mod old_config_v1_1_30;
|
||||
pub mod old_config_v1_1_33;
|
||||
mod persistence;
|
||||
mod template;
|
||||
|
||||
@@ -71,7 +72,7 @@ impl NymConfigTemplate for Config {
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientConfig for Config {
|
||||
impl CliClientConfig for Config {
|
||||
fn common_paths(&self) -> &CommonClientPaths {
|
||||
&self.storage_paths.common_paths
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@ use crate::config::old_config_v1_1_20_2::{
|
||||
ConfigV1_1_20_2, CoreConfigV1_1_20_2, SocksClientPathsV1_1_20_2,
|
||||
};
|
||||
use nym_bin_common::logging::LoggingSettings;
|
||||
use nym_client_core::config::disk_persistence::keys_paths::ClientKeysPaths;
|
||||
use nym_client_core::config::disk_persistence::old_v1_1_20_2::CommonClientPathsV1_1_20_2;
|
||||
use nym_client_core::config::disk_persistence::old_v1_1_33::ClientKeysPathsV1_1_33;
|
||||
use nym_client_core::config::old_config_v1_1_20::ConfigV1_1_20 as BaseConfigV1_1_20;
|
||||
use nym_client_core::config::old_config_v1_1_20_2::ClientV1_1_20_2;
|
||||
use nym_config::legacy_helpers::nym_config::MigrationNymConfig;
|
||||
@@ -50,7 +50,7 @@ impl From<ConfigV1_1_20> for ConfigV1_1_20_2 {
|
||||
},
|
||||
storage_paths: SocksClientPathsV1_1_20_2 {
|
||||
common_paths: CommonClientPathsV1_1_20_2 {
|
||||
keys: ClientKeysPaths {
|
||||
keys: ClientKeysPathsV1_1_33 {
|
||||
private_identity_key_file: value.base.client.private_identity_key_file,
|
||||
public_identity_key_file: value.base.client.public_identity_key_file,
|
||||
private_encryption_key_file: value.base.client.private_encryption_key_file,
|
||||
|
||||
@@ -2,13 +2,11 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::config::old_config_v1_1_30::ConfigV1_1_30;
|
||||
use crate::{
|
||||
config::{default_config_filepath, persistence::SocksClientPaths},
|
||||
error::Socks5ClientError,
|
||||
};
|
||||
use crate::config::old_config_v1_1_33::SocksClientPathsV1_1_33;
|
||||
use crate::{config::default_config_filepath, error::Socks5ClientError};
|
||||
use nym_bin_common::logging::LoggingSettings;
|
||||
use nym_client_core::config::disk_persistence::old_v1_1_20_2::CommonClientPathsV1_1_20_2;
|
||||
use nym_client_core::config::GatewayEndpointConfig;
|
||||
use nym_client_core::config::old_config_v1_1_33::OldGatewayEndpointConfigV1_1_33;
|
||||
use nym_config::read_config_from_toml_file;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::io;
|
||||
@@ -43,11 +41,13 @@ impl ConfigV1_1_20_2 {
|
||||
|
||||
// in this upgrade, gateway endpoint configuration was moved out of the config file,
|
||||
// so its returned to be stored elsewhere.
|
||||
pub fn upgrade(self) -> Result<(ConfigV1_1_30, GatewayEndpointConfig), Socks5ClientError> {
|
||||
pub fn upgrade(
|
||||
self,
|
||||
) -> Result<(ConfigV1_1_30, OldGatewayEndpointConfigV1_1_33), Socks5ClientError> {
|
||||
let gateway_details = self.core.base.client.gateway_endpoint.clone().into();
|
||||
let config = ConfigV1_1_30 {
|
||||
core: self.core.into(),
|
||||
storage_paths: SocksClientPaths {
|
||||
storage_paths: SocksClientPathsV1_1_33 {
|
||||
common_paths: self.storage_paths.common_paths.upgrade_default()?,
|
||||
},
|
||||
logging: self.logging,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::config::persistence::SocksClientPaths;
|
||||
use crate::config::{default_config_filepath, Config};
|
||||
use crate::config::default_config_filepath;
|
||||
use crate::config::old_config_v1_1_33::{ConfigV1_1_33, SocksClientPathsV1_1_33};
|
||||
use nym_bin_common::logging::LoggingSettings;
|
||||
use nym_config::read_config_from_toml_file;
|
||||
use nym_socks5_client_core::config::old_config_v1_1_30::ConfigV1_1_30 as CoreConfigV1_1_30;
|
||||
@@ -15,17 +15,14 @@ use std::path::Path;
|
||||
pub struct ConfigV1_1_30 {
|
||||
pub core: CoreConfigV1_1_30,
|
||||
|
||||
// I'm leaving a landmine here for when the paths actually do change the next time,
|
||||
// but propagating the change right now (in ALL clients) would be such a hassle...,
|
||||
// so sorry for the next person looking at it : )
|
||||
pub storage_paths: SocksClientPaths,
|
||||
pub storage_paths: SocksClientPathsV1_1_33,
|
||||
|
||||
pub logging: LoggingSettings,
|
||||
}
|
||||
|
||||
impl From<ConfigV1_1_30> for Config {
|
||||
impl From<ConfigV1_1_30> for ConfigV1_1_33 {
|
||||
fn from(value: ConfigV1_1_30) -> Self {
|
||||
Config {
|
||||
ConfigV1_1_33 {
|
||||
core: value.core.into(),
|
||||
storage_paths: value.storage_paths,
|
||||
logging: LoggingSettings::default(),
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::config::{default_config_filepath, Config, SocksClientPaths};
|
||||
use crate::error::Socks5ClientError;
|
||||
use nym_bin_common::logging::LoggingSettings;
|
||||
use nym_client_core::config::disk_persistence::old_v1_1_33::CommonClientPathsV1_1_33;
|
||||
use nym_config::read_config_from_toml_file;
|
||||
use nym_socks5_client_core::config::old_config_v1_1_33::ConfigV1_1_33 as CoreConfigV1_1_33;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::io;
|
||||
use std::path::Path;
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct SocksClientPathsV1_1_33 {
|
||||
#[serde(flatten)]
|
||||
pub common_paths: CommonClientPathsV1_1_33,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct ConfigV1_1_33 {
|
||||
pub core: CoreConfigV1_1_33,
|
||||
|
||||
// \/ CHANGED
|
||||
pub storage_paths: SocksClientPathsV1_1_33,
|
||||
// /\ CHANGED
|
||||
pub logging: LoggingSettings,
|
||||
}
|
||||
|
||||
impl ConfigV1_1_33 {
|
||||
pub fn read_from_toml_file<P: AsRef<Path>>(path: P) -> io::Result<Self> {
|
||||
read_config_from_toml_file(path)
|
||||
}
|
||||
|
||||
pub fn read_from_default_path<P: AsRef<Path>>(id: P) -> io::Result<Self> {
|
||||
Self::read_from_toml_file(default_config_filepath(id))
|
||||
}
|
||||
|
||||
pub fn try_upgrade(self) -> Result<Config, Socks5ClientError> {
|
||||
Ok(Config {
|
||||
core: self.core.into(),
|
||||
storage_paths: SocksClientPaths {
|
||||
common_paths: self.storage_paths.common_paths.upgrade_default()?,
|
||||
},
|
||||
logging: self.logging,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -50,10 +50,6 @@ keys.private_encryption_key_file = '{{ storage_paths.keys.private_encryption_key
|
||||
# Path to file containing public encryption key.
|
||||
keys.public_encryption_key_file = '{{ storage_paths.keys.public_encryption_key_file }}'
|
||||
|
||||
# A gateway specific, optional, base58 stringified shared key used for
|
||||
# communication with particular gateway.
|
||||
keys.gateway_shared_key_file = '{{ storage_paths.keys.gateway_shared_key_file }}'
|
||||
|
||||
# Path to file containing key used for encrypting and decrypting the content of an
|
||||
# acknowledgement so that nobody besides the client knows which packet it refers to.
|
||||
keys.ack_key_file = '{{ storage_paths.keys.ack_key_file }}'
|
||||
@@ -64,9 +60,9 @@ credentials_database = '{{ storage_paths.credentials_database }}'
|
||||
# Path to the persistent store for received reply surbs, unused encryption keys and used sender tags.
|
||||
reply_surb_database = '{{ storage_paths.reply_surb_database }}'
|
||||
|
||||
# Path to the file containing information about gateway used by this client,
|
||||
# i.e. details such as its public key, owner address or the network information.
|
||||
gateway_details = '{{ storage_paths.gateway_details }}'
|
||||
# Path to the file containing information about gateways used by this client,
|
||||
# i.e. details such as their public keys, owner addresses or the network information.
|
||||
gateway_registrations = '{{ storage_paths.gateway_registrations }}'
|
||||
|
||||
##### socket config options #####
|
||||
|
||||
@@ -77,7 +73,7 @@ provider_mix_address = '{{ core.socks5.provider_mix_address }}'
|
||||
|
||||
# The address on which the client will be listening for incoming requests
|
||||
# (default: 127.0.0.1:1080)
|
||||
bind_adddress = '{{ core.socks5.bind_adddress }}'
|
||||
bind_address = '{{ core.socks5.bind_address }}'
|
||||
|
||||
# Specifies whether this client is going to use an anonymous sender tag for communication with the service provider.
|
||||
# While this is going to hide its actual address information, it will make the actual communication
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use nym_client_core::error::ClientCoreError;
|
||||
use nym_credential_storage::error::StorageError;
|
||||
use time::OffsetDateTime;
|
||||
|
||||
use nym_id::NymIdError;
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum Socks5ClientError {
|
||||
@@ -23,21 +23,9 @@ pub enum Socks5ClientError {
|
||||
#[error(transparent)]
|
||||
ClientCoreError(#[from] ClientCoreError),
|
||||
|
||||
#[error("failed to store credential: {source}")]
|
||||
CredentialStorageFailure {
|
||||
#[from]
|
||||
source: StorageError,
|
||||
},
|
||||
#[error(transparent)]
|
||||
ConfigUpgradeFailure(#[from] nym_client_core::config::ConfigUpgradeFailure),
|
||||
|
||||
#[error(
|
||||
"failed to deserialize provided credential using revision {storage_revision}: {source}"
|
||||
)]
|
||||
CredentialDeserializationFailure {
|
||||
storage_revision: u8,
|
||||
#[source]
|
||||
source: nym_credentials::error::Error,
|
||||
},
|
||||
|
||||
#[error("attempted to import an expired credential (it expired on {expiration})")]
|
||||
ExpiredCredentialImport { expiration: OffsetDateTime },
|
||||
#[error(transparent)]
|
||||
NymIdError(#[from] NymIdError),
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
[package]
|
||||
name = "async-file-watcher"
|
||||
name = "nym-async-file-watcher"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
log = "0.4"
|
||||
tokio = { workspace = true, features = ["time"] }
|
||||
futures = { workspace = true }
|
||||
notify = "5.1.0"
|
||||
log = { workspace = true }
|
||||
notify = { workspace = true }
|
||||
tokio = { workspace = true, features = ["time"] }
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
[package]
|
||||
name = "nym-authenticator-requests"
|
||||
version = "0.1.0"
|
||||
authors.workspace = true
|
||||
repository.workspace = true
|
||||
homepage.workspace = true
|
||||
documentation.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
||||
[dependencies]
|
||||
bincode = { workspace = true }
|
||||
rand = { workspace = true }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
|
||||
nym-sphinx = { path = "../nymsphinx" }
|
||||
nym-wireguard-types = { path = "../wireguard-types" }
|
||||
@@ -0,0 +1,13 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pub mod v1;
|
||||
|
||||
pub const CURRENT_VERSION: u8 = 1;
|
||||
|
||||
fn make_bincode_serializer() -> impl bincode::Options {
|
||||
use bincode::Options;
|
||||
bincode::DefaultOptions::new()
|
||||
.with_big_endian()
|
||||
.with_varint_encoding()
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pub mod request;
|
||||
pub mod response;
|
||||
|
||||
const VERSION: u8 = 1;
|
||||
@@ -0,0 +1,70 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use nym_sphinx::addressing::Recipient;
|
||||
use nym_wireguard_types::{GatewayClient, InitMessage};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::make_bincode_serializer;
|
||||
|
||||
use super::VERSION;
|
||||
|
||||
fn generate_random() -> u64 {
|
||||
use rand::RngCore;
|
||||
let mut rng = rand::rngs::OsRng;
|
||||
rng.next_u64()
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct AuthenticatorRequest {
|
||||
pub version: u8,
|
||||
pub data: AuthenticatorRequestData,
|
||||
pub reply_to: Recipient,
|
||||
pub request_id: u64,
|
||||
}
|
||||
|
||||
impl AuthenticatorRequest {
|
||||
pub fn from_reconstructed_message(
|
||||
message: &nym_sphinx::receiver::ReconstructedMessage,
|
||||
) -> Result<Self, bincode::Error> {
|
||||
use bincode::Options;
|
||||
make_bincode_serializer().deserialize(&message.message)
|
||||
}
|
||||
|
||||
pub fn new_initial_request(init_message: InitMessage, reply_to: Recipient) -> (Self, u64) {
|
||||
let request_id = generate_random();
|
||||
(
|
||||
Self {
|
||||
version: VERSION,
|
||||
data: AuthenticatorRequestData::Initial(init_message),
|
||||
reply_to,
|
||||
request_id,
|
||||
},
|
||||
request_id,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new_final_request(gateway_client: GatewayClient, reply_to: Recipient) -> (Self, u64) {
|
||||
let request_id = generate_random();
|
||||
(
|
||||
Self {
|
||||
version: VERSION,
|
||||
data: AuthenticatorRequestData::Final(gateway_client),
|
||||
reply_to,
|
||||
request_id,
|
||||
},
|
||||
request_id,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn to_bytes(&self) -> Result<Vec<u8>, bincode::Error> {
|
||||
use bincode::Options;
|
||||
make_bincode_serializer().serialize(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub enum AuthenticatorRequestData {
|
||||
Initial(InitMessage),
|
||||
Final(GatewayClient),
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use nym_sphinx::addressing::Recipient;
|
||||
use nym_wireguard_types::registration::RegistrationData;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::make_bincode_serializer;
|
||||
|
||||
use super::VERSION;
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct AuthenticatorResponse {
|
||||
pub version: u8,
|
||||
pub data: AuthenticatorResponseData,
|
||||
pub reply_to: Recipient,
|
||||
}
|
||||
|
||||
impl AuthenticatorResponse {
|
||||
pub fn new_pending_registration_success(
|
||||
registration_data: RegistrationData,
|
||||
request_id: u64,
|
||||
reply_to: Recipient,
|
||||
) -> Self {
|
||||
Self {
|
||||
version: VERSION,
|
||||
data: AuthenticatorResponseData::PendingRegistration(PendingRegistrationResponse {
|
||||
reply: registration_data,
|
||||
reply_to,
|
||||
request_id,
|
||||
}),
|
||||
reply_to,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_registered(reply_to: Recipient, request_id: u64) -> Self {
|
||||
Self {
|
||||
version: VERSION,
|
||||
data: AuthenticatorResponseData::Registered(RegisteredResponse {
|
||||
reply_to,
|
||||
request_id,
|
||||
}),
|
||||
reply_to,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn recipient(&self) -> Recipient {
|
||||
self.reply_to
|
||||
}
|
||||
|
||||
pub fn to_bytes(&self) -> Result<Vec<u8>, bincode::Error> {
|
||||
use bincode::Options;
|
||||
make_bincode_serializer().serialize(self)
|
||||
}
|
||||
|
||||
pub fn from_reconstructed_message(
|
||||
message: &nym_sphinx::receiver::ReconstructedMessage,
|
||||
) -> Result<Self, bincode::Error> {
|
||||
use bincode::Options;
|
||||
make_bincode_serializer().deserialize(&message.message)
|
||||
}
|
||||
|
||||
pub fn id(&self) -> Option<u64> {
|
||||
match &self.data {
|
||||
AuthenticatorResponseData::PendingRegistration(response) => Some(response.request_id),
|
||||
AuthenticatorResponseData::Registered(response) => Some(response.request_id),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub enum AuthenticatorResponseData {
|
||||
PendingRegistration(PendingRegistrationResponse),
|
||||
Registered(RegisteredResponse),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct PendingRegistrationResponse {
|
||||
pub request_id: u64,
|
||||
pub reply_to: Recipient,
|
||||
pub reply: RegistrationData,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct RegisteredResponse {
|
||||
pub request_id: u64,
|
||||
pub reply_to: Recipient,
|
||||
}
|
||||
@@ -9,7 +9,7 @@ license.workspace = true
|
||||
[dependencies]
|
||||
bip39 = { workspace = true }
|
||||
log = { workspace = true }
|
||||
rand = "0.7.3"
|
||||
rand = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
url = { workspace = true }
|
||||
zeroize = { workspace = true }
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// See other comments for other TaskStatus message enumds about abusing the Error trait when we
|
||||
// should have a new trait for TaskStatus messages
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum BandwidthStatusMessage {
|
||||
#[error("remaining bandwidth: {0}")]
|
||||
RemainingBandwidth(i64),
|
||||
|
||||
#[error("no bandwidth left")]
|
||||
NoBandwidth,
|
||||
}
|
||||
@@ -14,10 +14,14 @@ use nym_validator_client::coconut::all_coconut_api_clients;
|
||||
use nym_validator_client::nym_api::EpochId;
|
||||
use nym_validator_client::nyxd::contract_traits::DkgQueryClient;
|
||||
|
||||
pub use event::BandwidthStatusMessage;
|
||||
|
||||
pub mod acquire;
|
||||
pub mod error;
|
||||
mod event;
|
||||
mod utils;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct BandwidthController<C, St> {
|
||||
storage: St,
|
||||
client: C,
|
||||
@@ -49,6 +53,7 @@ impl<C, St: Storage> BandwidthController<C, St> {
|
||||
/// It marks any retrieved intermediate credentials as expired.
|
||||
pub async fn get_next_usable_credential(
|
||||
&self,
|
||||
gateway_id: &str,
|
||||
) -> Result<RetrievedCredential, BandwidthControllerError>
|
||||
where
|
||||
<St as Storage>::StorageError: Send + Sync + 'static,
|
||||
@@ -56,7 +61,7 @@ impl<C, St: Storage> BandwidthController<C, St> {
|
||||
loop {
|
||||
let Some(maybe_next) = self
|
||||
.storage
|
||||
.get_next_unspent_credential()
|
||||
.get_next_unspent_credential(gateway_id)
|
||||
.await
|
||||
.map_err(|err| BandwidthControllerError::CredentialStorageError(Box::new(err)))?
|
||||
else {
|
||||
@@ -114,12 +119,13 @@ impl<C, St: Storage> BandwidthController<C, St> {
|
||||
|
||||
pub async fn prepare_bandwidth_credential(
|
||||
&self,
|
||||
gateway_id: &str,
|
||||
) -> Result<PreparedCredential, BandwidthControllerError>
|
||||
where
|
||||
C: DkgQueryClient + Sync + Send,
|
||||
<St as Storage>::StorageError: Send + Sync + 'static,
|
||||
{
|
||||
let retrieved_credential = self.get_next_usable_credential().await?;
|
||||
let retrieved_credential = self.get_next_usable_credential(gateway_id).await?;
|
||||
|
||||
let epoch_id = retrieved_credential.credential.epoch_id();
|
||||
let credential_id = retrieved_credential.credential_id;
|
||||
@@ -137,14 +143,16 @@ impl<C, St: Storage> BandwidthController<C, St> {
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn consume_credential(&self, id: i64) -> Result<(), BandwidthControllerError>
|
||||
pub async fn consume_credential(
|
||||
&self,
|
||||
id: i64,
|
||||
gateway_id: &str,
|
||||
) -> Result<(), BandwidthControllerError>
|
||||
where
|
||||
<St as Storage>::StorageError: Send + Sync + 'static,
|
||||
{
|
||||
// JS: shouldn't we send some contract/validator/gateway message here to actually, you know,
|
||||
// consume it?
|
||||
self.storage
|
||||
.consume_coconut_credential(id)
|
||||
.consume_coconut_credential(id, gateway_id)
|
||||
.await
|
||||
.map_err(|err| BandwidthControllerError::CredentialStorageError(Box::new(err)))
|
||||
}
|
||||
|
||||
@@ -8,46 +8,33 @@ license = { workspace = true }
|
||||
repository = { workspace = true }
|
||||
|
||||
[dependencies]
|
||||
atty = "0.2"
|
||||
const-str = "0.5.6"
|
||||
clap = { workspace = true, features = ["derive"] }
|
||||
clap_complete = "4.0"
|
||||
clap_complete_fig = "4.0"
|
||||
const-str = { workspace = true }
|
||||
clap = { workspace = true, features = ["derive"], optional = true }
|
||||
clap_complete = { workspace = true, optional = true }
|
||||
clap_complete_fig = { workspace = true, optional = true }
|
||||
log = { workspace = true }
|
||||
pretty_env_logger = "0.4.0"
|
||||
pretty_env_logger = { workspace = true }
|
||||
semver = "0.11"
|
||||
schemars = { workspace = true, features = ["preserve_order"], optional = true }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
serde_json = { workspace = true, optional = true }
|
||||
|
||||
## tracing
|
||||
tracing-subscriber = { version = "0.3.16", features = [
|
||||
"env-filter",
|
||||
], optional = true }
|
||||
tracing-tree = { version = "0.2.2", optional = true }
|
||||
opentelemetry-jaeger = { version = "0.18.0", optional = true, features = [
|
||||
"rt-tokio",
|
||||
"collector_client",
|
||||
"isahc_collector_client",
|
||||
] }
|
||||
tracing-opentelemetry = { version = "0.19.0", optional = true }
|
||||
tracing-subscriber = { workspace = true, features = ["env-filter"], optional = true }
|
||||
tracing-tree = { workspace = true, optional = true }
|
||||
opentelemetry-jaeger = { workspace = true, features = ["rt-tokio", "collector_client", "isahc_collector_client"], optional = true }
|
||||
tracing-opentelemetry = { workspace = true, optional = true }
|
||||
utoipa = { workspace = true, optional = true }
|
||||
opentelemetry = { version = "0.19.0", optional = true, features = ["rt-tokio"] }
|
||||
opentelemetry = { workspace = true, features = ["rt-tokio"], optional = true }
|
||||
|
||||
|
||||
[build-dependencies]
|
||||
vergen = { version = "=8.2.6", default-features = false, features = [
|
||||
"build",
|
||||
"git",
|
||||
"gitcl",
|
||||
"rustc",
|
||||
"cargo",
|
||||
] }
|
||||
vergen = { workspace = true, features = ["build", "git", "gitcl", "rustc", "cargo"] }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
openapi = ["utoipa"]
|
||||
output_format = ["serde_json"]
|
||||
output_format = ["serde_json", "dep:clap"]
|
||||
bin_info_schema = ["schemars"]
|
||||
basic_tracing = ["tracing-subscriber"]
|
||||
tracing = [
|
||||
@@ -57,3 +44,4 @@ tracing = [
|
||||
"tracing-opentelemetry",
|
||||
"opentelemetry",
|
||||
]
|
||||
clap = [ "dep:clap", "dep:clap_complete", "dep:clap_complete_fig" ]
|
||||
|
||||
@@ -44,6 +44,10 @@ pub struct BinaryBuildInformation {
|
||||
/// Provides the cargo debug mode that was used for the build.
|
||||
// NOTE: keep the old name cargo_profile instead of cargo_debug for backwards compatibility
|
||||
pub cargo_profile: &'static str,
|
||||
|
||||
// VERGEN_CARGO_TARGET_TRIPLE
|
||||
/// Provides the cargo target triple that was used for the build.
|
||||
pub cargo_triple: &'static str,
|
||||
}
|
||||
|
||||
impl BinaryBuildInformation {
|
||||
@@ -66,6 +70,37 @@ impl BinaryBuildInformation {
|
||||
rustc_version: env!("VERGEN_RUSTC_SEMVER"),
|
||||
rustc_channel: env!("VERGEN_RUSTC_CHANNEL"),
|
||||
cargo_profile,
|
||||
cargo_triple: env!("VERGEN_CARGO_TARGET_TRIPLE"),
|
||||
}
|
||||
}
|
||||
|
||||
// Varient where we want to use the metadata generated by vergen in the consuming crate.
|
||||
pub const fn new_with_local_vergen(
|
||||
binary_name: &'static str,
|
||||
build_timestamp: &'static str,
|
||||
build_version: &'static str,
|
||||
commit_sha: &'static str,
|
||||
commit_timestamp: &'static str,
|
||||
commit_branch: &'static str,
|
||||
) -> Self {
|
||||
let cargo_debug = env!("VERGEN_CARGO_DEBUG");
|
||||
let cargo_profile = if const_str::equal!(cargo_debug, "true") {
|
||||
"debug"
|
||||
} else {
|
||||
"release"
|
||||
};
|
||||
|
||||
BinaryBuildInformation {
|
||||
binary_name,
|
||||
build_timestamp,
|
||||
build_version,
|
||||
commit_sha,
|
||||
commit_timestamp,
|
||||
commit_branch,
|
||||
rustc_version: env!("VERGEN_RUSTC_SEMVER"),
|
||||
rustc_channel: env!("VERGEN_RUSTC_CHANNEL"),
|
||||
cargo_profile,
|
||||
cargo_triple: env!("VERGEN_CARGO_TARGET_TRIPLE"),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,6 +115,7 @@ impl BinaryBuildInformation {
|
||||
rustc_version: self.rustc_version.to_owned(),
|
||||
rustc_channel: self.rustc_channel.to_owned(),
|
||||
cargo_profile: self.cargo_profile.to_owned(),
|
||||
cargo_triple: self.cargo_triple.to_owned(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,6 +163,15 @@ pub struct BinaryBuildInformationOwned {
|
||||
/// Provides the cargo debug mode that was used for the build.
|
||||
// NOTE: keep the old name cargo_profile instead of cargo_debug for backwards compatibility
|
||||
pub cargo_profile: String,
|
||||
|
||||
// VERGEN_CARGO_TARGET_TRIPLE
|
||||
/// Provides the cargo target triple that was used for the build.
|
||||
#[serde(default = "unknown")]
|
||||
pub cargo_triple: String,
|
||||
}
|
||||
|
||||
fn unknown() -> String {
|
||||
"unknown".to_string()
|
||||
}
|
||||
|
||||
impl Display for BinaryBuildInformationOwned {
|
||||
@@ -187,3 +232,33 @@ macro_rules! bin_info_owned {
|
||||
.to_owned()
|
||||
};
|
||||
}
|
||||
|
||||
// variant that picks up the vergen build information generated by the build.rs in the consumer
|
||||
// crate.
|
||||
#[macro_export]
|
||||
macro_rules! bin_info_local_vergen {
|
||||
() => {
|
||||
$crate::build_information::BinaryBuildInformation::new_with_local_vergen(
|
||||
env!("CARGO_PKG_NAME"),
|
||||
env!("VERGEN_BUILD_TIMESTAMP"),
|
||||
env!("CARGO_PKG_VERSION"),
|
||||
env!("VERGEN_GIT_SHA"),
|
||||
env!("VERGEN_GIT_COMMIT_TIMESTAMP"),
|
||||
env!("VERGEN_GIT_BRANCH"),
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! bin_info_local_vergen_owned {
|
||||
() => {
|
||||
$crate::build_information::BinaryBuildInformation::new_with_local_vergen(
|
||||
env!("CARGO_PKG_NAME"),
|
||||
env!("VERGEN_BUILD_TIMESTAMP"),
|
||||
env!("CARGO_PKG_VERSION"),
|
||||
env!("VERGEN_GIT_SHA"),
|
||||
env!("VERGEN_GIT_COMMIT_TIMESTAMP"),
|
||||
env!("VERGEN_GIT_BRANCH"),
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -2,9 +2,11 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pub mod build_information;
|
||||
pub mod completions;
|
||||
pub mod logging;
|
||||
pub mod version_checker;
|
||||
|
||||
#[cfg(feature = "clap")]
|
||||
pub mod completions;
|
||||
|
||||
#[cfg(feature = "output_format")]
|
||||
pub mod output_format;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::io::IsTerminal;
|
||||
|
||||
#[cfg(feature = "tracing")]
|
||||
pub use opentelemetry;
|
||||
@@ -14,7 +15,7 @@ pub use tracing_subscriber;
|
||||
#[cfg(feature = "tracing")]
|
||||
pub use tracing_tree;
|
||||
|
||||
#[derive(Debug, Default, Clone, Deserialize, PartialEq, Eq, Serialize)]
|
||||
#[derive(Debug, Default, Copy, Clone, Deserialize, PartialEq, Eq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct LoggingSettings {
|
||||
// well, we need to implement something here at some point...
|
||||
@@ -120,7 +121,7 @@ pub fn banner(crate_name: &str, crate_version: &str) -> String {
|
||||
}
|
||||
|
||||
pub fn maybe_print_banner(crate_name: &str, crate_version: &str) {
|
||||
if atty::is(atty::Stream::Stdout) {
|
||||
if std::io::stdout().is_terminal() {
|
||||
println!("{}", banner(crate_name, crate_version))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,41 +3,42 @@ name = "nym-client-core"
|
||||
version = "1.1.15"
|
||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
|
||||
edition = "2021"
|
||||
rust-version = "1.66"
|
||||
rust-version = "1.70"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
async-trait = { workspace = true }
|
||||
base64 = "0.21.2"
|
||||
cfg-if = "1.0.0"
|
||||
base64 = { workspace = true }
|
||||
bs58 = { workspace = true }
|
||||
cfg-if = { workspace = true }
|
||||
clap = { workspace = true, optional = true }
|
||||
dashmap = { workspace = true }
|
||||
dirs = "4.0"
|
||||
futures = { workspace = true }
|
||||
humantime-serde = "1.0"
|
||||
humantime-serde = { workspace = true }
|
||||
log = { workspace = true }
|
||||
rand = { version = "0.7.3", features = ["wasm-bindgen"] }
|
||||
reqwest = { workspace = true }
|
||||
rand = { workspace = true }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
serde_json = { workspace = true }
|
||||
sha2 = "0.10.6"
|
||||
tap = "1.0.1"
|
||||
sha2 = { workspace = true }
|
||||
si-scale = { workspace = true }
|
||||
tap = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
url = { workspace = true, features = ["serde"] }
|
||||
tungstenite = { workspace = true, default-features = false }
|
||||
tokio = { workspace = true, features = ["macros"]}
|
||||
time = "0.3.17"
|
||||
tokio = { workspace = true, features = ["macros"] }
|
||||
time = { workspace = true }
|
||||
zeroize = { workspace = true }
|
||||
|
||||
# internal
|
||||
nym-id = { path = "../nym-id" }
|
||||
nym-bandwidth-controller = { path = "../bandwidth-controller" }
|
||||
nym-config = { path = "../config" }
|
||||
nym-country-group = { path = "../country-group" }
|
||||
nym-crypto = { path = "../crypto" }
|
||||
nym-explorer-client = { path = "../../explorer-api/explorer-client" }
|
||||
nym-gateway-client = { path = "../client-libs/gateway-client" }
|
||||
nym-gateway-requests = { path = "../../gateway/gateway-requests" }
|
||||
nym-metrics = { path = "../nym-metrics" }
|
||||
nym-nonexhaustive-delayqueue = { path = "../nonexhaustive-delayqueue" }
|
||||
nym-sphinx = { path = "../nymsphinx" }
|
||||
nym-pemstore = { path = "../pemstore" }
|
||||
@@ -46,7 +47,22 @@ nym-validator-client = { path = "../client-libs/validator-client", default-featu
|
||||
nym-task = { path = "../task" }
|
||||
nym-credential-storage = { path = "../credential-storage" }
|
||||
nym-network-defaults = { path = "../network-defaults" }
|
||||
si-scale = "0.2.2"
|
||||
nym-client-core-config-types = { path = "./config-types", features = ["disk-persistence"] }
|
||||
nym-client-core-surb-storage = { path = "./surb-storage" }
|
||||
nym-client-core-gateways-storage = { path = "./gateways-storage" }
|
||||
|
||||
### For serving prometheus metrics
|
||||
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.hyper]
|
||||
version = "1"
|
||||
features = ["server", "http1"]
|
||||
|
||||
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.http-body-util]
|
||||
version = "0.1"
|
||||
|
||||
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.hyper-util]
|
||||
version = "0.1"
|
||||
features = ["tokio"]
|
||||
###
|
||||
|
||||
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio-stream]
|
||||
version = "0.1.11"
|
||||
@@ -57,12 +73,17 @@ workspace = true
|
||||
features = ["time"]
|
||||
|
||||
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio-tungstenite]
|
||||
version = "0.20.1"
|
||||
|
||||
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.sqlx]
|
||||
workspace = true
|
||||
features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate"]
|
||||
optional = true
|
||||
features = ["rustls-tls-webpki-roots"]
|
||||
|
||||
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tungstenite]
|
||||
workspace = true
|
||||
default-features = true
|
||||
features = ["rustls-tls-webpki-roots"]
|
||||
|
||||
[target."cfg(target_arch = \"wasm32\")".dependencies.tungstenite]
|
||||
workspace = true
|
||||
default-features = false
|
||||
|
||||
[target."cfg(target_arch = \"wasm32\")".dependencies.wasm-bindgen-futures]
|
||||
workspace = true
|
||||
@@ -87,15 +108,12 @@ version = "0.3.17"
|
||||
features = ["wasm-bindgen"]
|
||||
|
||||
[dev-dependencies]
|
||||
tempfile = "3.1.0"
|
||||
|
||||
[build-dependencies]
|
||||
tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
|
||||
sqlx = { workspace = true, features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate"] }
|
||||
tempfile = { workspace = true }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
cli = ["clap"]
|
||||
fs-surb-storage = ["sqlx"]
|
||||
fs-surb-storage = ["nym-client-core-surb-storage/fs-surb-storage"]
|
||||
fs-gateways-storage = ["nym-client-core-gateways-storage/fs-gateways-storage"]
|
||||
wasm = ["nym-gateway-client/wasm"]
|
||||
|
||||
metrics-server = []
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
[package]
|
||||
name = "nym-client-core-config-types"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
humantime-serde = { workspace = true }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
thiserror.workspace = true
|
||||
url = { workspace = true, features = ["serde"] }
|
||||
|
||||
nym-config = { path = "../../config" }
|
||||
|
||||
nym-country-group = { path = "../../country-group" }
|
||||
nym-pemstore = { path = "../../pemstore", optional = true }
|
||||
|
||||
# those are pulling so many deps T.T
|
||||
nym-sphinx-params = { path = "../../nymsphinx/params" }
|
||||
nym-sphinx-addressing = { path = "../../nymsphinx/addressing" }
|
||||
|
||||
|
||||
[features]
|
||||
disk-persistence = ["nym-pemstore"]
|
||||
+39
-17
@@ -1,16 +1,53 @@
|
||||
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
pub mod old;
|
||||
|
||||
// preserve old structure for easier migration
|
||||
pub use old::{old_v1_1_20_2, old_v1_1_33};
|
||||
|
||||
pub const DEFAULT_REPLY_SURB_DB_FILENAME: &str = "persistent_reply_store.sqlite";
|
||||
pub const DEFAULT_CREDENTIALS_DB_FILENAME: &str = "credentials_database.db";
|
||||
pub const DEFAULT_GATEWAYS_DETAILS_DB_FILENAME: &str = "gateways_registrations.sqlite";
|
||||
|
||||
pub const DEFAULT_PRIVATE_IDENTITY_KEY_FILENAME: &str = "private_identity.pem";
|
||||
pub const DEFAULT_PUBLIC_IDENTITY_KEY_FILENAME: &str = "public_identity.pem";
|
||||
pub const DEFAULT_PRIVATE_ENCRYPTION_KEY_FILENAME: &str = "private_encryption.pem";
|
||||
pub const DEFAULT_PUBLIC_ENCRYPTION_KEY_FILENAME: &str = "public_encryption.pem";
|
||||
pub const DEFAULT_GATEWAY_SHARED_KEY_FILENAME: &str = "gateway_shared.pem";
|
||||
pub const DEFAULT_ACK_KEY_FILENAME: &str = "ack_key.pem";
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct CommonClientPaths {
|
||||
pub keys: ClientKeysPaths,
|
||||
|
||||
/// Path to the file containing information about gateways used by this client,
|
||||
/// i.e. details such as their public keys, owner addresses or the network information.
|
||||
pub gateway_registrations: PathBuf,
|
||||
|
||||
/// Path to the database containing bandwidth credentials of this client.
|
||||
pub credentials_database: PathBuf,
|
||||
|
||||
/// Path to the persistent store for received reply surbs, unused encryption keys and used sender tags.
|
||||
pub reply_surb_database: PathBuf,
|
||||
}
|
||||
|
||||
impl CommonClientPaths {
|
||||
pub fn new_base<P: AsRef<Path>>(base_data_directory: P) -> Self {
|
||||
let base_dir = base_data_directory.as_ref();
|
||||
|
||||
CommonClientPaths {
|
||||
credentials_database: base_dir.join(DEFAULT_CREDENTIALS_DB_FILENAME),
|
||||
reply_surb_database: base_dir.join(DEFAULT_REPLY_SURB_DB_FILENAME),
|
||||
gateway_registrations: base_dir.join(DEFAULT_GATEWAYS_DETAILS_DB_FILENAME),
|
||||
keys: ClientKeysPaths::new_base(base_data_directory),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
|
||||
pub struct ClientKeysPaths {
|
||||
/// Path to file containing private identity key.
|
||||
@@ -25,10 +62,6 @@ pub struct ClientKeysPaths {
|
||||
/// Path to file containing public encryption key.
|
||||
pub public_encryption_key_file: PathBuf,
|
||||
|
||||
/// Path to file containing shared key derived with the specified gateway that is used
|
||||
/// for all communication with it.
|
||||
pub gateway_shared_key_file: PathBuf,
|
||||
|
||||
/// Path to file containing key used for encrypting and decrypting the content of an
|
||||
/// acknowledgement so that nobody besides the client knows which packet it refers to.
|
||||
pub ack_key_file: PathBuf,
|
||||
@@ -43,7 +76,6 @@ impl ClientKeysPaths {
|
||||
public_identity_key_file: base_dir.join(DEFAULT_PUBLIC_IDENTITY_KEY_FILENAME),
|
||||
private_encryption_key_file: base_dir.join(DEFAULT_PRIVATE_ENCRYPTION_KEY_FILENAME),
|
||||
public_encryption_key_file: base_dir.join(DEFAULT_PUBLIC_ENCRYPTION_KEY_FILENAME),
|
||||
gateway_shared_key_file: base_dir.join(DEFAULT_GATEWAY_SHARED_KEY_FILENAME),
|
||||
ack_key_file: base_dir.join(DEFAULT_ACK_KEY_FILENAME),
|
||||
}
|
||||
}
|
||||
@@ -67,7 +99,6 @@ impl ClientKeysPaths {
|
||||
|| matches!(self.private_identity_key_file.try_exists(), Ok(true))
|
||||
|| matches!(self.public_encryption_key_file.try_exists(), Ok(true))
|
||||
|| matches!(self.private_encryption_key_file.try_exists(), Ok(true))
|
||||
|| matches!(self.gateway_shared_key_file.try_exists(), Ok(true))
|
||||
|| matches!(self.ack_key_file.try_exists(), Ok(true))
|
||||
}
|
||||
|
||||
@@ -76,14 +107,9 @@ impl ClientKeysPaths {
|
||||
.or_else(|| file_exists(&self.private_identity_key_file))
|
||||
.or_else(|| file_exists(&self.public_encryption_key_file))
|
||||
.or_else(|| file_exists(&self.private_encryption_key_file))
|
||||
.or_else(|| file_exists(&self.gateway_shared_key_file))
|
||||
.or_else(|| file_exists(&self.ack_key_file))
|
||||
}
|
||||
|
||||
pub fn gateway_key_file_exists(&self) -> bool {
|
||||
matches!(self.gateway_shared_key_file.try_exists(), Ok(true))
|
||||
}
|
||||
|
||||
pub fn private_identity_key(&self) -> &Path {
|
||||
&self.private_identity_key_file
|
||||
}
|
||||
@@ -100,10 +126,6 @@ impl ClientKeysPaths {
|
||||
&self.public_encryption_key_file
|
||||
}
|
||||
|
||||
pub fn gateway_shared_key(&self) -> &Path {
|
||||
&self.gateway_shared_key_file
|
||||
}
|
||||
|
||||
pub fn ack_key(&self) -> &Path {
|
||||
&self.ack_key_file
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pub mod v1;
|
||||
pub mod v2;
|
||||
|
||||
// aliases for backwards compatibility
|
||||
pub use v1 as old_v1_1_20_2;
|
||||
pub use v2 as old_v1_1_33;
|
||||
@@ -0,0 +1,37 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::disk_persistence::old::v2::{
|
||||
ClientKeysPathsV2, CommonClientPathsV2, DEFAULT_GATEWAY_DETAILS_FILENAME,
|
||||
};
|
||||
use crate::error::ConfigUpgradeFailure;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::path::PathBuf;
|
||||
|
||||
// aliases for backwards compatibility
|
||||
pub type CommonClientPathsV1_1_20_2 = CommonClientPathsV1;
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct CommonClientPathsV1 {
|
||||
pub keys: ClientKeysPathsV2,
|
||||
pub credentials_database: PathBuf,
|
||||
pub reply_surb_database: PathBuf,
|
||||
}
|
||||
|
||||
impl CommonClientPathsV1 {
|
||||
pub fn upgrade_default(self) -> Result<CommonClientPathsV2, ConfigUpgradeFailure> {
|
||||
let data_dir = self
|
||||
.reply_surb_database
|
||||
.parent()
|
||||
.ok_or_else(|| ConfigUpgradeFailure {
|
||||
current_version: "1.1.20-2".to_string(),
|
||||
})?;
|
||||
Ok(CommonClientPathsV2 {
|
||||
keys: self.keys,
|
||||
gateway_details: data_dir.join(DEFAULT_GATEWAY_DETAILS_FILENAME),
|
||||
credentials_database: self.credentials_database,
|
||||
reply_surb_database: self.reply_surb_database,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::disk_persistence::ClientKeysPaths;
|
||||
use crate::disk_persistence::{CommonClientPaths, DEFAULT_GATEWAYS_DETAILS_DB_FILENAME};
|
||||
use crate::error::ConfigUpgradeFailure;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub const DEFAULT_GATEWAY_DETAILS_FILENAME: &str = "gateway_details.json";
|
||||
|
||||
// aliases for backwards compatibility
|
||||
pub type CommonClientPathsV1_1_33 = CommonClientPathsV2;
|
||||
pub type ClientKeysPathsV1_1_33 = ClientKeysPathsV2;
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
|
||||
pub struct ClientKeysPathsV2 {
|
||||
/// Path to file containing private identity key.
|
||||
pub private_identity_key_file: PathBuf,
|
||||
|
||||
/// Path to file containing public identity key.
|
||||
pub public_identity_key_file: PathBuf,
|
||||
|
||||
/// Path to file containing private encryption key.
|
||||
pub private_encryption_key_file: PathBuf,
|
||||
|
||||
/// Path to file containing public encryption key.
|
||||
pub public_encryption_key_file: PathBuf,
|
||||
|
||||
/// Path to file containing shared key derived with the specified gateway that is used
|
||||
/// for all communication with it.
|
||||
pub gateway_shared_key_file: PathBuf,
|
||||
|
||||
/// Path to file containing key used for encrypting and decrypting the content of an
|
||||
/// acknowledgement so that nobody besides the client knows which packet it refers to.
|
||||
pub ack_key_file: PathBuf,
|
||||
}
|
||||
|
||||
impl ClientKeysPathsV2 {
|
||||
pub fn upgrade(self) -> ClientKeysPaths {
|
||||
ClientKeysPaths {
|
||||
private_identity_key_file: self.private_identity_key_file,
|
||||
public_identity_key_file: self.public_identity_key_file,
|
||||
private_encryption_key_file: self.private_encryption_key_file,
|
||||
public_encryption_key_file: self.public_encryption_key_file,
|
||||
ack_key_file: self.ack_key_file,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct CommonClientPathsV2 {
|
||||
pub keys: ClientKeysPathsV2,
|
||||
|
||||
/// Path to the file containing information about gateway used by this client,
|
||||
/// i.e. details such as its public key, owner address or the network information.
|
||||
pub gateway_details: PathBuf,
|
||||
|
||||
/// Path to the database containing bandwidth credentials of this client.
|
||||
pub credentials_database: PathBuf,
|
||||
|
||||
/// Path to the persistent store for received reply surbs, unused encryption keys and used sender tags.
|
||||
pub reply_surb_database: PathBuf,
|
||||
}
|
||||
|
||||
impl CommonClientPathsV2 {
|
||||
// note that during the upgrade process, the caller will need to extract the key and gateway details
|
||||
// manually and resave them in the new database
|
||||
pub fn upgrade_default(self) -> Result<CommonClientPaths, ConfigUpgradeFailure> {
|
||||
let data_dir = self
|
||||
.gateway_details
|
||||
.parent()
|
||||
.ok_or_else(|| ConfigUpgradeFailure {
|
||||
current_version: "1.1.33".to_string(),
|
||||
})?;
|
||||
|
||||
Ok(CommonClientPaths {
|
||||
keys: self.keys.upgrade(),
|
||||
gateway_registrations: data_dir.join(DEFAULT_GATEWAYS_DETAILS_DB_FILENAME),
|
||||
credentials_database: self.credentials_database,
|
||||
reply_surb_database: self.reply_surb_database,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
#[error("unable to upgrade config file from `{current_version}`")]
|
||||
pub struct ConfigUpgradeFailure {
|
||||
pub current_version: String,
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum InvalidTrafficModeFailure {
|
||||
#[error("attempted to set medium toggle traffic mode with fast mode flag")]
|
||||
MediumToggleWithFastMode,
|
||||
|
||||
#[error("attempted to set medium toggle traffic mode with no cover flag")]
|
||||
MediumToggleWithNoCover,
|
||||
}
|
||||
@@ -0,0 +1,677 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use nym_config::defaults::NymNetworkDetails;
|
||||
use nym_sphinx_addressing::Recipient;
|
||||
use nym_sphinx_params::{PacketSize, PacketType};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::time::Duration;
|
||||
use url::Url;
|
||||
|
||||
#[cfg(feature = "disk-persistence")]
|
||||
pub mod disk_persistence;
|
||||
pub mod error;
|
||||
pub mod old;
|
||||
|
||||
pub use error::ConfigUpgradeFailure;
|
||||
|
||||
// 'DEBUG'
|
||||
const DEFAULT_ACK_WAIT_MULTIPLIER: f64 = 1.5;
|
||||
|
||||
const DEFAULT_ACK_WAIT_ADDITION: Duration = Duration::from_millis(1_500);
|
||||
const DEFAULT_LOOP_COVER_STREAM_AVERAGE_DELAY: Duration = Duration::from_millis(200);
|
||||
const DEFAULT_MESSAGE_STREAM_AVERAGE_DELAY: Duration = Duration::from_millis(20);
|
||||
const DEFAULT_AVERAGE_PACKET_DELAY: Duration = Duration::from_millis(50);
|
||||
const DEFAULT_TOPOLOGY_REFRESH_RATE: Duration = Duration::from_secs(5 * 60); // every 5min
|
||||
const DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT: Duration = Duration::from_millis(5_000);
|
||||
|
||||
// the same values as our current (10.06.24) blacklist
|
||||
const DEFAULT_MIN_MIXNODE_PERFORMANCE: u8 = 50;
|
||||
const DEFAULT_MIN_GATEWAY_PERFORMANCE: u8 = 50;
|
||||
|
||||
const DEFAULT_MAX_STARTUP_GATEWAY_WAITING_PERIOD: Duration = Duration::from_secs(70 * 60); // 70min -> full epoch (1h) + a bit of overhead
|
||||
|
||||
// Set this to a high value for now, so that we don't risk sporadic timeouts that might cause
|
||||
// bought bandwidth tokens to not have time to be spent; Once we remove the gateway from the
|
||||
// bandwidth bridging protocol, we can come back to a smaller timeout value
|
||||
const DEFAULT_GATEWAY_RESPONSE_TIMEOUT: Duration = Duration::from_secs(5 * 60);
|
||||
|
||||
const DEFAULT_COVER_TRAFFIC_PRIMARY_SIZE_RATIO: f64 = 0.70;
|
||||
|
||||
// reply-surbs related:
|
||||
|
||||
// define when to request
|
||||
// clients/client-core/src/client/replies/reply_storage/surb_storage.rs
|
||||
const DEFAULT_MINIMUM_REPLY_SURB_STORAGE_THRESHOLD: usize = 10;
|
||||
const DEFAULT_MAXIMUM_REPLY_SURB_STORAGE_THRESHOLD: usize = 200;
|
||||
|
||||
// define how much to request at once
|
||||
// clients/client-core/src/client/replies/reply_controller.rs
|
||||
const DEFAULT_MINIMUM_REPLY_SURB_REQUEST_SIZE: u32 = 10;
|
||||
const DEFAULT_MAXIMUM_REPLY_SURB_REQUEST_SIZE: u32 = 100;
|
||||
|
||||
const DEFAULT_MAXIMUM_ALLOWED_SURB_REQUEST_SIZE: u32 = 500;
|
||||
|
||||
const DEFAULT_MAXIMUM_REPLY_SURB_REREQUEST_WAITING_PERIOD: Duration = Duration::from_secs(10);
|
||||
const DEFAULT_MAXIMUM_REPLY_SURB_DROP_WAITING_PERIOD: Duration = Duration::from_secs(5 * 60);
|
||||
|
||||
// 12 hours
|
||||
const DEFAULT_MAXIMUM_REPLY_SURB_AGE: Duration = Duration::from_secs(12 * 60 * 60);
|
||||
|
||||
// 24 hours
|
||||
const DEFAULT_MAXIMUM_REPLY_KEY_AGE: Duration = Duration::from_secs(24 * 60 * 60);
|
||||
|
||||
use crate::error::InvalidTrafficModeFailure;
|
||||
pub use nym_country_group::CountryGroup;
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Config {
|
||||
pub client: Client,
|
||||
|
||||
#[serde(default)]
|
||||
pub debug: DebugConfig,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub fn new<S1, S2>(id: S1, version: S2) -> Self
|
||||
where
|
||||
S1: Into<String>,
|
||||
S2: Into<String>,
|
||||
{
|
||||
Config {
|
||||
client: Client::new_default(id, version),
|
||||
debug: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_client_config(client: Client, debug: DebugConfig) -> Self {
|
||||
Config { client, debug }
|
||||
}
|
||||
|
||||
pub fn validate(&self) -> bool {
|
||||
self.debug.validate()
|
||||
}
|
||||
|
||||
pub fn with_debug_config(mut self, debug: DebugConfig) -> Self {
|
||||
self.debug = debug;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_disabled_credentials(mut self, disabled_credentials_mode: bool) -> Self {
|
||||
self.client.disabled_credentials_mode = disabled_credentials_mode;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_custom_nyxd(mut self, urls: Vec<Url>) -> Self {
|
||||
self.client.nyxd_urls = urls;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_custom_nyxd(&mut self, nyxd_urls: Vec<Url>) {
|
||||
self.client.nyxd_urls = nyxd_urls;
|
||||
}
|
||||
|
||||
pub fn with_custom_nym_apis(mut self, nym_api_urls: Vec<Url>) -> Self {
|
||||
self.client.nym_api_urls = nym_api_urls;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_custom_nym_apis(&mut self, nym_api_urls: Vec<Url>) {
|
||||
self.client.nym_api_urls = nym_api_urls;
|
||||
}
|
||||
|
||||
pub fn with_high_default_traffic_volume(mut self, enabled: bool) -> Self {
|
||||
if enabled {
|
||||
self.set_high_default_traffic_volume();
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_packet_type(mut self, packet_type: PacketType) -> Self {
|
||||
self.debug.traffic.packet_type = packet_type;
|
||||
self
|
||||
}
|
||||
|
||||
// TODO: this should be refactored properly
|
||||
// as of 12.09.23 the below is true (not sure how this comment will rot in the future)
|
||||
// medium_toggle:
|
||||
// - sets secondary packet size to 16kb
|
||||
// - disables poisson distribution of the main traffic stream
|
||||
// - sets the cover traffic stream to 1 packet / 5s (on average)
|
||||
// - disables per hop delay
|
||||
//
|
||||
// fastmode (to be renamed to `fast-poisson`):
|
||||
// - sets average per hop delay to 10ms
|
||||
// - sets the cover traffic stream to 1 packet / 2000s (on average); for all intents and purposes it disables the stream
|
||||
// - sets the poisson distribution of the main traffic stream to 4ms, i.e. 250 packets / s on average
|
||||
//
|
||||
// no_cover:
|
||||
// - disables poisson distribution of the main traffic stream
|
||||
// - disables the secondary cover traffic stream
|
||||
#[doc(hidden)]
|
||||
pub fn try_apply_traffic_modes(
|
||||
&mut self,
|
||||
disable_poisson_process: bool,
|
||||
medium_toggle: bool,
|
||||
fast_mode: bool,
|
||||
no_cover: bool,
|
||||
) -> Result<(), InvalidTrafficModeFailure> {
|
||||
if disable_poisson_process {
|
||||
self.set_no_poisson_process()
|
||||
}
|
||||
|
||||
if medium_toggle {
|
||||
if fast_mode {
|
||||
return Err(InvalidTrafficModeFailure::MediumToggleWithFastMode);
|
||||
}
|
||||
if no_cover {
|
||||
return Err(InvalidTrafficModeFailure::MediumToggleWithNoCover);
|
||||
}
|
||||
|
||||
self.set_experimental_medium_toggle();
|
||||
}
|
||||
|
||||
if fast_mode {
|
||||
self.set_high_default_traffic_volume()
|
||||
}
|
||||
|
||||
if no_cover {
|
||||
self.set_no_cover_traffic();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_high_default_traffic_volume(&mut self) {
|
||||
self.debug.traffic.average_packet_delay = Duration::from_millis(10);
|
||||
// basically don't really send cover messages
|
||||
self.debug.cover_traffic.loop_cover_traffic_average_delay =
|
||||
Duration::from_millis(2_000_000);
|
||||
// 250 "real" messages / s
|
||||
self.debug.traffic.message_sending_average_delay = Duration::from_millis(4);
|
||||
}
|
||||
|
||||
/// Enable medium mixnet traffic, for experiments only.
|
||||
/// This includes things like disabling cover traffic, no per hop delays, etc.
|
||||
#[doc(hidden)]
|
||||
pub fn set_experimental_medium_toggle(&mut self) {
|
||||
self.set_no_cover_traffic_with_keepalive();
|
||||
self.set_no_per_hop_delays();
|
||||
self.debug.traffic.secondary_packet_size = Some(PacketSize::ExtendedPacket16);
|
||||
}
|
||||
|
||||
pub fn with_disabled_poisson_process(mut self, disabled: bool) -> Self {
|
||||
if disabled {
|
||||
self.set_no_poisson_process()
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_no_poisson_process(&mut self) {
|
||||
self.debug.traffic.disable_main_poisson_packet_distribution = true;
|
||||
}
|
||||
|
||||
pub fn with_disabled_cover_traffic(mut self, disabled: bool) -> Self {
|
||||
if disabled {
|
||||
self.set_no_cover_traffic()
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_no_cover_traffic(&mut self) {
|
||||
self.debug.cover_traffic.disable_loop_cover_traffic_stream = true;
|
||||
self.debug.traffic.disable_main_poisson_packet_distribution = true;
|
||||
}
|
||||
|
||||
pub fn with_disabled_cover_traffic_with_keepalive(mut self, disabled: bool) -> Self {
|
||||
if disabled {
|
||||
self.set_no_cover_traffic_with_keepalive()
|
||||
}
|
||||
self
|
||||
}
|
||||
pub fn set_no_cover_traffic_with_keepalive(&mut self) {
|
||||
self.debug.traffic.disable_main_poisson_packet_distribution = true;
|
||||
self.debug.cover_traffic.loop_cover_traffic_average_delay = Duration::from_secs(5);
|
||||
}
|
||||
|
||||
pub fn with_disabled_topology_refresh(mut self, disable_topology_refresh: bool) -> Self {
|
||||
self.debug.topology.disable_refreshing = disable_topology_refresh;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_topology_structure(mut self, topology_structure: TopologyStructure) -> Self {
|
||||
self.set_topology_structure(topology_structure);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_topology_structure(&mut self, topology_structure: TopologyStructure) {
|
||||
self.debug.topology.topology_structure = topology_structure;
|
||||
}
|
||||
|
||||
pub fn with_no_per_hop_delays(mut self, no_per_hop_delays: bool) -> Self {
|
||||
if no_per_hop_delays {
|
||||
self.set_no_per_hop_delays()
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_no_per_hop_delays(&mut self) {
|
||||
self.debug.traffic.average_packet_delay = Duration::ZERO;
|
||||
self.debug.acknowledgements.average_ack_delay = Duration::ZERO;
|
||||
}
|
||||
|
||||
pub fn with_secondary_packet_size(mut self, secondary_packet_size: Option<PacketSize>) -> Self {
|
||||
self.set_secondary_packet_size(secondary_packet_size);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_secondary_packet_size(&mut self, secondary_packet_size: Option<PacketSize>) {
|
||||
self.debug.traffic.secondary_packet_size = secondary_packet_size;
|
||||
}
|
||||
|
||||
pub fn set_custom_version(&mut self, version: &str) {
|
||||
self.client.version = version.to_string();
|
||||
}
|
||||
|
||||
pub fn get_id(&self) -> String {
|
||||
self.client.id.clone()
|
||||
}
|
||||
|
||||
pub fn get_disabled_credentials_mode(&self) -> bool {
|
||||
self.client.disabled_credentials_mode
|
||||
}
|
||||
|
||||
pub fn get_validator_endpoints(&self) -> Vec<Url> {
|
||||
self.client.nyxd_urls.clone()
|
||||
}
|
||||
|
||||
pub fn get_nym_api_endpoints(&self) -> Vec<Url> {
|
||||
self.client.nym_api_urls.clone()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
|
||||
// note: the deny_unknown_fields is VITAL here to allow upgrades from v1.1.20_2
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Client {
|
||||
/// Version of the client for which this configuration was created.
|
||||
pub version: String,
|
||||
|
||||
/// ID specifies the human readable ID of this particular client.
|
||||
pub id: String,
|
||||
|
||||
/// Indicates whether this client is running in a disabled credentials mode, thus attempting
|
||||
/// to claim bandwidth without presenting bandwidth credentials.
|
||||
// TODO: this should be moved to `debug.gateway_connection`
|
||||
#[serde(default)]
|
||||
pub disabled_credentials_mode: bool,
|
||||
|
||||
/// Addresses to nyxd validators via which the client can communicate with the chain.
|
||||
#[serde(alias = "validator_urls")]
|
||||
pub nyxd_urls: Vec<Url>,
|
||||
|
||||
/// Addresses to APIs running on validator from which the client gets the view of the network.
|
||||
#[serde(alias = "validator_api_urls")]
|
||||
pub nym_api_urls: Vec<Url>,
|
||||
}
|
||||
|
||||
impl Client {
|
||||
pub fn new_default<S1, S2>(id: S1, version: S2) -> Self
|
||||
where
|
||||
S1: Into<String>,
|
||||
S2: Into<String>,
|
||||
{
|
||||
let network = NymNetworkDetails::new_mainnet();
|
||||
let nyxd_urls = network
|
||||
.endpoints
|
||||
.iter()
|
||||
.map(|validator| validator.nyxd_url())
|
||||
.collect();
|
||||
let nym_api_urls = network
|
||||
.endpoints
|
||||
.iter()
|
||||
.filter_map(|validator| validator.api_url())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
Client {
|
||||
version: version.into(),
|
||||
id: id.into(),
|
||||
disabled_credentials_mode: true,
|
||||
nyxd_urls,
|
||||
nym_api_urls,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new<S: Into<String>>(
|
||||
id: S,
|
||||
version: S,
|
||||
disabled_credentials_mode: bool,
|
||||
nyxd_urls: Vec<Url>,
|
||||
nym_api_urls: Vec<Url>,
|
||||
) -> Self {
|
||||
Client {
|
||||
version: version.into(),
|
||||
id: id.into(),
|
||||
disabled_credentials_mode,
|
||||
nyxd_urls,
|
||||
nym_api_urls,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct Traffic {
|
||||
/// The parameter of Poisson distribution determining how long, on average,
|
||||
/// sent packet is going to be delayed at any given mix node.
|
||||
/// So for a packet going through three mix nodes, on average, it will take three times this value
|
||||
/// until the packet reaches its destination.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub average_packet_delay: Duration,
|
||||
|
||||
/// The parameter of Poisson distribution determining how long, on average,
|
||||
/// it is going to take another 'real traffic stream' message to be sent.
|
||||
/// If no real packets are available and cover traffic is enabled,
|
||||
/// a loop cover message is sent instead in order to preserve the rate.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub message_sending_average_delay: Duration,
|
||||
|
||||
/// Controls whether the main packet stream constantly produces packets according to the predefined
|
||||
/// poisson distribution.
|
||||
pub disable_main_poisson_packet_distribution: bool,
|
||||
|
||||
/// Specifies the packet size used for sent messages.
|
||||
/// Do not override it unless you understand the consequences of that change.
|
||||
pub primary_packet_size: PacketSize,
|
||||
|
||||
/// Specifies the optional auxiliary packet size for optimizing message streams.
|
||||
/// Note that its use decreases overall anonymity.
|
||||
/// Do not set it it unless you understand the consequences of that change.
|
||||
pub secondary_packet_size: Option<PacketSize>,
|
||||
|
||||
pub packet_type: PacketType,
|
||||
}
|
||||
|
||||
impl Traffic {
|
||||
pub fn validate(&self) -> bool {
|
||||
if let Some(secondary_packet_size) = self.secondary_packet_size {
|
||||
if secondary_packet_size == PacketSize::AckPacket
|
||||
|| secondary_packet_size == self.primary_packet_size
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Traffic {
|
||||
fn default() -> Self {
|
||||
Traffic {
|
||||
average_packet_delay: DEFAULT_AVERAGE_PACKET_DELAY,
|
||||
message_sending_average_delay: DEFAULT_MESSAGE_STREAM_AVERAGE_DELAY,
|
||||
disable_main_poisson_packet_distribution: false,
|
||||
primary_packet_size: PacketSize::RegularPacket,
|
||||
secondary_packet_size: None,
|
||||
packet_type: PacketType::Mix,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct CoverTraffic {
|
||||
/// The parameter of Poisson distribution determining how long, on average,
|
||||
/// it is going to take for another loop cover traffic message to be sent.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub loop_cover_traffic_average_delay: Duration,
|
||||
|
||||
/// Specifies the ratio of `primary_packet_size` to `secondary_packet_size` used in cover traffic.
|
||||
/// Only applicable if `secondary_packet_size` is enabled.
|
||||
pub cover_traffic_primary_size_ratio: f64,
|
||||
|
||||
/// Controls whether the dedicated loop cover traffic stream should be enabled.
|
||||
/// (and sending packets, on average, every [Self::loop_cover_traffic_average_delay])
|
||||
pub disable_loop_cover_traffic_stream: bool,
|
||||
}
|
||||
|
||||
impl Default for CoverTraffic {
|
||||
fn default() -> Self {
|
||||
CoverTraffic {
|
||||
loop_cover_traffic_average_delay: DEFAULT_LOOP_COVER_STREAM_AVERAGE_DELAY,
|
||||
cover_traffic_primary_size_ratio: DEFAULT_COVER_TRAFFIC_PRIMARY_SIZE_RATIO,
|
||||
disable_loop_cover_traffic_stream: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct GatewayConnection {
|
||||
/// How long we're willing to wait for a response to a message sent to the gateway,
|
||||
/// before giving up on it.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub gateway_response_timeout: Duration,
|
||||
}
|
||||
|
||||
impl Default for GatewayConnection {
|
||||
fn default() -> Self {
|
||||
GatewayConnection {
|
||||
gateway_response_timeout: DEFAULT_GATEWAY_RESPONSE_TIMEOUT,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct Acknowledgements {
|
||||
/// The parameter of Poisson distribution determining how long, on average,
|
||||
/// sent acknowledgement is going to be delayed at any given mix node.
|
||||
/// So for an ack going through three mix nodes, on average, it will take three times this value
|
||||
/// until the packet reaches its destination.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub average_ack_delay: Duration,
|
||||
|
||||
/// Value multiplied with the expected round trip time of an acknowledgement packet before
|
||||
/// it is assumed it was lost and retransmission of the data packet happens.
|
||||
/// In an ideal network with 0 latency, this value would have been 1.
|
||||
pub ack_wait_multiplier: f64,
|
||||
|
||||
/// Value added to the expected round trip time of an acknowledgement packet before
|
||||
/// it is assumed it was lost and retransmission of the data packet happens.
|
||||
/// In an ideal network with 0 latency, this value would have been 0.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub ack_wait_addition: Duration,
|
||||
}
|
||||
|
||||
impl Default for Acknowledgements {
|
||||
fn default() -> Self {
|
||||
Acknowledgements {
|
||||
average_ack_delay: DEFAULT_AVERAGE_PACKET_DELAY,
|
||||
ack_wait_multiplier: DEFAULT_ACK_WAIT_MULTIPLIER,
|
||||
ack_wait_addition: DEFAULT_ACK_WAIT_ADDITION,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct Topology {
|
||||
/// The uniform delay every which clients are querying the directory server
|
||||
/// to try to obtain a compatible network topology to send sphinx packets through.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub topology_refresh_rate: Duration,
|
||||
|
||||
/// During topology refresh, test packets are sent through every single possible network
|
||||
/// path. This timeout determines waiting period until it is decided that the packet
|
||||
/// did not reach its destination.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub topology_resolution_timeout: Duration,
|
||||
|
||||
/// Specifies whether the client should not refresh the network topology after obtaining
|
||||
/// the first valid instance.
|
||||
/// Supersedes `topology_refresh_rate_ms`.
|
||||
pub disable_refreshing: bool,
|
||||
|
||||
/// Defines how long the client is going to wait on startup for its gateway to come online,
|
||||
/// before abandoning the procedure.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub max_startup_gateway_waiting_period: Duration,
|
||||
|
||||
/// Specifies the mixnode topology to be used for sending packets.
|
||||
pub topology_structure: TopologyStructure,
|
||||
|
||||
/// Specifies a minimum performance of a mixnode that is used on route construction.
|
||||
/// This setting is only applicable when `NymApi` topology is used.
|
||||
pub minimum_mixnode_performance: u8,
|
||||
|
||||
/// Specifies a minimum performance of a gateway that is used on route construction.
|
||||
/// This setting is only applicable when `NymApi` topology is used.
|
||||
pub minimum_gateway_performance: u8,
|
||||
}
|
||||
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
#[derive(Default, Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub enum TopologyStructure {
|
||||
#[default]
|
||||
NymApi,
|
||||
GeoAware(GroupBy),
|
||||
}
|
||||
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub enum GroupBy {
|
||||
CountryGroup(CountryGroup),
|
||||
NymAddress(Recipient),
|
||||
}
|
||||
|
||||
impl std::fmt::Display for GroupBy {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
GroupBy::CountryGroup(group) => write!(f, "group: {group}"),
|
||||
GroupBy::NymAddress(address) => write!(f, "address: {address}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Topology {
|
||||
fn default() -> Self {
|
||||
Topology {
|
||||
topology_refresh_rate: DEFAULT_TOPOLOGY_REFRESH_RATE,
|
||||
topology_resolution_timeout: DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT,
|
||||
disable_refreshing: false,
|
||||
max_startup_gateway_waiting_period: DEFAULT_MAX_STARTUP_GATEWAY_WAITING_PERIOD,
|
||||
topology_structure: TopologyStructure::default(),
|
||||
minimum_mixnode_performance: DEFAULT_MIN_MIXNODE_PERFORMANCE,
|
||||
minimum_gateway_performance: DEFAULT_MIN_GATEWAY_PERFORMANCE,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct ReplySurbs {
|
||||
/// Defines the minimum number of reply surbs the client wants to keep in its storage at all times.
|
||||
/// It can only allow to go below that value if its to request additional reply surbs.
|
||||
pub minimum_reply_surb_storage_threshold: usize,
|
||||
|
||||
/// Defines the maximum number of reply surbs the client wants to keep in its storage at any times.
|
||||
pub maximum_reply_surb_storage_threshold: usize,
|
||||
|
||||
/// Defines the minimum number of reply surbs the client would request.
|
||||
pub minimum_reply_surb_request_size: u32,
|
||||
|
||||
/// Defines the maximum number of reply surbs the client would request.
|
||||
pub maximum_reply_surb_request_size: u32,
|
||||
|
||||
/// Defines the maximum number of reply surbs a remote party is allowed to request from this client at once.
|
||||
pub maximum_allowed_reply_surb_request_size: u32,
|
||||
|
||||
/// Defines maximum amount of time the client is going to wait for reply surbs before explicitly asking
|
||||
/// for more even though in theory they wouldn't need to.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub maximum_reply_surb_rerequest_waiting_period: Duration,
|
||||
|
||||
/// Defines maximum amount of time the client is going to wait for reply surbs before
|
||||
/// deciding it's never going to get them and would drop all pending messages
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub maximum_reply_surb_drop_waiting_period: Duration,
|
||||
|
||||
/// Defines maximum amount of time given reply surb is going to be valid for.
|
||||
/// This is going to be superseded by key rotation once implemented.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub maximum_reply_surb_age: Duration,
|
||||
|
||||
/// Defines maximum amount of time given reply key is going to be valid for.
|
||||
/// This is going to be superseded by key rotation once implemented.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub maximum_reply_key_age: Duration,
|
||||
|
||||
/// Specifies the number of mixnet hops the packet should go through. If not specified, then
|
||||
/// the default value is used.
|
||||
pub surb_mix_hops: Option<u8>,
|
||||
}
|
||||
|
||||
impl Default for ReplySurbs {
|
||||
fn default() -> Self {
|
||||
ReplySurbs {
|
||||
minimum_reply_surb_storage_threshold: DEFAULT_MINIMUM_REPLY_SURB_STORAGE_THRESHOLD,
|
||||
maximum_reply_surb_storage_threshold: DEFAULT_MAXIMUM_REPLY_SURB_STORAGE_THRESHOLD,
|
||||
minimum_reply_surb_request_size: DEFAULT_MINIMUM_REPLY_SURB_REQUEST_SIZE,
|
||||
maximum_reply_surb_request_size: DEFAULT_MAXIMUM_REPLY_SURB_REQUEST_SIZE,
|
||||
maximum_allowed_reply_surb_request_size: DEFAULT_MAXIMUM_ALLOWED_SURB_REQUEST_SIZE,
|
||||
maximum_reply_surb_rerequest_waiting_period:
|
||||
DEFAULT_MAXIMUM_REPLY_SURB_REREQUEST_WAITING_PERIOD,
|
||||
maximum_reply_surb_drop_waiting_period: DEFAULT_MAXIMUM_REPLY_SURB_DROP_WAITING_PERIOD,
|
||||
maximum_reply_surb_age: DEFAULT_MAXIMUM_REPLY_SURB_AGE,
|
||||
maximum_reply_key_age: DEFAULT_MAXIMUM_REPLY_KEY_AGE,
|
||||
surb_mix_hops: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct DebugConfig {
|
||||
/// Defines all configuration options related to traffic streams.
|
||||
pub traffic: Traffic,
|
||||
|
||||
/// Defines all configuration options related to cover traffic stream(s).
|
||||
pub cover_traffic: CoverTraffic,
|
||||
|
||||
/// Defines all configuration options related to the gateway connection.
|
||||
pub gateway_connection: GatewayConnection,
|
||||
|
||||
/// Defines all configuration options related to acknowledgements, such as delays or wait timeouts.
|
||||
pub acknowledgements: Acknowledgements,
|
||||
|
||||
/// Defines all configuration options related topology, such as refresh rates or timeouts.
|
||||
pub topology: Topology,
|
||||
|
||||
/// Defines all configuration options related to reply SURBs.
|
||||
pub reply_surbs: ReplySurbs,
|
||||
}
|
||||
|
||||
impl DebugConfig {
|
||||
pub fn validate(&self) -> bool {
|
||||
// no other sections have explicit requirements (yet)
|
||||
self.traffic.validate()
|
||||
}
|
||||
}
|
||||
|
||||
// it could be derived, sure, but I'd rather have an explicit implementation in case we had to change
|
||||
// something manually at some point
|
||||
#[allow(clippy::derivable_impls)]
|
||||
impl Default for DebugConfig {
|
||||
fn default() -> Self {
|
||||
DebugConfig {
|
||||
traffic: Default::default(),
|
||||
cover_traffic: Default::default(),
|
||||
gateway_connection: Default::default(),
|
||||
acknowledgements: Default::default(),
|
||||
topology: Default::default(),
|
||||
reply_surbs: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pub mod v1;
|
||||
pub mod v2;
|
||||
pub mod v3;
|
||||
pub mod v4;
|
||||
pub mod v5;
|
||||
|
||||
// aliases for backwards compatibility
|
||||
pub use v1 as old_config_v1_1_13;
|
||||
pub use v2 as old_config_v1_1_20;
|
||||
pub use v3 as old_config_v1_1_20_2;
|
||||
pub use v4 as old_config_v1_1_30;
|
||||
pub use v5 as old_config_v1_1_33;
|
||||
+40
-35
@@ -1,23 +1,28 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::config::old_config_v1_1_20::{
|
||||
AcknowledgementsV1_1_20, ClientV1_1_20, ConfigV1_1_20, CoverTrafficV1_1_20, DebugConfigV1_1_20,
|
||||
GatewayConnectionV1_1_20, LoggingV1_1_20, ReplySurbsV1_1_20, TopologyV1_1_20, TrafficV1_1_20,
|
||||
DEFAULT_ACK_WAIT_ADDITION, DEFAULT_ACK_WAIT_MULTIPLIER, DEFAULT_AVERAGE_PACKET_DELAY,
|
||||
DEFAULT_GATEWAY_RESPONSE_TIMEOUT, DEFAULT_LOOP_COVER_STREAM_AVERAGE_DELAY,
|
||||
DEFAULT_MAXIMUM_ALLOWED_SURB_REQUEST_SIZE, DEFAULT_MAXIMUM_REPLY_KEY_AGE,
|
||||
DEFAULT_MAXIMUM_REPLY_SURB_AGE, DEFAULT_MAXIMUM_REPLY_SURB_DROP_WAITING_PERIOD,
|
||||
DEFAULT_MAXIMUM_REPLY_SURB_REQUEST_SIZE, DEFAULT_MAXIMUM_REPLY_SURB_REREQUEST_WAITING_PERIOD,
|
||||
use crate::old::v2::{
|
||||
AcknowledgementsV2, ClientV2, ConfigV2, CoverTrafficV2, DebugConfigV2, GatewayConnectionV2,
|
||||
LoggingV2, ReplySurbsV2, TopologyV2, TrafficV2, DEFAULT_ACK_WAIT_ADDITION,
|
||||
DEFAULT_ACK_WAIT_MULTIPLIER, DEFAULT_AVERAGE_PACKET_DELAY, DEFAULT_GATEWAY_RESPONSE_TIMEOUT,
|
||||
DEFAULT_LOOP_COVER_STREAM_AVERAGE_DELAY, DEFAULT_MAXIMUM_ALLOWED_SURB_REQUEST_SIZE,
|
||||
DEFAULT_MAXIMUM_REPLY_KEY_AGE, DEFAULT_MAXIMUM_REPLY_SURB_AGE,
|
||||
DEFAULT_MAXIMUM_REPLY_SURB_DROP_WAITING_PERIOD, DEFAULT_MAXIMUM_REPLY_SURB_REQUEST_SIZE,
|
||||
DEFAULT_MAXIMUM_REPLY_SURB_REREQUEST_WAITING_PERIOD,
|
||||
DEFAULT_MAXIMUM_REPLY_SURB_STORAGE_THRESHOLD, DEFAULT_MESSAGE_STREAM_AVERAGE_DELAY,
|
||||
DEFAULT_MINIMUM_REPLY_SURB_REQUEST_SIZE, DEFAULT_MINIMUM_REPLY_SURB_STORAGE_THRESHOLD,
|
||||
DEFAULT_TOPOLOGY_REFRESH_RATE, DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT,
|
||||
};
|
||||
use nym_sphinx::params::PacketSize;
|
||||
use nym_sphinx_params::PacketSize;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::marker::PhantomData;
|
||||
use std::time::Duration;
|
||||
|
||||
// aliases for backwards compatibility
|
||||
pub type OldConfigV1_1_13<T> = ConfigV1<T>;
|
||||
pub type OldLoggingV1_1_13 = LoggingV1;
|
||||
pub type OldDebugConfigV1_1_13 = DebugConfigV1;
|
||||
|
||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum ExtendedPacketSize {
|
||||
@@ -38,28 +43,28 @@ impl From<ExtendedPacketSize> for PacketSize {
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct OldConfigV1_1_13<T> {
|
||||
pub client: ClientV1_1_20<T>,
|
||||
pub struct ConfigV1<T> {
|
||||
pub client: ClientV2<T>,
|
||||
|
||||
#[serde(default)]
|
||||
pub logging: OldLoggingV1_1_13,
|
||||
pub logging: LoggingV1,
|
||||
#[serde(default)]
|
||||
pub debug: OldDebugConfigV1_1_13,
|
||||
pub debug: DebugConfigV1,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Deserialize, PartialEq, Eq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct OldLoggingV1_1_13 {}
|
||||
pub struct LoggingV1 {}
|
||||
|
||||
impl From<OldLoggingV1_1_13> for LoggingV1_1_20 {
|
||||
fn from(_value: OldLoggingV1_1_13) -> Self {
|
||||
LoggingV1_1_20 {}
|
||||
impl From<LoggingV1> for LoggingV2 {
|
||||
fn from(_value: LoggingV1) -> Self {
|
||||
LoggingV2 {}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct OldDebugConfigV1_1_13 {
|
||||
pub struct DebugConfigV1 {
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub average_packet_delay: Duration,
|
||||
|
||||
@@ -114,10 +119,10 @@ pub struct OldDebugConfigV1_1_13 {
|
||||
pub maximum_reply_key_age: Duration,
|
||||
}
|
||||
|
||||
impl From<OldDebugConfigV1_1_13> for DebugConfigV1_1_20 {
|
||||
fn from(value: OldDebugConfigV1_1_13) -> Self {
|
||||
DebugConfigV1_1_20 {
|
||||
traffic: TrafficV1_1_20 {
|
||||
impl From<DebugConfigV1> for DebugConfigV2 {
|
||||
fn from(value: DebugConfigV1) -> Self {
|
||||
DebugConfigV2 {
|
||||
traffic: TrafficV2 {
|
||||
average_packet_delay: value.average_packet_delay,
|
||||
message_sending_average_delay: value.message_sending_average_delay,
|
||||
disable_main_poisson_packet_distribution: value
|
||||
@@ -125,25 +130,25 @@ impl From<OldDebugConfigV1_1_13> for DebugConfigV1_1_20 {
|
||||
primary_packet_size: PacketSize::RegularPacket,
|
||||
secondary_packet_size: value.use_extended_packet_size.map(Into::into),
|
||||
},
|
||||
cover_traffic: CoverTrafficV1_1_20 {
|
||||
cover_traffic: CoverTrafficV2 {
|
||||
loop_cover_traffic_average_delay: value.loop_cover_traffic_average_delay,
|
||||
disable_loop_cover_traffic_stream: value.disable_loop_cover_traffic_stream,
|
||||
..CoverTrafficV1_1_20::default()
|
||||
..CoverTrafficV2::default()
|
||||
},
|
||||
gateway_connection: GatewayConnectionV1_1_20 {
|
||||
gateway_connection: GatewayConnectionV2 {
|
||||
gateway_response_timeout: value.gateway_response_timeout,
|
||||
},
|
||||
acknowledgements: AcknowledgementsV1_1_20 {
|
||||
acknowledgements: AcknowledgementsV2 {
|
||||
average_ack_delay: value.average_ack_delay,
|
||||
ack_wait_multiplier: value.ack_wait_multiplier,
|
||||
ack_wait_addition: value.ack_wait_addition,
|
||||
},
|
||||
topology: TopologyV1_1_20 {
|
||||
topology: TopologyV2 {
|
||||
topology_refresh_rate: value.topology_refresh_rate,
|
||||
topology_resolution_timeout: value.topology_resolution_timeout,
|
||||
disable_refreshing: false,
|
||||
},
|
||||
reply_surbs: ReplySurbsV1_1_20 {
|
||||
reply_surbs: ReplySurbsV2 {
|
||||
minimum_reply_surb_storage_threshold: value.minimum_reply_surb_storage_threshold,
|
||||
maximum_reply_surb_storage_threshold: value.maximum_reply_surb_storage_threshold,
|
||||
minimum_reply_surb_request_size: value.minimum_reply_surb_request_size,
|
||||
@@ -161,9 +166,9 @@ impl From<OldDebugConfigV1_1_13> for DebugConfigV1_1_20 {
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for OldDebugConfigV1_1_13 {
|
||||
impl Default for DebugConfigV1 {
|
||||
fn default() -> Self {
|
||||
OldDebugConfigV1_1_13 {
|
||||
DebugConfigV1 {
|
||||
average_packet_delay: DEFAULT_AVERAGE_PACKET_DELAY,
|
||||
average_ack_delay: DEFAULT_AVERAGE_PACKET_DELAY,
|
||||
ack_wait_multiplier: DEFAULT_ACK_WAIT_MULTIPLIER,
|
||||
@@ -190,10 +195,10 @@ impl Default for OldDebugConfigV1_1_13 {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> From<OldConfigV1_1_13<T>> for ConfigV1_1_20<U> {
|
||||
fn from(value: OldConfigV1_1_13<T>) -> Self {
|
||||
ConfigV1_1_20 {
|
||||
client: ClientV1_1_20 {
|
||||
impl<T, U> From<ConfigV1<T>> for ConfigV2<U> {
|
||||
fn from(value: ConfigV1<T>) -> Self {
|
||||
ConfigV2 {
|
||||
client: ClientV2 {
|
||||
version: value.client.version,
|
||||
id: value.client.id,
|
||||
disabled_credentials_mode: value.client.disabled_credentials_mode,
|
||||
+76
-63
@@ -1,12 +1,11 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::config::old_config_v1_1_20_2::{
|
||||
AcknowledgementsV1_1_20_2, CoverTrafficV1_1_20_2, DebugConfigV1_1_20_2,
|
||||
GatewayConnectionV1_1_20_2, GatewayEndpointConfigV1_1_20_2, ReplySurbsV1_1_20_2,
|
||||
TopologyV1_1_20_2, TrafficV1_1_20_2,
|
||||
use crate::old::v3::{
|
||||
AcknowledgementsV3, CoverTrafficV3, DebugConfigV3, GatewayConnectionV3,
|
||||
GatewayEndpointConfigV3, ReplySurbsV3, TopologyV3, TrafficV3,
|
||||
};
|
||||
use nym_sphinx::params::{PacketSize, PacketType};
|
||||
use nym_sphinx_params::{PacketSize, PacketType};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::marker::PhantomData;
|
||||
use std::path::PathBuf;
|
||||
@@ -54,27 +53,41 @@ pub(crate) const DEFAULT_MAXIMUM_REPLY_SURB_AGE: Duration = Duration::from_secs(
|
||||
// 24 hours
|
||||
pub(crate) const DEFAULT_MAXIMUM_REPLY_KEY_AGE: Duration = Duration::from_secs(24 * 60 * 60);
|
||||
|
||||
// aliases for backwards compatibility
|
||||
pub type ConfigV1_1_20<T> = ConfigV2<T>;
|
||||
pub type ClientV1_1_20<T> = ClientV2<T>;
|
||||
pub type LoggingV1_1_20 = LoggingV2;
|
||||
pub type DebugConfigV1_1_20 = DebugConfigV2;
|
||||
pub type GatewayEndpointConfigV1_1_20 = GatewayEndpointConfigV2;
|
||||
|
||||
pub type TrafficV1_1_20 = TrafficV2;
|
||||
pub type CoverTrafficV1_1_20 = CoverTrafficV2;
|
||||
pub type GatewayConnectionV1_1_20 = GatewayConnectionV2;
|
||||
pub type AcknowledgementsV1_1_20 = AcknowledgementsV2;
|
||||
pub type TopologyV1_1_20 = TopologyV2;
|
||||
pub type ReplySurbsV1_1_20 = ReplySurbsV2;
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct ConfigV1_1_20<T> {
|
||||
pub client: ClientV1_1_20<T>,
|
||||
pub struct ConfigV2<T> {
|
||||
pub client: ClientV2<T>,
|
||||
|
||||
#[serde(default)]
|
||||
pub logging: LoggingV1_1_20,
|
||||
pub logging: LoggingV2,
|
||||
#[serde(default)]
|
||||
pub debug: DebugConfigV1_1_20,
|
||||
pub debug: DebugConfigV2,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Eq, Serialize)]
|
||||
pub struct GatewayEndpointConfigV1_1_20 {
|
||||
pub struct GatewayEndpointConfigV2 {
|
||||
pub gateway_id: String,
|
||||
pub gateway_owner: String,
|
||||
pub gateway_listener: String,
|
||||
}
|
||||
|
||||
impl From<GatewayEndpointConfigV1_1_20> for GatewayEndpointConfigV1_1_20_2 {
|
||||
fn from(value: GatewayEndpointConfigV1_1_20) -> Self {
|
||||
GatewayEndpointConfigV1_1_20_2 {
|
||||
impl From<GatewayEndpointConfigV2> for GatewayEndpointConfigV3 {
|
||||
fn from(value: GatewayEndpointConfigV2) -> Self {
|
||||
GatewayEndpointConfigV3 {
|
||||
gateway_id: value.gateway_id,
|
||||
gateway_owner: value.gateway_owner,
|
||||
gateway_listener: value.gateway_listener,
|
||||
@@ -83,7 +96,7 @@ impl From<GatewayEndpointConfigV1_1_20> for GatewayEndpointConfigV1_1_20_2 {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
|
||||
pub struct ClientV1_1_20<T> {
|
||||
pub struct ClientV2<T> {
|
||||
pub version: String,
|
||||
pub id: String,
|
||||
#[serde(default)]
|
||||
@@ -98,7 +111,7 @@ pub struct ClientV1_1_20<T> {
|
||||
pub public_encryption_key_file: PathBuf,
|
||||
pub gateway_shared_key_file: PathBuf,
|
||||
pub ack_key_file: PathBuf,
|
||||
pub gateway_endpoint: GatewayEndpointConfigV1_1_20,
|
||||
pub gateway_endpoint: GatewayEndpointConfigV2,
|
||||
pub database_path: PathBuf,
|
||||
#[serde(default)]
|
||||
pub reply_surb_database_path: PathBuf,
|
||||
@@ -110,11 +123,11 @@ pub struct ClientV1_1_20<T> {
|
||||
|
||||
#[derive(Debug, Clone, Default, Deserialize, PartialEq, Eq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct LoggingV1_1_20 {}
|
||||
pub struct LoggingV2 {}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default)]
|
||||
pub struct TrafficV1_1_20 {
|
||||
pub struct TrafficV2 {
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub average_packet_delay: Duration,
|
||||
#[serde(with = "humantime_serde")]
|
||||
@@ -124,9 +137,9 @@ pub struct TrafficV1_1_20 {
|
||||
pub secondary_packet_size: Option<PacketSize>,
|
||||
}
|
||||
|
||||
impl From<TrafficV1_1_20> for TrafficV1_1_20_2 {
|
||||
fn from(value: TrafficV1_1_20) -> Self {
|
||||
TrafficV1_1_20_2 {
|
||||
impl From<TrafficV2> for TrafficV3 {
|
||||
fn from(value: TrafficV2) -> Self {
|
||||
TrafficV3 {
|
||||
average_packet_delay: value.average_packet_delay,
|
||||
message_sending_average_delay: value.message_sending_average_delay,
|
||||
disable_main_poisson_packet_distribution: value
|
||||
@@ -138,9 +151,9 @@ impl From<TrafficV1_1_20> for TrafficV1_1_20_2 {
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for TrafficV1_1_20 {
|
||||
impl Default for TrafficV2 {
|
||||
fn default() -> Self {
|
||||
TrafficV1_1_20 {
|
||||
TrafficV2 {
|
||||
average_packet_delay: DEFAULT_AVERAGE_PACKET_DELAY,
|
||||
message_sending_average_delay: DEFAULT_MESSAGE_STREAM_AVERAGE_DELAY,
|
||||
disable_main_poisson_packet_distribution: false,
|
||||
@@ -152,16 +165,16 @@ impl Default for TrafficV1_1_20 {
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct CoverTrafficV1_1_20 {
|
||||
pub struct CoverTrafficV2 {
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub loop_cover_traffic_average_delay: Duration,
|
||||
pub cover_traffic_primary_size_ratio: f64,
|
||||
pub disable_loop_cover_traffic_stream: bool,
|
||||
}
|
||||
|
||||
impl From<CoverTrafficV1_1_20> for CoverTrafficV1_1_20_2 {
|
||||
fn from(value: CoverTrafficV1_1_20) -> Self {
|
||||
CoverTrafficV1_1_20_2 {
|
||||
impl From<CoverTrafficV2> for CoverTrafficV3 {
|
||||
fn from(value: CoverTrafficV2) -> Self {
|
||||
CoverTrafficV3 {
|
||||
loop_cover_traffic_average_delay: value.loop_cover_traffic_average_delay,
|
||||
cover_traffic_primary_size_ratio: value.cover_traffic_primary_size_ratio,
|
||||
disable_loop_cover_traffic_stream: value.disable_loop_cover_traffic_stream,
|
||||
@@ -169,9 +182,9 @@ impl From<CoverTrafficV1_1_20> for CoverTrafficV1_1_20_2 {
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for CoverTrafficV1_1_20 {
|
||||
impl Default for CoverTrafficV2 {
|
||||
fn default() -> Self {
|
||||
CoverTrafficV1_1_20 {
|
||||
CoverTrafficV2 {
|
||||
loop_cover_traffic_average_delay: DEFAULT_LOOP_COVER_STREAM_AVERAGE_DELAY,
|
||||
cover_traffic_primary_size_ratio: DEFAULT_COVER_TRAFFIC_PRIMARY_SIZE_RATIO,
|
||||
disable_loop_cover_traffic_stream: false,
|
||||
@@ -181,22 +194,22 @@ impl Default for CoverTrafficV1_1_20 {
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct GatewayConnectionV1_1_20 {
|
||||
pub struct GatewayConnectionV2 {
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub gateway_response_timeout: Duration,
|
||||
}
|
||||
|
||||
impl From<GatewayConnectionV1_1_20> for GatewayConnectionV1_1_20_2 {
|
||||
fn from(value: GatewayConnectionV1_1_20) -> Self {
|
||||
GatewayConnectionV1_1_20_2 {
|
||||
impl From<GatewayConnectionV2> for GatewayConnectionV3 {
|
||||
fn from(value: GatewayConnectionV2) -> Self {
|
||||
GatewayConnectionV3 {
|
||||
gateway_response_timeout: value.gateway_response_timeout,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for GatewayConnectionV1_1_20 {
|
||||
impl Default for GatewayConnectionV2 {
|
||||
fn default() -> Self {
|
||||
GatewayConnectionV1_1_20 {
|
||||
GatewayConnectionV2 {
|
||||
gateway_response_timeout: DEFAULT_GATEWAY_RESPONSE_TIMEOUT,
|
||||
}
|
||||
}
|
||||
@@ -204,7 +217,7 @@ impl Default for GatewayConnectionV1_1_20 {
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct AcknowledgementsV1_1_20 {
|
||||
pub struct AcknowledgementsV2 {
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub average_ack_delay: Duration,
|
||||
pub ack_wait_multiplier: f64,
|
||||
@@ -212,9 +225,9 @@ pub struct AcknowledgementsV1_1_20 {
|
||||
pub ack_wait_addition: Duration,
|
||||
}
|
||||
|
||||
impl From<AcknowledgementsV1_1_20> for AcknowledgementsV1_1_20_2 {
|
||||
fn from(value: AcknowledgementsV1_1_20) -> Self {
|
||||
AcknowledgementsV1_1_20_2 {
|
||||
impl From<AcknowledgementsV2> for AcknowledgementsV3 {
|
||||
fn from(value: AcknowledgementsV2) -> Self {
|
||||
AcknowledgementsV3 {
|
||||
average_ack_delay: value.average_ack_delay,
|
||||
ack_wait_multiplier: value.ack_wait_multiplier,
|
||||
ack_wait_addition: value.ack_wait_addition,
|
||||
@@ -222,9 +235,9 @@ impl From<AcknowledgementsV1_1_20> for AcknowledgementsV1_1_20_2 {
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for AcknowledgementsV1_1_20 {
|
||||
impl Default for AcknowledgementsV2 {
|
||||
fn default() -> Self {
|
||||
AcknowledgementsV1_1_20 {
|
||||
AcknowledgementsV2 {
|
||||
average_ack_delay: DEFAULT_AVERAGE_PACKET_DELAY,
|
||||
ack_wait_multiplier: DEFAULT_ACK_WAIT_MULTIPLIER,
|
||||
ack_wait_addition: DEFAULT_ACK_WAIT_ADDITION,
|
||||
@@ -234,7 +247,7 @@ impl Default for AcknowledgementsV1_1_20 {
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct TopologyV1_1_20 {
|
||||
pub struct TopologyV2 {
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub topology_refresh_rate: Duration,
|
||||
#[serde(with = "humantime_serde")]
|
||||
@@ -242,9 +255,9 @@ pub struct TopologyV1_1_20 {
|
||||
pub disable_refreshing: bool,
|
||||
}
|
||||
|
||||
impl From<TopologyV1_1_20> for TopologyV1_1_20_2 {
|
||||
fn from(value: TopologyV1_1_20) -> Self {
|
||||
TopologyV1_1_20_2 {
|
||||
impl From<TopologyV2> for TopologyV3 {
|
||||
fn from(value: TopologyV2) -> Self {
|
||||
TopologyV3 {
|
||||
topology_refresh_rate: value.topology_refresh_rate,
|
||||
topology_resolution_timeout: value.topology_resolution_timeout,
|
||||
disable_refreshing: value.disable_refreshing,
|
||||
@@ -252,9 +265,9 @@ impl From<TopologyV1_1_20> for TopologyV1_1_20_2 {
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for TopologyV1_1_20 {
|
||||
impl Default for TopologyV2 {
|
||||
fn default() -> Self {
|
||||
TopologyV1_1_20 {
|
||||
TopologyV2 {
|
||||
topology_refresh_rate: DEFAULT_TOPOLOGY_REFRESH_RATE,
|
||||
topology_resolution_timeout: DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT,
|
||||
disable_refreshing: false,
|
||||
@@ -264,7 +277,7 @@ impl Default for TopologyV1_1_20 {
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct ReplySurbsV1_1_20 {
|
||||
pub struct ReplySurbsV2 {
|
||||
pub minimum_reply_surb_storage_threshold: usize,
|
||||
pub maximum_reply_surb_storage_threshold: usize,
|
||||
pub minimum_reply_surb_request_size: u32,
|
||||
@@ -280,9 +293,9 @@ pub struct ReplySurbsV1_1_20 {
|
||||
pub maximum_reply_key_age: Duration,
|
||||
}
|
||||
|
||||
impl From<ReplySurbsV1_1_20> for ReplySurbsV1_1_20_2 {
|
||||
fn from(value: ReplySurbsV1_1_20) -> Self {
|
||||
ReplySurbsV1_1_20_2 {
|
||||
impl From<ReplySurbsV2> for ReplySurbsV3 {
|
||||
fn from(value: ReplySurbsV2) -> Self {
|
||||
ReplySurbsV3 {
|
||||
minimum_reply_surb_storage_threshold: value.minimum_reply_surb_storage_threshold,
|
||||
maximum_reply_surb_storage_threshold: value.maximum_reply_surb_storage_threshold,
|
||||
minimum_reply_surb_request_size: value.minimum_reply_surb_request_size,
|
||||
@@ -297,9 +310,9 @@ impl From<ReplySurbsV1_1_20> for ReplySurbsV1_1_20_2 {
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for ReplySurbsV1_1_20 {
|
||||
impl Default for ReplySurbsV2 {
|
||||
fn default() -> Self {
|
||||
ReplySurbsV1_1_20 {
|
||||
ReplySurbsV2 {
|
||||
minimum_reply_surb_storage_threshold: DEFAULT_MINIMUM_REPLY_SURB_STORAGE_THRESHOLD,
|
||||
maximum_reply_surb_storage_threshold: DEFAULT_MAXIMUM_REPLY_SURB_STORAGE_THRESHOLD,
|
||||
minimum_reply_surb_request_size: DEFAULT_MINIMUM_REPLY_SURB_REQUEST_SIZE,
|
||||
@@ -316,18 +329,18 @@ impl Default for ReplySurbsV1_1_20 {
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct DebugConfigV1_1_20 {
|
||||
pub traffic: TrafficV1_1_20,
|
||||
pub cover_traffic: CoverTrafficV1_1_20,
|
||||
pub gateway_connection: GatewayConnectionV1_1_20,
|
||||
pub acknowledgements: AcknowledgementsV1_1_20,
|
||||
pub topology: TopologyV1_1_20,
|
||||
pub reply_surbs: ReplySurbsV1_1_20,
|
||||
pub struct DebugConfigV2 {
|
||||
pub traffic: TrafficV2,
|
||||
pub cover_traffic: CoverTrafficV2,
|
||||
pub gateway_connection: GatewayConnectionV2,
|
||||
pub acknowledgements: AcknowledgementsV2,
|
||||
pub topology: TopologyV2,
|
||||
pub reply_surbs: ReplySurbsV2,
|
||||
}
|
||||
|
||||
impl From<DebugConfigV1_1_20> for DebugConfigV1_1_20_2 {
|
||||
fn from(value: DebugConfigV1_1_20) -> Self {
|
||||
DebugConfigV1_1_20_2 {
|
||||
impl From<DebugConfigV2> for DebugConfigV3 {
|
||||
fn from(value: DebugConfigV2) -> Self {
|
||||
DebugConfigV3 {
|
||||
traffic: value.traffic.into(),
|
||||
cover_traffic: value.cover_traffic.into(),
|
||||
gateway_connection: value.gateway_connection.into(),
|
||||
+80
-67
@@ -1,12 +1,12 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::config::old_config_v1_1_30::{
|
||||
AcknowledgementsV1_1_30, ClientV1_1_30, ConfigV1_1_30, CoverTrafficV1_1_30, DebugConfigV1_1_30,
|
||||
GatewayConnectionV1_1_30, ReplySurbsV1_1_30, TopologyV1_1_30, TrafficV1_1_30,
|
||||
use crate::old::v4::{
|
||||
AcknowledgementsV4, ClientV4, ConfigV4, CoverTrafficV4, DebugConfigV4, GatewayConnectionV4,
|
||||
ReplySurbsV4, TopologyV4, TrafficV4,
|
||||
};
|
||||
use crate::config::GatewayEndpointConfig;
|
||||
use nym_sphinx::params::{PacketSize, PacketType};
|
||||
use crate::old::v5::GatewayEndpointConfigV5;
|
||||
use nym_sphinx_params::{PacketSize, PacketType};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::time::Duration;
|
||||
use url::Url;
|
||||
@@ -50,18 +50,31 @@ const DEFAULT_MAXIMUM_REPLY_SURB_AGE: Duration = Duration::from_secs(12 * 60 * 6
|
||||
// 24 hours
|
||||
const DEFAULT_MAXIMUM_REPLY_KEY_AGE: Duration = Duration::from_secs(24 * 60 * 60);
|
||||
|
||||
// aliases for backwards compatibility
|
||||
pub type ConfigV1_1_20_2 = ConfigV3;
|
||||
pub type ClientV1_1_20_2 = ClientV3;
|
||||
pub type DebugConfigV1_1_20_2 = DebugConfigV3;
|
||||
pub type GatewayEndpointConfigV1_1_20_2 = GatewayEndpointConfigV3;
|
||||
|
||||
pub type TrafficV1_1_20_2 = TrafficV3;
|
||||
pub type CoverTrafficV1_1_20_2 = CoverTrafficV3;
|
||||
pub type GatewayConnectionV1_1_20_2 = GatewayConnectionV3;
|
||||
pub type AcknowledgementsV1_1_20_2 = AcknowledgementsV3;
|
||||
pub type TopologyV1_1_20_2 = TopologyV3;
|
||||
pub type ReplySurbsV1_1_20_2 = ReplySurbsV3;
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct ConfigV1_1_20_2 {
|
||||
pub client: ClientV1_1_20_2,
|
||||
pub struct ConfigV3 {
|
||||
pub client: ClientV3,
|
||||
|
||||
#[serde(default)]
|
||||
pub debug: DebugConfigV1_1_20_2,
|
||||
pub debug: DebugConfigV3,
|
||||
}
|
||||
|
||||
impl From<ConfigV1_1_20_2> for ConfigV1_1_30 {
|
||||
fn from(value: ConfigV1_1_20_2) -> Self {
|
||||
ConfigV1_1_30 {
|
||||
impl From<ConfigV3> for ConfigV4 {
|
||||
fn from(value: ConfigV3) -> Self {
|
||||
ConfigV4 {
|
||||
client: value.client.into(),
|
||||
debug: value.debug.into(),
|
||||
}
|
||||
@@ -69,7 +82,7 @@ impl From<ConfigV1_1_20_2> for ConfigV1_1_30 {
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Eq, Serialize)]
|
||||
pub struct GatewayEndpointConfigV1_1_20_2 {
|
||||
pub struct GatewayEndpointConfigV3 {
|
||||
/// gateway_id specifies ID of the gateway to which the client should send messages.
|
||||
/// If initially omitted, a random gateway will be chosen from the available topology.
|
||||
pub gateway_id: String,
|
||||
@@ -81,9 +94,9 @@ pub struct GatewayEndpointConfigV1_1_20_2 {
|
||||
pub gateway_listener: String,
|
||||
}
|
||||
|
||||
impl From<GatewayEndpointConfigV1_1_20_2> for GatewayEndpointConfig {
|
||||
fn from(value: GatewayEndpointConfigV1_1_20_2) -> Self {
|
||||
GatewayEndpointConfig {
|
||||
impl From<GatewayEndpointConfigV3> for GatewayEndpointConfigV5 {
|
||||
fn from(value: GatewayEndpointConfigV3) -> Self {
|
||||
GatewayEndpointConfigV5 {
|
||||
gateway_id: value.gateway_id,
|
||||
gateway_owner: value.gateway_owner,
|
||||
gateway_listener: value.gateway_listener,
|
||||
@@ -92,7 +105,7 @@ impl From<GatewayEndpointConfigV1_1_20_2> for GatewayEndpointConfig {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
|
||||
pub struct ClientV1_1_20_2 {
|
||||
pub struct ClientV3 {
|
||||
pub version: String,
|
||||
|
||||
pub id: String,
|
||||
@@ -105,12 +118,12 @@ pub struct ClientV1_1_20_2 {
|
||||
|
||||
#[serde(alias = "validator_api_urls")]
|
||||
pub nym_api_urls: Vec<Url>,
|
||||
pub gateway_endpoint: GatewayEndpointConfigV1_1_20_2,
|
||||
pub gateway_endpoint: GatewayEndpointConfigV3,
|
||||
}
|
||||
|
||||
impl From<ClientV1_1_20_2> for ClientV1_1_30 {
|
||||
fn from(value: ClientV1_1_20_2) -> Self {
|
||||
ClientV1_1_30 {
|
||||
impl From<ClientV3> for ClientV4 {
|
||||
fn from(value: ClientV3) -> Self {
|
||||
ClientV4 {
|
||||
version: value.version,
|
||||
id: value.id,
|
||||
disabled_credentials_mode: value.disabled_credentials_mode,
|
||||
@@ -122,7 +135,7 @@ impl From<ClientV1_1_20_2> for ClientV1_1_30 {
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default)]
|
||||
pub struct TrafficV1_1_20_2 {
|
||||
pub struct TrafficV3 {
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub average_packet_delay: Duration,
|
||||
#[serde(with = "humantime_serde")]
|
||||
@@ -133,9 +146,9 @@ pub struct TrafficV1_1_20_2 {
|
||||
pub packet_type: PacketType,
|
||||
}
|
||||
|
||||
impl From<TrafficV1_1_20_2> for TrafficV1_1_30 {
|
||||
fn from(value: TrafficV1_1_20_2) -> Self {
|
||||
TrafficV1_1_30 {
|
||||
impl From<TrafficV3> for TrafficV4 {
|
||||
fn from(value: TrafficV3) -> Self {
|
||||
TrafficV4 {
|
||||
average_packet_delay: value.average_packet_delay,
|
||||
message_sending_average_delay: value.message_sending_average_delay,
|
||||
disable_main_poisson_packet_distribution: value
|
||||
@@ -147,9 +160,9 @@ impl From<TrafficV1_1_20_2> for TrafficV1_1_30 {
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for TrafficV1_1_20_2 {
|
||||
impl Default for TrafficV3 {
|
||||
fn default() -> Self {
|
||||
TrafficV1_1_20_2 {
|
||||
TrafficV3 {
|
||||
average_packet_delay: DEFAULT_AVERAGE_PACKET_DELAY,
|
||||
message_sending_average_delay: DEFAULT_MESSAGE_STREAM_AVERAGE_DELAY,
|
||||
disable_main_poisson_packet_distribution: false,
|
||||
@@ -162,16 +175,16 @@ impl Default for TrafficV1_1_20_2 {
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct CoverTrafficV1_1_20_2 {
|
||||
pub struct CoverTrafficV3 {
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub loop_cover_traffic_average_delay: Duration,
|
||||
pub cover_traffic_primary_size_ratio: f64,
|
||||
pub disable_loop_cover_traffic_stream: bool,
|
||||
}
|
||||
|
||||
impl From<CoverTrafficV1_1_20_2> for CoverTrafficV1_1_30 {
|
||||
fn from(value: CoverTrafficV1_1_20_2) -> Self {
|
||||
CoverTrafficV1_1_30 {
|
||||
impl From<CoverTrafficV3> for CoverTrafficV4 {
|
||||
fn from(value: CoverTrafficV3) -> Self {
|
||||
CoverTrafficV4 {
|
||||
loop_cover_traffic_average_delay: value.loop_cover_traffic_average_delay,
|
||||
cover_traffic_primary_size_ratio: value.cover_traffic_primary_size_ratio,
|
||||
disable_loop_cover_traffic_stream: value.disable_loop_cover_traffic_stream,
|
||||
@@ -179,9 +192,9 @@ impl From<CoverTrafficV1_1_20_2> for CoverTrafficV1_1_30 {
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for CoverTrafficV1_1_20_2 {
|
||||
impl Default for CoverTrafficV3 {
|
||||
fn default() -> Self {
|
||||
CoverTrafficV1_1_20_2 {
|
||||
CoverTrafficV3 {
|
||||
loop_cover_traffic_average_delay: DEFAULT_LOOP_COVER_STREAM_AVERAGE_DELAY,
|
||||
cover_traffic_primary_size_ratio: DEFAULT_COVER_TRAFFIC_PRIMARY_SIZE_RATIO,
|
||||
disable_loop_cover_traffic_stream: false,
|
||||
@@ -191,22 +204,22 @@ impl Default for CoverTrafficV1_1_20_2 {
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct GatewayConnectionV1_1_20_2 {
|
||||
pub struct GatewayConnectionV3 {
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub gateway_response_timeout: Duration,
|
||||
}
|
||||
|
||||
impl From<GatewayConnectionV1_1_20_2> for GatewayConnectionV1_1_30 {
|
||||
fn from(value: GatewayConnectionV1_1_20_2) -> Self {
|
||||
GatewayConnectionV1_1_30 {
|
||||
impl From<GatewayConnectionV3> for GatewayConnectionV4 {
|
||||
fn from(value: GatewayConnectionV3) -> Self {
|
||||
GatewayConnectionV4 {
|
||||
gateway_response_timeout: value.gateway_response_timeout,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for GatewayConnectionV1_1_20_2 {
|
||||
impl Default for GatewayConnectionV3 {
|
||||
fn default() -> Self {
|
||||
GatewayConnectionV1_1_20_2 {
|
||||
GatewayConnectionV3 {
|
||||
gateway_response_timeout: DEFAULT_GATEWAY_RESPONSE_TIMEOUT,
|
||||
}
|
||||
}
|
||||
@@ -214,7 +227,7 @@ impl Default for GatewayConnectionV1_1_20_2 {
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct AcknowledgementsV1_1_20_2 {
|
||||
pub struct AcknowledgementsV3 {
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub average_ack_delay: Duration,
|
||||
pub ack_wait_multiplier: f64,
|
||||
@@ -222,9 +235,9 @@ pub struct AcknowledgementsV1_1_20_2 {
|
||||
pub ack_wait_addition: Duration,
|
||||
}
|
||||
|
||||
impl From<AcknowledgementsV1_1_20_2> for AcknowledgementsV1_1_30 {
|
||||
fn from(value: AcknowledgementsV1_1_20_2) -> Self {
|
||||
AcknowledgementsV1_1_30 {
|
||||
impl From<AcknowledgementsV3> for AcknowledgementsV4 {
|
||||
fn from(value: AcknowledgementsV3) -> Self {
|
||||
AcknowledgementsV4 {
|
||||
average_ack_delay: value.average_ack_delay,
|
||||
ack_wait_multiplier: value.ack_wait_multiplier,
|
||||
ack_wait_addition: value.ack_wait_addition,
|
||||
@@ -232,9 +245,9 @@ impl From<AcknowledgementsV1_1_20_2> for AcknowledgementsV1_1_30 {
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for AcknowledgementsV1_1_20_2 {
|
||||
impl Default for AcknowledgementsV3 {
|
||||
fn default() -> Self {
|
||||
AcknowledgementsV1_1_20_2 {
|
||||
AcknowledgementsV3 {
|
||||
average_ack_delay: DEFAULT_AVERAGE_PACKET_DELAY,
|
||||
ack_wait_multiplier: DEFAULT_ACK_WAIT_MULTIPLIER,
|
||||
ack_wait_addition: DEFAULT_ACK_WAIT_ADDITION,
|
||||
@@ -244,7 +257,7 @@ impl Default for AcknowledgementsV1_1_20_2 {
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct TopologyV1_1_20_2 {
|
||||
pub struct TopologyV3 {
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub topology_refresh_rate: Duration,
|
||||
#[serde(with = "humantime_serde")]
|
||||
@@ -252,9 +265,9 @@ pub struct TopologyV1_1_20_2 {
|
||||
pub disable_refreshing: bool,
|
||||
}
|
||||
|
||||
impl Default for TopologyV1_1_20_2 {
|
||||
impl Default for TopologyV3 {
|
||||
fn default() -> Self {
|
||||
TopologyV1_1_20_2 {
|
||||
TopologyV3 {
|
||||
topology_refresh_rate: DEFAULT_TOPOLOGY_REFRESH_RATE,
|
||||
topology_resolution_timeout: DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT,
|
||||
disable_refreshing: false,
|
||||
@@ -262,9 +275,9 @@ impl Default for TopologyV1_1_20_2 {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TopologyV1_1_20_2> for TopologyV1_1_30 {
|
||||
fn from(value: TopologyV1_1_20_2) -> Self {
|
||||
TopologyV1_1_30 {
|
||||
impl From<TopologyV3> for TopologyV4 {
|
||||
fn from(value: TopologyV3) -> Self {
|
||||
TopologyV4 {
|
||||
topology_refresh_rate: value.topology_refresh_rate,
|
||||
topology_resolution_timeout: value.topology_resolution_timeout,
|
||||
disable_refreshing: value.disable_refreshing,
|
||||
@@ -275,7 +288,7 @@ impl From<TopologyV1_1_20_2> for TopologyV1_1_30 {
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct ReplySurbsV1_1_20_2 {
|
||||
pub struct ReplySurbsV3 {
|
||||
pub minimum_reply_surb_storage_threshold: usize,
|
||||
pub maximum_reply_surb_storage_threshold: usize,
|
||||
pub minimum_reply_surb_request_size: u32,
|
||||
@@ -291,9 +304,9 @@ pub struct ReplySurbsV1_1_20_2 {
|
||||
pub maximum_reply_key_age: Duration,
|
||||
}
|
||||
|
||||
impl Default for ReplySurbsV1_1_20_2 {
|
||||
impl Default for ReplySurbsV3 {
|
||||
fn default() -> Self {
|
||||
ReplySurbsV1_1_20_2 {
|
||||
ReplySurbsV3 {
|
||||
minimum_reply_surb_storage_threshold: DEFAULT_MINIMUM_REPLY_SURB_STORAGE_THRESHOLD,
|
||||
maximum_reply_surb_storage_threshold: DEFAULT_MAXIMUM_REPLY_SURB_STORAGE_THRESHOLD,
|
||||
minimum_reply_surb_request_size: DEFAULT_MINIMUM_REPLY_SURB_REQUEST_SIZE,
|
||||
@@ -308,9 +321,9 @@ impl Default for ReplySurbsV1_1_20_2 {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ReplySurbsV1_1_20_2> for ReplySurbsV1_1_30 {
|
||||
fn from(value: ReplySurbsV1_1_20_2) -> Self {
|
||||
ReplySurbsV1_1_30 {
|
||||
impl From<ReplySurbsV3> for ReplySurbsV4 {
|
||||
fn from(value: ReplySurbsV3) -> Self {
|
||||
ReplySurbsV4 {
|
||||
minimum_reply_surb_storage_threshold: value.minimum_reply_surb_storage_threshold,
|
||||
maximum_reply_surb_storage_threshold: value.maximum_reply_surb_storage_threshold,
|
||||
minimum_reply_surb_request_size: value.minimum_reply_surb_request_size,
|
||||
@@ -327,18 +340,18 @@ impl From<ReplySurbsV1_1_20_2> for ReplySurbsV1_1_30 {
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct DebugConfigV1_1_20_2 {
|
||||
pub traffic: TrafficV1_1_20_2,
|
||||
pub cover_traffic: CoverTrafficV1_1_20_2,
|
||||
pub gateway_connection: GatewayConnectionV1_1_20_2,
|
||||
pub acknowledgements: AcknowledgementsV1_1_20_2,
|
||||
pub topology: TopologyV1_1_20_2,
|
||||
pub reply_surbs: ReplySurbsV1_1_20_2,
|
||||
pub struct DebugConfigV3 {
|
||||
pub traffic: TrafficV3,
|
||||
pub cover_traffic: CoverTrafficV3,
|
||||
pub gateway_connection: GatewayConnectionV3,
|
||||
pub acknowledgements: AcknowledgementsV3,
|
||||
pub topology: TopologyV3,
|
||||
pub reply_surbs: ReplySurbsV3,
|
||||
}
|
||||
|
||||
impl From<DebugConfigV1_1_20_2> for DebugConfigV1_1_30 {
|
||||
fn from(value: DebugConfigV1_1_20_2) -> Self {
|
||||
DebugConfigV1_1_30 {
|
||||
impl From<DebugConfigV3> for DebugConfigV4 {
|
||||
fn from(value: DebugConfigV3) -> Self {
|
||||
DebugConfigV4 {
|
||||
traffic: value.traffic.into(),
|
||||
cover_traffic: value.cover_traffic.into(),
|
||||
gateway_connection: value.gateway_connection.into(),
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user