Compare commits
698 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a8582b2a0f | |||
| 8493dbc47b | |||
| 602b9e2ae9 | |||
| 103a2cbd4f | |||
| e4b11ecab4 | |||
| 781606bec5 | |||
| f4d709c0dd | |||
| 8699e1887c | |||
| bf39319cbb | |||
| e92ce0a5f3 | |||
| f7b90b3808 | |||
| 837a33480e | |||
| 7b02c3d24a | |||
| c59845e746 | |||
| 119782920a | |||
| 30ba38c2b3 | |||
| 87547576de | |||
| 5febb8c4e2 | |||
| ddc6986401 | |||
| c0cabc9739 | |||
| 9a1da5b7c2 | |||
| 5daa2b9dff | |||
| 5988acb12b | |||
| 011d05f7b6 | |||
| 294d1a525e | |||
| e5770a5343 | |||
| 7a65e1feb5 | |||
| 4e55f53fb4 | |||
| 4d944d3dc3 | |||
| 3d3b4837ff | |||
| 8270e0898b | |||
| 2ed63ab3ac | |||
| d99a48d87d | |||
| 27375e7382 | |||
| a81d3c4989 | |||
| b922440fc7 | |||
| 6ca6f2ed3d | |||
| 954b9252c1 | |||
| e355f45544 | |||
| ed32664b9e | |||
| 8619057224 | |||
| 10978c59e4 | |||
| ed56206c30 | |||
| 513c2dfc3b | |||
| 0b544bf55a | |||
| a9d39f0803 | |||
| 2248739dd5 | |||
| b83b691714 | |||
| 887611c9d8 | |||
| 390cf0257e | |||
| 2503dca0e3 | |||
| 8fd45cc977 | |||
| 8d9b9e505e | |||
| 2453c08194 | |||
| f149613d54 | |||
| 2c5cfb6442 | |||
| cfddaf1508 | |||
| 6eff190f87 | |||
| e40c5190b1 | |||
| 2584799415 | |||
| 0463901db7 | |||
| c2704af523 | |||
| 328e9cade9 | |||
| 2b61fff449 | |||
| d8bbe2110e | |||
| 1ef88622d6 | |||
| b1d3fb63f3 | |||
| f44ffd1959 | |||
| e7545db663 | |||
| fcf9d2ad15 | |||
| 7986321a52 | |||
| 8e0f28ee30 | |||
| fecfa18999 | |||
| d8b23cd13c | |||
| 0e0101f507 | |||
| 17a17850ea | |||
| 71d4a6dab0 | |||
| 936d3b5280 | |||
| fac9c23103 | |||
| 3674401923 | |||
| 66d6d0dc33 | |||
| 31ce134413 | |||
| b8e6aae289 | |||
| 8f620712ef | |||
| 1069d1c066 | |||
| bc0634a541 | |||
| 8d65a99fe4 | |||
| 6e68714c26 | |||
| 06ff7b661a | |||
| 70a6442b46 | |||
| 9e7d394ae7 | |||
| 326b2d7a04 | |||
| f3045a5e80 | |||
| b3d72cbfcb | |||
| 76c4573c39 | |||
| 741bec9874 | |||
| 46aed06523 | |||
| 7630c1a883 | |||
| 2877e5dfc1 | |||
| 05b88a48a3 | |||
| c74b567fe4 | |||
| a6b6cb0f09 | |||
| 86e9af6fd7 | |||
| 8776f7dfbb | |||
| 929f908a86 | |||
| 229d7b052a | |||
| a5896f7ae8 | |||
| 114c2cee93 | |||
| 7f413ec994 | |||
| bd30a68e7d | |||
| f4a18726b5 | |||
| 50e284357c | |||
| 2ddb03e2be | |||
| ebae616138 | |||
| 0f88640575 | |||
| 75cc82ae0c | |||
| 32dc235aa5 | |||
| 6ffe1d81c2 | |||
| 5b245e64d3 | |||
| a067361d74 | |||
| a7f66c8883 | |||
| e03e7d831e | |||
| 1219ed0dd6 | |||
| fe2ff95f19 | |||
| d72f0ce40c | |||
| df43e2c126 | |||
| d8ecc1174d | |||
| 3e269b49d4 | |||
| 72c9f3b0db | |||
| 2f5b0db786 | |||
| 8d9f16c387 | |||
| d6cb0ee8a0 | |||
| 5444701c38 | |||
| 396479c2bf | |||
| d78885dcd4 | |||
| ede72ff1d8 | |||
| e5bf27030d | |||
| 375bf56e2e | |||
| f79be1b343 | |||
| 3554adf0c1 | |||
| a32cc9f0f5 | |||
| 3759fd4ac4 | |||
| ac58e8be2e | |||
| 1c7646f98f | |||
| 1b9d14e89d | |||
| 3c41388eb7 | |||
| a9a2113ea4 | |||
| b5fa34e1a1 | |||
| 192f1d722d | |||
| b857664d27 | |||
| 19491f0994 | |||
| 6738b57ba2 | |||
| 30560e6cf8 | |||
| e1de021fba | |||
| 8b4f05dc78 | |||
| 950330b5f7 | |||
| 9927718e25 | |||
| b7ff4f2c2c | |||
| 47c79459a6 | |||
| 143960937e | |||
| ee16ce10c1 | |||
| 3988a69946 | |||
| 738b2e416e | |||
| b96dfa602b | |||
| 9d6f232dd1 | |||
| d808ba6cbf | |||
| 818fab8909 | |||
| 1ffaf3a292 | |||
| 8e11c3dffd | |||
| a7496dbc02 | |||
| 9e439044de | |||
| 536552b9db | |||
| 183bab110e | |||
| beea3e2184 | |||
| e0a3add5f2 | |||
| fd8e5e4eed | |||
| 6f7139fe28 | |||
| 57d996491e | |||
| ba8e0578ed | |||
| 65b267c497 | |||
| 512064de61 | |||
| 2cdb8b5323 | |||
| d08ac60fd9 | |||
| fbc0159453 | |||
| 3d526cebbc | |||
| 2d10a6a270 | |||
| 5f7ce28682 | |||
| 9d0f835186 | |||
| 3fdadf3eb5 | |||
| cd57ab6ad9 | |||
| eab8a51bb7 | |||
| dbb4efb98a | |||
| a83d6deec1 | |||
| f212de64f5 | |||
| 6a4583f758 | |||
| 325f2dc22f | |||
| 7134187dc9 | |||
| b20db0a117 | |||
| 3c7fcf65a9 | |||
| 4fa344a0f7 | |||
| 9aa748e628 | |||
| bba4f8d0c5 | |||
| be8b38e5cf | |||
| db9e5ba332 | |||
| 689fa14cfd | |||
| fa924171c7 | |||
| 8a222d5e75 | |||
| fcb62894a5 | |||
| c94b627808 | |||
| 754eb78a05 | |||
| 045929ca7c | |||
| 98b2d2057c | |||
| 98a9eb4f18 | |||
| 58d32ffd1f | |||
| 76c3e89faf | |||
| abf48fde02 | |||
| c31d5b7d3c | |||
| f455ce398c | |||
| b498084388 | |||
| 75c156578c | |||
| fd67ec1f86 | |||
| b1041ea8a8 | |||
| 51a075c0df | |||
| 8bf045974f | |||
| 44d2005ab1 | |||
| 21f827112d | |||
| 5f18eed14d | |||
| 7a83fd2f30 | |||
| 6e258bb210 | |||
| 72adfd3126 | |||
| 196b27f3b2 | |||
| ce192670a3 | |||
| 14ab9f462a | |||
| 93365973a7 | |||
| 950ecd6bbc | |||
| 8420f5f1b1 | |||
| 80352f6b30 | |||
| 6ef166ba33 | |||
| 9368b96129 | |||
| 025f0bdd0b | |||
| 2d76846d3c | |||
| f6cc7abac9 | |||
| 572d2251d7 | |||
| 7dd9fb9b47 | |||
| 92827035e0 | |||
| 5f7b8c3371 | |||
| 03eddddc0e | |||
| 080fbaa26c | |||
| f6a285de87 | |||
| 55e4ea0277 | |||
| bb80fe12a0 | |||
| 5c67f0df20 | |||
| 3697c079fa | |||
| 2e6041dcf5 | |||
| 645de31fe3 | |||
| eef90da7ae | |||
| c0586a5089 | |||
| b30018bb38 | |||
| 6c45573976 | |||
| b6c1b1a6d7 | |||
| d41a441e98 | |||
| 86b6cf2d65 | |||
| cf11993cb1 | |||
| fe7ef30650 | |||
| bb4c7f0298 | |||
| a7db46d69b | |||
| ce81c2769c | |||
| d4a57370ef | |||
| 634039e551 | |||
| a83edceae3 | |||
| 19cc044cab | |||
| 79ad29e99a | |||
| f96e291681 | |||
| 6685a22118 | |||
| a84a0bd8dc | |||
| c2d8c806d2 | |||
| 387860aa4a | |||
| de7bdba95f | |||
| 6baf5247cb | |||
| 146d29b627 | |||
| c1a1249be1 | |||
| 8e7a797586 | |||
| 14a1918fda | |||
| 54e755efdd | |||
| 3df7430663 | |||
| c71d89c95a | |||
| 1b5860eec8 | |||
| 4741880044 | |||
| 02a0cb174a | |||
| e53fd7a062 | |||
| a76d8049c0 | |||
| 0ce1558f54 | |||
| 2807f9a51c | |||
| 03a3423da0 | |||
| 12a011a9ff | |||
| 7a1afc7a95 | |||
| 262b4f2a2e | |||
| fadc5055b2 | |||
| 1c908c261d | |||
| 39216df8eb | |||
| ed59579a9d | |||
| 2aa7389c3f | |||
| 02970e2f8f | |||
| 2e00ac402a | |||
| c94dd46294 | |||
| df802c3b26 | |||
| 8430a506cc | |||
| 46a6196c92 | |||
| e64a0acfb3 | |||
| 14f7a1cb61 | |||
| 1cfacf4118 | |||
| 975679ef87 | |||
| dfa27016fd | |||
| 25d083ef25 | |||
| c989bdb0ea | |||
| cb9e98dc88 | |||
| c7ba11c607 | |||
| 8876af53d8 | |||
| 70f78ebfd1 | |||
| be434329d1 | |||
| 67f091b843 | |||
| 33a592ee52 | |||
| a574e68bb7 | |||
| 001c9e937d | |||
| f01bd88edd | |||
| 8700edb330 | |||
| 9b686673ae | |||
| c841a2d2a9 | |||
| c8248b2d33 | |||
| 5e373b5304 | |||
| d73b506d09 | |||
| d332f6cf23 | |||
| 1c4806e0d7 | |||
| f5ac485ac8 | |||
| 595196b5ec | |||
| 85d177d394 | |||
| 4ee8890166 | |||
| 5e8858c40e | |||
| 420cb71990 | |||
| 451778d704 | |||
| c855bb769a | |||
| f95d56d1eb | |||
| fe5e209eb1 | |||
| f206e4b334 | |||
| 5bd518da4b | |||
| ec8e40907d | |||
| e828709090 | |||
| d4329ae594 | |||
| 2c4c2b8469 | |||
| 14f667de74 | |||
| 578baeae96 | |||
| 1ad3fdfd46 | |||
| 5eaf5d1f51 | |||
| 8e7df958b8 | |||
| 4f2ad9a93c | |||
| 850eb8e6e0 | |||
| 47f551c046 | |||
| ae6747c82d | |||
| 1bd04c2840 | |||
| 11e4c459c9 | |||
| 647319b731 | |||
| e0913f9068 | |||
| af0fa872ae | |||
| 1ce8f28105 | |||
| a525f34fec | |||
| 632f3faac5 | |||
| 4f34c4466a | |||
| ccc5117172 | |||
| b346b93285 | |||
| 2b61c1d90f | |||
| baf5a64c51 | |||
| 260564cff1 | |||
| 248f74d948 | |||
| 724a9e49df | |||
| 726224b253 | |||
| 421e087d81 | |||
| a1ec97a221 | |||
| d151ed9354 | |||
| 7502481f26 | |||
| 76e7e4956d | |||
| 15d25bca27 | |||
| dffc8bcea0 | |||
| a61966ed61 | |||
| e6d77a40e2 | |||
| edcb933874 | |||
| be18ad4177 | |||
| 07a5b191bb | |||
| da12b329be | |||
| 3902612c4b | |||
| 9bce415523 | |||
| 3e4f877ec0 | |||
| 1b601343ff | |||
| 77ee46e153 | |||
| 357c1a20df | |||
| 67bbfea87d | |||
| 220c6939b1 | |||
| fd27ea0e8f | |||
| 4bb1982806 | |||
| 9283677a2b | |||
| d4180a5084 | |||
| 2721b16c46 | |||
| f1ff6a21ee | |||
| 530079b8a5 | |||
| 2ca428bbbb | |||
| 8a27a8cce4 | |||
| 7eec4d742c | |||
| 3f66975e1b | |||
| b7f8c973f4 | |||
| 98e51feb46 | |||
| 68fccd2edb | |||
| 72e414b2b7 | |||
| 79a31ce57c | |||
| 488ed8e562 | |||
| b3bce1651b | |||
| e9a2e4b076 | |||
| cc2f031a32 | |||
| d0eea1bf91 | |||
| 53ba29b288 | |||
| c5f3a03d1e | |||
| da9cdf7df3 | |||
| 8a7f1b1b3a | |||
| aa14620a50 | |||
| 1fa6a7c11a | |||
| 25806b67a2 | |||
| 47ff7e228e | |||
| c135787620 | |||
| bbc3d44526 | |||
| 2e747beda6 | |||
| b9a9be2795 | |||
| 19414b061b | |||
| 74b5ab1798 | |||
| 83cda110aa | |||
| 6f87546492 | |||
| 1f7c89a95c | |||
| 0df11d24f5 | |||
| a6c27a1e3f | |||
| 0a5fa12ce5 | |||
| c090b0cf62 | |||
| 45660e3d96 | |||
| 732190bb11 | |||
| b667f88d0e | |||
| 255d312ae0 | |||
| cc92ae7998 | |||
| ae9905e4c7 | |||
| 38469c26ff | |||
| 07b460147e | |||
| 6cf1b13500 | |||
| 4a8d4ab8d9 | |||
| 65a9574e52 | |||
| 6eacb677a4 | |||
| d081c8ea74 | |||
| 0342e7ffb5 | |||
| c029e5c39d | |||
| a917a9493c | |||
| 02405bb8ff | |||
| d8bb85a1d8 | |||
| fd6b2360aa | |||
| 3e655961e9 | |||
| 077837054b | |||
| 45674ef554 | |||
| eabf856dbd | |||
| 32ea0f2cf6 | |||
| 47f40c0be3 | |||
| 6a66615f37 | |||
| 314a1ba39b | |||
| 2daa7f9fea | |||
| f0d576e1b0 | |||
| be76c58264 | |||
| 8245f232d4 | |||
| 7468af0779 | |||
| 38a6d3e549 | |||
| 3022588e35 | |||
| b81f1c4975 | |||
| ed78e9df6e | |||
| f044149004 | |||
| f126eb7611 | |||
| afa9cf371e | |||
| f813cf6d36 | |||
| 3dcd3dbb7f | |||
| d80a06bc8e | |||
| 947178f10a | |||
| e92cc7d50c | |||
| 989a28a8ca | |||
| e4dd46b498 | |||
| c49e8d4770 | |||
| 86156f3fec | |||
| fec826b10e | |||
| 229b07391b | |||
| e157477b6d | |||
| d40bb61da8 | |||
| 4733d42932 | |||
| e6030dcc3f | |||
| 6615fa67f5 | |||
| dc4b88d08e | |||
| cc2abe3c30 | |||
| 70640b65ea | |||
| 4599d81a59 | |||
| 3ea5b575b7 | |||
| b9eb66e2b3 | |||
| bde5b19c77 | |||
| cc60ab3d63 | |||
| 42f7e6f486 | |||
| 5f68b5923d | |||
| 85abbdd699 | |||
| 3802886722 | |||
| d4e27a27cb | |||
| e882b91b06 | |||
| 4c8dbee79d | |||
| 1438175477 | |||
| 30861bbf91 | |||
| ea6a19a260 | |||
| fc81fa8745 | |||
| 948436e57e | |||
| 3dde71f1ff | |||
| be0e220fe4 | |||
| 2e9a209a78 | |||
| 3ce4f06b6c | |||
| 555414cd51 | |||
| c33033b2f4 | |||
| 3c697c2d7e | |||
| 0e7c1aa481 | |||
| 7d5ff13f75 | |||
| 02a8a512dc | |||
| 4733f46a28 | |||
| 945de348f3 | |||
| 20dd9d7adc | |||
| c5bd184bbc | |||
| ae161fac49 | |||
| 8eb780a8b5 | |||
| 1c33cc9f3d | |||
| 9d692d5194 | |||
| a7da7f932c | |||
| 2e4f7adee4 | |||
| dcb822f812 | |||
| 5da286fed4 | |||
| 4ec0fe8d96 | |||
| 340a3e85c8 | |||
| 64baf660bb | |||
| 4f24f18b27 | |||
| c5ea4dca67 | |||
| deaf47155f | |||
| a1d1420ec3 | |||
| a133a25cc3 | |||
| 65e15b5205 | |||
| ac123939e5 | |||
| 2cafc570a8 | |||
| 9e5d5cecd4 | |||
| deb8d59130 | |||
| 14bbf96feb | |||
| ee1c5a0a56 | |||
| a281db1cbb | |||
| b25e5449c8 | |||
| b267c19a45 | |||
| 0bda37057a | |||
| 2aa8d2bdcc | |||
| eebcbb5cc2 | |||
| acf37ff10f | |||
| 56c239a368 | |||
| ae7386e7be | |||
| 9ddf510716 | |||
| d79fefe546 | |||
| 921cbb0b69 | |||
| 7f1b849394 | |||
| 9f4388843a | |||
| 37fba30c79 | |||
| 8f1fd55e2f | |||
| 8af9e9b27d | |||
| 8b681d6efb | |||
| 75b9a0228b | |||
| cbc00e6416 | |||
| a0778c8d7b | |||
| 0c4dc82c65 | |||
| a35d4b2701 | |||
| 05b0973a23 | |||
| 09f46beeb4 | |||
| b4c7eea4d9 | |||
| 8159ecfce4 | |||
| 662e2b5ba0 | |||
| 5ca9f968aa | |||
| 6ef34bb3f5 | |||
| 9a5be0a321 | |||
| c203f6eb0a | |||
| b713f4e702 | |||
| 111087d96a | |||
| 9e7666d12f | |||
| cb147773b5 | |||
| d84bef8f14 | |||
| 32bb318af4 | |||
| 055b5e2256 | |||
| c1754d122f | |||
| 6d121122f8 | |||
| bfa8334aeb | |||
| 0e222afd6a | |||
| b191962d32 | |||
| 1cf13e142a | |||
| 8f1f81749d | |||
| 72d70eba16 | |||
| ae3612f595 | |||
| 37b6457054 | |||
| 9579be5c7d | |||
| d05d47fa75 | |||
| bd88c04e9e | |||
| eb3a3872eb | |||
| 5cea7be405 | |||
| 516c382fe4 | |||
| 710e55422a | |||
| 3406cf78b4 | |||
| 8fa354796c | |||
| 6c6ef1c1b8 | |||
| c3c326c680 | |||
| 92e20485b2 | |||
| edd782ac23 | |||
| a4d84e318d | |||
| 08ee599f79 | |||
| 134f2d68a3 | |||
| d23c46ff84 | |||
| 820c5db5e8 | |||
| 990916ab62 | |||
| d4e362cd76 | |||
| 1dd06cc509 | |||
| 2e2bd1d137 | |||
| 0818d91f4f | |||
| 6e1f34b168 | |||
| 1a35177633 | |||
| c45689b02b | |||
| 8f27d940e3 | |||
| 6b4640c413 | |||
| 8aebcdc580 | |||
| e23a2e77a8 | |||
| 0f9362e14e | |||
| ab974b9684 | |||
| 54acfee036 | |||
| a78ddb50d5 | |||
| b2f86a5f6b | |||
| 2a77695832 | |||
| 21d8cb917b | |||
| 2c70bf8616 | |||
| 7522111bb7 | |||
| 7b5b910f3f | |||
| afb52e4235 | |||
| 93cd9a659a | |||
| 9e287ab4f0 | |||
| 094209f311 | |||
| dee66c3f32 | |||
| 32533e3c96 | |||
| a073923a82 | |||
| 3484b24caa | |||
| 1b3c1eb850 | |||
| 7fe032915f | |||
| 5b9b73abcc | |||
| a2afa29052 | |||
| a2d3dbad5e | |||
| e50cf060cb | |||
| 915988d694 | |||
| 345c231a9a | |||
| a7aed2f221 | |||
| 292e2580e5 | |||
| 028a5d0c88 | |||
| 8b27faad6d | |||
| cdc3206ee8 | |||
| 0c2b7d6010 | |||
| ef15c3b54f | |||
| f4bcdc7fe9 | |||
| aada1bb5cc | |||
| 796850d8c5 | |||
| ab0bc0488e | |||
| f3af02111d | |||
| c21d052d7a | |||
| 62b1690780 | |||
| 52050bbcfb | |||
| 0db57e5047 | |||
| e7919514d4 | |||
| 7ab21c6afd | |||
| 2209e0cc70 | |||
| a73b4616a4 | |||
| 9593311332 | |||
| 9a09d15bea | |||
| f082488e4b | |||
| c56773d4d6 | |||
| 752e2381d6 | |||
| 03f829e18c | |||
| 06b66c99db | |||
| 0b0ad9ff82 | |||
| de9f13d393 | |||
| 272d206741 | |||
| c9493ec7fa | |||
| 5ef4134955 | |||
| 8045c40026 | |||
| d4a1b14820 | |||
| cc6ce4a366 | |||
| 25e5f80a81 | |||
| d4b339b1a3 | |||
| 4bdd524d84 | |||
| b78fe02405 | |||
| dfa0c7ffb1 | |||
| ec97a14da7 | |||
| 3a2e9e8b94 | |||
| 069c96aa1d |
@@ -0,0 +1,2 @@
|
||||
**/build
|
||||
**/docker-compose
|
||||
+535
-41
@@ -2,30 +2,129 @@ name: C/C++ CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
paths-ignore:
|
||||
- 'docker-compose/**'
|
||||
- 'docs/**'
|
||||
- 'README.md'
|
||||
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
jobs:
|
||||
build-alpine-static:
|
||||
|
||||
timeout-minutes: 75
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
config:
|
||||
- {arch: x86_64, flags: "-flto=2 -fuse-linker-plugin -ffunction-sections -Wno-error=inline"}
|
||||
- {arch: aarch64, flags: "-flto=2 -fuse-linker-plugin -ffunction-sections -Wno-error=inline -mfix-cortex-a53-835769 -mfix-cortex-a53-843419"}
|
||||
|
||||
steps:
|
||||
- name: Setup Alpine Linux
|
||||
uses: jirutka/setup-alpine@v1
|
||||
with:
|
||||
arch: ${{ matrix.config.arch }}
|
||||
|
||||
- name: Install dependencies
|
||||
shell: alpine.sh --root {0}
|
||||
run: |
|
||||
apk add git cmake gcc g++ make
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Build libcurl
|
||||
shell: alpine.sh {0}
|
||||
run: |
|
||||
cd external/src/curl
|
||||
cmake . -DCMAKE_C_FLAGS="-Os ${{ matrix.config.flags }}" -DBUILD_CURL_EXE=OFF -DBUILD_SHARED_LIBS=OFF -DCURL_ZLIB=OFF -DCURL_DISABLE_ALTSVC=ON -DCURL_DISABLE_COOKIES=ON -DCURL_DISABLE_DOH=ON -DCURL_DISABLE_GETOPTIONS=ON -DCURL_DISABLE_HSTS=ON -DCURL_DISABLE_LIBCURL_OPTION=ON -DCURL_DISABLE_MIME=ON -DCURL_DISABLE_NETRC=ON -DCURL_DISABLE_NTLM=ON -DCURL_DISABLE_PARSEDATE=ON -DCURL_DISABLE_PROGRESS_METER=ON -DCURL_DISABLE_SHUFFLE_DNS=ON -DCURL_DISABLE_SOCKETPAIR=ON -DCURL_DISABLE_VERBOSE_STRINGS=ON -DHTTP_ONLY=ON -DCURL_ENABLE_SSL=OFF -DUSE_LIBIDN2=OFF -DCURL_USE_LIBPSL=OFF -DCURL_USE_LIBSSH2=OFF -DENABLE_UNIX_SOCKETS=OFF
|
||||
make -j$(nproc)
|
||||
cd lib && mkdir .libs && cp libcurl.a .libs
|
||||
|
||||
- name: Build libuv
|
||||
shell: alpine.sh {0}
|
||||
run: |
|
||||
cd external/src/libuv
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_FLAGS='-Os ${{ matrix.config.flags }}' -DBUILD_TESTING=OFF -DLIBUV_BUILD_SHARED=OFF
|
||||
make -j$(nproc)
|
||||
|
||||
- name: Build libzmq
|
||||
shell: alpine.sh {0}
|
||||
run: |
|
||||
cd external/src/libzmq
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_FLAGS='-Os ${{ matrix.config.flags }}' -DCMAKE_CXX_FLAGS='-Os ${{ matrix.config.flags }}' -DWITH_LIBSODIUM=OFF -DWITH_LIBBSD=OFF -DBUILD_TESTS=OFF -DWITH_DOCS=OFF -DENABLE_DRAFTS=OFF -DBUILD_SHARED=OFF
|
||||
make -j$(nproc)
|
||||
|
||||
- name: Build p2pool
|
||||
shell: alpine.sh {0}
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_FLAGS='${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections' -DCMAKE_CXX_FLAGS='${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections' -DSTATIC_BINARY=ON -DARCH_ID=${{ matrix.config.arch }}
|
||||
make -j$(nproc)
|
||||
|
||||
- name: Run RandomX tests
|
||||
shell: alpine.sh {0}
|
||||
run: |
|
||||
build/p2pool --test
|
||||
build/external/src/RandomX/randomx-tests
|
||||
|
||||
- name: Build tests
|
||||
shell: alpine.sh {0}
|
||||
run: |
|
||||
cd tests
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_FLAGS='${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections' -DCMAKE_CXX_FLAGS='${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections' -DSTATIC_LIBS=ON -DARCH_ID=${{ matrix.config.arch }}
|
||||
make -j$(nproc)
|
||||
|
||||
- name: Run tests
|
||||
shell: alpine.sh {0}
|
||||
run: |
|
||||
cd tests/build
|
||||
gunzip *.gz
|
||||
./p2pool_tests
|
||||
|
||||
- name: List directory
|
||||
run: |
|
||||
cd build
|
||||
ls -la
|
||||
file p2pool
|
||||
|
||||
- name: Archive binary
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: p2pool-alpine-static-${{ matrix.config.arch }}
|
||||
path: build/p2pool
|
||||
|
||||
build-ubuntu:
|
||||
|
||||
timeout-minutes: 10
|
||||
runs-on: ${{ matrix.config.os }}
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
config:
|
||||
- {os: ubuntu-latest, c: gcc-11, cpp: g++-11}
|
||||
- {os: ubuntu-18.04, c: gcc, cpp: g++}
|
||||
- {os: ubuntu-20.04, c: gcc-11, cpp: g++-11}
|
||||
- {os: ubuntu-22.04, c: gcc-12, cpp: g++-12}
|
||||
|
||||
steps:
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
|
||||
sudo apt update
|
||||
sudo apt install -y git build-essential cmake libuv1-dev libzmq3-dev libsodium-dev libpgm-dev libnorm-dev libgss-dev ${{ matrix.config.c }} ${{ matrix.config.cpp }}
|
||||
sudo apt install -y git build-essential cmake libuv1-dev libzmq3-dev libsodium-dev libpgm-dev libnorm-dev libgss-dev libcurl4-openssl-dev libidn2-0-dev ${{ matrix.config.c }} ${{ matrix.config.cpp }}
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
@@ -33,37 +132,207 @@ jobs:
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_COMPILER=${{ matrix.config.c }} -DCMAKE_CXX_COMPILER=${{ matrix.config.cpp }}
|
||||
make -j2
|
||||
cmake .. -DCMAKE_C_COMPILER=${{ matrix.config.c }} -DCMAKE_CXX_COMPILER=${{ matrix.config.cpp }} -DCMAKE_C_FLAGS='-flto=2' -DCMAKE_CXX_FLAGS='-flto=2'
|
||||
make -j$(nproc)
|
||||
|
||||
- name: Run RandomX tests
|
||||
run: |
|
||||
build/p2pool --test
|
||||
build/external/src/RandomX/randomx-tests
|
||||
|
||||
- name: Build tests
|
||||
run: |
|
||||
cd tests
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_COMPILER=${{ matrix.config.c }} -DCMAKE_CXX_COMPILER=${{ matrix.config.cpp }}
|
||||
make -j2
|
||||
cmake .. -DCMAKE_C_COMPILER=${{ matrix.config.c }} -DCMAKE_CXX_COMPILER=${{ matrix.config.cpp }} -DCMAKE_C_FLAGS='-flto=2' -DCMAKE_CXX_FLAGS='-flto=2'
|
||||
make -j$(nproc)
|
||||
|
||||
- name: Run tests
|
||||
run: cd tests/build && ./p2pool_tests
|
||||
run: |
|
||||
cd tests/build
|
||||
gunzip *.gz
|
||||
./p2pool_tests
|
||||
|
||||
- name: Archive binary
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: p2pool-${{ matrix.config.os }}
|
||||
path: build/p2pool
|
||||
|
||||
build-ubuntu-static-libs:
|
||||
|
||||
timeout-minutes: 15
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
config:
|
||||
- {flags: "-flto=2 -fuse-linker-plugin -ffunction-sections -Wno-error=inline"}
|
||||
|
||||
steps:
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
|
||||
sudo apt update
|
||||
sudo apt install -y git build-essential cmake libgss-dev gcc-12 g++-12
|
||||
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-12 100 --slave /usr/bin/g++ g++ /usr/bin/g++-12 --slave /usr/bin/gcov gcov /usr/bin/gcov-12
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Build libcurl
|
||||
run: |
|
||||
cd external/src/curl
|
||||
cmake . -DCMAKE_C_FLAGS="-Os ${{ matrix.config.flags }}" -DBUILD_CURL_EXE=OFF -DBUILD_SHARED_LIBS=OFF -DCURL_ZLIB=OFF -DCURL_DISABLE_ALTSVC=ON -DCURL_DISABLE_COOKIES=ON -DCURL_DISABLE_DOH=ON -DCURL_DISABLE_GETOPTIONS=ON -DCURL_DISABLE_HSTS=ON -DCURL_DISABLE_LIBCURL_OPTION=ON -DCURL_DISABLE_MIME=ON -DCURL_DISABLE_NETRC=ON -DCURL_DISABLE_NTLM=ON -DCURL_DISABLE_PARSEDATE=ON -DCURL_DISABLE_PROGRESS_METER=ON -DCURL_DISABLE_SHUFFLE_DNS=ON -DCURL_DISABLE_SOCKETPAIR=ON -DCURL_DISABLE_VERBOSE_STRINGS=ON -DHTTP_ONLY=ON -DCURL_ENABLE_SSL=OFF -DUSE_LIBIDN2=OFF -DCURL_USE_LIBPSL=OFF -DCURL_USE_LIBSSH2=OFF -DENABLE_UNIX_SOCKETS=OFF
|
||||
make -j$(nproc)
|
||||
cd lib && mkdir .libs && cp libcurl.a .libs
|
||||
|
||||
- name: Build libuv
|
||||
run: |
|
||||
cd external/src/libuv
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_FLAGS='-Os ${{ matrix.config.flags }}' -DBUILD_TESTING=OFF -DLIBUV_BUILD_SHARED=OFF
|
||||
make -j$(nproc)
|
||||
|
||||
- name: Build libzmq
|
||||
run: |
|
||||
cd external/src/libzmq
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_FLAGS='-Os ${{ matrix.config.flags }}' -DCMAKE_CXX_FLAGS='-Os ${{ matrix.config.flags }}' -DWITH_LIBSODIUM=OFF -DWITH_LIBBSD=OFF -DBUILD_TESTS=OFF -DWITH_DOCS=OFF -DENABLE_DRAFTS=OFF -DBUILD_SHARED=OFF
|
||||
make -j$(nproc)
|
||||
|
||||
- name: Build p2pool
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_FLAGS='${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections' -DCMAKE_CXX_FLAGS='${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections' -DSTATIC_LIBS=ON
|
||||
make -j$(nproc)
|
||||
|
||||
- name: Run RandomX tests
|
||||
run: |
|
||||
build/p2pool --test
|
||||
build/external/src/RandomX/randomx-tests
|
||||
|
||||
- name: Build tests
|
||||
run: |
|
||||
cd tests
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_FLAGS='${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections' -DCMAKE_CXX_FLAGS='${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections' -DSTATIC_LIBS=ON
|
||||
make -j$(nproc)
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
cd tests/build
|
||||
gunzip *.gz
|
||||
./p2pool_tests
|
||||
|
||||
- name: Archive binary
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: p2pool-ubuntu-static-libs
|
||||
path: build/p2pool
|
||||
|
||||
build-ubuntu-aarch64:
|
||||
|
||||
timeout-minutes: 15
|
||||
runs-on: ${{ matrix.config.os }}
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
config:
|
||||
- {os: ubuntu-20.04, flags: "-flto=2 -fuse-linker-plugin -ffunction-sections -mfix-cortex-a53-835769 -mfix-cortex-a53-843419"}
|
||||
- {os: ubuntu-22.04, flags: "-flto=2 -fuse-linker-plugin -ffunction-sections -mfix-cortex-a53-835769 -mfix-cortex-a53-843419"}
|
||||
|
||||
steps:
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt install -y git build-essential cmake gcc-aarch64-linux-gnu g++-aarch64-linux-gnu binutils-aarch64-linux-gnu qemu-user
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Build libcurl
|
||||
run: |
|
||||
cd external/src/curl
|
||||
cmake . -DCMAKE_C_COMPILER=aarch64-linux-gnu-gcc -DCMAKE_C_FLAGS="-Os ${{ matrix.config.flags }}" -DBUILD_CURL_EXE=OFF -DBUILD_SHARED_LIBS=OFF -DCURL_ZLIB=OFF -DCURL_DISABLE_ALTSVC=ON -DCURL_DISABLE_COOKIES=ON -DCURL_DISABLE_DOH=ON -DCURL_DISABLE_GETOPTIONS=ON -DCURL_DISABLE_HSTS=ON -DCURL_DISABLE_LIBCURL_OPTION=ON -DCURL_DISABLE_MIME=ON -DCURL_DISABLE_NETRC=ON -DCURL_DISABLE_NTLM=ON -DCURL_DISABLE_PARSEDATE=ON -DCURL_DISABLE_PROGRESS_METER=ON -DCURL_DISABLE_SHUFFLE_DNS=ON -DCURL_DISABLE_SOCKETPAIR=ON -DCURL_DISABLE_VERBOSE_STRINGS=ON -DHTTP_ONLY=ON -DCURL_ENABLE_SSL=OFF -DUSE_LIBIDN2=OFF -DCURL_USE_LIBPSL=OFF -DCURL_USE_LIBSSH2=OFF -DENABLE_UNIX_SOCKETS=OFF
|
||||
make -j$(nproc)
|
||||
cd lib && mkdir .libs && cp libcurl.a .libs
|
||||
|
||||
- name: Build libuv
|
||||
run: |
|
||||
cd external/src/libuv
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_COMPILER=aarch64-linux-gnu-gcc -DCMAKE_C_FLAGS='-Os ${{ matrix.config.flags }}' -DBUILD_TESTING=OFF -DLIBUV_BUILD_SHARED=OFF
|
||||
make -j$(nproc)
|
||||
|
||||
- name: Build libzmq
|
||||
run: |
|
||||
cd external/src/libzmq
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_COMPILER=aarch64-linux-gnu-gcc -DCMAKE_CXX_COMPILER=aarch64-linux-gnu-g++ -DCMAKE_C_FLAGS='-Os ${{ matrix.config.flags }}' -DCMAKE_CXX_FLAGS='-Os ${{ matrix.config.flags }}' -DWITH_LIBSODIUM=OFF -DWITH_LIBBSD=OFF -DBUILD_TESTS=OFF -DWITH_DOCS=OFF -DENABLE_DRAFTS=OFF -DBUILD_SHARED=OFF
|
||||
make -j$(nproc)
|
||||
|
||||
- name: Build p2pool
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_COMPILER=aarch64-linux-gnu-gcc -DCMAKE_CXX_COMPILER=aarch64-linux-gnu-g++ -DCMAKE_STRIP=/usr/bin/aarch64-linux-gnu-strip -DCMAKE_C_FLAGS='${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections' -DCMAKE_CXX_FLAGS='${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections' -DSTATIC_LIBS=ON -DARCH_ID=aarch64
|
||||
make -j$(nproc)
|
||||
|
||||
- name: Run RandomX tests
|
||||
run: |
|
||||
qemu-aarch64 -L /usr/aarch64-linux-gnu build/p2pool --test
|
||||
qemu-aarch64 -L /usr/aarch64-linux-gnu build/external/src/RandomX/randomx-tests
|
||||
|
||||
- name: Build tests
|
||||
run: |
|
||||
cd tests
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_COMPILER=aarch64-linux-gnu-gcc -DCMAKE_CXX_COMPILER=aarch64-linux-gnu-g++ -DCMAKE_STRIP=/usr/bin/aarch64-linux-gnu-strip -DCMAKE_C_FLAGS='${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections' -DCMAKE_CXX_FLAGS='${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections' -DSTATIC_LIBS=ON -DARCH_ID=aarch64
|
||||
make -j$(nproc)
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
cd tests/build
|
||||
gunzip *.gz
|
||||
qemu-aarch64 -L /usr/aarch64-linux-gnu ./p2pool_tests
|
||||
|
||||
- name: Archive binary
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: p2pool-${{ matrix.config.os }}-aarch64
|
||||
path: build/p2pool
|
||||
|
||||
build-windows-msys2:
|
||||
|
||||
timeout-minutes: 45
|
||||
runs-on: windows-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
config:
|
||||
- {c: "gcc", cxx: "g++", flags: "-flto=2 -fuse-linker-plugin -ffunction-sections -Wno-error=maybe-uninitialized -Wno-error=attributes"}
|
||||
- {c: "clang", cxx: "clang++", flags: "-flto -ffunction-sections -fuse-ld=lld -Wno-unused-command-line-argument"}
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
@@ -71,47 +340,78 @@ jobs:
|
||||
uses: eine/setup-msys2@v2
|
||||
with:
|
||||
update: true
|
||||
install: mingw-w64-x86_64-toolchain make mingw-w64-x86_64-cmake mingw-w64-x86_64-zeromq mingw-w64-x86_64-libsodium mingw-w64-x86_64-libuv
|
||||
install: mingw-w64-x86_64-toolchain mingw-w64-x86_64-clang mingw-w64-x86_64-lld mingw-w64-x86_64-cmake make
|
||||
|
||||
- name: Build libcurl
|
||||
run: |
|
||||
cd external/src/curl
|
||||
cmake . -G "Unix Makefiles" -DCMAKE_C_COMPILER=${{ matrix.config.c }} -DCMAKE_C_FLAGS="-Os ${{ matrix.config.flags }}" -DCURL_TARGET_WINDOWS_VERSION=0x0600 -DBUILD_CURL_EXE=OFF -DBUILD_SHARED_LIBS=OFF -DCURL_ZLIB=OFF -DCURL_DISABLE_ALTSVC=ON -DCURL_DISABLE_COOKIES=ON -DCURL_DISABLE_DOH=ON -DCURL_DISABLE_GETOPTIONS=ON -DCURL_DISABLE_HSTS=ON -DCURL_DISABLE_LIBCURL_OPTION=ON -DCURL_DISABLE_MIME=ON -DCURL_DISABLE_NETRC=ON -DCURL_DISABLE_NTLM=ON -DCURL_DISABLE_PARSEDATE=ON -DCURL_DISABLE_PROGRESS_METER=ON -DCURL_DISABLE_SHUFFLE_DNS=ON -DCURL_DISABLE_SOCKETPAIR=ON -DCURL_DISABLE_VERBOSE_STRINGS=ON -DHTTP_ONLY=ON -DCURL_ENABLE_SSL=OFF -DUSE_LIBIDN2=OFF -DCURL_USE_LIBPSL=OFF -DCURL_USE_LIBSSH2=OFF -DENABLE_UNIX_SOCKETS=OFF
|
||||
make -j$(nproc)
|
||||
cd lib && mkdir .libs && cp libcurl.a .libs
|
||||
|
||||
- name: Build libuv
|
||||
run: |
|
||||
cd external/src/libuv
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -G "Unix Makefiles" -DCMAKE_C_COMPILER=${{ matrix.config.c }} -DCMAKE_C_FLAGS='-Os ${{ matrix.config.flags }}' -DBUILD_TESTING=OFF -DLIBUV_BUILD_SHARED=OFF
|
||||
make -j$(nproc)
|
||||
|
||||
- name: Build libzmq
|
||||
run: |
|
||||
cd external/src/libzmq
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -G "Unix Makefiles" -DCMAKE_C_COMPILER=${{ matrix.config.c }} -DCMAKE_CXX_COMPILER=${{ matrix.config.cxx }} -DCMAKE_C_FLAGS='-Os ${{ matrix.config.flags }}' -DCMAKE_CXX_FLAGS='-Os ${{ matrix.config.flags }}' -DWITH_LIBSODIUM=OFF -DWITH_LIBBSD=OFF -DBUILD_TESTS=OFF -DZMQ_HAVE_IPC=OFF -DWITH_DOCS=OFF -DENABLE_DRAFTS=OFF -DBUILD_SHARED=OFF
|
||||
make -j$(nproc)
|
||||
|
||||
- name: Build p2pool
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -G "Unix Makefiles"
|
||||
make -j2
|
||||
cmake .. -G "Unix Makefiles" -DCMAKE_C_COMPILER=${{ matrix.config.c }} -DCMAKE_CXX_COMPILER=${{ matrix.config.cxx }} -DCMAKE_C_FLAGS="${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections" -DCMAKE_CXX_FLAGS="${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections" -DSTATIC_LIBS=ON
|
||||
make -j$(nproc)
|
||||
|
||||
- name: Run RandomX tests
|
||||
run: |
|
||||
build/p2pool.exe --test
|
||||
build/external/src/RandomX/randomx-tests.exe
|
||||
|
||||
- name: Build tests
|
||||
run: |
|
||||
cd tests
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -G "Unix Makefiles"
|
||||
make -j2
|
||||
cmake .. -G "Unix Makefiles" -DCMAKE_C_COMPILER=${{ matrix.config.c }} -DCMAKE_CXX_COMPILER=${{ matrix.config.cxx }} -DCMAKE_C_FLAGS="${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections" -DCMAKE_CXX_FLAGS="${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections" -DSTATIC_LIBS=ON
|
||||
make -j$(nproc)
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
cd tests/build
|
||||
gunzip *.gz
|
||||
./p2pool_tests.exe
|
||||
|
||||
- name: Archive binary
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: p2pool-msys2.exe
|
||||
name: p2pool-msys2-${{ matrix.config.c }}.exe
|
||||
path: build/p2pool.exe
|
||||
|
||||
build-windows-msbuild:
|
||||
|
||||
timeout-minutes: 20
|
||||
runs-on: windows-${{ matrix.config.os }}
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
config:
|
||||
- {vs: Visual Studio 16 2019, os: 2019, msbuild: "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Enterprise\\MSBuild\\Current\\Bin\\amd64\\"}
|
||||
- {vs: Visual Studio 17 2022, os: 2022, msbuild: "C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\Msbuild\\Current\\Bin\\amd64\\"}
|
||||
- {vs: Visual Studio 16 2019, os: 2019, vspath: "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Enterprise", rx: "ON", upnp: "ON"}
|
||||
- {vs: Visual Studio 16 2019, os: 2019, vspath: "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Enterprise", rx: "OFF", upnp: "ON"}
|
||||
- {vs: Visual Studio 16 2019, os: 2019, vspath: "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Enterprise", rx: "OFF", upnp: "OFF"}
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
@@ -122,8 +422,24 @@ jobs:
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -G "${{ matrix.config.vs }}"
|
||||
& "${{ matrix.config.msbuild }}msbuild" /m /p:Configuration=Release p2pool.vcxproj
|
||||
cmake .. -G "${{ matrix.config.vs }}" -DWITH_RANDOMX=${{ matrix.config.rx }} -DWITH_UPNP=${{ matrix.config.upnp }}
|
||||
& "${{ matrix.config.vspath }}\\MSBuild\\Current\\Bin\\amd64\\msbuild" -v:m /m /p:Configuration=Release p2pool.vcxproj
|
||||
|
||||
- name: Check Windows 7 compatibility
|
||||
shell: cmd
|
||||
run: |
|
||||
call "${{ matrix.config.vspath }}\\VC\\Auxiliary\\Build\\vcvarsall.bat" amd64
|
||||
dumpbin /IMPORTS build/Release/p2pool.exe > 1.txt
|
||||
findstr /R /C:"^ *[0-9A-F][0-9A-F]* [a-zA-Z][a-zA-Z0-9]*$" 1.txt > 2.txt
|
||||
python tests/src/check_win7.py 2.txt
|
||||
|
||||
- name: Run RandomX tests
|
||||
if: matrix.config.rx == 'ON'
|
||||
run: |
|
||||
build/Release/p2pool.exe --test
|
||||
cd build/external/src/RandomX
|
||||
& "${{ matrix.config.vspath }}\\MSBuild\\Current\\Bin\\amd64\\msbuild" -v:m /m /p:Configuration=Release randomx-tests.vcxproj
|
||||
Release/randomx-tests.exe
|
||||
|
||||
- name: Build tests
|
||||
run: |
|
||||
@@ -131,58 +447,236 @@ jobs:
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -G "${{ matrix.config.vs }}"
|
||||
& "${{ matrix.config.msbuild }}msbuild" /m /p:Configuration=Release p2pool_tests.vcxproj
|
||||
& "${{ matrix.config.vspath }}\\MSBuild\\Current\\Bin\\amd64\\msbuild" -v:m /m /p:Configuration=Debug p2pool_tests.vcxproj
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
cd tests/build/Release
|
||||
cd tests/build/Debug
|
||||
7z x *.gz
|
||||
./p2pool_tests.exe
|
||||
|
||||
- name: Archive binary
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: p2pool-msbuild-${{ matrix.config.os }}.exe
|
||||
name: p2pool-vs-${{ matrix.config.os }}-randomx-${{ matrix.config.rx }}-upnp-${{ matrix.config.upnp }}.exe
|
||||
path: build/Release/p2pool.exe
|
||||
|
||||
build-macos:
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
os: [macos-10.15, macos-11]
|
||||
timeout-minutes: 20
|
||||
runs-on: macos-11
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Install dependencies
|
||||
run: HOMEBREW_NO_AUTO_UPDATE=1 brew install cmake libuv zmq libpgm
|
||||
- name: Build libcurl
|
||||
run: |
|
||||
cd external/src/curl
|
||||
cmake . -DCMAKE_C_COMPILER="$(brew --prefix llvm@15)/bin/clang" -DCMAKE_AR="$(brew --prefix llvm@15)/bin/llvm-ar" -DCMAKE_RANLIB="$(brew --prefix llvm@15)/bin/llvm-ranlib" -DCMAKE_C_FLAGS="-Os -flto" -DBUILD_CURL_EXE=OFF -DBUILD_SHARED_LIBS=OFF -DCURL_ZLIB=OFF -DCURL_DISABLE_ALTSVC=ON -DCURL_DISABLE_COOKIES=ON -DCURL_DISABLE_DOH=ON -DCURL_DISABLE_GETOPTIONS=ON -DCURL_DISABLE_HSTS=ON -DCURL_DISABLE_LIBCURL_OPTION=ON -DCURL_DISABLE_MIME=ON -DCURL_DISABLE_NETRC=ON -DCURL_DISABLE_NTLM=ON -DCURL_DISABLE_PARSEDATE=ON -DCURL_DISABLE_PROGRESS_METER=ON -DCURL_DISABLE_SHUFFLE_DNS=ON -DCURL_DISABLE_SOCKETPAIR=ON -DCURL_DISABLE_VERBOSE_STRINGS=ON -DHTTP_ONLY=ON -DCURL_ENABLE_SSL=OFF -DUSE_LIBIDN2=OFF -DCURL_USE_LIBPSL=OFF -DCURL_USE_LIBSSH2=OFF -DENABLE_UNIX_SOCKETS=OFF
|
||||
make -j3
|
||||
cd lib && mkdir .libs && cp libcurl.a .libs
|
||||
|
||||
- name: Build libuv
|
||||
run: |
|
||||
cd external/src/libuv
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_COMPILER="$(brew --prefix llvm@15)/bin/clang" -DCMAKE_AR="$(brew --prefix llvm@15)/bin/llvm-ar" -DCMAKE_RANLIB="$(brew --prefix llvm@15)/bin/llvm-ranlib" -DCMAKE_C_FLAGS='-Os -flto' -DBUILD_TESTING=OFF -DLIBUV_BUILD_SHARED=OFF
|
||||
make -j3
|
||||
|
||||
- name: Build libzmq
|
||||
run: |
|
||||
cd external/src/libzmq
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_COMPILER="$(brew --prefix llvm@15)/bin/clang" -DCMAKE_CXX_COMPILER="$(brew --prefix llvm@15)/bin/clang++" -DCMAKE_AR="$(brew --prefix llvm@15)/bin/llvm-ar" -DCMAKE_RANLIB="$(brew --prefix llvm@15)/bin/llvm-ranlib" -DCMAKE_C_FLAGS='-Os -flto' -DCMAKE_CXX_FLAGS='-Os -flto' -DWITH_LIBSODIUM=OFF -DWITH_LIBBSD=OFF -DBUILD_TESTS=OFF -DWITH_DOCS=OFF -DENABLE_DRAFTS=OFF -DBUILD_SHARED=OFF
|
||||
make -j3
|
||||
|
||||
- name: Build p2pool
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
cmake .. -DCMAKE_C_COMPILER="$(brew --prefix llvm@15)/bin/clang" -DCMAKE_CXX_COMPILER="$(brew --prefix llvm@15)/bin/clang++" -DCMAKE_AR="$(brew --prefix llvm@15)/bin/llvm-ar" -DCMAKE_RANLIB="$(brew --prefix llvm@15)/bin/llvm-ranlib" -DCMAKE_C_FLAGS="-flto" -DCMAKE_CXX_FLAGS="-flto" -DSTATIC_LIBS=ON
|
||||
make -j3
|
||||
|
||||
- name: Run RandomX tests
|
||||
run: |
|
||||
build/p2pool --test
|
||||
build/external/src/RandomX/randomx-tests
|
||||
|
||||
- name: Build tests
|
||||
run: |
|
||||
cd tests
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
cmake .. -DCMAKE_C_COMPILER="$(brew --prefix llvm@15)/bin/clang" -DCMAKE_CXX_COMPILER="$(brew --prefix llvm@15)/bin/clang++" -DCMAKE_AR="$(brew --prefix llvm@15)/bin/llvm-ar" -DCMAKE_RANLIB="$(brew --prefix llvm@15)/bin/llvm-ranlib" -DCMAKE_C_FLAGS="-flto" -DCMAKE_CXX_FLAGS="-flto" -DSTATIC_LIBS=ON
|
||||
make -j3
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
cd tests/build
|
||||
gunzip *.gz
|
||||
./p2pool_tests
|
||||
|
||||
- name: Archive binary
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: p2pool-${{ matrix.os }}
|
||||
name: p2pool-macos-11
|
||||
path: build/p2pool
|
||||
|
||||
build-macos-aarch64:
|
||||
|
||||
timeout-minutes: 20
|
||||
runs-on: macos-11
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Build libcurl
|
||||
run: |
|
||||
cd external/src/curl
|
||||
cmake . -DCMAKE_C_COMPILER="$(brew --prefix llvm@15)/bin/clang" -DCMAKE_AR="$(brew --prefix llvm@15)/bin/llvm-ar" -DCMAKE_RANLIB="$(brew --prefix llvm@15)/bin/llvm-ranlib" -DCMAKE_C_FLAGS="-Os -target arm64-apple-macos-11" -DBUILD_CURL_EXE=OFF -DBUILD_SHARED_LIBS=OFF -DCURL_ZLIB=OFF -DCURL_DISABLE_ALTSVC=ON -DCURL_DISABLE_COOKIES=ON -DCURL_DISABLE_DOH=ON -DCURL_DISABLE_GETOPTIONS=ON -DCURL_DISABLE_HSTS=ON -DCURL_DISABLE_LIBCURL_OPTION=ON -DCURL_DISABLE_MIME=ON -DCURL_DISABLE_NETRC=ON -DCURL_DISABLE_NTLM=ON -DCURL_DISABLE_PARSEDATE=ON -DCURL_DISABLE_PROGRESS_METER=ON -DCURL_DISABLE_SHUFFLE_DNS=ON -DCURL_DISABLE_SOCKETPAIR=ON -DCURL_DISABLE_VERBOSE_STRINGS=ON -DHTTP_ONLY=ON -DCURL_ENABLE_SSL=OFF -DUSE_LIBIDN2=OFF -DCURL_USE_LIBPSL=OFF -DCURL_USE_LIBSSH2=OFF -DENABLE_UNIX_SOCKETS=OFF
|
||||
make -j3
|
||||
cd lib && mkdir .libs && cp libcurl.a .libs
|
||||
|
||||
- name: Build libuv
|
||||
run: |
|
||||
cd external/src/libuv
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_COMPILER="$(brew --prefix llvm@15)/bin/clang" -DCMAKE_AR="$(brew --prefix llvm@15)/bin/llvm-ar" -DCMAKE_RANLIB="$(brew --prefix llvm@15)/bin/llvm-ranlib" -DCMAKE_C_FLAGS='-Os -target arm64-apple-macos-11' -DBUILD_TESTING=OFF -DLIBUV_BUILD_SHARED=OFF
|
||||
make -j3
|
||||
|
||||
- name: Build libzmq
|
||||
run: |
|
||||
cd external/src/libzmq
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_COMPILER="$(brew --prefix llvm@15)/bin/clang" -DCMAKE_CXX_COMPILER="$(brew --prefix llvm@15)/bin/clang++" -DCMAKE_AR="$(brew --prefix llvm@15)/bin/llvm-ar" -DCMAKE_RANLIB="$(brew --prefix llvm@15)/bin/llvm-ranlib" -DCMAKE_C_FLAGS='-Os -target arm64-apple-macos-11' -DCMAKE_CXX_FLAGS='-Os -target arm64-apple-macos-11' -DWITH_LIBSODIUM=OFF -DWITH_LIBBSD=OFF -DBUILD_TESTS=OFF -DWITH_DOCS=OFF -DENABLE_DRAFTS=OFF -DBUILD_SHARED=OFF
|
||||
make -j3
|
||||
|
||||
- name: Build p2pool
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_COMPILER="$(brew --prefix llvm@15)/bin/clang" -DCMAKE_CXX_COMPILER="$(brew --prefix llvm@15)/bin/clang++" -DCMAKE_AR="$(brew --prefix llvm@15)/bin/llvm-ar" -DCMAKE_RANLIB="$(brew --prefix llvm@15)/bin/llvm-ranlib" -DCMAKE_C_FLAGS="-target arm64-apple-macos-11" -DCMAKE_CXX_FLAGS="-target arm64-apple-macos-11" -DSTATIC_LIBS=ON -DWITH_LTO=OFF -DARCH_ID=aarch64
|
||||
make -j3
|
||||
|
||||
- name: Archive binary
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: p2pool-macos-11-aarch64
|
||||
path: build/p2pool
|
||||
|
||||
build-freebsd:
|
||||
|
||||
timeout-minutes: 75
|
||||
runs-on: ${{ matrix.os.host }}
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
os:
|
||||
- name: freebsd
|
||||
architecture: x86-64
|
||||
version: '12.4'
|
||||
host: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Build p2pool
|
||||
uses: cross-platform-actions/action@v0.19.0
|
||||
with:
|
||||
operating_system: ${{ matrix.os.name }}
|
||||
architecture: ${{ matrix.os.architecture }}
|
||||
version: ${{ matrix.os.version }}
|
||||
shell: bash
|
||||
run: |
|
||||
sudo pkg install -y cmake
|
||||
cd external/src/curl
|
||||
cmake . -DCMAKE_C_FLAGS="-Os -flto" -DBUILD_CURL_EXE=OFF -DBUILD_SHARED_LIBS=OFF -DCURL_ZLIB=OFF -DCURL_DISABLE_ALTSVC=ON -DCURL_DISABLE_COOKIES=ON -DCURL_DISABLE_DOH=ON -DCURL_DISABLE_GETOPTIONS=ON -DCURL_DISABLE_HSTS=ON -DCURL_DISABLE_LIBCURL_OPTION=ON -DCURL_DISABLE_MIME=ON -DCURL_DISABLE_NETRC=ON -DCURL_DISABLE_NTLM=ON -DCURL_DISABLE_PARSEDATE=ON -DCURL_DISABLE_PROGRESS_METER=ON -DCURL_DISABLE_SHUFFLE_DNS=ON -DCURL_DISABLE_SOCKETPAIR=ON -DCURL_DISABLE_VERBOSE_STRINGS=ON -DHTTP_ONLY=ON -DCURL_ENABLE_SSL=OFF -DUSE_LIBIDN2=OFF -DCURL_USE_LIBPSL=OFF -DCURL_USE_LIBSSH2=OFF -DENABLE_UNIX_SOCKETS=OFF
|
||||
make -j2
|
||||
cd lib && mkdir .libs && cp libcurl.a .libs
|
||||
cd ../../libuv
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_FLAGS='-Os -flto' -DBUILD_TESTING=OFF -DLIBUV_BUILD_SHARED=OFF
|
||||
make -j2
|
||||
cd ../../libzmq
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_FLAGS='-Os -flto' -DCMAKE_CXX_FLAGS='-Os -flto' -DWITH_LIBSODIUM=OFF -DWITH_LIBBSD=OFF -DBUILD_TESTS=OFF -DWITH_DOCS=OFF -DENABLE_DRAFTS=OFF -DBUILD_SHARED=OFF
|
||||
make -j2
|
||||
cd ../../../..
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_FLAGS='-flto' -DCMAKE_CXX_FLAGS='-flto' -DSTATIC_LIBS=ON
|
||||
make -j2
|
||||
./p2pool --test
|
||||
external/src/RandomX/randomx-tests
|
||||
cd ../tests
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_FLAGS='-flto' -DCMAKE_CXX_FLAGS='-flto' -DSTATIC_LIBS=ON
|
||||
make -j2
|
||||
gunzip *.gz
|
||||
./p2pool_tests
|
||||
|
||||
- name: Archive binary
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: p2pool-${{ matrix.os.name }}-${{ matrix.os.version }}
|
||||
path: build/p2pool
|
||||
|
||||
build-openbsd:
|
||||
|
||||
timeout-minutes: 75
|
||||
runs-on: ${{ matrix.os.host }}
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
os:
|
||||
- name: openbsd
|
||||
architecture: x86-64
|
||||
version: '7.2'
|
||||
host: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Build p2pool
|
||||
uses: cross-platform-actions/action@v0.19.0
|
||||
with:
|
||||
operating_system: ${{ matrix.os.name }}
|
||||
architecture: ${{ matrix.os.architecture }}
|
||||
version: ${{ matrix.os.version }}
|
||||
shell: bash
|
||||
run: |
|
||||
sudo pkg_add -I cmake libuv zeromq curl
|
||||
mkdir build && cd build
|
||||
cmake ..
|
||||
make -j2
|
||||
cd ../tests
|
||||
mkdir build && cd build
|
||||
cmake ..
|
||||
make -j2
|
||||
gunzip *.gz
|
||||
./p2pool_tests
|
||||
|
||||
- name: Archive binary
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: p2pool-${{ matrix.os.name }}-${{ matrix.os.version }}
|
||||
path: build/p2pool
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
name: clang-tidy
|
||||
|
||||
on:
|
||||
push:
|
||||
paths-ignore:
|
||||
- 'docker-compose/**'
|
||||
- 'docs/**'
|
||||
- 'README.md'
|
||||
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
clang-tidy:
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt install -y libuv1-dev libzmq3-dev libcurl4-openssl-dev
|
||||
|
||||
- name: Install clang
|
||||
run: |
|
||||
wget https://apt.llvm.org/llvm.sh
|
||||
chmod +x llvm.sh
|
||||
sudo ./llvm.sh 17
|
||||
sudo apt-get install -y clang-tidy-17
|
||||
clang-tidy-17 --verify-config
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: cmake p2pool
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_C_COMPILER=clang-17 -DCMAKE_CXX_COMPILER=clang++-17 -DDEV_CLANG_TIDY=ON
|
||||
|
||||
- name: Run clang-tidy
|
||||
run: |
|
||||
cd src
|
||||
clang-tidy-17 *.cpp -p ../build -checks=-clang-diagnostic-undefined-internal -warnings-as-errors=* -header-filter=^[^\.]
|
||||
@@ -13,16 +13,20 @@ name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
paths-ignore:
|
||||
- 'docker-compose/**'
|
||||
- 'docs/**'
|
||||
- 'README.md'
|
||||
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches: [ master ]
|
||||
|
||||
schedule:
|
||||
- cron: '44 11 * * 0'
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
timeout-minutes: 20
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: read
|
||||
@@ -40,16 +44,16 @@ jobs:
|
||||
steps:
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt update && sudo apt install git build-essential cmake libuv1-dev libzmq3-dev libsodium-dev libpgm-dev libnorm-dev libgss-dev
|
||||
sudo apt update && sudo apt install git build-essential cmake libuv1-dev libzmq3-dev libsodium-dev libpgm-dev libnorm-dev libgss-dev libcurl4-openssl-dev libidn2-0-dev
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v1
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
@@ -60,7 +64,7 @@ jobs:
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v1
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
@@ -74,4 +78,4 @@ jobs:
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v1
|
||||
uses: github/codeql-action/analyze@v2
|
||||
|
||||
@@ -2,42 +2,84 @@ name: cppcheck
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
paths-ignore:
|
||||
- 'docker-compose/**'
|
||||
- 'docs/**'
|
||||
- 'README.md'
|
||||
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
schedule:
|
||||
- cron: '57 0 * * *'
|
||||
|
||||
jobs:
|
||||
cppcheck-ubuntu:
|
||||
|
||||
timeout-minutes: 60
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Install cppcheck
|
||||
run: sudo apt update && sudo apt install cppcheck
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt install -y libuv1-dev libzmq3-dev libcurl4-openssl-dev
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Checkout cppcheck
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
repository: danmar/cppcheck
|
||||
path: cppcheck-main
|
||||
|
||||
- name: Build cppcheck
|
||||
run: |
|
||||
cd cppcheck-main
|
||||
make -j$(nproc) cppcheck
|
||||
|
||||
- name: cmake p2pool
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DSTATIC_LIBS=ON
|
||||
python ../cppcheck/remove_external.py compile_commands.json
|
||||
|
||||
- name: Run cppcheck
|
||||
run: |
|
||||
cd cppcheck
|
||||
./run.sh
|
||||
|
||||
- name: Archive full error list
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: errors_full-linux
|
||||
path: cppcheck/errors_full.txt
|
||||
|
||||
cppcheck-windows:
|
||||
|
||||
timeout-minutes: 60
|
||||
runs-on: windows-latest
|
||||
|
||||
steps:
|
||||
- name: Install cppcheck
|
||||
run: choco install cppcheck
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Checkout cppcheck
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
repository: danmar/cppcheck
|
||||
path: cppcheck-main
|
||||
|
||||
- name: Build cppcheck
|
||||
run: |
|
||||
cd cppcheck-main
|
||||
& "C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\Msbuild\\Current\\Bin\\amd64\\msbuild.exe" /m /p:Configuration=Release /p:Platform=x64
|
||||
|
||||
- name: Setup cmake
|
||||
uses: lukka/get-cmake@latest
|
||||
|
||||
@@ -45,9 +87,15 @@ jobs:
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -G "Visual Studio 16 2019"
|
||||
cmake .. -G "Visual Studio 17 2022" -DSTATIC_LIBS=ON
|
||||
|
||||
- name: Run cppcheck
|
||||
run: |
|
||||
cd cppcheck
|
||||
./run.cmd
|
||||
|
||||
- name: Archive full error list
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: errors_full-windows
|
||||
path: cppcheck/errors_full.txt
|
||||
|
||||
@@ -10,9 +10,13 @@ name: Microsoft C++ Code Analysis
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
paths-ignore:
|
||||
- 'docker-compose/**'
|
||||
- 'docs/**'
|
||||
- 'README.md'
|
||||
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
schedule:
|
||||
- cron: '40 10 * * 0'
|
||||
|
||||
@@ -24,11 +28,12 @@ env:
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
timeout-minutes: 15
|
||||
runs-on: windows-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
@@ -40,7 +45,7 @@ jobs:
|
||||
# run: cmake --build ${{ env.build }}
|
||||
|
||||
- name: Initialize MSVC Code Analysis
|
||||
uses: microsoft/msvc-code-analysis-action@47ecec99bf7ce0399ed85cbb5012b6f24eab5959
|
||||
uses: microsoft/msvc-code-analysis-action@24c285ab36952c9e9182f4b78dfafbac38a7e5ee
|
||||
# Provide a unique ID to access the sarif output path
|
||||
id: run-analysis
|
||||
with:
|
||||
@@ -51,13 +56,13 @@ jobs:
|
||||
|
||||
# Upload SARIF file to GitHub Code Scanning Alerts
|
||||
- name: Upload SARIF to GitHub
|
||||
uses: github/codeql-action/upload-sarif@v1
|
||||
uses: github/codeql-action/upload-sarif@v2
|
||||
with:
|
||||
sarif_file: ${{ steps.run-analysis.outputs.sarif }}
|
||||
|
||||
# Upload SARIF file as an Artifact to download and view
|
||||
- name: Upload SARIF as an Artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: sarif-file
|
||||
path: ${{ steps.run-analysis.outputs.sarif }}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
name: source-snapshot
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
source-snapshot:
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Compress source code
|
||||
run: |
|
||||
mkdir build
|
||||
XZ_OPT=-e9 tar --exclude=".git" --exclude="build" -f build/p2pool_source.tar.xz -c ../p2pool --xz
|
||||
|
||||
- name: Archive source code
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: p2pool_source.tar.xz
|
||||
path: build/p2pool_source.tar.xz
|
||||
@@ -0,0 +1,416 @@
|
||||
name: Sync test
|
||||
|
||||
on:
|
||||
push:
|
||||
paths-ignore:
|
||||
- 'docker-compose/**'
|
||||
- 'docs/**'
|
||||
- 'README.md'
|
||||
|
||||
pull_request:
|
||||
|
||||
schedule:
|
||||
- cron: '17 0/3 * * *'
|
||||
|
||||
jobs:
|
||||
sync-test-ubuntu-tsan:
|
||||
|
||||
timeout-minutes: 30
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
|
||||
sudo apt update
|
||||
sudo apt install -y git build-essential cmake gcc-12 g++-12
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Build libcurl
|
||||
run: |
|
||||
cd external/src/curl
|
||||
cmake . -DCMAKE_C_COMPILER=gcc-12 -DCMAKE_C_FLAGS='-fsanitize=thread -Os -fno-omit-frame-pointer -g' -DBUILD_CURL_EXE=OFF -DBUILD_SHARED_LIBS=OFF -DCURL_ZLIB=OFF -DCURL_DISABLE_ALTSVC=ON -DCURL_DISABLE_COOKIES=ON -DCURL_DISABLE_DOH=ON -DCURL_DISABLE_GETOPTIONS=ON -DCURL_DISABLE_HSTS=ON -DCURL_DISABLE_LIBCURL_OPTION=ON -DCURL_DISABLE_MIME=ON -DCURL_DISABLE_NETRC=ON -DCURL_DISABLE_NTLM=ON -DCURL_DISABLE_PARSEDATE=ON -DCURL_DISABLE_PROGRESS_METER=ON -DCURL_DISABLE_SHUFFLE_DNS=ON -DCURL_DISABLE_SOCKETPAIR=ON -DCURL_DISABLE_VERBOSE_STRINGS=ON -DHTTP_ONLY=ON -DCURL_ENABLE_SSL=OFF -DUSE_LIBIDN2=OFF -DCURL_USE_LIBPSL=OFF -DCURL_USE_LIBSSH2=OFF -DENABLE_UNIX_SOCKETS=OFF
|
||||
make -j$(nproc)
|
||||
cd lib && mkdir .libs && cp libcurl.a .libs
|
||||
|
||||
- name: Build libuv
|
||||
run: |
|
||||
cd external/src/libuv
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_COMPILER=gcc-12 -DCMAKE_C_FLAGS='-fsanitize=thread -Os -fno-omit-frame-pointer -g' -DBUILD_TESTING=OFF -DLIBUV_BUILD_SHARED=OFF
|
||||
make -j$(nproc)
|
||||
|
||||
- name: Build libzmq
|
||||
run: |
|
||||
cd external/src/libzmq
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_COMPILER=gcc-12 -DCMAKE_CXX_COMPILER=g++-12 -DCMAKE_C_FLAGS='-fsanitize=thread -Os -fno-omit-frame-pointer -g' -DCMAKE_CXX_FLAGS='-fsanitize=thread -Os -fno-omit-frame-pointer -g' -DWITH_LIBSODIUM=OFF -DWITH_LIBBSD=OFF -DBUILD_TESTS=OFF -DWITH_DOCS=OFF -DENABLE_DRAFTS=OFF -DBUILD_SHARED=OFF
|
||||
make -j$(nproc)
|
||||
|
||||
- name: Build p2pool
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DDEV_TEST_SYNC=ON -DDEV_WITH_TSAN=ON -DCMAKE_C_COMPILER=gcc-12 -DCMAKE_CXX_COMPILER=g++-12 -DWITH_LTO=OFF -DSTATIC_LIBS=ON
|
||||
make -j$(nproc)
|
||||
|
||||
- name: Run p2pool
|
||||
run: |
|
||||
cd build
|
||||
mkdir data
|
||||
python ../tests/src/stratum_dummy.py 1 &
|
||||
python ../tests/src/stratum_dummy.py 2 &
|
||||
python ../tests/src/stratum_dummy.py 3 &
|
||||
TSAN_OPTIONS="suppressions=../tests/src/tsan_sup.txt halt_on_error=1" ./p2pool --host xmrnode.facspro.net --rpc-port 18089 --zmq-port 18084 --host xmr2.rs.me --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --mini --out-peers 200 --data-api data --local-api --loglevel 6
|
||||
|
||||
- name: Check p2pool.log
|
||||
run: |
|
||||
cd build
|
||||
grep 'Synchronization finished successfully' p2pool.log
|
||||
|
||||
- name: Archive p2pool.log
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: p2pool_ubuntu_data_tsan
|
||||
path: |
|
||||
build/*.log
|
||||
build/data/
|
||||
|
||||
sync-test-ubuntu-msan:
|
||||
timeout-minutes: 30
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt install -y git build-essential cmake ninja-build
|
||||
|
||||
- name: Install clang
|
||||
run: |
|
||||
wget https://apt.llvm.org/llvm.sh
|
||||
chmod +x llvm.sh
|
||||
sudo ./llvm.sh 17
|
||||
|
||||
- name: Build libcxx_msan
|
||||
run: |
|
||||
git clone --depth=1 https://github.com/llvm/llvm-project -b release/17.x
|
||||
cd llvm-project
|
||||
mkdir build
|
||||
cmake -G Ninja -S runtimes -B build -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi" -DCMAKE_C_COMPILER=clang-17 -DCMAKE_CXX_COMPILER=clang++-17 -DLLVM_USE_SANITIZER=MemoryWithOrigins
|
||||
ninja -C build cxx cxxabi
|
||||
cd build
|
||||
mkdir /tmp/libcxx_msan
|
||||
cp -r include /tmp/libcxx_msan
|
||||
cp -r lib /tmp/libcxx_msan
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Build libcurl
|
||||
run: |
|
||||
cd external/src/curl
|
||||
cmake . -DCMAKE_C_COMPILER=clang-17 -DCMAKE_C_FLAGS='-fsanitize=memory -fsanitize-recover -fsanitize-memory-track-origins -Os -fno-omit-frame-pointer -g' -DBUILD_CURL_EXE=OFF -DBUILD_SHARED_LIBS=OFF -DCURL_ZLIB=OFF -DCURL_DISABLE_ALTSVC=ON -DCURL_DISABLE_COOKIES=ON -DCURL_DISABLE_DOH=ON -DCURL_DISABLE_GETOPTIONS=ON -DCURL_DISABLE_HSTS=ON -DCURL_DISABLE_LIBCURL_OPTION=ON -DCURL_DISABLE_MIME=ON -DCURL_DISABLE_NETRC=ON -DCURL_DISABLE_NTLM=ON -DCURL_DISABLE_PARSEDATE=ON -DCURL_DISABLE_PROGRESS_METER=ON -DCURL_DISABLE_SHUFFLE_DNS=ON -DCURL_DISABLE_SOCKETPAIR=ON -DCURL_DISABLE_VERBOSE_STRINGS=ON -DHTTP_ONLY=ON -DCURL_ENABLE_SSL=OFF -DUSE_LIBIDN2=OFF -DCURL_USE_LIBPSL=OFF -DCURL_USE_LIBSSH2=OFF -DENABLE_UNIX_SOCKETS=OFF
|
||||
make -j$(nproc)
|
||||
cd lib && mkdir .libs && cp libcurl.a .libs
|
||||
|
||||
- name: Build libuv
|
||||
run: |
|
||||
cd external/src/libuv
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_COMPILER=clang-17 -DCMAKE_C_FLAGS='-fsanitize=memory -fsanitize-recover -fsanitize-memory-track-origins -Os -fno-omit-frame-pointer -g' -DBUILD_TESTING=OFF -DLIBUV_BUILD_SHARED=OFF
|
||||
make -j$(nproc)
|
||||
|
||||
- name: Build libzmq
|
||||
run: |
|
||||
cd external/src/libzmq
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_COMPILER=clang-17 -DCMAKE_CXX_COMPILER=clang++-17 -DCMAKE_C_FLAGS='-fsanitize=memory -fsanitize-recover -fsanitize-memory-track-origins -Os -fno-omit-frame-pointer -g' -DCMAKE_CXX_FLAGS='-nostdinc++ -nostdlib++ -fsanitize=memory -fsanitize-recover -fsanitize-memory-track-origins -Os -fno-omit-frame-pointer -g -isystem /tmp/libcxx_msan/include/c++/v1 -L/tmp/libcxx_msan/lib -lc++ -lc++abi -Wno-unused-command-line-argument' -DWITH_LIBSODIUM=OFF -DWITH_LIBBSD=OFF -DBUILD_TESTS=OFF -DWITH_DOCS=OFF -DENABLE_DRAFTS=OFF -DBUILD_SHARED=OFF
|
||||
make -j$(nproc)
|
||||
|
||||
- name: Build p2pool
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_COMPILER=clang-17 -DCMAKE_CXX_COMPILER=clang++-17 -DCMAKE_C_FLAGS='-fsanitize=memory -fsanitize-recover -fsanitize-memory-track-origins -fno-omit-frame-pointer -g' -DCMAKE_CXX_FLAGS='-nostdinc++ -nostdlib++ -fsanitize=memory -fsanitize-recover -fsanitize-memory-track-origins -isystem /tmp/libcxx_msan/include/c++/v1 -L/tmp/libcxx_msan/lib -Wl,-rpath /tmp/libcxx_msan/lib -lc++ -lc++abi -Wno-unused-command-line-argument -fuse-ld=lld-17 -fno-omit-frame-pointer -g' -DDEV_TEST_SYNC=ON -DDEV_WITH_MSAN=ON -DSTATIC_LIBS=ON
|
||||
make -j$(nproc)
|
||||
|
||||
- name: Run p2pool
|
||||
run: |
|
||||
cd build
|
||||
mkdir data
|
||||
python ../tests/src/stratum_dummy.py 1 &
|
||||
python ../tests/src/stratum_dummy.py 2 &
|
||||
python ../tests/src/stratum_dummy.py 3 &
|
||||
MSAN_OPTIONS="halt_on_error=1" ./p2pool --host xmrnode.facspro.net --rpc-port 18089 --zmq-port 18084 --host xmr2.rs.me --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --mini --out-peers 200 --data-api data --local-api --loglevel 6
|
||||
|
||||
- name: Check p2pool.log
|
||||
run: |
|
||||
cd build
|
||||
grep 'Synchronization finished successfully' p2pool.log
|
||||
|
||||
- name: Archive p2pool.log
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: p2pool_ubuntu_data_msan
|
||||
path: |
|
||||
build/*.log
|
||||
build/data/
|
||||
|
||||
sync-test-ubuntu-ubsan:
|
||||
|
||||
timeout-minutes: 30
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
|
||||
sudo apt update
|
||||
sudo apt install -y git build-essential cmake libuv1-dev libzmq3-dev libsodium-dev libpgm-dev libnorm-dev libgss-dev libcurl4-openssl-dev libidn2-0-dev gcc-12 g++-12
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Build p2pool
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DDEV_TEST_SYNC=ON -DDEV_WITH_UBSAN=ON -DCMAKE_C_COMPILER=gcc-12 -DCMAKE_CXX_COMPILER=g++-12 -DCMAKE_C_FLAGS="-flto=2" -DCMAKE_CXX_FLAGS="-flto=2"
|
||||
make -j$(nproc)
|
||||
|
||||
- name: Run p2pool
|
||||
run: |
|
||||
cd build
|
||||
mkdir data
|
||||
python ../tests/src/stratum_dummy.py 1 &
|
||||
python ../tests/src/stratum_dummy.py 2 &
|
||||
python ../tests/src/stratum_dummy.py 3 &
|
||||
UBSAN_OPTIONS="suppressions=../tests/src/ubsan_sup.txt halt_on_error=1" ./p2pool --host xmrnode.facspro.net --rpc-port 18089 --zmq-port 18084 --host xmr2.rs.me --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --mini --out-peers 200 --data-api data --local-api --loglevel 6
|
||||
|
||||
- name: Check p2pool.log
|
||||
run: |
|
||||
cd build
|
||||
grep 'Synchronization finished successfully' p2pool.log
|
||||
|
||||
- name: Archive p2pool.log
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: p2pool_ubuntu_data_ubsan
|
||||
path: |
|
||||
build/*.log
|
||||
build/data/
|
||||
|
||||
sync-test-ubuntu-asan:
|
||||
|
||||
timeout-minutes: 30
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
|
||||
sudo apt update
|
||||
sudo apt install -y git build-essential cmake libuv1-dev libzmq3-dev libsodium-dev libpgm-dev libnorm-dev libgss-dev libcurl4-openssl-dev libidn2-0-dev gcc-12 g++-12
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Build p2pool
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DDEV_TEST_SYNC=ON -DDEV_WITH_ASAN=ON -DCMAKE_C_COMPILER=gcc-12 -DCMAKE_CXX_COMPILER=g++-12 -DCMAKE_C_FLAGS="-flto=2" -DCMAKE_CXX_FLAGS="-flto=2"
|
||||
make -j$(nproc)
|
||||
|
||||
- name: Run p2pool
|
||||
run: |
|
||||
cd build
|
||||
mkdir data
|
||||
python ../tests/src/stratum_dummy.py 1 &
|
||||
python ../tests/src/stratum_dummy.py 2 &
|
||||
python ../tests/src/stratum_dummy.py 3 &
|
||||
ASAN_OPTIONS="detect_stack_use_after_return=1 atexit=1" ./p2pool --host xmrnode.facspro.net --rpc-port 18089 --zmq-port 18084 --host xmr2.rs.me --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --mini --out-peers 200 --data-api data --local-api --loglevel 6
|
||||
|
||||
- name: Check p2pool.log
|
||||
run: |
|
||||
cd build
|
||||
grep 'Synchronization finished successfully' p2pool.log
|
||||
|
||||
- name: Archive p2pool.log
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: p2pool_ubuntu_data_asan
|
||||
path: |
|
||||
build/*.log
|
||||
build/data/
|
||||
|
||||
sync-test-macos:
|
||||
|
||||
timeout-minutes: 30
|
||||
runs-on: macos-11
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
HOMEBREW_NO_AUTO_UPDATE=1 brew install pyenv
|
||||
pyenv install 3:latest
|
||||
|
||||
- name: Build libcurl
|
||||
run: |
|
||||
cd external/src/curl
|
||||
cmake . -DCMAKE_C_COMPILER="$(brew --prefix llvm@15)/bin/clang" -DCMAKE_AR="$(brew --prefix llvm@15)/bin/llvm-ar" -DCMAKE_RANLIB="$(brew --prefix llvm@15)/bin/llvm-ranlib" -DCMAKE_C_FLAGS="-Os -flto" -DBUILD_CURL_EXE=OFF -DBUILD_SHARED_LIBS=OFF -DCURL_ZLIB=OFF -DCURL_DISABLE_ALTSVC=ON -DCURL_DISABLE_COOKIES=ON -DCURL_DISABLE_DOH=ON -DCURL_DISABLE_GETOPTIONS=ON -DCURL_DISABLE_HSTS=ON -DCURL_DISABLE_LIBCURL_OPTION=ON -DCURL_DISABLE_MIME=ON -DCURL_DISABLE_NETRC=ON -DCURL_DISABLE_NTLM=ON -DCURL_DISABLE_PARSEDATE=ON -DCURL_DISABLE_PROGRESS_METER=ON -DCURL_DISABLE_SHUFFLE_DNS=ON -DCURL_DISABLE_SOCKETPAIR=ON -DCURL_DISABLE_VERBOSE_STRINGS=ON -DHTTP_ONLY=ON -DCURL_ENABLE_SSL=OFF -DUSE_LIBIDN2=OFF -DCURL_USE_LIBPSL=OFF -DCURL_USE_LIBSSH2=OFF -DENABLE_UNIX_SOCKETS=OFF
|
||||
make -j3
|
||||
cd lib && mkdir .libs && cp libcurl.a .libs
|
||||
|
||||
- name: Build libuv
|
||||
run: |
|
||||
cd external/src/libuv
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_COMPILER="$(brew --prefix llvm@15)/bin/clang" -DCMAKE_AR="$(brew --prefix llvm@15)/bin/llvm-ar" -DCMAKE_RANLIB="$(brew --prefix llvm@15)/bin/llvm-ranlib" -DCMAKE_C_FLAGS='-Os -flto' -DBUILD_TESTING=OFF -DLIBUV_BUILD_SHARED=OFF
|
||||
make -j3
|
||||
|
||||
- name: Build libzmq
|
||||
run: |
|
||||
cd external/src/libzmq
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_COMPILER="$(brew --prefix llvm@15)/bin/clang" -DCMAKE_CXX_COMPILER="$(brew --prefix llvm@15)/bin/clang++" -DCMAKE_AR="$(brew --prefix llvm@15)/bin/llvm-ar" -DCMAKE_RANLIB="$(brew --prefix llvm@15)/bin/llvm-ranlib" -DCMAKE_C_FLAGS='-Os -flto' -DCMAKE_CXX_FLAGS='-Os -flto' -DWITH_LIBSODIUM=OFF -DWITH_LIBBSD=OFF -DBUILD_TESTS=OFF -DWITH_DOCS=OFF -DENABLE_DRAFTS=OFF -DBUILD_SHARED=OFF
|
||||
make -j3
|
||||
|
||||
- name: Build p2pool
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_COMPILER="$(brew --prefix llvm@15)/bin/clang" -DCMAKE_CXX_COMPILER="$(brew --prefix llvm@15)/bin/clang++" -DCMAKE_AR="$(brew --prefix llvm@15)/bin/llvm-ar" -DCMAKE_RANLIB="$(brew --prefix llvm@15)/bin/llvm-ranlib" -DCMAKE_C_FLAGS="-flto" -DCMAKE_CXX_FLAGS="-flto" -DSTATIC_LIBS=ON -DDEV_TEST_SYNC=ON
|
||||
make -j3
|
||||
|
||||
- name: Run p2pool
|
||||
run: |
|
||||
cd build
|
||||
mkdir data
|
||||
python3 ../tests/src/stratum_dummy.py 1 &
|
||||
python3 ../tests/src/stratum_dummy.py 2 &
|
||||
python3 ../tests/src/stratum_dummy.py 3 &
|
||||
./p2pool --host xmrnode.facspro.net --rpc-port 18089 --zmq-port 18084 --host xmr2.rs.me --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --mini --out-peers 200 --data-api data --local-api --loglevel 6
|
||||
|
||||
- name: Check p2pool.log
|
||||
run: |
|
||||
cd build
|
||||
grep 'Synchronization finished successfully' p2pool.log
|
||||
|
||||
- name: Archive p2pool.log
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: p2pool_macos_data
|
||||
path: |
|
||||
build/*.log
|
||||
build/data/
|
||||
|
||||
sync-test-windows-debug-asan:
|
||||
|
||||
timeout-minutes: 30
|
||||
runs-on: windows-2022
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Setup cmake
|
||||
uses: lukka/get-cmake@latest
|
||||
|
||||
- name: Build p2pool
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -G "Visual Studio 17 2022" -DDEV_TEST_SYNC=ON
|
||||
& "C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\Msbuild\\Current\\Bin\\amd64\\msbuild" -v:m /m /p:Configuration=Debug p2pool.vcxproj
|
||||
|
||||
- name: Run p2pool
|
||||
shell: cmd
|
||||
run: |
|
||||
call "C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\VC\\Auxiliary\\Build\\vcvarsall.bat" amd64
|
||||
cd build/Debug
|
||||
mkdir data
|
||||
start python ../../tests/src/stratum_dummy.py 1
|
||||
start python ../../tests/src/stratum_dummy.py 2
|
||||
start python ../../tests/src/stratum_dummy.py 3
|
||||
p2pool.exe --host xmrnode.facspro.net --rpc-port 18089 --zmq-port 18084 --host xmr2.rs.me --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --mini --out-peers 200 --data-api data --local-api --loglevel 6
|
||||
|
||||
- name: Check p2pool.log
|
||||
run: |
|
||||
cd build/Debug
|
||||
findstr /C:"Synchronization finished successfully" p2pool.log
|
||||
|
||||
- name: Archive p2pool.log
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: p2pool_windows_data_debug_asan
|
||||
path: |
|
||||
build/Debug/*.log
|
||||
build/Debug/data/
|
||||
|
||||
sync-test-windows-leaks:
|
||||
|
||||
timeout-minutes: 30
|
||||
runs-on: windows-2022
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Setup cmake
|
||||
uses: lukka/get-cmake@latest
|
||||
|
||||
- name: Build p2pool
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -G "Visual Studio 17 2022" -DDEV_TEST_SYNC=ON -DDEV_TRACK_MEMORY=ON
|
||||
& "C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\Msbuild\\Current\\Bin\\amd64\\msbuild" -v:m /m /p:Configuration=RelWithDebInfo p2pool.vcxproj
|
||||
|
||||
- name: Run p2pool
|
||||
run: |
|
||||
cd build/RelWithDebInfo
|
||||
mkdir data
|
||||
Start-Process python -ArgumentList "../../tests/src/stratum_dummy.py 1"
|
||||
Start-Process python -ArgumentList "../../tests/src/stratum_dummy.py 2"
|
||||
Start-Process python -ArgumentList "../../tests/src/stratum_dummy.py 3"
|
||||
./p2pool.exe --host xmrnode.facspro.net --rpc-port 18089 --zmq-port 18084 --host xmr2.rs.me --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --mini --out-peers 200 --data-api data --local-api --loglevel 6
|
||||
|
||||
- name: Check p2pool.log
|
||||
run: |
|
||||
cd build/RelWithDebInfo
|
||||
findstr /C:"Synchronization finished successfully" p2pool.log
|
||||
|
||||
- name: Archive p2pool.log
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: p2pool_windows_data_leaks
|
||||
path: |
|
||||
build/RelWithDebInfo/*.log
|
||||
build/RelWithDebInfo/data/
|
||||
+6
-3
@@ -10,9 +10,6 @@
|
||||
[submodule "external/src/cppzmq"]
|
||||
path = external/src/cppzmq
|
||||
url = https://github.com/SChernykh/cppzmq
|
||||
[submodule "external/src/libsodium"]
|
||||
path = external/src/libsodium
|
||||
url = https://github.com/SChernykh/libsodium
|
||||
[submodule "external/src/libuv"]
|
||||
path = external/src/libuv
|
||||
url = https://github.com/SChernykh/libuv
|
||||
@@ -22,3 +19,9 @@
|
||||
[submodule "external/src/robin-hood-hashing"]
|
||||
path = external/src/robin-hood-hashing
|
||||
url = https://github.com/SChernykh/robin-hood-hashing
|
||||
[submodule "external/src/curl"]
|
||||
path = external/src/curl
|
||||
url = https://github.com/SChernykh/curl
|
||||
[submodule "external/src/miniupnp"]
|
||||
path = external/src/miniupnp
|
||||
url = https://github.com/SChernykh/miniupnp
|
||||
|
||||
+255
-26
@@ -1,7 +1,19 @@
|
||||
cmake_minimum_required(VERSION 2.8.12)
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
project(p2pool)
|
||||
|
||||
option(STATIC_LINUX_BINARY "Build static Linux binary" OFF)
|
||||
option(STATIC_BINARY "Build static binary" OFF)
|
||||
option(STATIC_LIBS "Link libuv and libzmq statically" OFF)
|
||||
option(WITH_RANDOMX "Include the RandomX library in the build. If this is turned off, p2pool will rely on monerod for verifying RandomX hashes" ON)
|
||||
option(WITH_LTO "Use link-time compiler optimization (if linking fails for you, run cmake with -DWITH_LTO=OFF)" ON)
|
||||
option(WITH_UPNP "Include UPnP support. If this is turned off, p2pool will not be able to configure port forwarding on UPnP-enabled routers." ON)
|
||||
|
||||
option(DEV_TEST_SYNC "[Developer only] Sync test, stop p2pool after sync is complete" OFF)
|
||||
option(DEV_WITH_TSAN "[Developer only] Compile with thread sanitizer" OFF)
|
||||
option(DEV_WITH_MSAN "[Developer only] Compile with memory sanitizer" OFF)
|
||||
option(DEV_WITH_UBSAN "[Developer only] Compile with undefined behavior sanitizer" OFF)
|
||||
option(DEV_WITH_ASAN "[Developer only] Compile with address sanitizer" OFF)
|
||||
option(DEV_CLANG_TIDY "[Developer only] Compile for clang-tidy" OFF)
|
||||
option(DEV_TRACK_MEMORY "[Developer only] Track memory allocations" OFF)
|
||||
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake")
|
||||
|
||||
@@ -9,14 +21,51 @@ if (${CMAKE_VERSION} VERSION_GREATER "3.5.2")
|
||||
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT p2pool)
|
||||
endif()
|
||||
|
||||
add_subdirectory(external/src/RandomX)
|
||||
set(LIBS randomx)
|
||||
if (WITH_RANDOMX)
|
||||
add_definitions(-DWITH_RANDOMX)
|
||||
add_subdirectory(external/src/RandomX)
|
||||
set(LIBS ${LIBS} randomx)
|
||||
endif()
|
||||
|
||||
if (WITH_UPNP)
|
||||
add_definitions(-DWITH_UPNP)
|
||||
add_subdirectory(external/src/miniupnp/miniupnpc)
|
||||
set(LIBS ${LIBS} libminiupnpc-static)
|
||||
endif()
|
||||
|
||||
if (DEV_TEST_SYNC)
|
||||
add_definitions(-DDEV_TEST_SYNC)
|
||||
endif()
|
||||
|
||||
if (DEV_WITH_TSAN)
|
||||
add_definitions(-DDEV_WITH_TSAN)
|
||||
endif()
|
||||
|
||||
if (DEV_WITH_MSAN)
|
||||
add_definitions(-DDEV_WITH_MSAN)
|
||||
endif()
|
||||
|
||||
if (DEV_WITH_UBSAN)
|
||||
add_definitions(-DDEV_WITH_UBSAN)
|
||||
endif()
|
||||
|
||||
if (DEV_WITH_ASAN)
|
||||
add_definitions(-DDEV_WITH_ASAN)
|
||||
endif()
|
||||
|
||||
if (DEV_CLANG_TIDY)
|
||||
add_definitions(-DDEV_CLANG_TIDY)
|
||||
endif()
|
||||
|
||||
if (DEV_TRACK_MEMORY)
|
||||
add_definitions(-DDEV_TRACK_MEMORY)
|
||||
endif()
|
||||
|
||||
include(cmake/flags.cmake)
|
||||
|
||||
set(HEADERS
|
||||
external/src/cryptonote/crypto-ops.h
|
||||
external/src/llhttp/llhttp.h
|
||||
external/src/hardforks/hardforks.h
|
||||
src/block_cache.h
|
||||
src/block_template.h
|
||||
src/common.h
|
||||
@@ -27,7 +76,6 @@ set(HEADERS
|
||||
src/keccak.h
|
||||
src/log.h
|
||||
src/mempool.h
|
||||
src/miner.h
|
||||
src/p2p_server.h
|
||||
src/p2pool.h
|
||||
src/p2pool_api.h
|
||||
@@ -38,7 +86,6 @@ set(HEADERS
|
||||
src/side_chain.h
|
||||
src/stratum_server.h
|
||||
src/tcp_server.h
|
||||
src/tcp_server.inl
|
||||
src/util.h
|
||||
src/uv_util.h
|
||||
src/wallet.h
|
||||
@@ -48,9 +95,7 @@ set(HEADERS
|
||||
set(SOURCES
|
||||
external/src/cryptonote/crypto-ops-data.c
|
||||
external/src/cryptonote/crypto-ops.c
|
||||
external/src/llhttp/api.c
|
||||
external/src/llhttp/http.c
|
||||
external/src/llhttp/llhttp.c
|
||||
external/src/hardforks/hardforks.cpp
|
||||
src/block_cache.cpp
|
||||
src/block_template.cpp
|
||||
src/console_commands.cpp
|
||||
@@ -61,7 +106,6 @@ set(SOURCES
|
||||
src/main.cpp
|
||||
src/memory_leak_debug.cpp
|
||||
src/mempool.cpp
|
||||
src/miner.cpp
|
||||
src/p2p_server.cpp
|
||||
src/p2pool.cpp
|
||||
src/p2pool_api.cpp
|
||||
@@ -70,38 +114,90 @@ set(SOURCES
|
||||
src/pow_hash.cpp
|
||||
src/side_chain.cpp
|
||||
src/stratum_server.cpp
|
||||
src/tcp_server.cpp
|
||||
src/util.cpp
|
||||
src/wallet.cpp
|
||||
src/zmq_reader.cpp
|
||||
)
|
||||
|
||||
if (WITH_RANDOMX)
|
||||
set(HEADERS ${HEADERS} src/miner.h)
|
||||
set(SOURCES ${SOURCES} src/miner.cpp)
|
||||
endif()
|
||||
|
||||
if (NOT ((CMAKE_CXX_COMPILER_ID MATCHES MSVC) OR STATIC_BINARY OR STATIC_LIBS))
|
||||
include(FindCURL)
|
||||
endif()
|
||||
|
||||
if (CURL_INCLUDE_DIRS)
|
||||
include_directories(${CURL_INCLUDE_DIRS})
|
||||
else()
|
||||
include_directories(external/src/curl/include)
|
||||
endif()
|
||||
|
||||
if ((CMAKE_CXX_COMPILER_ID MATCHES MSVC) OR STATIC_BINARY OR STATIC_LIBS)
|
||||
set(UV_INCLUDE_DIR external/src/libuv/include)
|
||||
set(ZMQ_INCLUDE_DIR external/src/libzmq/include)
|
||||
else()
|
||||
find_path(UV_INCLUDE_DIR NAMES uv.h PATH_SUFFIXES "include")
|
||||
find_path(ZMQ_INCLUDE_DIR NAMES zmq.h PATH_SUFFIXES "include")
|
||||
endif()
|
||||
|
||||
include_directories(src)
|
||||
include_directories(external/src)
|
||||
include_directories(external/src/cryptonote)
|
||||
include_directories(external/src/libuv/include)
|
||||
include_directories(${UV_INCLUDE_DIR})
|
||||
include_directories(external/src/cppzmq)
|
||||
include_directories(external/src/libzmq/include)
|
||||
include_directories(external/src/llhttp)
|
||||
include_directories(external/src/RandomX/src)
|
||||
include_directories(${ZMQ_INCLUDE_DIR})
|
||||
if (WITH_RANDOMX)
|
||||
include_directories(external/src/RandomX/src)
|
||||
endif()
|
||||
include_directories(external/src/rapidjson/include)
|
||||
include_directories(external/src/robin-hood-hashing/src/include)
|
||||
if (WITH_UPNP)
|
||||
include_directories(external/src/miniupnp/miniupnpc/include)
|
||||
endif()
|
||||
|
||||
if (WIN32)
|
||||
set(LIBS ${LIBS} ws2_32 iphlpapi userenv psapi)
|
||||
set(LIBS ${LIBS} ws2_32 iphlpapi userenv psapi dnsapi dbghelp)
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES GNU)
|
||||
set(LIBS ${LIBS} bcrypt)
|
||||
endif()
|
||||
add_definitions(-DCURL_STATICLIB)
|
||||
add_definitions(-DWIN32_LEAN_AND_MEAN)
|
||||
add_definitions(-D_WIN32_WINNT=0x0600)
|
||||
elseif (CMAKE_SYSTEM_NAME STREQUAL FreeBSD)
|
||||
set(LIBS ${LIBS} pthread)
|
||||
elseif (NOT APPLE)
|
||||
set(LIBS ${LIBS} pthread gss dl)
|
||||
set(LIBS ${LIBS} pthread)
|
||||
endif()
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES MSVC)
|
||||
find_library(ZMQ_LIBRARY_DEBUG NAMES libzmq-v142-mt-sgd-4_3_5 PATHS "external/lib/libzmq/Debug")
|
||||
find_library(ZMQ_LIBRARY NAMES libzmq-v142-mt-s-4_3_5 PATHS "external/lib/libzmq/Release")
|
||||
find_library(UV_LIBRARY_DEBUG NAMES uv_a PATHS "external/lib/libuv/Debug")
|
||||
find_library(UV_LIBRARY NAMES uv_a PATHS "external/lib/libuv/Release")
|
||||
find_library(UV_LIBRARY_DEBUG NAMES libuv PATHS "external/lib/libuv/Debug")
|
||||
find_library(UV_LIBRARY NAMES libuv PATHS "external/lib/libuv/Release")
|
||||
find_library(CURL_LIBRARY_DEBUG NAMES libcurl-d PATHS "external/lib/libcurl/Debug")
|
||||
find_library(CURL_LIBRARY NAMES libcurl PATHS "external/lib/libcurl/Release")
|
||||
add_definitions(-D_DISABLE_VECTOR_ANNOTATION)
|
||||
add_definitions(-D_DISABLE_STRING_ANNOTATION)
|
||||
elseif (CMAKE_CXX_COMPILER_ID MATCHES GNU OR CMAKE_CXX_COMPILER_ID MATCHES Clang)
|
||||
find_library(ZMQ_LIBRARY_DEBUG NAMES zmq libzmq.a)
|
||||
find_library(ZMQ_LIBRARY NAMES zmq libzmq.a)
|
||||
find_library(UV_LIBRARY_DEBUG NAMES uv libuv.a)
|
||||
find_library(UV_LIBRARY NAMES uv libuv.a)
|
||||
if (WIN32)
|
||||
find_library(CURL_LIBRARY_DEBUG NAMES libcurl.a PATHS "external/src/curl/lib/.libs" NO_DEFAULT_PATH)
|
||||
find_library(CURL_LIBRARY NAMES libcurl.a PATHS "external/src/curl/lib/.libs" NO_DEFAULT_PATH)
|
||||
else()
|
||||
if (CURL_LIBRARIES)
|
||||
set(CURL_LIBRARY_DEBUG ${CURL_LIBRARIES})
|
||||
set(CURL_LIBRARY ${CURL_LIBRARIES})
|
||||
else()
|
||||
find_library(CURL_LIBRARY_DEBUG NAMES curl)
|
||||
find_library(CURL_LIBRARY NAMES curl)
|
||||
endif()
|
||||
endif()
|
||||
find_library(SODIUM_LIBRARY sodium)
|
||||
endif()
|
||||
|
||||
@@ -120,20 +216,153 @@ if (SODIUM_LIBRARY)
|
||||
set(LIBS ${LIBS} ${SODIUM_LIBRARY})
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
find_library(FOUNDATION_LIB Foundation)
|
||||
find_library(CORE_FOUNDATION_LIB CoreFoundation)
|
||||
find_library(SYSTEM_CONFIGURATION_LIB SystemConfiguration)
|
||||
set(LIBS ${LIBS} ${FOUNDATION_LIB} ${CORE_FOUNDATION_LIB} ${SYSTEM_CONFIGURATION_LIB})
|
||||
endif()
|
||||
|
||||
add_definitions(/DZMQ_STATIC)
|
||||
|
||||
include(CheckCXXSourceCompiles)
|
||||
|
||||
check_cxx_source_compiles("int main(){ return __builtin_clzll(1);}" HAVE_BUILTIN_CLZLL)
|
||||
check_cxx_source_compiles("#include <intrin.h>\n#pragma intrinsic(_BitScanReverse64)\nint main(){unsigned long r;_BitScanReverse64(&r,1);return r;}" HAVE_BITSCANREVERSE64)
|
||||
check_cxx_source_compiles("#include <sched.h>\nint main(){sched_param param;return sched_setscheduler(0, SCHED_IDLE, ¶m);}" HAVE_SCHED)
|
||||
|
||||
include(CheckCSourceCompiles)
|
||||
|
||||
set(CMAKE_REQUIRED_LIBRARIES "resolv")
|
||||
|
||||
check_c_source_compiles("int main() { return 0; }" HAVE_RESOLV_LIB)
|
||||
|
||||
if (NOT HAVE_RESOLV_LIB)
|
||||
set(CMAKE_REQUIRED_LIBRARIES)
|
||||
endif()
|
||||
|
||||
check_c_source_compiles("
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/nameser.h>
|
||||
#include <resolv.h>
|
||||
#include <stdio.h>
|
||||
#include <memory.h>
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
if (argc < 2) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
res_init();
|
||||
|
||||
uint8_t answer[4096];
|
||||
const int anslen = res_query(argv[1], ns_c_in, ns_t_txt, answer, sizeof(answer));
|
||||
|
||||
if (anslen > (int) sizeof(answer)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
ns_msg handle;
|
||||
ns_initparse(answer, anslen, &handle);
|
||||
|
||||
for (int rrnum = 0, n = ns_msg_count(handle, ns_s_an); rrnum < n; ++rrnum) {
|
||||
ns_rr rr;
|
||||
if ((ns_parserr(&handle, ns_s_an, rrnum, &rr) == 0) && (ns_rr_type(rr) == ns_t_txt)) {
|
||||
for (const uint8_t* data = ns_rr_rdata(rr), *e = data + ns_rr_rdlen(rr); data < e;) {
|
||||
const int k = *(data++);
|
||||
if (k && (data + k <= e)) {
|
||||
char buf[256];
|
||||
memcpy(buf, data, k);
|
||||
buf[k] = 0;
|
||||
puts(buf);
|
||||
}
|
||||
data += k;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}" HAVE_RES_QUERY)
|
||||
|
||||
set(CMAKE_REQUIRED_LIBRARIES)
|
||||
|
||||
if (HAVE_BUILTIN_CLZLL)
|
||||
add_definitions(/DHAVE_BUILTIN_CLZLL)
|
||||
endif()
|
||||
|
||||
if (HAVE_BITSCANREVERSE64)
|
||||
add_definitions(/DHAVE_BITSCANREVERSE64)
|
||||
endif()
|
||||
|
||||
if (HAVE_SCHED)
|
||||
add_definitions(/DHAVE_SCHED)
|
||||
endif()
|
||||
|
||||
if (HAVE_RES_QUERY)
|
||||
add_definitions(/DHAVE_RES_QUERY)
|
||||
if (HAVE_RESOLV_LIB)
|
||||
set(LIBS ${LIBS} resolv)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_definitions("-DRAPIDJSON_PARSE_DEFAULT_FLAGS=kParseTrailingCommasFlag")
|
||||
|
||||
add_executable(${CMAKE_PROJECT_NAME} ${HEADERS} ${SOURCES})
|
||||
|
||||
if (STATIC_LINUX_BINARY)
|
||||
add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_STRIP} ${CMAKE_PROJECT_NAME})
|
||||
if (STATIC_BINARY OR STATIC_LIBS)
|
||||
if (NOT (DEV_WITH_TSAN OR DEV_WITH_MSAN OR DEV_WITH_UBSAN OR DEV_WITH_ASAN))
|
||||
if (WIN32)
|
||||
add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_STRIP} "${CMAKE_PROJECT_NAME}.exe")
|
||||
else()
|
||||
add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_STRIP} ${CMAKE_PROJECT_NAME})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(STATIC_LIBS "")
|
||||
|
||||
if (WITH_RANDOMX)
|
||||
set(STATIC_LIBS randomx)
|
||||
endif()
|
||||
|
||||
if (WITH_UPNP)
|
||||
set(STATIC_LIBS ${STATIC_LIBS} libminiupnpc-static)
|
||||
endif()
|
||||
|
||||
if (WIN32)
|
||||
set(STATIC_LIBS ${STATIC_LIBS} ws2_32 iphlpapi userenv psapi dnsapi dbghelp)
|
||||
if ((CMAKE_CXX_COMPILER_ID MATCHES GNU) OR (CMAKE_CXX_COMPILER_ID MATCHES Clang))
|
||||
set(STATIC_LIBS ${STATIC_LIBS} bcrypt)
|
||||
endif()
|
||||
elseif (CMAKE_SYSTEM_NAME STREQUAL FreeBSD)
|
||||
set(STATIC_LIBS ${STATIC_LIBS} pthread)
|
||||
elseif (APPLE)
|
||||
find_library(FOUNDATION_LIB Foundation)
|
||||
find_library(CORE_FOUNDATION_LIB CoreFoundation)
|
||||
find_library(SYSTEM_CONFIGURATION_LIB SystemConfiguration)
|
||||
set(STATIC_LIBS ${STATIC_LIBS} ${FOUNDATION_LIB} ${CORE_FOUNDATION_LIB} ${SYSTEM_CONFIGURATION_LIB})
|
||||
else()
|
||||
set(STATIC_LIBS ${STATIC_LIBS} pthread)
|
||||
endif()
|
||||
|
||||
if (HAVE_RES_QUERY AND HAVE_RESOLV_LIB)
|
||||
set(STATIC_LIBS ${STATIC_LIBS} resolv)
|
||||
endif()
|
||||
|
||||
target_link_libraries(${CMAKE_PROJECT_NAME}
|
||||
"${CMAKE_SOURCE_DIR}/external/src/libsodium/src/libsodium/.libs/libsodium.a"
|
||||
"${CMAKE_SOURCE_DIR}/external/src/libzmq/build/lib/libzmq.a"
|
||||
"${CMAKE_SOURCE_DIR}/external/src/libuv/build/libuv_a.a"
|
||||
randomx
|
||||
pthread
|
||||
"${CMAKE_SOURCE_DIR}/external/src/libuv/build/libuv.a"
|
||||
"${CMAKE_SOURCE_DIR}/external/src/curl/lib/.libs/libcurl.a"
|
||||
${STATIC_LIBS}
|
||||
)
|
||||
else()
|
||||
target_link_libraries(${CMAKE_PROJECT_NAME} debug ${ZMQ_LIBRARY_DEBUG} debug ${UV_LIBRARY_DEBUG} optimized ${ZMQ_LIBRARY} optimized ${UV_LIBRARY} ${LIBS})
|
||||
target_link_libraries(${CMAKE_PROJECT_NAME} debug ${ZMQ_LIBRARY_DEBUG} debug ${UV_LIBRARY_DEBUG} debug ${CURL_LIBRARY_DEBUG} optimized ${ZMQ_LIBRARY} optimized ${UV_LIBRARY} optimized ${CURL_LIBRARY} ${LIBS})
|
||||
endif()
|
||||
|
||||
message(STATUS "Summary of build options:
|
||||
C compiler: ${CMAKE_C_COMPILER} (${CMAKE_C_COMPILER_ID})
|
||||
CXX compiler: ${CMAKE_CXX_COMPILER} (${CMAKE_CXX_COMPILER_ID})
|
||||
C_FLAGS: ${CMAKE_C_FLAGS}
|
||||
CXX_FLAGS: ${CMAKE_CXX_FLAGS}
|
||||
")
|
||||
|
||||
+6
-3
@@ -1,4 +1,4 @@
|
||||
FROM ubuntu:latest
|
||||
FROM ubuntu:20.04
|
||||
|
||||
RUN set -e && \
|
||||
apt-get update -q -y --no-install-recommends && \
|
||||
@@ -12,7 +12,8 @@ RUN set -e && \
|
||||
libsodium-dev \
|
||||
libpgm-dev \
|
||||
libnorm-dev \
|
||||
libgss-dev
|
||||
libgss-dev \
|
||||
libcurl4-openssl-dev
|
||||
|
||||
ADD . /usr/src/p2pool
|
||||
WORKDIR /usr/src/p2pool
|
||||
@@ -24,7 +25,7 @@ RUN git submodule update --init --recursive && \
|
||||
|
||||
# ---
|
||||
|
||||
FROM ubuntu:latest
|
||||
FROM ubuntu:20.04
|
||||
COPY --from=0 /usr/src/p2pool/build/p2pool /
|
||||
|
||||
RUN set -e && \
|
||||
@@ -32,6 +33,7 @@ RUN set -e && \
|
||||
DEBIAN_FRONTEND="noninteractive" apt-get install -q -y --no-install-recommends \
|
||||
libzmq5 \
|
||||
libuv1 \
|
||||
libcurl4 \
|
||||
&& \
|
||||
apt-get clean
|
||||
|
||||
@@ -43,6 +45,7 @@ USER p2pool
|
||||
|
||||
EXPOSE 3333
|
||||
EXPOSE 37889
|
||||
EXPOSE 37888
|
||||
|
||||
VOLUME /home/p2pool/.p2pool
|
||||
|
||||
|
||||
@@ -2,18 +2,36 @@
|
||||
|
||||
Decentralized pool for Monero mining.
|
||||
|
||||
Pool status and monitoring pages can be found at https://p2pool.io/ and https://p2pool.observer/
|
||||
Pool status and monitoring pages can be found at https://p2pool.io/, https://p2pool.io/mini/ and https://p2pool.observer/, https://mini.p2pool.observer/
|
||||
|
||||
### Build status
|
||||
These are 3rd-party pages. If they are down, it doesn't mean there is a problem with P2Pool itself - it keeps mining always thanks to its decentralized nature.
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
### Build Status
|
||||
|
||||

|
||||

|
||||
|
||||

|
||||

|
||||

|
||||
<a href="https://scan.coverity.com/projects/schernykh-p2pool">
|
||||
<img alt="Coverity Scan Build Status"
|
||||
src="https://scan.coverity.com/projects/23659/badge.svg"/>
|
||||
</a>
|
||||

|
||||
# Contents
|
||||
- [Pool mining vs Solo mining vs P2Pool mining](#pool-mining-vs-solo-mining-vs-p2pool-mining)
|
||||
- [Features](#features)
|
||||
- [How payouts work in P2Pool](#how-payouts-work-in-p2pool)
|
||||
- [Default P2Pool parameters](#default-p2pool-parameters)
|
||||
- [Monero version support](#monero-version-support)
|
||||
- [How to mine on P2Pool](#how-to-mine-on-p2pool)
|
||||
- [General Considerations](#general-considerations)
|
||||
- [GUI for P2Pool](#gui-for-p2pool)
|
||||
- [GNU/Linux](#gnulinux)
|
||||
- [Windows](#windows)
|
||||
- [Build instructions](#build-instructions)
|
||||
- [Donations](#donations)
|
||||
|
||||
## Pool mining vs Solo mining vs P2Pool mining
|
||||
|
||||
@@ -23,121 +41,202 @@ Here's the comparison table of the different ways of mining. While pool mining i
|
||||
|-|-|-|-|-|-|-|-|
|
||||
|Centralized pool|Regular|0-3%|0.001-0.01 XMR|Yes|Less stable due to pool server outages|Pool admin controls your mined funds, what you mine and can execute network attacks|Only miner software is required
|
||||
|Solo|Rare|0%|0.6 XMR or more|No|As stable as your Monero node|100% under your control|Monero node + optional miner
|
||||
|**P2Pool**|Regular|0%|~0.0003 XMR|No|As stable as your Monero node|100% under your control|Monero node + P2Pool node + miner
|
||||
|**P2Pool**|Regular|0%|~0.00027 XMR|No|Very stable: node failover and multiple Monero nodes are supported|100% under your control|Monero node(s) + P2Pool node(s) + optional miner(s)
|
||||
|
||||
## Features
|
||||
|
||||
* Decentralized: no central server that can be shutdown/blocked. P2Pool uses a separate blockchain to merge mine with Monero. Pool admin can't go rogue or be pressured to do an attack on the network because there is no pool admin!
|
||||
* Permissionless: there is no one to decide who can mine on the pool and who can't.
|
||||
* Trustless: there is no pool wallet, funds are never in custody. All pool blocks pay out to miners immediately.
|
||||
* Trustless: there is no pool wallet, funds are never in custody. All pool blocks pay out to miners directly.
|
||||
* PPLNS payout scheme
|
||||
* **0% fee**
|
||||
* **0 XMR payout fee**
|
||||
* **~0.0003 XMR minimal payout**
|
||||
* **~0.00027 XMR minimal payout**
|
||||
* Fast block times, down to 1 second
|
||||
* Uncle blocks are supported to avoid orphans - all your shares will be accounted for!
|
||||
* Configurable PPLNS window size and block time
|
||||
* Advanced mempool picking algorithm, it creates blocks with better reward than what monerod solo mining does
|
||||
* Password protected private pools
|
||||
* Highly reliable configurations are supported (multiple P2Pool nodes mining to the same wallet, each P2Pool node can use multiple Monero nodes and switch on the fly if an issue is detected)
|
||||
|
||||
## How PPLNS works in P2Pool
|
||||
## How payouts work in P2Pool
|
||||
|
||||
First you need to find a pool share. This share will stay in PPLNS window for 2160 pool blocks (6 hours). The moment P2Pool finds a Monero block and you have at least 1 pool share in PPLNS window, you'll get a payout! Monero block reward is split between all miner wallets in PPLNS window. Each miner gets a part of block reward proportional to the total difficulty of his/her shares in PPLNS window.
|
||||
First you need to find a pool share. This share will stay in [PPLNS](https://en.wikipedia.org/wiki/Mining_pool#Pay-per-last-N-shares) window for up to 2160 pool blocks (6 hours, auto adjustable to balance payout sizes and frequency). The moment P2Pool finds a Monero block and you have at least 1 pool share in PPLNS window, you'll get a payout! Monero block reward is split between all miner wallets in PPLNS window. Each miner gets a part of block reward proportional to the total difficulty of his/her shares in PPLNS window.
|
||||
|
||||
**NOTE** If P2Pool doesn't have enough hashrate to find Monero blocks faster than every 6 hours on average (~15 MH/s), **not all your pool shares will result in a payout**. Even if pool hashrate is higher, bad luck can sometimes result in a share going through PPLNS window without a payout. But in the long run it will be compensated by other shares receiving multiple payouts - your payouts will average out to what you'd get with regular pool mining.
|
||||
|
||||
## Default P2Pool parameters
|
||||
|
||||
* Block time: 10 seconds
|
||||
* PPLNS window: 2160 blocks (6 hours)
|
||||
* Minimum payout = Monero block reward/2160, ~0.0003 XMR
|
||||
* PPLNS window: up to 2160 blocks (6 hours, auto adjustable to balance payout sizes and frequency)
|
||||
* Minimum payout = Monero block reward/2160, ~0.00027 XMR
|
||||
|
||||
## Monero version support
|
||||
|
||||
- The latest Monero network upgrade happened on August 13th, 2022 (block 2,688,888).
|
||||
- The latest P2Pool network upgrade happened on March 18th, 2023 at 21:00 UTC.
|
||||
|
||||
In order to continue mining on P2Pool, you must update both Monero and P2Pool software to the latest available versions as soon as they are released.
|
||||
|
||||
|Monero protocol version|Required Monero software version|Required P2Pool version
|
||||
|-|-|-|
|
||||
|v15, v16 (active after August 13th, 2022)|v0.18.0.0 or newer, v0.18.3.1 is recommended|v3.0 or newer
|
||||
|
||||
## How to mine on P2Pool
|
||||
|
||||
This guide assumes that you run everything on the same machine. If it's not the case, change `127.0.0.1` to appropriate IP addresses for your setup. It's highly recommended to create a new mainnet wallet for mining because **wallet addresses are public on p2pool**.
|
||||
### General Considerations
|
||||
|
||||
**Wallet software compatible with p2pool payouts**
|
||||
- Official Monero CLI and GUI v0.17.2.3 and newer
|
||||
- Monerujo v2.1.0 "Vertant" and newer
|
||||
- Cake Wallet v4.2.7 and newer
|
||||
- Feather Wallet v1.0.0 and newer
|
||||
- MyMonero
|
||||
- In order to mine on P2Pool, a synced Monero node using monerod v0.18.0.0 or newer is required. If you don't currently have one, you can download the official Monero binaries, start `monerod` on your PC and wait until it's fully synced. Advanced Monero node setup instructions are [here](https://sethforprivacy.com/guides/run-a-monero-node-advanced/).
|
||||
- It is highly recommended that you create a separate restricted user account (in your OS) for mining. While P2Pool has been battle-tested for a long time now, any software may have unknown bugs/vulnerabilities.
|
||||
- You have to use a primary wallet address (the one starting with `4`) for mining. Subaddresses and integrated addresses are not supported, just like with monerod solo mining.
|
||||
- You can add the `--mini` parameter to your P2Pool command to connect to the **p2pool-mini** sidechain. Note that it will also change the default p2p port from 37889 to 37888.
|
||||
- Check that ports 18080 (Monero p2p port) and 37889/37888 (P2Pool/P2Pool mini p2p port) are open in your firewall to ensure better connectivity. If you're mining from a computer behind NAT (like a router) you could consider forwarding the ports to your local machine.
|
||||
- You can connect multiple miners to the same P2Pool node. The more the better!
|
||||
- The steps below assume that you run everything on the same machine. If it's not the case, change `127.0.0.1` to appropriate IP addresses for your setup.
|
||||
- It is highly recommended to create a new mainnet wallet for P2Pool mining because **wallet addresses are public on P2Pool**.
|
||||
|
||||
**General Considerations**
|
||||
**Wallet software compatible with P2Pool payouts**
|
||||
- [Official Monero CLI and GUI v0.18.0.0 and newer](https://www.getmonero.org/downloads/)
|
||||
- [Monerujo v3.0.2 "Fluorine Fermi" and newer](https://www.monerujo.io/)
|
||||
- [Cake Wallet v4.4.5 and newer](https://cakewallet.com/)
|
||||
- [Monero.com by Cake Wallet](https://monero.com/)
|
||||
- [Feather Wallet v2.1.0 and newer](https://featherwallet.org/)
|
||||
- [MyMonero](https://mymonero.com/)
|
||||
|
||||
- Create a separate restricted user account for mining. p2pool is relatively new and may still have serious bugs/vulnerabilities!
|
||||
- You have to use the primary wallet address for mining. Subaddresses and integrated addresses are not supported, just like with monerod solo mining.
|
||||
- Check that ports 18080 (Monero p2p port) and 37889 (p2pool p2p port) are open in your firewall to ensure better connectivity. If you're mining from a computer behind NAT (like a router) you could consider forwarding the ports to your local machine.
|
||||
- You can connect multiple miners to the same p2pool node. The more the better!
|
||||
- Starting from p2pool v1.7, you can add `--mini` to p2pool command line to connect to the **p2pool-mini** sidechain. Note that it will also change the default p2p port from 37889 to 37888.
|
||||
### GUI for P2Pool
|
||||
|
||||
Step-by-step guide:
|
||||
- [Gupax](https://github.com/hinto-janai/gupax) project aims to provide an easy to use cross-platform GUI to configure and run P2Pool & [XMRig](https://github.com/xmrig/xmrig).
|
||||
|
||||
### GNU/Linux
|
||||
|
||||
- Download binaries from https://github.com/SChernykh/p2pool/releases/latest
|
||||
- Alternatively, grab the latest source code for p2pool and build it
|
||||
- Prepare enough huge pages (each of monerod/p2pool/xmrig needs them): `sudo sysctl vm.nr_hugepages=3072`
|
||||
- Get xmrig (linux-static-x64) binary from https://github.com/xmrig/xmrig/releases/latest
|
||||
- Check that ports 18080 (Monero p2p port) and 37889 (p2pool p2p port) are open in your firewall to ensure better connectivity
|
||||
- Use the `monerod` binary v0.17.3.0 or newer
|
||||
- Run `./monerod --zmq-pub tcp://127.0.0.1:18083 --disable-dns-checkpoints --enable-dns-blocklist` **don't forget --zmq-pub parameter in the command line**
|
||||
- Run `./p2pool --host 127.0.0.1 --wallet YOUR_WALLET_ADDRESS`
|
||||
- p2pool has verbose logging by default, you can reduce it by using "loglevel N" command where N is between 0 and 6. Default loglevel is 3.
|
||||
- You can use `logrotate` with a config like this to control logfile growth:
|
||||
```
|
||||
<path-to-logfile>
|
||||
{
|
||||
rotate 7
|
||||
daily
|
||||
missingok
|
||||
delaycompress
|
||||
nocreate
|
||||
}
|
||||
```
|
||||
- Wait until initial p2pool sync is finished, it shouldn't take more than 5-10 minutes, once completed xmrig should be able to connect to the stratum server on port 3333.
|
||||
- Run `./xmrig -o 127.0.0.1:3333`. Note that you don't need to specify wallet address for xmrig. **Wallet address set in xmrig config will be ignored!**
|
||||
- To set custom fixed difficulty for your miner (for example, 10000), run `./xmrig -u x+10000 -o 127.0.0.1:3333`
|
||||
- xmrig should connect and start mining
|
||||
- Also check p2pool.log for any warnings and errors: `grep -E 'WARNING|ERROR' p2pool.log`
|
||||
1. Download the latest P2Pool binaries [here](https://github.com/SChernykh/p2pool/releases/latest).
|
||||
- Alternatively, grab the latest source code for P2Pool and [build it](#build-instructions).
|
||||
2. Download the latest XMRig (linux-static-x64) binary [here](https://github.com/xmrig/xmrig/releases/latest).
|
||||
3. Prepare enough huge pages (each of monerod/P2Pool/XMRig needs them):
|
||||
```
|
||||
sudo sysctl vm.nr_hugepages=3072
|
||||
```
|
||||
4. Check that ports 18080 (Monero p2p port) and 37889/37888 (P2Pool/P2Pool mini p2p port) are open in your local firewall to ensure better connectivity.
|
||||
5. Start `monerod` with the following command/options:
|
||||
```
|
||||
./monerod --zmq-pub tcp://127.0.0.1:18083 --out-peers 32 --in-peers 64 --add-priority-node=p2pmd.xmrvsbeast.com:18080 --add-priority-node=nodes.hashvault.pro:18080 --disable-dns-checkpoints --enable-dns-blocklist
|
||||
```
|
||||
**Note:**
|
||||
The `--zmq-pub` option is required for P2Pool to work properly.
|
||||
|
||||
`--out-peers 32 --in-peers 64` is needed to (1) have many connections to other nodes and (2) limit incoming connection count because it can grow uncontrollably and cause problems when it goes above 1000 (open files limit in Linux). If your network connection's **upload** bandwidth is less than **10 Mbit**, use `--out-peers 8 --in-peers 16` instead.
|
||||
|
||||
`--add-priority-node=p2pmd.xmrvsbeast.com:18080 --add-priority-node=nodes.hashvault.pro:18080` is needed to have guaranteed good working nodes in your connected peers.
|
||||
|
||||
`--disable-dns-checkpoints` is needed to avoid periodical lags when DNS is updated (it's not needed when mining)
|
||||
|
||||
`--enable-dns-blocklist` is needed to ban known bad nodes
|
||||
|
||||
|
||||
6. Start P2Pool with the following command/options:
|
||||
```
|
||||
./p2pool --host 127.0.0.1 --wallet YOUR_WALLET_ADDRESS
|
||||
```
|
||||
7. Wait until the initial P2Pool sync is finished (shouldn't take more than 5-10 minutes).
|
||||
8. Start XMRig with the following command/options:
|
||||
```
|
||||
./xmrig -o 127.0.0.1:3333
|
||||
```
|
||||
- Note that you don't need to specify your wallet address for XMRig. **Wallet addresses set in XMRig config will be ignored!**
|
||||
- To set a custom fixed difficulty for your miner (for example, 10000), instead start XMRig with the following options:
|
||||
```
|
||||
./xmrig -u x+10000 -o 127.0.0.1:3333
|
||||
```
|
||||
9. XMRig should connect and start mining!
|
||||
|
||||
**Additional Information:**
|
||||
- For a more in-depth beginner friendly walk-through with the option of using Docker, please see SethForPrivacy's guide at: https://sethforprivacy.com/guides/run-a-p2pool-node/
|
||||
- You can check the p2pool.log for any warnings or errors using the following command:
|
||||
```
|
||||
grep -E 'WARNING|ERROR' p2pool.log
|
||||
```
|
||||
- P2Pool has verbose logging by default, you can reduce it by using "loglevel N" command where N is between 0 and 6. Default loglevel is 3.
|
||||
- You can use `logrotate` with a config like this to control logfile growth:
|
||||
```
|
||||
<path-to-logfile>
|
||||
{
|
||||
rotate 7
|
||||
daily
|
||||
missingok
|
||||
delaycompress
|
||||
nocreate
|
||||
}
|
||||
```
|
||||
|
||||
### Windows
|
||||
|
||||
*NOTE: Windows SmartScreen may block incoming connections by files that are "Downloaded from the Internet". You can allow 'p2pool.exe' and 'monerod.exe' by double-clicking them, clicking "More Info", then click "Run Anyway" and then closing them immediately so you can run them from the command line. Advanced users can use the PowerShell cmdlet `Unblock-File` to remove this flag.*
|
||||
**Note:** *Windows SmartScreen may block incoming connections by files that are "Downloaded from the Internet". You can allow 'p2pool.exe' and 'monerod.exe' by double-clicking them, clicking "More Info", then click "Run Anyway" and then closing them immediately so you can run them from the command line. Advanced users can use the PowerShell cmdlet `Unblock-File` to remove this flag.*
|
||||
|
||||
- Download p2pool binaries from https://github.com/SChernykh/p2pool/releases/latest
|
||||
- Download xmrig binary from https://github.com/xmrig/xmrig/releases/latest *(xmrig-6.15.2-gcc-win64.zip is the current version)*
|
||||
- Expand the p2pool binaries into an appropriate location (`%USERPROFILE%/bin` or `C:/bin/` are good options)
|
||||
- Expand xmrig binary into appropriate location (same folder as p2pool is fine)
|
||||
- Prepare huge pages (each of monerod/p2pool/xmrig needs them):
|
||||
- On Windows 10 or above, run xmrig at least once as Administrator (right-click Run As Administrator)
|
||||
- On earlier versions of Windows, you'll need to run it as admin at least once per login.
|
||||
- Open a command prompt and navigate to the folder where you extracted p2pool.
|
||||
- *When running these commands, Windows Firewall may prompt to allow connections, click "Allow"*
|
||||
- Run `.\Monero\monerod.exe --zmq-pub tcp://127.0.0.1:18083 --disable-dns-checkpoints --enable-dns-blocklist` *NOTE: don't forget --zmq-pub parameter in the command line*
|
||||
- Run `.\p2pool.exe --host 127.0.0.1 --wallet YOUR_WALLET_ADDRESS`
|
||||
- Wait until initial p2pool sync is finished, it shouldn't take more than 5-10 minutes, once completed xmrig should be able to connect to the stratum server on port 3333.
|
||||
- Run `.\xmrig.exe -o 127.0.0.1:3333`. Note that you don't need to specify wallet address for xmrig. **Wallet address set in xmrig config will be ignored!**
|
||||
- To set custom fixed difficulty for your miner (for example, 10000), run `xmrig.exe -u x+10000 -o 127.0.0.1:3333`
|
||||
- Windows Quickstart: Create a batch (.bat) file with the following contents and place it in your p2pool directory along with xmrig.exe.
|
||||
1. Download the latest P2Pool binaries [here](https://github.com/SChernykh/p2pool/releases/latest).
|
||||
- Alternatively, grab the latest source code for P2Pool and [build it](#build-instructions).
|
||||
2. Download the latest XMRig binary [here](https://github.com/xmrig/xmrig/releases/latest).
|
||||
3. Expand the P2Pool binaries into an appropriate location (`%USERPROFILE%/bin` or `C:/bin/` are good options)
|
||||
4. Expand XMRig binary into an appropriate location (the same folder as P2Pool is fine).
|
||||
5. Prepare huge pages to work properly (each of monerod/P2Pool/XMRig needs them):
|
||||
- On Windows 10 or above, run XMRig at least once as Administrator (right-click Run As Administrator)
|
||||
- On earlier versions of Windows, you'll need to run XMRig as Administrator at least once per login.
|
||||
6. Create "Monero" folder inside extracted P2Pool folder and copy Monero binaries there.
|
||||
7. Open a command prompt and navigate to the folder where you extracted P2Pool.
|
||||
|
||||
**Note:** *When running the below commands, Windows Firewall may prompt to allow connections, click "Allow" if prompted.*
|
||||
|
||||
8. Start `monerod` with the following command/options:
|
||||
```
|
||||
.\Monero\monerod.exe --zmq-pub tcp://127.0.0.1:18083 --out-peers 32 --in-peers 64 --add-priority-node=p2pmd.xmrvsbeast.com:18080 --add-priority-node=nodes.hashvault.pro:18080 --disable-dns-checkpoints --enable-dns-blocklist
|
||||
```
|
||||
**Note:**
|
||||
The `--zmq-pub` option is required for P2Pool to work properly.
|
||||
|
||||
`--out-peers 32 --in-peers 64` is needed to (1) have many connections to other nodes and (2) limit incoming connection count because it can grow uncontrollably and cause problems when it goes above 1000 (open files limit in Linux). If your network connection's **upload** bandwidth is less than **10 Mbit**, use `--out-peers 8 --in-peers 16` instead.
|
||||
|
||||
`--add-priority-node=p2pmd.xmrvsbeast.com:18080 --add-priority-node=nodes.hashvault.pro:18080` is needed to have guaranteed good working nodes in your connected peers.
|
||||
|
||||
`--disable-dns-checkpoints` is needed to avoid periodical lags when DNS is updated (it's not needed when mining)
|
||||
|
||||
`--enable-dns-blocklist` is needed to ban known bad nodes
|
||||
|
||||
9. Start P2Pool with the following command/options:
|
||||
```
|
||||
.\p2pool.exe --host 127.0.0.1 --wallet YOUR_WALLET_ADDRESS --mini
|
||||
```
|
||||
10. Wait until the initial P2Pool sync is finished (shouldn't take more than 5-10 minutes).
|
||||
11. Start XMRig with the following command/options:
|
||||
```
|
||||
.\xmrig.exe -o 127.0.0.1:3333
|
||||
```
|
||||
- Note that you don't need to specify your wallet address for XMRig. **Wallet addresses set in XMRig config will be ignored!**
|
||||
- To set a custom fixed difficulty for your miner (for example, 10000), instead start XMRig with the following options:
|
||||
```
|
||||
xmrig.exe -u x+10000 -o 127.0.0.1:3333
|
||||
```
|
||||
12. XMRig should connect and start mining!
|
||||
13. *(Optional but highly recommended)* You can create a Quickstart by creating a batch (.bat) file with the following contents and placing it in your P2Pool directory along with `xmrig.exe`.
|
||||
```
|
||||
@ECHO OFF
|
||||
start cmd /k %~dp0\Monero\monerod.exe --zmq-pub tcp://127.0.0.1:18083 --disable-dns-checkpoints --enable-dns-blocklist
|
||||
start cmd /k %~dp0\Monero\monerod.exe --zmq-pub tcp://127.0.0.1:18083 --out-peers 32 --in-peers 64 --add-priority-node=p2pmd.xmrvsbeast.com:18080 --add-priority-node=nodes.hashvault.pro:18080 --disable-dns-checkpoints --enable-dns-blocklist
|
||||
ECHO Wait until the Monero daemon shows fully synced before continuing. This can take some time. Type 'status' in other window to check progress.
|
||||
PAUSE
|
||||
start cmd /k %~dp0\p2pool.exe --wallet YOUR_WALLET_ADDRESS
|
||||
start cmd /k %~dp0\p2pool.exe --wallet YOUR_WALLET_ADDRESS --mini
|
||||
ECHO Wait until the daemon shows fully synced before continuing. This can take some time.
|
||||
PAUSE
|
||||
%~dp0\xmrig.exe -u x+30000 -o 127.0.0.1
|
||||
%~dp0\xmrig.exe -o 127.0.0.1
|
||||
```
|
||||
|
||||
## Build instructions
|
||||
Only 64-bit builds are supported, in particular ARMv7 or older CPUs are not supported. The reason is that RandomX hashing algorithm is too slow in 32-bit mode, and P2Pool needs to check new blocks very fast to keep up with other nodes.
|
||||
|
||||
Please see the relevant instructions for your platform:
|
||||
|
||||
### Ubuntu 20.04
|
||||
|
||||
p2pool binary:
|
||||
Run the following commands to install the necessary prerequisites, clone this repo, and build P2Pool locally on Ubuntu 20.04:
|
||||
```
|
||||
sudo apt update && sudo apt install git build-essential cmake libuv1-dev libzmq3-dev libsodium-dev libpgm-dev libnorm-dev libgss-dev
|
||||
sudo apt update && sudo apt install git build-essential cmake libuv1-dev libzmq3-dev libsodium-dev libpgm-dev libnorm-dev libgss-dev libcurl4-openssl-dev libidn2-0-dev
|
||||
git clone --recursive https://github.com/SChernykh/p2pool
|
||||
cd p2pool
|
||||
mkdir build && cd build
|
||||
@@ -145,13 +244,15 @@ cmake ..
|
||||
make -j$(nproc)
|
||||
```
|
||||
|
||||
### Arch Linux [AUR](https://wiki.archlinux.org/title/Arch_User_Repository)
|
||||
### [Arch Linux](https://archlinux.org/packages/extra/x86_64/p2pool/)
|
||||
|
||||
Make the package: [p2pool-git](https://aur.archlinux.org/packages/p2pool-git/)
|
||||
```
|
||||
pacman -S p2pool
|
||||
```
|
||||
|
||||
### [Nix/NixOS](https://nixos.org)
|
||||
|
||||
This is a flake only project. So you have to use [nixUnstable with nix flakes](https://nixos.wiki/wiki/Flakes) to build or install p2pool.
|
||||
This is a flake only project. So you have to use [nixUnstable with nix flakes](https://nixos.wiki/wiki/Flakes) to build or install P2Pool.
|
||||
The commands below use the new flake specific reference-format, so be sure to also set `ca-references` in `--experimental-features`.
|
||||
|
||||
Because this project has submodules which are not fixed in _nixUnstable_ yet you have to use the `nix/master` branch:
|
||||
@@ -161,29 +262,17 @@ nix shell github:nixos/nix/master
|
||||
|
||||
Run the binary:
|
||||
```
|
||||
nix run git+https://github.com/SChernykh/p2pool?ref=master
|
||||
nix run git+https://github.com/SChernykh/p2pool?ref=master&submodules=1
|
||||
```
|
||||
|
||||
Run the binary with arguments:
|
||||
```
|
||||
nix run git+https://github.com/SChernykh/p2pool?ref=master -- --help
|
||||
```
|
||||
|
||||
### macOS
|
||||
|
||||
p2pool binary:
|
||||
```
|
||||
brew update && brew install git cmake libuv zmq libpgm
|
||||
git clone --recursive https://github.com/SChernykh/p2pool
|
||||
cd p2pool
|
||||
mkdir build && cd build
|
||||
cmake ..
|
||||
make -j$(sysctl -n hw.logicalcpu)
|
||||
nix run git+https://github.com/SChernykh/p2pool?ref=master&submodules=1 -- --help
|
||||
```
|
||||
|
||||
### Windows
|
||||
|
||||
p2pool binary (Visual Studio Community 2019 build):
|
||||
P2Pool binary (Visual Studio Community 2019 build):
|
||||
*NOTE: You need to have the "Desktop Development with C++" module installed.*
|
||||
```
|
||||
git clone --recursive https://github.com/SChernykh/p2pool
|
||||
@@ -196,6 +285,41 @@ then open generated build\p2pool.sln in Visual Studio and build it there
|
||||
|
||||
Alternatively, you can select "Clone a repository" within the GUI, then select "Build" from the menu.
|
||||
|
||||
### macOS
|
||||
|
||||
Run the following commands to install the necessary prerequisites, clone this repo, and build P2Pool locally on your Mac:
|
||||
```
|
||||
brew update && brew install git cmake libuv zmq libpgm curl
|
||||
git clone --recursive https://github.com/SChernykh/p2pool
|
||||
cd p2pool
|
||||
mkdir build && cd build
|
||||
cmake ..
|
||||
make -j$(sysctl -n hw.logicalcpu)
|
||||
```
|
||||
|
||||
### FreeBSD
|
||||
|
||||
Run the following commands to install the necessary prerequisites, clone this repo, and build P2Pool locally on FreeBSD:
|
||||
```
|
||||
pkg install git cmake libuv libzmq4 curl
|
||||
git clone --recursive https://github.com/SChernykh/p2pool
|
||||
cd p2pool
|
||||
mkdir build && cd build
|
||||
cmake ..
|
||||
make
|
||||
```
|
||||
|
||||
### Android (Termux)
|
||||
|
||||
Run the following commands to install the necessary prerequisites, clone this repo, and build P2Pool locally in Termux:
|
||||
```
|
||||
pkg install git build-essential cmake libuv libzmq libcurl
|
||||
git clone --recursive https://github.com/SChernykh/p2pool
|
||||
cd p2pool
|
||||
mkdir build && cd build
|
||||
cmake ..
|
||||
make -j$(nproc)
|
||||
```
|
||||
|
||||
## Donations
|
||||
|
||||
|
||||
+83
-19
@@ -5,46 +5,110 @@ set(CMAKE_CXX_STANDARD 14)
|
||||
set(CMAKE_C_STANDARD 99)
|
||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||
|
||||
if(NOT ARCH_ID)
|
||||
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "")
|
||||
set(CMAKE_SYSTEM_PROCESSOR ${CMAKE_HOST_SYSTEM_PROCESSOR})
|
||||
endif()
|
||||
string(TOLOWER "${CMAKE_SYSTEM_PROCESSOR}" ARCH_ID)
|
||||
endif()
|
||||
|
||||
if (ARCH_ID MATCHES "^(aarch64|arm64|armv8-a)$")
|
||||
set(ARMv8 1)
|
||||
endif()
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES GNU)
|
||||
set(WARNING_FLAGS "-Wall -Wextra -Werror")
|
||||
set(OPTIMIZATION_FLAGS "-Ofast -s")
|
||||
set(GENERAL_FLAGS "-pthread")
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WARNING_FLAGS} ${OPTIMIZATION_FLAGS}")
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${WARNING_FLAGS} ${OPTIMIZATION_FLAGS}")
|
||||
if (ARMv8)
|
||||
set(GENERAL_FLAGS "${GENERAL_FLAGS} -mfix-cortex-a53-835769 -mfix-cortex-a53-843419")
|
||||
endif()
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNING_FLAGS} ${OPTIMIZATION_FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${WARNING_FLAGS} ${OPTIMIZATION_FLAGS}")
|
||||
if (DEV_WITH_TSAN)
|
||||
set(GENERAL_FLAGS "${GENERAL_FLAGS} -fno-omit-frame-pointer -fsanitize=thread")
|
||||
endif()
|
||||
|
||||
if (DEV_WITH_UBSAN)
|
||||
set(GENERAL_FLAGS "${GENERAL_FLAGS} -fno-omit-frame-pointer -fsanitize=undefined")
|
||||
endif()
|
||||
|
||||
if (DEV_WITH_ASAN)
|
||||
set(GENERAL_FLAGS "${GENERAL_FLAGS} -fno-omit-frame-pointer -fsanitize=address")
|
||||
endif()
|
||||
|
||||
set(WARNING_FLAGS "-Wall -Wextra -Wcast-qual -Wlogical-op -Wstrict-overflow=2 -Wundef -Wformat=2 -Wpointer-arith -Werror")
|
||||
|
||||
if (DEV_WITH_TSAN OR DEV_WITH_UBSAN OR DEV_WITH_ASAN)
|
||||
set(OPTIMIZATION_FLAGS "-O2 -g")
|
||||
else()
|
||||
set(OPTIMIZATION_FLAGS "-Ofast -s")
|
||||
endif()
|
||||
|
||||
if (WITH_LTO)
|
||||
set(OPTIMIZATION_FLAGS "${OPTIMIZATION_FLAGS} -flto -fuse-linker-plugin")
|
||||
endif()
|
||||
|
||||
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9)
|
||||
set(OPTIMIZATION_FLAGS "${OPTIMIZATION_FLAGS} -fno-associative-math")
|
||||
endif()
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${GENERAL_FLAGS} ${WARNING_FLAGS} ${OPTIMIZATION_FLAGS}")
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${GENERAL_FLAGS} ${WARNING_FLAGS} ${OPTIMIZATION_FLAGS}")
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GENERAL_FLAGS} ${WARNING_FLAGS} ${OPTIMIZATION_FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${GENERAL_FLAGS} ${WARNING_FLAGS} ${OPTIMIZATION_FLAGS}")
|
||||
|
||||
if (WIN32)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static")
|
||||
else()
|
||||
if (STATIC_LINUX_BINARY)
|
||||
if (STATIC_BINARY)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static")
|
||||
else()
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc -static-libstdc++")
|
||||
endif()
|
||||
endif()
|
||||
elseif (CMAKE_CXX_COMPILER_ID MATCHES MSVC)
|
||||
set(GENERAL_FLAGS "/MP /EHa")
|
||||
set(WARNING_FLAGS "/Wall /WX /sdl")
|
||||
set(SECURITY_FLAGS "/GS /guard:cf")
|
||||
set(OPTIMIZATION_FLAGS "/O2 /Oi /Ob2 /Ot /DNDEBUG /GL")
|
||||
|
||||
set(CMAKE_C_FLAGS_DEBUG "${WARNING_FLAGS} ${SECURITY_FLAGS} /Od /Ob0 /Zi /MTd /fsanitize=address")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${WARNING_FLAGS} ${SECURITY_FLAGS} /Od /Ob0 /Zi /MTd /fsanitize=address")
|
||||
set(CMAKE_C_FLAGS_DEBUG "${GENERAL_FLAGS} ${WARNING_FLAGS} ${SECURITY_FLAGS} /Od /Ob0 /Zi /MTd /fsanitize=address")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${GENERAL_FLAGS} ${WARNING_FLAGS} ${SECURITY_FLAGS} /Od /Ob0 /Zi /MTd /fsanitize=address")
|
||||
|
||||
set(CMAKE_C_FLAGS_RELEASE "${WARNING_FLAGS} ${SECURITY_FLAGS} ${OPTIMIZATION_FLAGS} /MT")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${WARNING_FLAGS} ${SECURITY_FLAGS} ${OPTIMIZATION_FLAGS} /MT")
|
||||
set(CMAKE_C_FLAGS_RELEASE "${GENERAL_FLAGS} ${WARNING_FLAGS} ${SECURITY_FLAGS} ${OPTIMIZATION_FLAGS} /MT")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${GENERAL_FLAGS} ${WARNING_FLAGS} ${SECURITY_FLAGS} ${OPTIMIZATION_FLAGS} /MT")
|
||||
|
||||
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${WARNING_FLAGS} ${SECURITY_FLAGS} /Ob1 /Ot /Zi /MT")
|
||||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${WARNING_FLAGS} ${SECURITY_FLAGS} /Ob1 /Ot /Zi /MT")
|
||||
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${GENERAL_FLAGS} ${WARNING_FLAGS} ${SECURITY_FLAGS} /Ob1 /Ot /Zi /MT")
|
||||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${GENERAL_FLAGS} ${WARNING_FLAGS} ${SECURITY_FLAGS} /Ob1 /Ot /Zi /MT")
|
||||
|
||||
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /LTCG")
|
||||
elseif (CMAKE_CXX_COMPILER_ID MATCHES Clang)
|
||||
set(WARNING_FLAGS "-Wall -Wextra -Wno-undefined-internal -Werror")
|
||||
set(OPTIMIZATION_FLAGS "-Ofast -funroll-loops -fmerge-all-constants")
|
||||
if (WIN32)
|
||||
set(GENERAL_FLAGS "")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static")
|
||||
else()
|
||||
set(GENERAL_FLAGS "-pthread")
|
||||
endif()
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WARNING_FLAGS} ${OPTIMIZATION_FLAGS}")
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${WARNING_FLAGS} ${OPTIMIZATION_FLAGS}")
|
||||
if (ARMv8)
|
||||
set(GENERAL_FLAGS "${GENERAL_FLAGS} -mfix-cortex-a53-835769")
|
||||
endif()
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNING_FLAGS} ${OPTIMIZATION_FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${WARNING_FLAGS} ${OPTIMIZATION_FLAGS}")
|
||||
set(WARNING_FLAGS "-Wall -Wextra -Wno-undefined-internal -Wunreachable-code-aggressive -Wmissing-prototypes -Wmissing-variable-declarations -Werror")
|
||||
|
||||
if (DEV_WITH_MSAN)
|
||||
set(OPTIMIZATION_FLAGS "-O2 -g")
|
||||
else()
|
||||
set(OPTIMIZATION_FLAGS "-Ofast -funroll-loops -fmerge-all-constants")
|
||||
endif()
|
||||
|
||||
if (WITH_LTO)
|
||||
set(OPTIMIZATION_FLAGS "${OPTIMIZATION_FLAGS} -flto")
|
||||
endif()
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${GENERAL_FLAGS} ${WARNING_FLAGS} ${OPTIMIZATION_FLAGS}")
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${GENERAL_FLAGS} ${WARNING_FLAGS} ${OPTIMIZATION_FLAGS}")
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GENERAL_FLAGS} ${WARNING_FLAGS} ${OPTIMIZATION_FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${GENERAL_FLAGS} ${WARNING_FLAGS} ${OPTIMIZATION_FLAGS}")
|
||||
endif()
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
// Fixed difficulty for miners that connect to your node must be set in their config.json
|
||||
//
|
||||
{
|
||||
"name": "mainnet test 2",
|
||||
"name": "default",
|
||||
"password": "",
|
||||
"block_time": 10,
|
||||
"min_diff": 100000,
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
../src/
|
||||
../external/src/
|
||||
../external/src/cryptonote/
|
||||
../external/src/libuv/
|
||||
../external/src/cppzmq/
|
||||
../external/src/libzmq/
|
||||
../external/src/llhttp/
|
||||
../external/src/RandomX/src/
|
||||
../external/src/rapidjson/include
|
||||
../external/src/robin-hood-hashing/src/include
|
||||
@@ -0,0 +1,15 @@
|
||||
import sys
|
||||
import json
|
||||
|
||||
f = open(sys.argv[1])
|
||||
data = json.load(f)
|
||||
f.close()
|
||||
|
||||
v = []
|
||||
for el in data:
|
||||
if not ("/external/" in el['file']):
|
||||
v.append(el)
|
||||
|
||||
f = open(sys.argv[1], 'w')
|
||||
json.dump(v, f, indent=2)
|
||||
f.close()
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
@echo off
|
||||
"C:\Program Files\cppcheck\cppcheck.exe" --project=..\build\p2pool.vcxproj --project-configuration="Release|x64" -DZMQ_STATIC --platform=win64 --std=c++14 --enable=all --inconclusive --inline-suppr --template="{file}:{line}:{id}{inconclusive: INCONCLUSIVE} {message}" --includes-file=includes.txt --suppressions-list=suppressions.txt --output-file=errors_full.txt
|
||||
"..\cppcheck-main\bin\cppcheck.exe" --project=..\build\p2pool.vcxproj --project-configuration="Release|x64" -DSIZE_MAX=UINT64_MAX -DRAPIDJSON_ENDIAN=RAPIDJSON_LITTLEENDIAN --platform=win64 --std=c++14 --enable=all --inconclusive --inline-suppr --template="{file}:{line}:{id}{inconclusive: INCONCLUSIVE} {message}" --suppressions-list=suppressions.txt --output-file=errors_full.txt --max-ctu-depth=3 --check-level=exhaustive
|
||||
findstr /V /C:"external\src" errors_full.txt > errors_filtered.txt
|
||||
for /f %%i in ("errors_filtered.txt") do set size=%%~zi
|
||||
if %size% gtr 0 (
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
cppcheck ../src -DZMQ_STATIC --platform=unix64 --std=c++14 --enable=all --inconclusive --inline-suppr --template="{file}:{line}:{id}{inconclusive: INCONCLUSIVE} {message}" -I ../src/ -I ../external/src/ -I ../external/src/cryptonote/ -I ../external/src/libuv/ -I ../external/src/cppzmq/ -I ../external/src/libzmq/ -I ../external/src/llhttp/ -I ../external/src/RandomX/src/ -I ../external/src/rapidjson/include -I ../external/src/robin-hood-hashing/src/include --suppressions-list=suppressions.txt --output-file=errors_full.txt
|
||||
grep -v 'external' errors_full.txt | grep -v 'unmatchedSuppression' > errors_filtered.txt
|
||||
../cppcheck-main/cppcheck --project=../build/compile_commands.json -DSIZE_MAX=UINT64_MAX -DRAPIDJSON_ENDIAN=RAPIDJSON_LITTLEENDIAN -D__SSE2__=1 --platform=unix64 --std=c++14 --enable=all --inconclusive --inline-suppr --template="{file}:{line}:{id}{inconclusive: INCONCLUSIVE} {message}" --suppressions-list=suppressions.txt --output-file=errors_full.txt --max-ctu-depth=3 --check-level=exhaustive
|
||||
grep -v 'external' errors_full.txt > errors_filtered.txt
|
||||
if [ -s errors_filtered.txt ]; then
|
||||
cat errors_filtered.txt
|
||||
exit 1
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
unmatchedSuppression
|
||||
missingIncludeSystem
|
||||
unusedFunction
|
||||
useStlAlgorithm
|
||||
functionStatic
|
||||
functionConst
|
||||
unmatchedSuppression
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
##
|
||||
# Monero Wallet Address for mining rewards (replace this with your own address)
|
||||
WALLET_ADDRESS="44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg"
|
||||
|
||||
##
|
||||
# p2pool settings
|
||||
#
|
||||
# Which port to listen for miner connections
|
||||
P2POOL_STRATUM_PORT=3333
|
||||
#
|
||||
# How much logging - (Less) 0 - 6 (More)
|
||||
P2POOL_LOGLEVEL=2
|
||||
#
|
||||
# The name of docker volume to hold p2pool data (created automatically if it doesnt exist)
|
||||
P2POOL_VOLUME=p2pool
|
||||
|
||||
|
||||
##
|
||||
# Monero Node Settings
|
||||
#
|
||||
# Version of Monero to build. Must be v0.17.3.0 or later for p2pool support. "latest" pulls the most recent release tag
|
||||
MONERO_GIT_TAG=latest
|
||||
#
|
||||
# Limit the size of the blockchain on disk (comment to disable)
|
||||
PRUNE_NODE="--prune-blockchain"
|
||||
#
|
||||
# The name of docker volume to hold p2pool data (created automatically if it doesnt exist)
|
||||
MONERO_VOLUME=monero
|
||||
|
||||
|
||||
##
|
||||
# Xmrig Miner Settings
|
||||
#
|
||||
# Submit shares at a lower fixed difficulty to show mining progress (comment to disable, edit to customize)
|
||||
FIXED_MINING_DIFFICULTY="-u x+500000"
|
||||
#
|
||||
# Limit the number of CPU cores to use for mining (uncomment to enable, edit to customize)
|
||||
#NUM_MINING_CPU="-t 4"
|
||||
+21
-13
@@ -8,6 +8,8 @@ Run your own <b>Monero Node + P2Pool + XMRig</b> in Docker
|
||||
[Install Docker](https://docs.docker.com/engine/install/)
|
||||
[Install Docker Compose](https://docs.docker.com/compose/install/)
|
||||
|
||||
Note: The docker compose plugin uses the command "docker compose" while the pip installed command is "docker-compose".
|
||||
|
||||
#### Clone the P2Pool project
|
||||
```
|
||||
git clone --recursive https://github.com/SChernykh/p2pool
|
||||
@@ -16,34 +18,40 @@ git clone --recursive https://github.com/SChernykh/p2pool
|
||||
#### Configure your Monero address for mining rewards
|
||||
```
|
||||
cd p2pool/docker-compose
|
||||
vi .env
|
||||
./configure
|
||||
```
|
||||
**WALLET_ADDRESS** is the only setting that needs to be updated in that file
|
||||
Make sure to set your own monero **Wallet Address**. The default is to donate mining to P2Pool development.
|
||||
|
||||
#### Build the docker containers
|
||||
```
|
||||
docker-compose build
|
||||
docker compose build --no-cache
|
||||
```
|
||||
|
||||
#### Run the node, pool, and CPU miner
|
||||
#### Run the node, pool, and CPU miner (or updated configuration)
|
||||
```
|
||||
docker-compose up
|
||||
docker compose up
|
||||
```
|
||||
|
||||
#### Optional
|
||||
* Open ports 18080 (Monero p2p port) and 37889 (P2Pool p2p port) in your firewall to ensure better connectivity. If you're mining from a computer behind NAT (like a router) you could consider forwarding the ports to your local machine
|
||||
* An XMRig CPU miner is included by default, but you can connect additional miners to this same p2pool node using port 3333
|
||||
* Open ports 18080 (Monero p2p port) and 37889 (P2Pool p2p port) or 37888 (P2Pool-mini p2p port) in your firewall to ensure better connectivity. If you're mining from a computer behind NAT (like a router) you could consider forwarding the ports to your local machine
|
||||
* An XMRig CPU miner is included by default, but you can connect additional miners to this same p2pool node using port 3333 (or alternate if configured) when you set it as "exposed" in the configuration
|
||||
* Configure your kernel for maximum mining performance: [XMRig RandomX Optimization Guide](https://xmrig.com/docs/miner/randomx-optimization-guide)
|
||||
* Many optional configurations and customizations are available by running './configure'
|
||||
|
||||
|
||||
#### Other usefull commands
|
||||
* You can **run everythng in the background** by adding the "-d" argument to the "docker-compose up" command: ```docker-compose up -d```
|
||||
* You can **stop everything** with CTRL-C or ```docker-compose down```
|
||||
* You can see logs when running in the background for with the "docker logs" command: ```docker logs -f p2pool-xmrig``` or ```docker logs -f p2pool-p2pool``` or ```docker logs -f p2pool-monero```
|
||||
* You can **run everything in the background** by adding the "-d" argument to the "docker compose up" command: ```docker compose up -d```
|
||||
* You can **stop everything** with CTRL-C or ```docker compose down```
|
||||
* You can **update** by building new images with the ```--no-cache``` option. Example: ```docker compose build --no-cache``` or just update Monero with: ```docker compose build --no-cache monero``` followed by ```docker compose up```
|
||||
* You can see logs when running in the background for with the "docker compose logs" command: ```docker compose logs -f```
|
||||
* You can pause mining with: ```docker compose pause xmrig``` and resume mining with: ```docker compose unpause xmrig```
|
||||
* You can disable mining with: ```docker compose stop xmrig``` and re-enable mining with: ```docker compose start xmrig```
|
||||
* You can view your Server Statistics using a web browser if you enabled that feature in the configuration at: http://localhost:3380 (or alternate port as configured)
|
||||
|
||||
|
||||
#### Uninstall
|
||||
Change to p2pool/docker-compose directory
|
||||
Stop and remove all containers: ```docker-compose down```
|
||||
Remove the p2pool data: ```docker volume rm p2pool```
|
||||
Change to p2pool/docker-compose directory <br />
|
||||
Stop and remove all containers: ```docker compose down``` <br />
|
||||
Remove the p2pool data: ```docker volume rm p2pool``` <br />
|
||||
Remove the p2pool-mini data: ```docker volume rm p2pool-mini``` <br />
|
||||
Remove the monero data: ```docker volume rm monero```
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
FROM python:3.10.5-bullseye
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
ADD requirements.txt /app/
|
||||
RUN /usr/local/bin/pip3 install -r requirements.txt
|
||||
|
||||
ADD configure.py /app/
|
||||
ADD defaults /app/
|
||||
ADD current_config.jinja2 /app/
|
||||
ADD docker-compose.jinja2 /app/
|
||||
|
||||
ENTRYPOINT ["/usr/local/bin/python3"]
|
||||
CMD ["/app/configure.py"]
|
||||
Executable
+951
@@ -0,0 +1,951 @@
|
||||
#!/bin/env python3
|
||||
import sys
|
||||
import time
|
||||
import json
|
||||
from jinja2 import Template
|
||||
import npyscreen
|
||||
|
||||
# Help text in a box at the bottom of the screen
|
||||
class HelpBoxBase(npyscreen.BoxTitle):
|
||||
def splitlines(self):
|
||||
all_help = []
|
||||
for fld, msg in self.help_msgs.items():
|
||||
if fld[-1] != ":":
|
||||
fld += ":"
|
||||
message = [m.lstrip() for m in msg if m != ""]
|
||||
helpline = f"{fld:<28}{'. '.join(message)}"
|
||||
all_help.append(helpline)
|
||||
all_help.append("")
|
||||
return all_help
|
||||
|
||||
def display_help_message(self, field):
|
||||
self.set_values(
|
||||
self.help_msgs.get(field, "No help availabe for {}".format(field))
|
||||
)
|
||||
self.clear()
|
||||
self.display()
|
||||
|
||||
|
||||
class P2PoolHelpBox(HelpBoxBase):
|
||||
help_msgs = {
|
||||
"Wallet Address:": [
|
||||
"Your monero wallet address for receiving mining reqards",
|
||||
"",
|
||||
"Note: You have to use a primary wallet address for mining",
|
||||
" Subaddresses and integrated addresses are not supported!",
|
||||
],
|
||||
"P2Pool Sidechain:": [
|
||||
"Which P2Pool sidechain to mine on",
|
||||
" use main for faster miners",
|
||||
" use mini for slower miners",
|
||||
],
|
||||
"Enable Server Statistics": [
|
||||
"Provide access to your P2Pool server statictics via a web interface",
|
||||
],
|
||||
"Statistics Port:": [
|
||||
"Port number (or IP:Port) to expose web access to your P2Pool server",
|
||||
"statictics",
|
||||
],
|
||||
"Expose Stratum Port": [
|
||||
"Expose the P2Pool stratum port to your network so external miners",
|
||||
"can connect",
|
||||
"Note: You may choose to open this port in your hosts firewall and/or",
|
||||
" router to allow miners outside your network to connect",
|
||||
],
|
||||
"Stratum Port:": [
|
||||
"Port number (or IP:Port) to expose P2Pool stratum to your network to",
|
||||
"allow external miners to connect",
|
||||
"Note: You may choose to open this port in your hosts firewall and/or",
|
||||
" router to allow miners outside your network to connect",
|
||||
],
|
||||
"P2Pool Log Level:": [
|
||||
"Verbosity of the log; (Less) 0 - 6 (More)",
|
||||
],
|
||||
"Enable Autodiff": [
|
||||
"Use automatic difficulty adjustment for miners connected to stratum",
|
||||
],
|
||||
"Enable Light Mode": [
|
||||
"Don't allocate RandomX dataset, saves 2GB of RAM",
|
||||
],
|
||||
"Disable Cache": [
|
||||
"Disable p2pool.cache (not recommended)",
|
||||
],
|
||||
"Additional P2Pool Options:": [
|
||||
"Additional options to pass to p2pool commandline",
|
||||
"",
|
||||
"Note: Advanced - Only add options if you know what you are doing",
|
||||
" See ouput of 'p2pool --help' for available options",
|
||||
],
|
||||
"Next": [
|
||||
"Next configuration menu",
|
||||
],
|
||||
"Save": [
|
||||
"Save current configuration and exit",
|
||||
],
|
||||
"Cancel": [
|
||||
"Exit without saving",
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
class MoneroHelpBox(HelpBoxBase):
|
||||
help_msgs = {
|
||||
"Configure Monero Node": [
|
||||
"Configure and run a Monero Node",
|
||||
"",
|
||||
"Note: You must either configure a local node or specify a public node",
|
||||
],
|
||||
"Monero Version:": [
|
||||
"Version of Monero to build; 'latest' for the most recent release",
|
||||
"",
|
||||
"Note: Must be v0.17.3.0 or later for p2pool support",
|
||||
" See: https://github.com/monero-project/monero/tags",
|
||||
],
|
||||
"Prune Blockchain": [
|
||||
"Prune the Monero node to limit the size of the blockchain on disk",
|
||||
],
|
||||
"Monero Log Level:": [
|
||||
"Verbosity of the log; (Less) 0 - 4 (More)",
|
||||
"",
|
||||
"Note: settings above 0 are very noisy",
|
||||
],
|
||||
"Expose RPC Port": [
|
||||
"Expose restricted RPC API port to your network so external services",
|
||||
"(wallets for example) can connect. Port 18083 (ZMQ-pub) will also be exposed.",
|
||||
"Note: You may choose to open this port in your hosts firewall and/or",
|
||||
" router to allow services outside your network to connect",
|
||||
],
|
||||
"RPC Port:": [
|
||||
"TCP port to listen on for RPC connections",
|
||||
],
|
||||
"RPC Login:": [
|
||||
"Specify username[:password] required to connect to the RPC API",
|
||||
],
|
||||
"Limit Data Rates": [
|
||||
"Set a limit value for incoming and outgoing data transfer",
|
||||
],
|
||||
"Rate Limit Up:": [
|
||||
"Set outgoing data transfer limit [kB/s]",
|
||||
],
|
||||
"Rate Limit Down:": [
|
||||
"Set incoming data transfer limit [kB/s]",
|
||||
],
|
||||
"Sync Pruned Blocks": [
|
||||
"Accept pruned blocks instead of pruning yourself to save",
|
||||
"network transfer",
|
||||
],
|
||||
"Fast Block Sync": [
|
||||
'Sync up most of the way by using embedded, "known" (old) block',
|
||||
"hashes without calculating the block hash to verify the proof of work",
|
||||
"",
|
||||
"Note: Faster initial sync by trusting the monerod binary",
|
||||
],
|
||||
"Public Node:": [
|
||||
"Public Monero Node to Use",
|
||||
"",
|
||||
"Note: The public node must have both Monero RPC and zmq-pub ports",
|
||||
" available",
|
||||
],
|
||||
"Node Login:": [
|
||||
"Specify username[:password] required to connect to public monero",
|
||||
"node RPC API (if required)",
|
||||
],
|
||||
"Additional monerod Options:": [
|
||||
"Additional options to pass to monerod commandline",
|
||||
"",
|
||||
"Note: Advanced - Only add options if you know what you are doing",
|
||||
" See 'https://monerodocs.org/interacting/monerod-reference/'",
|
||||
],
|
||||
"Prev": [
|
||||
"Previous configuration menu",
|
||||
],
|
||||
"Next": [
|
||||
"Next configuration menu",
|
||||
],
|
||||
"Save": [
|
||||
"Save current configuration and exit",
|
||||
],
|
||||
"Cancel": [
|
||||
"Exit without saving",
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
class XMRigHelpBox(HelpBoxBase):
|
||||
help_msgs = {
|
||||
"Configure XMRig CPU Miner": [
|
||||
"Configure and run an XMRig CPU Miner",
|
||||
"",
|
||||
"Note: You must either configure am XMRig CPU Miner or expose the",
|
||||
" P2Pool stratum port and connect an external miner, or both",
|
||||
],
|
||||
"Username:": [
|
||||
"Set a username for the miner",
|
||||
],
|
||||
"Use Fixed Difficulty": [
|
||||
"Used a fixed minig difficulty",
|
||||
"",
|
||||
"Note: Allows you to see XMRig submitting shares below P2Pool threshold",
|
||||
],
|
||||
"Fixed Difficulty:": [
|
||||
"Set a fixed mining difficulty",
|
||||
"",
|
||||
"Note: Allows you to see XMRig submitting shares below P2Pool threshold",
|
||||
],
|
||||
"CPU Use %:": [
|
||||
"Maximum CPU threads count (in percentage) hint for autoconfig",
|
||||
"Note: Applies to cores only. If you have HyperThreading enabled you",
|
||||
" should divide this value by 2 (use 0-50%). Reference:",
|
||||
" https://github.com/xmrig/xmrig/issues/1670#issuecomment-644433778",
|
||||
],
|
||||
"CPU Priority:": [
|
||||
"Set process priority (0 idle, 2 normal to 5 highest)",
|
||||
],
|
||||
"Additional XMRig Options:": [
|
||||
"Additional options to pass to xmrig",
|
||||
"",
|
||||
"Note: Advanced - Only add options if you know what you are doing",
|
||||
" See 'https://xmrig.com/docs/miner/command-line-options'",
|
||||
],
|
||||
"Prev": [
|
||||
"Previous configuration menu",
|
||||
],
|
||||
"Save": [
|
||||
"Save current configuration and exit",
|
||||
],
|
||||
"Cancel": [
|
||||
"Exit without saving",
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
##
|
||||
# Custom (integer) values for title slider
|
||||
class IntegerSlider(npyscreen.Slider):
|
||||
def translate_value(self):
|
||||
from_val = int(str(self.value).split(".")[0])
|
||||
out_of_val = int(str(self.out_of).split(".")[0])
|
||||
if from_val >= 1000:
|
||||
from_val = str(from_val / 1000).split(".")[0] + "K"
|
||||
out_of_val = str(out_of_val / 1000).split(".")[0] + "K"
|
||||
return "{}/{}".format(from_val, out_of_val)
|
||||
|
||||
|
||||
class TitleIntegerSlider(npyscreen.TitleSlider):
|
||||
_entry_type = IntegerSlider
|
||||
|
||||
|
||||
##
|
||||
# Patched updateDependents for FormControlCheckbox
|
||||
class PatchedFormControlCheckbox(npyscreen.FormControlCheckbox):
|
||||
def updateDependents(self):
|
||||
if self.value:
|
||||
for w in self._visibleWhenSelected:
|
||||
try:
|
||||
w.fc_visible
|
||||
except AttributeError:
|
||||
w.fc_visible = {}
|
||||
w.fc_visible[self.name] = True
|
||||
for w in self._notVisibleWhenSelected:
|
||||
try:
|
||||
w.fc_visible
|
||||
except AttributeError:
|
||||
w.fc_visible = {}
|
||||
w.fc_visible[self.name] = False
|
||||
else:
|
||||
for w in self._visibleWhenSelected:
|
||||
try:
|
||||
w.fc_visible
|
||||
except AttributeError:
|
||||
w.fc_visible = {}
|
||||
w.fc_visible[self.name] = False
|
||||
for w in self._notVisibleWhenSelected:
|
||||
try:
|
||||
w.fc_visible
|
||||
except AttributeError:
|
||||
w.fc_visible = {}
|
||||
w.fc_visible[self.name] = True
|
||||
for w in self._visibleWhenSelected + self._notVisibleWhenSelected:
|
||||
w.hidden = False in w.fc_visible.values()
|
||||
w.editable = not False in w.fc_visible.values()
|
||||
self.parent.display()
|
||||
|
||||
def set_value(self, value):
|
||||
self.value = value
|
||||
self.display()
|
||||
|
||||
def display(self):
|
||||
self.updateDependents()
|
||||
super()
|
||||
|
||||
|
||||
class PrevButton(npyscreen.Button):
|
||||
def whenToggled(self):
|
||||
self.value = False
|
||||
self.parent.prev_form()
|
||||
|
||||
|
||||
class NextButton(npyscreen.Button):
|
||||
def whenToggled(self):
|
||||
self.value = False
|
||||
self.parent.next_form()
|
||||
|
||||
|
||||
class SaveButton(npyscreen.Button):
|
||||
def whenToggled(self):
|
||||
self.find_parent_app().save_and_exit()
|
||||
|
||||
|
||||
class CancelButton(npyscreen.Button):
|
||||
def whenToggled(self):
|
||||
self.find_parent_app().cancel_and_exit()
|
||||
|
||||
|
||||
##
|
||||
# Config Forms Base Class
|
||||
class ConfigFormBase(npyscreen.FormBaseNew):
|
||||
name_size = 20
|
||||
indent = 5
|
||||
current_config = None
|
||||
defaults = None
|
||||
ALLOW_RESIZE = False
|
||||
|
||||
def while_editing(self, arg):
|
||||
self.help.display_help_message(arg.name)
|
||||
self.display()
|
||||
|
||||
def get_default_config(self):
|
||||
# Return defaults
|
||||
if self.defaults is None:
|
||||
with open("defaults") as defaults_file:
|
||||
self.defaults = json.load(defaults_file)
|
||||
return self.defaults
|
||||
|
||||
def get_current_config(self):
|
||||
# Return current config
|
||||
if self.current_config is None:
|
||||
# Read current config
|
||||
with open("/docker-compose/current_config") as current_config:
|
||||
self.current_config = json.load(current_config)
|
||||
return self.current_config
|
||||
|
||||
def reset_defaults(self, arg):
|
||||
# Set config to default values
|
||||
ok = npyscreen.notify_ok_cancel(
|
||||
"Set current form values to defaults", title="Reset to Defaults"
|
||||
)
|
||||
if not ok:
|
||||
return
|
||||
defaults = self.get_default_config()
|
||||
self.set_config(defaults)
|
||||
|
||||
|
||||
##
|
||||
# P2Pool Configuration Form
|
||||
class P2PoolConfigForm(ConfigFormBase):
|
||||
def create(self):
|
||||
# Add Hot-Key Controls
|
||||
self.add_handlers({"^D": self.reset_defaults})
|
||||
# Add P2Pool Configuration
|
||||
self.add(
|
||||
npyscreen.TitleText,
|
||||
name="## P2Pool Configuration",
|
||||
editable=False,
|
||||
begin_entry_at=50,
|
||||
)
|
||||
self.wallet_address = self.add(
|
||||
npyscreen.TitleText,
|
||||
name="Wallet Address:",
|
||||
value="",
|
||||
begin_entry_at=self.name_size,
|
||||
relx=self.indent,
|
||||
)
|
||||
self.nextrely += 1
|
||||
self.sidechain = self.add(
|
||||
npyscreen.TitleSelectOne,
|
||||
name="P2Pool Sidechain:",
|
||||
values=["main", "mini"],
|
||||
scroll_exit=True,
|
||||
max_height=2,
|
||||
value=[
|
||||
0,
|
||||
],
|
||||
begin_entry_at=self.name_size,
|
||||
relx=self.indent,
|
||||
)
|
||||
self.nextrely += 1
|
||||
self.enable_statistics = self.add(
|
||||
PatchedFormControlCheckbox,
|
||||
name="Enable Server Statistics",
|
||||
value=True,
|
||||
begin_entry_at=self.name_size,
|
||||
relx=self.indent,
|
||||
)
|
||||
self.statistics_port = self.add(
|
||||
npyscreen.TitleText,
|
||||
name="Statistics Port:",
|
||||
value="3334",
|
||||
begin_entry_at=self.name_size,
|
||||
relx=self.indent,
|
||||
)
|
||||
self.enable_statistics.addVisibleWhenSelected(self.statistics_port)
|
||||
self.nextrely += 1
|
||||
self.expose_stratum_port = self.add(
|
||||
PatchedFormControlCheckbox,
|
||||
name="Expose Stratum Port",
|
||||
value=True,
|
||||
begin_entry_at=self.name_size,
|
||||
relx=self.indent,
|
||||
)
|
||||
self.stratum_port = self.add(
|
||||
npyscreen.TitleText,
|
||||
name="Stratum Port:",
|
||||
value="3333",
|
||||
begin_entry_at=self.name_size,
|
||||
relx=self.indent,
|
||||
)
|
||||
self.expose_stratum_port.addVisibleWhenSelected(self.stratum_port)
|
||||
self.nextrely += 1
|
||||
self.p2pool_log_level = self.add(
|
||||
TitleIntegerSlider,
|
||||
name="P2Pool Log Level:",
|
||||
out_of=6,
|
||||
value=3,
|
||||
lowest=0,
|
||||
step=1,
|
||||
width=43,
|
||||
begin_entry_at=20,
|
||||
label=True,
|
||||
block_color=None,
|
||||
relx=self.indent,
|
||||
)
|
||||
self.nextrely += 1
|
||||
self.autodiff = self.add(
|
||||
PatchedFormControlCheckbox,
|
||||
name="Enable Autodiff",
|
||||
value=True,
|
||||
begin_entry_at=self.name_size,
|
||||
relx=self.indent,
|
||||
)
|
||||
self.nextrely += 1
|
||||
self.light_mode = self.add(
|
||||
PatchedFormControlCheckbox,
|
||||
name="Enable Light Mode",
|
||||
value=False,
|
||||
begin_entry_at=self.name_size,
|
||||
relx=self.indent,
|
||||
)
|
||||
self.nextrely += 1
|
||||
self.no_cache = self.add(
|
||||
npyscreen.Checkbox,
|
||||
name="Disable Cache",
|
||||
value=False,
|
||||
begin_entry_at=self.name_size,
|
||||
relx=self.indent,
|
||||
)
|
||||
self.nextrely += 1
|
||||
self.p2pool_extra = self.add(
|
||||
npyscreen.TitleText,
|
||||
name="Additional P2Pool Options:",
|
||||
value="",
|
||||
begin_entry_at=self.name_size + 10,
|
||||
relx=self.indent,
|
||||
)
|
||||
self.nextrely += 1
|
||||
self.nextrely += 1
|
||||
# Add "Next", "Save", and "Cancel" buttons
|
||||
self.next_button = self.add(NextButton, name="Next", relx=1)
|
||||
self.nextrely -= 1
|
||||
self.save_button = self.add(SaveButton, name="Save", relx=8)
|
||||
self.nextrely -= 1
|
||||
self.cancel_button = self.add(CancelButton, name="Cancel", relx=15)
|
||||
self.nextrely += 1
|
||||
# Add Help Box
|
||||
self.help = self.add(
|
||||
P2PoolHelpBox,
|
||||
name="Commands: ^D: Load Defaults - ^C: Exit Without Saving",
|
||||
values=[""],
|
||||
editable=False,
|
||||
)
|
||||
# Start with current config
|
||||
self.set_config(self.get_current_config())
|
||||
|
||||
def next_form(self):
|
||||
self.find_parent_app().switchForm("MONERO")
|
||||
|
||||
def set_config(self, config):
|
||||
self.wallet_address.set_value(config["wallet_address"])
|
||||
self.sidechain.set_value(config["sidechain"])
|
||||
self.enable_statistics.set_value(config["enable_statistics"])
|
||||
self.statistics_port.set_value(config["statistics_port"])
|
||||
self.expose_stratum_port.set_value(config["expose_stratum_port"])
|
||||
self.stratum_port.set_value(config["stratum_port"])
|
||||
self.p2pool_log_level.set_value(config["p2pool_log_level"])
|
||||
self.autodiff.set_value(config["enable_autodiff"])
|
||||
self.light_mode.set_value(config["light_mode"])
|
||||
self.no_cache.value = config["no_cache"]
|
||||
self.p2pool_extra.set_value(config["p2pool_options"])
|
||||
self.DISPLAY()
|
||||
|
||||
def get_config(self):
|
||||
config = {
|
||||
"wallet_address": self.wallet_address.value,
|
||||
"sidechain": self.sidechain.value,
|
||||
"enable_statistics": self.enable_statistics.value,
|
||||
"statistics_port": self.statistics_port.value,
|
||||
"expose_stratum_port": self.expose_stratum_port.value,
|
||||
"stratum_port": self.stratum_port.value,
|
||||
"p2pool_log_level": self.p2pool_log_level.value,
|
||||
"enable_autodiff": self.autodiff.value,
|
||||
"light_mode": self.light_mode.value,
|
||||
"no_cache": self.no_cache.value,
|
||||
"p2pool_options": self.p2pool_extra.value,
|
||||
}
|
||||
return config
|
||||
|
||||
|
||||
##
|
||||
# Monero Configuration Form
|
||||
class MoneroConfigForm(ConfigFormBase):
|
||||
def create(self):
|
||||
# Add Hot-Key Controls
|
||||
self.add_handlers({"^D": self.reset_defaults})
|
||||
# Add Monero Configuration
|
||||
self.add(
|
||||
npyscreen.TitleText,
|
||||
name="## Monero Node Configuration",
|
||||
editable=False,
|
||||
begin_entry_at=50,
|
||||
)
|
||||
self.configure_monero_node = self.add(
|
||||
PatchedFormControlCheckbox,
|
||||
name="Configure Monero Node",
|
||||
value=True,
|
||||
relx=self.indent,
|
||||
)
|
||||
self.nextrely += 1
|
||||
self.monero_git_tag = self.add(
|
||||
npyscreen.TitleText,
|
||||
name="Monero Version:",
|
||||
value="latest",
|
||||
begin_entry_at=self.name_size,
|
||||
relx=self.indent,
|
||||
)
|
||||
self.configure_monero_node.addVisibleWhenSelected(self.monero_git_tag)
|
||||
self.prune_node = self.add(
|
||||
PatchedFormControlCheckbox,
|
||||
name="Prune Blockchain",
|
||||
value=True,
|
||||
begin_entry_at=self.name_size,
|
||||
relx=self.indent,
|
||||
)
|
||||
self.configure_monero_node.addVisibleWhenSelected(self.prune_node)
|
||||
self.monero_log_level = self.add(
|
||||
TitleIntegerSlider,
|
||||
name="Monero Log Level:",
|
||||
out_of=4,
|
||||
value=0,
|
||||
lowest=0,
|
||||
step=1,
|
||||
width=43,
|
||||
begin_entry_at=20,
|
||||
label=True,
|
||||
block_color=None,
|
||||
relx=self.indent,
|
||||
)
|
||||
self.configure_monero_node.addVisibleWhenSelected(self.monero_log_level)
|
||||
self.nextrely += 1
|
||||
self.expose_rpc_port = self.add(
|
||||
PatchedFormControlCheckbox,
|
||||
name="Expose RPC Port",
|
||||
value=False,
|
||||
relx=self.indent,
|
||||
)
|
||||
self.configure_monero_node.addVisibleWhenSelected(self.expose_rpc_port)
|
||||
self.rpc_port = self.add(
|
||||
npyscreen.TitleText,
|
||||
name="RPC Port:",
|
||||
value="18081",
|
||||
begin_entry_at=self.name_size,
|
||||
relx=self.indent,
|
||||
)
|
||||
self.configure_monero_node.addVisibleWhenSelected(self.rpc_port)
|
||||
self.expose_rpc_port.addVisibleWhenSelected(self.rpc_port)
|
||||
self.rpc_login = self.add(
|
||||
npyscreen.TitleText,
|
||||
name="RPC Login:",
|
||||
value="",
|
||||
begin_entry_at=self.name_size,
|
||||
relx=self.indent,
|
||||
)
|
||||
self.expose_rpc_port.addVisibleWhenSelected(self.rpc_login)
|
||||
self.configure_monero_node.addVisibleWhenSelected(self.rpc_login)
|
||||
self.nextrely += 1
|
||||
self.limit_data_rates = self.add(
|
||||
PatchedFormControlCheckbox,
|
||||
name="Limit Data Rates",
|
||||
value=False,
|
||||
begin_entry_at=self.name_size,
|
||||
relx=self.indent,
|
||||
)
|
||||
self.configure_monero_node.addVisibleWhenSelected(self.limit_data_rates)
|
||||
self.rate_limit_up = self.add(
|
||||
npyscreen.TitleText,
|
||||
name="Rate Limit Up:",
|
||||
value="2048",
|
||||
begin_entry_at=self.name_size,
|
||||
relx=self.indent,
|
||||
)
|
||||
self.limit_data_rates.addVisibleWhenSelected(self.rate_limit_up)
|
||||
self.configure_monero_node.addVisibleWhenSelected(self.rate_limit_up)
|
||||
self.rate_limit_down = self.add(
|
||||
npyscreen.TitleText,
|
||||
name="Rate Limit Down:",
|
||||
value="8192",
|
||||
begin_entry_at=self.name_size,
|
||||
relx=self.indent,
|
||||
)
|
||||
self.limit_data_rates.addVisibleWhenSelected(self.rate_limit_down)
|
||||
self.configure_monero_node.addVisibleWhenSelected(self.rate_limit_down)
|
||||
self.nextrely += 1
|
||||
self.sync_pruned_blocks = self.add(
|
||||
npyscreen.Checkbox,
|
||||
name="Sync Pruned Blocks",
|
||||
value=False,
|
||||
begin_entry_at=self.name_size,
|
||||
relx=self.indent,
|
||||
)
|
||||
self.configure_monero_node.addVisibleWhenSelected(self.sync_pruned_blocks)
|
||||
self.prune_node.addVisibleWhenSelected(self.sync_pruned_blocks)
|
||||
self.fast_sync = self.add(
|
||||
npyscreen.Checkbox,
|
||||
name="Fast Block Sync",
|
||||
value=True,
|
||||
begin_entry_at=self.name_size,
|
||||
relx=self.indent,
|
||||
)
|
||||
self.configure_monero_node.addVisibleWhenSelected(self.fast_sync)
|
||||
self.nextrely += 1
|
||||
self.public_node = self.add(
|
||||
npyscreen.TitleText,
|
||||
name="Public Node:",
|
||||
value="",
|
||||
begin_entry_at=self.name_size,
|
||||
relx=self.indent,
|
||||
)
|
||||
self.configure_monero_node.addInvisibleWhenSelected(self.public_node)
|
||||
self.node_login = self.add(
|
||||
npyscreen.TitleText,
|
||||
name="Node Login:",
|
||||
value="",
|
||||
begin_entry_at=self.name_size,
|
||||
relx=self.indent,
|
||||
)
|
||||
self.configure_monero_node.addInvisibleWhenSelected(self.node_login)
|
||||
self.nextrely += 1
|
||||
self.monero_extra = self.add(
|
||||
npyscreen.TitleText,
|
||||
name="Additional monerod Options:",
|
||||
value="",
|
||||
begin_entry_at=self.name_size + 10,
|
||||
relx=self.indent,
|
||||
)
|
||||
self.configure_monero_node.addVisibleWhenSelected(self.monero_extra)
|
||||
self.nextrely += 1
|
||||
self.nextrely += 1
|
||||
# Add "Prev", "Next", "Save", and "Cancel" buttons
|
||||
self.prev_button = self.add(PrevButton, name="Prev", relx=1)
|
||||
self.nextrely -= 1
|
||||
self.next_button = self.add(NextButton, name="Next", relx=8)
|
||||
self.nextrely -= 1
|
||||
self.save_button = self.add(SaveButton, name="Save", relx=15)
|
||||
self.nextrely -= 1
|
||||
self.cancel_button = self.add(CancelButton, name="Cancel", relx=22)
|
||||
self.nextrely += 1
|
||||
# Add Help Box
|
||||
self.help = self.add(
|
||||
MoneroHelpBox,
|
||||
name="Commands: ^D: Load Defaults - ^C: Exit Without Saving",
|
||||
values=[""],
|
||||
editable=False,
|
||||
)
|
||||
# Start with current config
|
||||
self.set_config(self.get_current_config())
|
||||
|
||||
def prev_form(self):
|
||||
self.find_parent_app().switchForm("MAIN")
|
||||
|
||||
def next_form(self):
|
||||
self.find_parent_app().switchForm("XMRIG")
|
||||
|
||||
def set_config(self, config):
|
||||
self.configure_monero_node.set_value(config["configure_monero"])
|
||||
self.monero_git_tag.set_value(config["monero_version"])
|
||||
self.prune_node.value = config["prune_blockchain"]
|
||||
self.monero_log_level.set_value(config["monero_log_level"])
|
||||
self.expose_rpc_port.set_value(config["expose_rpc_port"])
|
||||
self.rpc_port.set_value(config["rpc_port"])
|
||||
self.rpc_login.set_value(config["rpc_login"])
|
||||
self.limit_data_rates.set_value(config["limit_data_rates"])
|
||||
self.rate_limit_up.set_value(config["rate_limit_up"])
|
||||
self.rate_limit_down.set_value(config["rate_limit_down"])
|
||||
self.sync_pruned_blocks.value = config["sync_pruned_blocks"]
|
||||
self.fast_sync.value = config["fast_sync"]
|
||||
self.monero_extra.set_value(config["monero_options"])
|
||||
self.public_node.set_value(config["public_monero_node"])
|
||||
self.node_login.set_value(config["monero_node_login"])
|
||||
self.DISPLAY()
|
||||
|
||||
def get_config(self):
|
||||
config = {
|
||||
"configure_monero": self.configure_monero_node.value,
|
||||
"monero_version": self.monero_git_tag.value,
|
||||
"prune_blockchain": self.prune_node.value,
|
||||
"monero_log_level": self.monero_log_level.value,
|
||||
"expose_rpc_port": self.expose_rpc_port.value,
|
||||
"rpc_port": self.rpc_port.value,
|
||||
"rpc_login": self.rpc_login.value,
|
||||
"limit_data_rates": self.limit_data_rates.value,
|
||||
"rate_limit_up": self.rate_limit_up.value,
|
||||
"rate_limit_down": self.rate_limit_down.value,
|
||||
"sync_pruned_blocks": self.sync_pruned_blocks.value,
|
||||
"fast_sync": self.fast_sync.value,
|
||||
"monero_options": self.monero_extra.value,
|
||||
"public_monero_node": self.public_node.value,
|
||||
"monero_node_login": self.node_login.value,
|
||||
}
|
||||
return config
|
||||
|
||||
|
||||
##
|
||||
# XMRig Configuration Form
|
||||
class XMRigConfigForm(ConfigFormBase):
|
||||
def create(self):
|
||||
# Add Hot-Key Controls
|
||||
self.add_handlers({"^D": self.reset_defaults})
|
||||
# Hidden caryover from P2Pool form
|
||||
self.autodiff = self.add(
|
||||
PatchedFormControlCheckbox,
|
||||
name="Enable Autodiff",
|
||||
value=True,
|
||||
begin_entry_at=self.name_size,
|
||||
relx=self.indent,
|
||||
)
|
||||
self.autodiff.hide = True
|
||||
self.autodiff.editable = False
|
||||
self.nextrely -= 1
|
||||
# Add XMRig Configuration
|
||||
self.add(
|
||||
npyscreen.TitleText,
|
||||
name="## XMRig Miner Configuration",
|
||||
editable=False,
|
||||
begin_entry_at=50,
|
||||
)
|
||||
self.configure_xmrig_miner = self.add(
|
||||
PatchedFormControlCheckbox,
|
||||
name="Configure XMRig CPU Miner",
|
||||
value=True,
|
||||
relx=self.indent,
|
||||
)
|
||||
self.nextrely += 1
|
||||
self.username = self.add(
|
||||
npyscreen.TitleText,
|
||||
name="Username:",
|
||||
value="",
|
||||
begin_entry_at=self.name_size,
|
||||
relx=self.indent,
|
||||
)
|
||||
self.configure_xmrig_miner.addVisibleWhenSelected(self.username)
|
||||
self.nextrely += 1
|
||||
self.use_fixed_difficulty = self.add(
|
||||
PatchedFormControlCheckbox,
|
||||
name="Use Fixed Difficulty",
|
||||
value=True,
|
||||
relx=self.indent,
|
||||
)
|
||||
self.configure_xmrig_miner.addVisibleWhenSelected(self.use_fixed_difficulty)
|
||||
self.autodiff.addInvisibleWhenSelected(self.use_fixed_difficulty)
|
||||
self.fixed_difficulty = self.add(
|
||||
TitleIntegerSlider,
|
||||
name="Fixed Difficulty:",
|
||||
out_of=2000000,
|
||||
value=500000,
|
||||
lowest=50000,
|
||||
step=50000,
|
||||
width=51,
|
||||
begin_entry_at=20,
|
||||
label=True,
|
||||
relx=self.indent,
|
||||
)
|
||||
self.configure_xmrig_miner.addVisibleWhenSelected(self.fixed_difficulty)
|
||||
self.use_fixed_difficulty.addVisibleWhenSelected(self.fixed_difficulty)
|
||||
self.autodiff.addInvisibleWhenSelected(self.fixed_difficulty)
|
||||
self.nextrely += 1
|
||||
self.cpu_threads = self.add(
|
||||
TitleIntegerSlider,
|
||||
name="CPU Use %:",
|
||||
out_of=100,
|
||||
value=100,
|
||||
lowest=1,
|
||||
step=10,
|
||||
width=48,
|
||||
begin_entry_at=20,
|
||||
label=True,
|
||||
relx=self.indent,
|
||||
)
|
||||
self.configure_xmrig_miner.addVisibleWhenSelected(self.cpu_threads)
|
||||
self.nextrely += 1
|
||||
self.cpu_priority = self.add(
|
||||
TitleIntegerSlider,
|
||||
name="CPU Priority:",
|
||||
out_of=5,
|
||||
value=2,
|
||||
lowest=0,
|
||||
step=1,
|
||||
width=48,
|
||||
begin_entry_at=20,
|
||||
label=True,
|
||||
relx=self.indent,
|
||||
)
|
||||
self.configure_xmrig_miner.addVisibleWhenSelected(self.cpu_priority)
|
||||
self.nextrely += 1
|
||||
self.xmrig_extra = self.add(
|
||||
npyscreen.TitleText,
|
||||
name="Additional XMRig Options:",
|
||||
value="",
|
||||
begin_entry_at=self.name_size + 10,
|
||||
relx=self.indent,
|
||||
)
|
||||
self.configure_xmrig_miner.addVisibleWhenSelected(self.xmrig_extra)
|
||||
self.nextrely += 1
|
||||
self.nextrely += 1
|
||||
# Add "Prev", "Save", and "Cancel" buttons
|
||||
self.prev_button = self.add(PrevButton, name="Prev", relx=1)
|
||||
self.nextrely -= 1
|
||||
self.save_button = self.add(SaveButton, name="Save", relx=8)
|
||||
self.nextrely -= 1
|
||||
self.cancel_button = self.add(CancelButton, name="Cancel", relx=15)
|
||||
self.nextrely += 1
|
||||
# Add Help Box
|
||||
self.help = self.add(
|
||||
XMRigHelpBox,
|
||||
name="Commands: ^D: Load Defaults - ^C: Exit Without Saving",
|
||||
values=[""],
|
||||
editable=False,
|
||||
)
|
||||
# Start with current config
|
||||
self.set_config(self.get_current_config())
|
||||
|
||||
def prev_form(self):
|
||||
self.find_parent_app().switchForm("MONERO")
|
||||
|
||||
def next_form(self):
|
||||
self.find_parent_app().switchForm(None)
|
||||
|
||||
def beforeEditing(self):
|
||||
# Cary autodiff value from P2Pool config form
|
||||
enable_autodiff = self.find_parent_app().get_p2pool_config()["enable_autodiff"]
|
||||
self.autodiff.set_value(enable_autodiff)
|
||||
|
||||
def set_config(self, config):
|
||||
self.configure_xmrig_miner.set_value(config["configure_xmrig"])
|
||||
self.username.set_value(config["xmrig_username"])
|
||||
self.use_fixed_difficulty.set_value(config["use_fixed_difficulty"])
|
||||
self.fixed_difficulty.set_value(config["fixed_difficulty"])
|
||||
self.cpu_threads.set_value(config["cpu_percent"])
|
||||
self.cpu_priority.set_value(config["cpu_priority"])
|
||||
self.xmrig_extra.set_value(config["xmrig_options"])
|
||||
self.DISPLAY()
|
||||
|
||||
def get_config(self):
|
||||
config = {
|
||||
"configure_xmrig": self.configure_xmrig_miner.value,
|
||||
"xmrig_username": self.username.value,
|
||||
"use_fixed_difficulty": self.use_fixed_difficulty.value,
|
||||
"fixed_difficulty": self.fixed_difficulty.value,
|
||||
"cpu_percent": self.cpu_threads.value,
|
||||
"cpu_priority": self.cpu_priority.value,
|
||||
"xmrig_options": self.xmrig_extra.value,
|
||||
}
|
||||
return config
|
||||
|
||||
|
||||
##
|
||||
# Our P2Pool configuration App
|
||||
class ConfigApp(npyscreen.NPSAppManaged):
|
||||
current_config = None
|
||||
defaults = None
|
||||
|
||||
def onStart(self):
|
||||
self.p2pool_form = self.addForm(
|
||||
"MAIN",
|
||||
P2PoolConfigForm,
|
||||
name="P2Pool for docker-compose: P2Pool Configuration",
|
||||
minimum_lines=35,
|
||||
minimum_columns=80,
|
||||
)
|
||||
self.monero_form = self.addForm(
|
||||
"MONERO",
|
||||
MoneroConfigForm,
|
||||
name="P2Pool for docker-compose: Monero Configuration",
|
||||
minimum_lines=35,
|
||||
minimum_columns=80,
|
||||
)
|
||||
self.xmrig_form = self.addForm(
|
||||
"XMRIG",
|
||||
XMRigConfigForm,
|
||||
name="P2Pool for docker-compose: XMRig Configuration",
|
||||
minimum_lines=35,
|
||||
minimum_columns=80,
|
||||
)
|
||||
|
||||
def get_p2pool_config(self):
|
||||
return self.p2pool_form.get_config()
|
||||
|
||||
def get_config(self):
|
||||
p2pool_config = self.p2pool_form.get_config()
|
||||
monero_config = self.monero_form.get_config()
|
||||
xmrig_config = self.xmrig_form.get_config()
|
||||
return p2pool_config | monero_config | xmrig_config
|
||||
|
||||
def save_and_exit(self):
|
||||
# Get config from all forms
|
||||
config = self.get_config()
|
||||
# Save "current config" values file
|
||||
with open("current_config.jinja2", "r") as current_config:
|
||||
template = current_config.read()
|
||||
rendered = Template(template).render(config)
|
||||
with open("/docker-compose/current_config", "w") as current_config:
|
||||
current_config.write(rendered)
|
||||
# Render and save docker-compose file
|
||||
with open("docker-compose.jinja2", "r") as compose_file:
|
||||
template = compose_file.read()
|
||||
rendered = Template(template).render(config, trim_blocks=True)
|
||||
with open("/docker-compose/docker-compose.yml", "w") as compose_file:
|
||||
compose_file.write(rendered)
|
||||
npyscreen.notify("Saved current settings", title="Saved")
|
||||
self.switchForm(None)
|
||||
self.saved = True
|
||||
|
||||
def cancel_and_exit(self):
|
||||
self.switchForm(None)
|
||||
self.saved = False
|
||||
|
||||
|
||||
##
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
time.sleep(1) # Give docker a second to initialize the terminal
|
||||
App = ConfigApp()
|
||||
App.run()
|
||||
print("\n\n")
|
||||
if App.saved:
|
||||
print("Configuration Saved")
|
||||
else:
|
||||
print("Configuration Aborted")
|
||||
sys.exit(1)
|
||||
except KeyboardInterrupt:
|
||||
print("Configuration Aborted")
|
||||
sys.exit(1)
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"wallet_address": {{ wallet_address | tojson(indent=2) }},
|
||||
"configure_monero": {{ configure_monero | tojson(indent=2) }},
|
||||
"configure_xmrig": {{ configure_xmrig | tojson(indent=2) }},
|
||||
"sidechain": {{ sidechain | tojson(indent=2) }},
|
||||
"enable_statistics": {{ enable_statistics | tojson(indent=2) }},
|
||||
"statistics_port": {{ statistics_port | tojson(indent=2) }},
|
||||
"expose_stratum_port": {{ expose_stratum_port | tojson(indent=2) }},
|
||||
"stratum_port": {{ stratum_port | tojson(indent=2) }},
|
||||
"p2pool_log_level": {{ p2pool_log_level | int | tojson(indent=2) }},
|
||||
"enable_autodiff": {{ enable_autodiff | tojson(indent=2) }},
|
||||
"light_mode": {{ light_mode | tojson(indent=2) }},
|
||||
"no_cache": {{ no_cache | tojson(indent=2) }},
|
||||
"p2pool_options": {{ p2pool_options | tojson(indent=2) }},
|
||||
"monero_version": {{ monero_version | tojson(indent=2) }},
|
||||
"prune_blockchain": {{ prune_blockchain | tojson(indent=2) }},
|
||||
"monero_log_level": {{ monero_log_level | int | tojson(indent=2) }},
|
||||
"expose_rpc_port": {{ expose_rpc_port | tojson(indent=2) }},
|
||||
"rpc_port": {{ rpc_port | tojson(indent=2) }},
|
||||
"rpc_login": {{ rpc_login | tojson(indent=2) }},
|
||||
"limit_data_rates": {{ limit_data_rates | tojson(indent=2) }},
|
||||
"rate_limit_up": {{ rate_limit_up | tojson(indent=2) }},
|
||||
"rate_limit_down": {{ rate_limit_down | tojson(indent=2) }},
|
||||
"sync_pruned_blocks": {{ sync_pruned_blocks | tojson(indent=2) }},
|
||||
"fast_sync": {{ fast_sync | tojson(indent=2) }},
|
||||
"monero_options": {{ monero_options | tojson(indent=2) }},
|
||||
"public_monero_node": {{ public_monero_node | tojson(indent=2) }},
|
||||
"monero_node_login": {{ monero_node_login | tojson(indent=2) }},
|
||||
"xmrig_username": {{ xmrig_username | tojson(indent=2) }},
|
||||
"use_fixed_difficulty": {{ use_fixed_difficulty | tojson(indent=2) }},
|
||||
"fixed_difficulty": {{ fixed_difficulty | int | tojson(indent=2) }},
|
||||
"cpu_percent": {{ cpu_percent | int | tojson(indent=2) }},
|
||||
"cpu_priority": {{ cpu_priority | int | tojson(indent=2) }},
|
||||
"xmrig_options": {{ xmrig_options | tojson(indent=2) }}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"wallet_address": "44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg",
|
||||
"configure_monero": true,
|
||||
"configure_xmrig": true,
|
||||
"sidechain": [0],
|
||||
"enable_statistics": true,
|
||||
"statistics_port": "3380",
|
||||
"expose_stratum_port": false,
|
||||
"stratum_port": "3333",
|
||||
"p2pool_log_level": 3,
|
||||
"enable_autodiff": true,
|
||||
"light_mode": false,
|
||||
"no_cache": false,
|
||||
"p2pool_options": "",
|
||||
"monero_version": "latest",
|
||||
"prune_blockchain": true,
|
||||
"monero_log_level": 0,
|
||||
"expose_rpc_port": false,
|
||||
"rpc_port": "18081",
|
||||
"rpc_login": "",
|
||||
"limit_data_rates": false,
|
||||
"rate_limit_up": "2048",
|
||||
"rate_limit_down": "8192",
|
||||
"sync_pruned_blocks": false,
|
||||
"fast_sync": true,
|
||||
"monero_options": "",
|
||||
"public_monero_node": "",
|
||||
"monero_node_login": "",
|
||||
"xmrig_username": "p2pool",
|
||||
"use_fixed_difficulty": true,
|
||||
"fixed_difficulty": 500000,
|
||||
"cpu_percent": 100,
|
||||
"cpu_priority": 2,
|
||||
"xmrig_options": ""
|
||||
}
|
||||
@@ -0,0 +1,187 @@
|
||||
---
|
||||
version: '3.4'
|
||||
|
||||
networks:
|
||||
p2pool:
|
||||
driver: bridge
|
||||
|
||||
volumes:
|
||||
p2pool:
|
||||
{% if sidechain[0] == 0 %}
|
||||
name: p2pool
|
||||
{% else %}
|
||||
name: p2pool-mini
|
||||
{% endif %}
|
||||
|
||||
{% if configure_monero == True %}
|
||||
monero:
|
||||
name: monero
|
||||
{% endif %}
|
||||
|
||||
services:
|
||||
p2pool:
|
||||
image: p2pool:latest
|
||||
build: ../
|
||||
container_name: p2pool-p2pool
|
||||
networks:
|
||||
- p2pool
|
||||
privileged: true
|
||||
ports:
|
||||
{% if sidechain[0] == 0 %}
|
||||
- 37888:37888/tcp
|
||||
{% else %}
|
||||
- 37889:37889/tcp
|
||||
{% endif %}
|
||||
{% if expose_stratum_port == True %}
|
||||
- {{ stratum_port }}:3333/tcp
|
||||
{% endif %}
|
||||
volumes:
|
||||
- p2pool:/home/p2pool/.p2pool:rw
|
||||
- /dev/null:/home/p2pool/.p2pool/p2pool.log:rw
|
||||
- /dev/hugepages:/dev/hugepages:rw
|
||||
{% if configure_monero == True %}
|
||||
depends_on:
|
||||
- monero
|
||||
{% endif %}
|
||||
restart: unless-stopped
|
||||
command: >-
|
||||
{% if configure_monero == True %}
|
||||
--host monero
|
||||
{% else %}
|
||||
--host {{ public_monero_node }}
|
||||
--rpc-login {{ monero_node_login }}
|
||||
{% endif %}
|
||||
--wallet {{ wallet_address }}
|
||||
--loglevel {{ p2pool_log_level | int }}
|
||||
{% if sidechain[0] == 1 %}
|
||||
--mini
|
||||
{% endif %}
|
||||
{% if enable_autodiff == False %}
|
||||
--no-autodiff
|
||||
{% endif %}
|
||||
{% if enable_statistics == True %}
|
||||
--local-api
|
||||
--data-api /home/p2pool/.p2pool
|
||||
{% endif %}
|
||||
{% if light_mode == True %}
|
||||
--light-mode
|
||||
{% endif %}
|
||||
{% if no_cache == True %}
|
||||
--no-cache
|
||||
{% endif %}
|
||||
{% if rpc_login != "" %}
|
||||
--rpc-login {{ rpc_login }}
|
||||
{% endif %}
|
||||
{% if p2pool_options != "" %}
|
||||
{{ p2pool_options }}
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% if enable_statistics == True %}
|
||||
statistics:
|
||||
image: statistics:latest
|
||||
build:
|
||||
context: statistics
|
||||
container_name: p2pool-statistics
|
||||
networks:
|
||||
- p2pool
|
||||
ports:
|
||||
- {{ statistics_port }}:80/tcp
|
||||
volumes:
|
||||
- p2pool:/data:ro
|
||||
depends_on:
|
||||
- p2pool
|
||||
restart: unless-stopped
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% if configure_monero == True %}
|
||||
monero:
|
||||
image: monero:latest
|
||||
build:
|
||||
context: monero
|
||||
args:
|
||||
- MONERO_GIT_TAG={{ monero_version }}
|
||||
container_name: p2pool-monero
|
||||
networks:
|
||||
- p2pool
|
||||
ports:
|
||||
- 18080:18080/tcp
|
||||
{% if expose_rpc_port == True %}
|
||||
- {{ rpc_port }}:18081/tcp
|
||||
- 18083:18083/tcp
|
||||
{% endif %}
|
||||
volumes:
|
||||
- monero:/home/monero/.bitmonero:rw
|
||||
- /dev/null:/home/monero/.bitmonero/bitmonero.log:rw
|
||||
- /dev/hugepages:/dev/hugepages:rw
|
||||
restart: unless-stopped
|
||||
command: >-
|
||||
--zmq-pub tcp://0.0.0.0:18083
|
||||
--disable-dns-checkpoints
|
||||
--enable-dns-blocklist
|
||||
--out-peers 16
|
||||
--in-peers 32
|
||||
--add-priority-node=nodes.hashvault.pro:18080
|
||||
--add-priority-node=p2pmd.xmrvsbeast.com:18080
|
||||
--non-interactive
|
||||
--p2p-bind-ip=0.0.0.0
|
||||
--p2p-bind-port=18080
|
||||
--rpc-bind-ip=0.0.0.0
|
||||
--rpc-bind-port=18081
|
||||
--restricted-rpc
|
||||
--confirm-external-bind
|
||||
--log-level={{ monero_log_level | int }}
|
||||
{% if prune_blockchain == True %}
|
||||
--prune-blockchain
|
||||
{% if sync_pruned_blocks == True %}
|
||||
--sync-pruned-blocks
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if rpc_login != "" %}
|
||||
--rpc-login {{ rpc_login }}
|
||||
{% endif %}
|
||||
{% if limit_data_rates == True %}
|
||||
--limit-rate-up {{ rate_limit_up }}
|
||||
--limit-rate-down {{ rate_limit_down }}
|
||||
{% endif %}
|
||||
{% if fast_sync == True %}
|
||||
--fast-block-sync=1
|
||||
{% else %}
|
||||
--fast-block-sync=0
|
||||
{% endif %}
|
||||
{% if monero_options != "" %}
|
||||
{{ monero_options }}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% if configure_xmrig == True %}
|
||||
xmrig:
|
||||
image: xmrig:latest
|
||||
build: xmrig
|
||||
container_name: p2pool-xmrig
|
||||
networks:
|
||||
- p2pool
|
||||
privileged: true
|
||||
volumes:
|
||||
- /dev:/dev:ro
|
||||
- /lib/modules:/lib/modules:ro
|
||||
- /dev/hugepages:/dev/hugepages:rw
|
||||
depends_on:
|
||||
- p2pool
|
||||
restart: unless-stopped
|
||||
command: >-
|
||||
--randomx-1gb-pages
|
||||
-o p2pool:3333
|
||||
{% if enable_autodiff == False and use_fixed_difficulty == True %}
|
||||
-u {{ xmrig_username }}+{{ fixed_difficulty | int }}
|
||||
{% else %}
|
||||
-u {{ xmrig_username }}
|
||||
{% endif %}
|
||||
--cpu-max-threads-hint={{ cpu_percent | int }}
|
||||
--cpu-priority={{ cpu_priority | int }}
|
||||
{% if xmrig_options != "" %}
|
||||
{{ xmrig_options }}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
@@ -0,0 +1,3 @@
|
||||
npyscreen==4.10.5
|
||||
MarkupSafe==2.0.1
|
||||
jinja2==2.11.3
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
#!/bin/bash
|
||||
echo ""
|
||||
echo ""
|
||||
echo "Verifying Requirements:"
|
||||
DOCKER_VER=$(docker version -f "{{.Server.Version}}" 2> /dev/null)
|
||||
if [ -z "$DOCKER_VER" ]; then
|
||||
echo "Docker not found; install it: https://docs.docker.com/engine/install/"
|
||||
exit 1
|
||||
fi
|
||||
if [ "$(echo "$DOCKER_VER"| cut -d'.' -f 1)" -ge 19 ] && \
|
||||
[ "$(echo "$DOCKER_VER"| cut -d'.' -f 2)" -ge 0 ] && \
|
||||
[ "$(echo "$DOCKER_VER"| cut -d'.' -f 3)" -ge 3 ]; then
|
||||
echo "Docker Found; OK"
|
||||
else
|
||||
echo "Docker version less than 19.0.3; upgrade it: https://docs.docker.com/engine/install/"
|
||||
exit 1
|
||||
fi
|
||||
docker compose version 2>&1 > /dev/null
|
||||
COMPOSE_PLUGIN_RC=$?
|
||||
docker-compose --version 2>&1 > /dev/null
|
||||
COMPOSE_CLI_RC=$?
|
||||
if [ "$COMPOSE_PLUGIN_RC" -eq 0 ] || [ "$COMPOSE_CLI_RC" -eq 0 ]; then
|
||||
echo "Docker Compose found; OK"
|
||||
if [ "$COMPOSE_PLUGIN_RC" -eq 0 ]; then
|
||||
COMPOSE_COMMAND="docker compose"
|
||||
else
|
||||
COMPOSE_COMMAND="docker-compose"
|
||||
fi
|
||||
else
|
||||
echo "Docker Compose not found; install it: https://docs.docker.com/compose/install/compose-plugin/"
|
||||
exit 1
|
||||
fi
|
||||
echo ""
|
||||
echo ""
|
||||
echo "Building and Running P2Pool docker-compose Configuration"
|
||||
docker build -t p2pool_config:latest cfg
|
||||
docker run -it --rm -v $PWD:/docker-compose --user $(id -u):$(id -g) p2pool_config:latest
|
||||
CONFIGURE_RC=$?
|
||||
echo ""
|
||||
echo ""
|
||||
if [ "$CONFIGURE_RC" -eq 0 ]; then
|
||||
echo "P2Pool is configured. Start the project with: $COMPOSE_COMMAND up --build -d"
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"wallet_address": "44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg",
|
||||
"configure_monero": true,
|
||||
"configure_xmrig": true,
|
||||
"sidechain": [
|
||||
0
|
||||
],
|
||||
"enable_statistics": true,
|
||||
"statistics_port": "3380",
|
||||
"expose_stratum_port": false,
|
||||
"stratum_port": "3333",
|
||||
"p2pool_log_level": 3,
|
||||
"enable_autodiff": true,
|
||||
"light_mode": false,
|
||||
"no_cache": false,
|
||||
"p2pool_options": "",
|
||||
"monero_version": "latest",
|
||||
"prune_blockchain": true,
|
||||
"monero_log_level": 0,
|
||||
"expose_rpc_port": false,
|
||||
"rpc_port": "18081",
|
||||
"rpc_login": "",
|
||||
"limit_data_rates": false,
|
||||
"rate_limit_up": "2048",
|
||||
"rate_limit_down": "8192",
|
||||
"sync_pruned_blocks": false,
|
||||
"fast_sync": true,
|
||||
"monero_options": "",
|
||||
"public_monero_node": "",
|
||||
"monero_node_login": "",
|
||||
"xmrig_username": "p2pool",
|
||||
"use_fixed_difficulty": true,
|
||||
"fixed_difficulty": 500000,
|
||||
"cpu_percent": 100,
|
||||
"cpu_priority": 2,
|
||||
"xmrig_options": ""
|
||||
}
|
||||
@@ -7,22 +7,86 @@ networks:
|
||||
|
||||
volumes:
|
||||
p2pool:
|
||||
name: ${P2POOL_VOLUME}
|
||||
|
||||
name: p2pool
|
||||
|
||||
|
||||
|
||||
monero:
|
||||
name: ${MONERO_VOLUME}
|
||||
name: monero
|
||||
|
||||
|
||||
services:
|
||||
p2pool:
|
||||
image: p2pool:latest
|
||||
build: ../
|
||||
container_name: p2pool-p2pool
|
||||
networks:
|
||||
- p2pool
|
||||
privileged: true
|
||||
ports:
|
||||
|
||||
- 37888:37888/tcp
|
||||
|
||||
|
||||
volumes:
|
||||
- p2pool:/home/p2pool/.p2pool:rw
|
||||
- /dev/null:/home/p2pool/.p2pool/p2pool.log:rw
|
||||
- /dev/hugepages:/dev/hugepages:rw
|
||||
|
||||
depends_on:
|
||||
- monero
|
||||
|
||||
restart: unless-stopped
|
||||
command: >-
|
||||
|
||||
--host monero
|
||||
|
||||
--wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg
|
||||
--loglevel 3
|
||||
|
||||
|
||||
|
||||
--local-api
|
||||
--data-api /home/p2pool/.p2pool
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
statistics:
|
||||
image: statistics:latest
|
||||
build:
|
||||
context: statistics
|
||||
container_name: p2pool-statistics
|
||||
networks:
|
||||
- p2pool
|
||||
ports:
|
||||
- 3380:80/tcp
|
||||
volumes:
|
||||
- p2pool:/data:ro
|
||||
depends_on:
|
||||
- p2pool
|
||||
restart: unless-stopped
|
||||
|
||||
|
||||
|
||||
|
||||
monero:
|
||||
image: monero:latest
|
||||
build:
|
||||
context: monero
|
||||
args:
|
||||
- MONERO_GIT_TAG=$MONERO_GIT_TAG
|
||||
- MONERO_GIT_TAG=latest
|
||||
container_name: p2pool-monero
|
||||
networks:
|
||||
- p2pool
|
||||
ports:
|
||||
- 18080:18080/tcp
|
||||
|
||||
volumes:
|
||||
- monero:/home/monero/.bitmonero:rw
|
||||
- /dev/null:/home/monero/.bitmonero/bitmonero.log:rw
|
||||
@@ -32,34 +96,31 @@ services:
|
||||
--zmq-pub tcp://0.0.0.0:18083
|
||||
--disable-dns-checkpoints
|
||||
--enable-dns-blocklist
|
||||
--out-peers 16
|
||||
--in-peers 32
|
||||
--add-priority-node=nodes.hashvault.pro:18080
|
||||
--add-priority-node=p2pmd.xmrvsbeast.com:18080
|
||||
--non-interactive
|
||||
--p2p-bind-ip=0.0.0.0
|
||||
--p2p-bind-port=18080
|
||||
--rpc-bind-ip=0.0.0.0
|
||||
--rpc-bind-port=18081
|
||||
--restricted-rpc
|
||||
--confirm-external-bind
|
||||
${PRUNE_NODE}
|
||||
--log-level=0
|
||||
|
||||
--prune-blockchain
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
--fast-block-sync=1
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
p2pool:
|
||||
image: p2pool:latest
|
||||
build: ../
|
||||
container_name: p2pool-p2pool
|
||||
networks:
|
||||
- p2pool
|
||||
ports:
|
||||
- ${P2POOL_STRATUM_PORT}:3333/tcp
|
||||
- 37889:37889/tcp
|
||||
volumes:
|
||||
- p2pool:/home/p2pool/.p2pool:rw
|
||||
- /dev/null:/home/p2pool/.p2pool/p2pool.log:rw
|
||||
- /dev/hugepages:/dev/hugepages:rw
|
||||
depends_on:
|
||||
- monero
|
||||
restart: unless-stopped
|
||||
command: >-
|
||||
--host monero
|
||||
--wallet ${WALLET_ADDRESS}
|
||||
--loglevel ${P2POOL_LOGLEVEL}
|
||||
|
||||
xmrig:
|
||||
image: xmrig:latest
|
||||
@@ -76,8 +137,11 @@ services:
|
||||
- p2pool
|
||||
restart: unless-stopped
|
||||
command: >-
|
||||
${FIXED_MINING_DIFFICULTY}
|
||||
${NUM_MINING_CPU}
|
||||
--randomx-1gb-pages
|
||||
-o p2pool:3333
|
||||
|
||||
-u p2pool
|
||||
|
||||
--cpu-max-threads-hint=100
|
||||
--cpu-priority=2
|
||||
|
||||
|
||||
@@ -1,79 +1,59 @@
|
||||
FROM ubuntu:latest
|
||||
# Multistage docker build, requires docker 17.05
|
||||
|
||||
# builder stage
|
||||
FROM ubuntu:20.04 as builder
|
||||
ARG MONERO_GIT_TAG="latest"
|
||||
|
||||
RUN set -e && \
|
||||
apt-get update -q -y --no-install-recommends && \
|
||||
DEBIAN_FRONTEND="noninteractive" apt-get install -q -y --no-install-recommends \
|
||||
git \
|
||||
ca-certificates \
|
||||
automake \
|
||||
autotools-dev \
|
||||
bsdmainutils \
|
||||
build-essential \
|
||||
pkg-config \
|
||||
cmake \
|
||||
libuv1-dev \
|
||||
libzmq3-dev \
|
||||
libsodium-dev \
|
||||
libpgm-dev \
|
||||
libnorm-dev \
|
||||
libgss-dev \
|
||||
libssl-dev \
|
||||
libzmq3-dev \
|
||||
libunbound-dev \
|
||||
libsodium-dev \
|
||||
libunwind8-dev \
|
||||
liblzma-dev \
|
||||
libreadline6-dev \
|
||||
libldns-dev \
|
||||
libexpat1-dev \
|
||||
libpgm-dev \
|
||||
qttools5-dev-tools \
|
||||
libhidapi-dev \
|
||||
libusb-1.0-0-dev \
|
||||
libprotobuf-dev \
|
||||
protobuf-compiler \
|
||||
libudev-dev \
|
||||
libboost-chrono-dev \
|
||||
libboost-date-time-dev \
|
||||
libboost-filesystem-dev \
|
||||
libboost-locale-dev \
|
||||
libboost-program-options-dev \
|
||||
libboost-regex-dev \
|
||||
libboost-serialization-dev \
|
||||
libboost-system-dev \
|
||||
libboost-thread-dev \
|
||||
ca-certificates \
|
||||
ccache \
|
||||
doxygen \
|
||||
graphviz
|
||||
cmake \
|
||||
curl \
|
||||
git \
|
||||
libtool \
|
||||
pkg-config \
|
||||
gperf
|
||||
|
||||
WORKDIR /usr/src
|
||||
|
||||
WORKDIR /src
|
||||
RUN git clone --recursive https://github.com/monero-project/monero && \
|
||||
cd monero && \
|
||||
if [ "x$MONERO_GIT_TAG" = "xlatest" ]; then MONERO_GIT_TAG=$(git describe --tags $(git rev-list --tags --max-count=1)); fi && \
|
||||
git checkout $MONERO_GIT_TAG && \
|
||||
git submodule sync && git submodule update --init --force --recursive && \
|
||||
make release-static -j$(nproc)
|
||||
make -j$(nproc) depends target=$(contrib/depends/config.guess)
|
||||
|
||||
# ---
|
||||
|
||||
FROM ubuntu:latest
|
||||
# runtime stage
|
||||
FROM ubuntu:20.04
|
||||
|
||||
COPY --from=0 /usr/src/monero/build/Linux/*/release/bin/* /
|
||||
COPY --from=0 /src/monero/build/*/release/bin /usr/local/bin/
|
||||
|
||||
RUN set -e && \
|
||||
apt-get update -q -y --no-install-recommends && \
|
||||
DEBIAN_FRONTEND="noninteractive" apt-get install -q -y --no-install-recommends \
|
||||
libgssapi-krb5-2 \
|
||||
&& \
|
||||
apt-get clean
|
||||
ca-certificates \
|
||||
netcat \
|
||||
&& \
|
||||
apt-get clean && \
|
||||
rm -rf /var/lib/apt
|
||||
|
||||
RUN groupadd -r monero -g 1000 && \
|
||||
useradd -u 1000 -r -g monero -s /sbin/nologin -c "monero node user" monero
|
||||
RUN mkdir -p /home/monero/.bitmonero && \
|
||||
chown monero.monero /home/monero /home/monero/.bitmonero
|
||||
adduser --uid 1000 --gid 1000 --system --disabled-password monero && \
|
||||
mkdir -p /home/monero/.bitmonero && \
|
||||
chown -R monero:monero /home/monero/.bitmonero
|
||||
|
||||
USER monero
|
||||
WORKDIR /home/monero
|
||||
|
||||
EXPOSE 18080 18081 18083
|
||||
|
||||
VOLUME /home/monero/.bitmonero
|
||||
|
||||
WORKDIR /home/monero
|
||||
ENTRYPOINT ["/monerod"]
|
||||
ENTRYPOINT ["/usr/local/bin/monerod"]
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
FROM python:slim
|
||||
|
||||
COPY app /app
|
||||
|
||||
WORKDIR /app
|
||||
RUN pip install -r requirements.txt
|
||||
|
||||
CMD ["/app/p2pool_statistics.py"]
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
#!/usr/bin/env python3
|
||||
import json
|
||||
from datetime import datetime
|
||||
from prefixed import Float
|
||||
import humanfriendly
|
||||
from flask import Flask, render_template
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
|
||||
##
|
||||
# Add some custom jinja filters
|
||||
def timeago(value):
|
||||
"""Format a date time to human friendly time ago"""
|
||||
if value is None:
|
||||
return ""
|
||||
if type(value) is int:
|
||||
dt = datetime.fromtimestamp(value).replace(microsecond=0)
|
||||
now = datetime.now().replace(microsecond=0)
|
||||
return humanfriendly.format_timespan(now - dt)
|
||||
|
||||
|
||||
app.jinja_env.filters["timeago"] = timeago
|
||||
|
||||
|
||||
def human_numbers(value):
|
||||
"""Format a number in human readable format"""
|
||||
if value is None:
|
||||
return ""
|
||||
return "{:!.3h}".format(Float(value))
|
||||
|
||||
|
||||
app.jinja_env.filters["humanize"] = human_numbers
|
||||
|
||||
|
||||
##
|
||||
# Get Pool Instance Birth Date
|
||||
def birthdate():
|
||||
try:
|
||||
with open("/data/p2pool.blocks") as reader:
|
||||
first_block = reader.readline().rstrip()
|
||||
bday_ts = int(first_block.split(" ")[0])
|
||||
bday = timeago(bday_ts)
|
||||
return bday
|
||||
except Exception as e:
|
||||
return "unknown time"
|
||||
|
||||
|
||||
##
|
||||
# The App Routes
|
||||
@app.route("/")
|
||||
def render():
|
||||
try:
|
||||
my_bday = birthdate()
|
||||
with open("/data/stats_mod", "r") as reader:
|
||||
stats_mod = json.loads(reader.read())
|
||||
with open("/data/pool/stats", "r") as reader:
|
||||
pool_stats = json.loads(reader.read())
|
||||
with open("/data/network/stats", "r") as reader:
|
||||
network_stats = json.loads(reader.read())
|
||||
with open("/data/local/stratum", "r") as reader:
|
||||
local_stats = json.loads(reader.read())
|
||||
return render_template(
|
||||
"index.html",
|
||||
my_bday=my_bday,
|
||||
stats_mod=stats_mod,
|
||||
pool_stats=pool_stats,
|
||||
network_stats=network_stats,
|
||||
local_stats=local_stats,
|
||||
)
|
||||
except Exception as e:
|
||||
return render_template("oops.html", error=str(e))
|
||||
|
||||
|
||||
##
|
||||
# main()
|
||||
if __name__ == "__main__":
|
||||
app.run(debug=False, host="0.0.0.0", port=80)
|
||||
@@ -0,0 +1,3 @@
|
||||
flask
|
||||
prefixed
|
||||
humanfriendly
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
|
After Width: | Height: | Size: 5.6 KiB |
File diff suppressed because one or more lines are too long
@@ -0,0 +1,166 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel="stylesheet" href="{{url_for('static', filename='bootstrap.min.css')}}">
|
||||
<title>Monero P2Pool Server Statistics</title>
|
||||
</head>
|
||||
<body style="font-size:85%;">
|
||||
<script src="{{url_for('static', filename='jquery-3.2.1.slim.min.js')}}"></script>
|
||||
<script src="{{url_for('static', filename='popper.min.js')}}"></script>
|
||||
<script src="{{url_for('static', filename='bootstrap.min.js')}}"></script>
|
||||
<div style="text-align:center;">
|
||||
<img src="{{url_for('static', filename='monero-symbol-480.png')}}" width="75px" height="75px" alt="Monero"/>
|
||||
<h1 style="color: #FF6600;">P2Pool Server Statistics</h1>
|
||||
</div>
|
||||
|
||||
<div class="card-group">
|
||||
<div class="col-sm-4 grid-margin stretch-card">
|
||||
<div class="card">
|
||||
<div class="card-header text-black mb-1 pb-1" style="text-align: center; background-color: #FF6600;"><h2>Local Pool</h2></div>
|
||||
<div class="card-body mb-0 pb-0">
|
||||
<h6 class="card-subtitle text-muted" style="font-size:80%;">(note: stats reset on restart)</h6>
|
||||
<div class="table-responsive table-hover table-condensed table-striped">
|
||||
<table class="table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Hashrate 15 Minutes</td>
|
||||
<td>{{ local_stats["hashrate_15m"]|humanize }}H/s</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Hashrate 1 Hour</td>
|
||||
<td>{{ local_stats["hashrate_1h"]|humanize }}H/s</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Hashrate 24 Hours</td>
|
||||
<td>{{ local_stats["hashrate_24h"]|humanize }}H/s</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Shares Found</td>
|
||||
<td>{{ local_stats["shares_found"] }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Shares Failed</td>
|
||||
<td>{{ local_stats["shares_failed"] }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Current Effort</td>
|
||||
<td>{{ local_stats["current_effort"] }}%</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Average Effort</td>
|
||||
<td>{{ local_stats["average_effort"] }}%</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Total Hashes</td>
|
||||
<td>{{ local_stats["total_hashes"]|humanize }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Miner Connections</td>
|
||||
<td>{{ local_stats["incoming_connections"] }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Block reward share</td>
|
||||
<td>{{ local_stats["block_reward_share_percent"] }}%</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-4 grid-margin stretch-card">
|
||||
<div class="card">
|
||||
<div class="card-header text-black mb-1 pb-1" style="text-align: center; background-color: #FF6600;"><h2>Global Pool</h2></div>
|
||||
<div class="card-body mb-0 pb-0">
|
||||
<h6 class="card-subtitle text-muted" style="font-size:80%;"> </h6>
|
||||
<div class="table-responsive table-hover table-condensed table-striped">
|
||||
<table class="table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Hash Rate</td>
|
||||
<td>{{ pool_stats["pool_statistics"]["hashRate"]|humanize }}H/s</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Round Hashes</td>
|
||||
<td>{{ stats_mod["pool"]["roundHashes"]|humanize }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Last Block Found</td>
|
||||
<td>{{ pool_stats["pool_statistics"]["lastBlockFound"] }} <br>
|
||||
{{ pool_stats["pool_statistics"]["lastBlockFoundTime"]|timeago }} ago</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Payout Method</td>
|
||||
<td>{{ pool_stats["pool_list"]|join(',') }}<br>2160 block window (~6 hours)</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<h6 class="card-subtitle text-muted" style="font-size:80%;">(since instance birth: {{ my_bday }} ago)</h6>
|
||||
<div class="table-responsive table-hover table-condensed table-striped">
|
||||
<table class="table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Total Hashes</td>
|
||||
<td>{{ pool_stats["pool_statistics"]["totalHashes"]|humanize }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Blocks Found</td>
|
||||
<td>{{ pool_stats["pool_statistics"]["totalBlocksFound"] }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Known Miners</td>
|
||||
<td>{{ pool_stats["pool_statistics"]["miners"] }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-4 grid-margin stretch-card">
|
||||
<div class="card">
|
||||
<div class="card-header text-black mb-1 pb-1" style="text-align: center; background-color: #FF6600;"><h2>Monero Network</h2></div>
|
||||
<div class="card-body mb-0 pb-0">
|
||||
<h6 class="card-subtitle text-muted" style="font-size:80%;"> </h6>
|
||||
<div class="table-responsive table-hover table-condensed table-striped">
|
||||
<table class="table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Height</td>
|
||||
<td>{{ network_stats["height"] }}<br>
|
||||
{{ network_stats["timestamp"]|timeago }} ago</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Difficulty</td>
|
||||
<td>{{ network_stats["difficulty"]|humanize }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Reward</td>
|
||||
<td>0.{{ network_stats["reward"] }} Monero</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Head Hash</td>
|
||||
<td>{{ network_stats["hash"] }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
window.setInterval('refresh()', 30000); // Call refresh function every 30000 milliseconds (30 seconds).
|
||||
function refresh() {
|
||||
window .location.reload();
|
||||
}
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Oops</title>
|
||||
</head>
|
||||
<body>
|
||||
<h2>Ooops, something went wrong:</h2>
|
||||
{{ error }}
|
||||
(Maybe you need to wait a few minutes for p2pool to start and sync for the first time?)
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM ubuntu:latest
|
||||
FROM ubuntu:20.04
|
||||
|
||||
RUN set -e && \
|
||||
apt-get update -q -y --no-install-recommends && \
|
||||
@@ -20,7 +20,7 @@ RUN git clone https://github.com/xmrig/xmrig.git && \
|
||||
|
||||
# ---
|
||||
|
||||
FROM ubuntu:latest
|
||||
FROM ubuntu:20.04
|
||||
|
||||
COPY --from=0 /usr/src/xmrig/build/xmrig /
|
||||
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
### P2Pool command line options
|
||||
|
||||
```
|
||||
--wallet Wallet address to mine to. Subaddresses and integrated addresses are not supported!
|
||||
--host IP address of your Monero node, default is 127.0.0.1
|
||||
--rpc-port monerod RPC API port number, default is 18081
|
||||
--zmq-port monerod ZMQ pub port number, default is 18083 (same port as in monerod's "--zmq-pub" command line parameter)
|
||||
--stratum Comma-separated list of IP:port for stratum server to listen on
|
||||
--p2p Comma-separated list of IP:port for p2p server to listen on
|
||||
--addpeers Comma-separated list of IP:port of other p2pool nodes to connect to
|
||||
--light-mode Don't allocate RandomX dataset, saves 2GB of RAM
|
||||
--loglevel Verbosity of the log, integer number between 0 and 6
|
||||
--config Name of the p2pool config file
|
||||
--data-api Path to the p2pool JSON data (use it in tandem with an external web-server)
|
||||
--local-api Enable /local/ path in api path for Stratum Server and built-in miner statistics
|
||||
--stratum-api An alias for --local-api
|
||||
--no-cache Disable p2pool.cache
|
||||
--no-color Disable colors in console output
|
||||
--no-randomx Disable internal RandomX hasher: p2pool will use RPC calls to monerod to check PoW hashes
|
||||
--out-peers N Maximum number of outgoing connections for p2p server (any value between 10 and 450)
|
||||
--in-peers N Maximum number of incoming connections for p2p server (any value between 10 and 450)
|
||||
--start-mining N Start built-in miner using N threads (any value between 1 and 64)
|
||||
--mini Connect to p2pool-mini sidechain. Note that it will also change default p2p port from 37889 to 37888
|
||||
--no-autodiff Disable automatic difficulty adjustment for miners connected to stratum (WARNING: incompatible with Nicehash and MRR)
|
||||
--rpc-login Specify username[:password] required for Monero RPC server
|
||||
--socks5 Specify IP:port of a SOCKS5 proxy to use for outgoing connections
|
||||
--no-dns Disable DNS queries, use only IP addresses to connect to peers (seed node DNS will be unavailable too)
|
||||
--p2p-external-port Port number that your router uses for mapping to your local p2p port. Use it if you are behind a NAT and still want to accept incoming connections
|
||||
--no-upnp Disable UPnP port forwarding
|
||||
--no-igd An alias for --no-upnp
|
||||
--upnp-stratum Port forward Stratum port (it's not forwarded by default)
|
||||
--version Print p2pool's version and build details
|
||||
```
|
||||
|
||||
### Example command line
|
||||
|
||||
```
|
||||
p2pool.exe --host 127.0.0.1 --rpc-port 18081 --zmq-port 18083 --wallet YOUR_WALLET_ADDRESS --stratum 0.0.0.0:3333 --p2p 0.0.0.0:37889
|
||||
```
|
||||
|
||||
### Multiple backup hosts
|
||||
|
||||
You can have multiple hosts in command line. If P2Pool detects that the host it's currently using is down or stuck, it will cycle through hosts until it finds a working one. It will not switch back as long as the current host it found is working.
|
||||
|
||||
Each new host uses RPC and zmq-pub port numbers from the previous host (or default 18081/18083 if none were specified). Note that `--rpc-login` is not copied from the previous host, you must specify it for each host that has username/password.
|
||||
|
||||
In this example, you have local Monero host running on ports 18081/18083 (RPC/zmq-pub), and several backup hosts running on ports 18089/18084.
|
||||
|
||||
|
||||
```
|
||||
p2pool.exe --host 127.0.0.1 --host xmr1.rs.me --rpc-port 18089 --zmq-port 18084 --host xmr2.rs.me --host xmr3.rs.me --wallet YOUR_WALLET_ADDRESS
|
||||
```
|
||||
@@ -0,0 +1,20 @@
|
||||
### P2Pool console commands
|
||||
|
||||
Command|Description
|
||||
-|-
|
||||
help|display list of commands
|
||||
status|display p2pool status
|
||||
loglevel **N**|set log level (**N** can be between 0 and 6)
|
||||
addpeers **L**|**L** is a comma-separated list of IP:port of other p2pool nodes to connect to
|
||||
droppeers|disconnect all currently connected peers
|
||||
peers|show all currently connected peers (p2p)
|
||||
workers|show all currently connected workers (stratum)
|
||||
bans|show all banned IPs
|
||||
hosts|show Monero hosts which were configured in the command line
|
||||
next_host|switch to the next Monero host configured in the command line
|
||||
outpeers **N**|set maximum number of outgoing connections (values above 50 are not recommended)
|
||||
inpeers **N**|set maximum number of incoming connections (values above 50 are not recommended)
|
||||
start_mining **T**|start mining (**T** is the number of threads to use, must be between 1 and 64)
|
||||
stop_mining|stop mining
|
||||
exit|terminate p2pool
|
||||
version|show p2pool version
|
||||
@@ -0,0 +1,49 @@
|
||||
## Setting up P2Pool as a systemd service (Linux)
|
||||
|
||||
With this config, P2Pool will run as a service with redirected I/O. It uses `p2pool` user which you should setup beforehand.
|
||||
|
||||
You can execute console commands by running `echo "status" > /run/p2pool/p2pool.control`
|
||||
|
||||
### p2pool.service
|
||||
```
|
||||
[Unit]
|
||||
Description=p2pool daemon
|
||||
After=network-online.target systemd-modules-load.service monerod.service
|
||||
Wants=network-online.target systemd-modules-load.service monerod.service
|
||||
Requires=p2pool.socket
|
||||
|
||||
[Service]
|
||||
Type=exec
|
||||
Sockets=p2pool.socket
|
||||
StandardInput=socket
|
||||
StandardOutput=journal
|
||||
StandardError=journal
|
||||
|
||||
# /usr/local/bin/p2pool.sh simply invokes the p2pool executable with your chosen command-line options.
|
||||
ExecStart=/usr/local/bin/p2pool.sh
|
||||
TimeoutStopSec=60
|
||||
|
||||
# Run as p2pool:p2pool
|
||||
User=p2pool
|
||||
Group=p2pool
|
||||
|
||||
WorkingDirectory=/var/lib/p2pool
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
### p2pool.socket
|
||||
```
|
||||
# FIFO socket for controlling p2pool daemon
|
||||
[Unit]
|
||||
Description=Command FIFO for p2pool daemon
|
||||
|
||||
[Socket]
|
||||
ListenFIFO=/run/p2pool/p2pool.control
|
||||
DirectoryMode=0755
|
||||
SocketMode=0666
|
||||
SocketUser=p2pool
|
||||
SocketGroup=p2pool
|
||||
RemoveOnStop=true
|
||||
```
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 671 B |
@@ -0,0 +1,317 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>P2Pool - Decentralized Monero mining pool</title>
|
||||
<link rel="shortcut icon" type="image/png" href="favicon-32x32.png"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.5">
|
||||
<style>
|
||||
a {
|
||||
color: #e09000;
|
||||
-ms-touch-action: none;
|
||||
touch-action: none;
|
||||
}
|
||||
|
||||
a:visited {
|
||||
color: #808080;
|
||||
-ms-touch-action: none;
|
||||
touch-action: none;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: #383838;
|
||||
color: #e0e0e0;
|
||||
font-family: Arial, sans-serif;
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
table {
|
||||
color: #c0c0c0;
|
||||
border-spacing:15px 5px;
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
table.menu_page {
|
||||
width: 100%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
details > summary {
|
||||
padding: 0.25rem;
|
||||
font-size: 2.5rem;
|
||||
-ms-touch-action: none;
|
||||
touch-action: none;
|
||||
}
|
||||
|
||||
details > ul > li > span {
|
||||
color: #e09000;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
function elapsedTimeStr(ts1, ts2, short_form) {
|
||||
let s = ts2 - ts1;
|
||||
if (s < 0) s = 0;
|
||||
let m = Math.floor(s / 60) % 60;
|
||||
let h = Math.floor(s / 3600) % 24;
|
||||
let d = Math.floor(s / 86400);
|
||||
if (short_form) {
|
||||
if (s >= 86400) return d + 'd';
|
||||
if (s >= 3600) return h + 'h';
|
||||
return m + 'm';
|
||||
}
|
||||
else {
|
||||
let result = m + 'm';
|
||||
if (s >= 3600) result = h + 'h ' + result;
|
||||
if (s >= 86400) result = d + 'd ' + h + 'h';
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
function set_effort(el, value) {
|
||||
el.innerHTML = value.toFixed(2) + '%';
|
||||
el.style = (value < 100.0) ? "color:#00C000;" : (value < 200.0) ? "color:#E0E000;" : "color:#FF0000;";
|
||||
}
|
||||
|
||||
async function load_data() {
|
||||
init_menu();
|
||||
window.onresize = init_menu;
|
||||
|
||||
let pool_stats_req = await fetch('api/pool/stats');
|
||||
let pool_blocks_req = await fetch('api/pool/blocks');
|
||||
let network_stats_req = await fetch('api/network/stats');
|
||||
let latest_release_req = await fetch('api/latest_release');
|
||||
|
||||
let pool_stats = JSON.parse(await pool_stats_req.text());
|
||||
let pool_blocks = JSON.parse(await pool_blocks_req.text());
|
||||
let network_stats = JSON.parse(await network_stats_req.text());
|
||||
let latest_release = JSON.parse(await latest_release_req.text());
|
||||
|
||||
let pool_hashrate = pool_stats.pool_statistics.hashRate / 1e6;
|
||||
let pplns_duration = pool_stats.pool_statistics.pplnsWeight / pool_stats.pool_statistics.hashRate;
|
||||
let min_payout = 0.6 * pool_stats.pool_statistics.sidechainDifficulty / pool_stats.pool_statistics.pplnsWeight;
|
||||
|
||||
document.getElementById("pool_hashrate").innerHTML = pool_hashrate.toFixed(3) + ' MH/s';
|
||||
document.getElementById("pplns_duration").innerHTML = elapsedTimeStr(0, pplns_duration, 0) + ' ' + Math.floor(pplns_duration % 60) + 's';
|
||||
document.getElementById("pool_miners").innerHTML = pool_stats.pool_statistics.miners;
|
||||
document.getElementById("min_payout").innerHTML = min_payout.toFixed(5) + ' XMR';
|
||||
document.getElementById("latest_release").innerHTML = '<a href="' + latest_release.html_url + '" target="_blank">' + latest_release.name + '</a>';
|
||||
|
||||
let ts = Math.floor(Date.now() / 1000);
|
||||
|
||||
let n = pool_stats.pool_statistics.lastBlockFound;
|
||||
document.getElementById("pool_last_block").innerHTML = n ? ('<a href="/explorer/block/' + n + '" target="_blank">' + n + '</a> (' + elapsedTimeStr(pool_stats.pool_statistics.lastBlockFoundTime, ts, 0) + ' ago)') : 'N/A';
|
||||
document.getElementById("pool_total_blocks").innerHTML = pool_stats.pool_statistics.totalBlocksFound;
|
||||
|
||||
let t = document.getElementById('menu_blocks');
|
||||
let cur_effort = (pool_stats.pool_statistics.totalHashes - ((pool_blocks.length > 0) ? pool_blocks[0].totalHashes : 0)) * 100.0 / network_stats.difficulty;
|
||||
set_effort(document.getElementById("current_effort"), (cur_effort >= 0) ? cur_effort : 0);
|
||||
let total_effort = 0.0;
|
||||
let num_blocks_with_effort = 0;
|
||||
for (let i = 0, m = Math.min(pool_blocks.length, 50); i < m; ++i) {
|
||||
if (t.rows.length <= i + 1) t.insertRow(-1);
|
||||
let row = t.rows[i + 1];
|
||||
while (row.cells.length < 3) row.insertCell(-1);
|
||||
|
||||
let height = row.cells[0];
|
||||
let effort = row.cells[1];
|
||||
let age = row.cells[2];
|
||||
|
||||
n = pool_blocks[i].height;
|
||||
height.innerHTML = '<a href="/explorer/block/' + pool_blocks[i].hash + '" target="_blank">' + n + '</a>';
|
||||
|
||||
if ((i + 1 < pool_blocks.length) && (pool_blocks[i + 1].totalHashes > 0)) {
|
||||
let value = (pool_blocks[i].totalHashes - pool_blocks[i + 1].totalHashes) * 100.0 / pool_blocks[i].difficulty;
|
||||
total_effort += value;
|
||||
++num_blocks_with_effort;
|
||||
set_effort(effort, value);
|
||||
}
|
||||
else {
|
||||
effort.innerHTML = "N/A";
|
||||
}
|
||||
|
||||
age.innerHTML = elapsedTimeStr(pool_blocks[i].ts, ts, 1);
|
||||
}
|
||||
if (num_blocks_with_effort > 0) {
|
||||
let average_effort = total_effort / num_blocks_with_effort;
|
||||
set_effort(document.getElementById("average_effort"), average_effort);
|
||||
}
|
||||
|
||||
let network_hashrate = network_stats.difficulty / 120e6;
|
||||
document.getElementById("monero_hashrate").innerHTML = network_hashrate.toFixed(3) + ' MH/s';
|
||||
document.getElementById("monero_last_block").innerHTML = network_stats.height + ' (' + elapsedTimeStr(network_stats.timestamp, ts, 0) + ' ago)';
|
||||
}
|
||||
|
||||
const menu = ['pool', 'blocks', 'help', 'faq'];
|
||||
|
||||
function init_menu()
|
||||
{
|
||||
let is_mobile = false;
|
||||
|
||||
if (navigator.userAgentData) {
|
||||
is_mobile = navigator.userAgentData.mobile;
|
||||
}
|
||||
else {
|
||||
const mobile_preg = /Android|webOS|iPhone|iPad|iPod|BlackBerry/i;
|
||||
is_mobile = mobile_preg.test(navigator.userAgent) || mobile_preg.test(navigator.platform);
|
||||
}
|
||||
|
||||
let e = document.getElementById('main_menu');
|
||||
|
||||
if (!is_mobile) {
|
||||
e.style.cursor = "pointer";
|
||||
document.querySelectorAll("details > summary").forEach(el => { el.style.cursor = "pointer"; });
|
||||
}
|
||||
|
||||
e.style.width = (window.innerWidth > 1600) ? "1600px" : "100%";
|
||||
|
||||
menu.forEach(element => {
|
||||
let e2 = document.getElementById('menu_' + element);
|
||||
e2.style.width = e.style.width;
|
||||
});
|
||||
}
|
||||
|
||||
function toggle_menu(name) {
|
||||
if (!name) {
|
||||
name = 'pool';
|
||||
}
|
||||
|
||||
menu.forEach(element => {
|
||||
let e = document.getElementById('menu_' + element);
|
||||
let b = document.getElementById('button_' + element);
|
||||
if (element == name) {
|
||||
e.style.display = 'block';
|
||||
b.style.backgroundColor = '#646464';
|
||||
window.location.hash = '#' + name;
|
||||
}
|
||||
else {
|
||||
e.style.display = 'none';
|
||||
b.style.backgroundColor = '#404040';
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body onload="load_data();setInterval(load_data, 2000);toggle_menu(window.location.hash.substr(1));">
|
||||
<div style="font-size:3rem;text-align:center;">P2Pool</div><div style="font-size:1.1rem;text-align:center;">Decentralized Monero mining pool</div>
|
||||
<div style="font-size:1rem;text-align:center;">Latest release: <span id="latest_release"><a href="https://github.com/SChernykh/p2pool/releases/latest" target="_blank">P2Pool</a></span></div>
|
||||
<br>
|
||||
<table id="main_menu" style="width:100%;margin-left:auto;margin-right:auto;table-layout:fixed;text-align:center;-ms-touch-action:none;touch-action:none;"><tr>
|
||||
<td onclick="toggle_menu('pool')" id="button_pool">Pool</td>
|
||||
<td onclick="toggle_menu('blocks')" id="button_blocks">Blocks</td>
|
||||
<td onclick="toggle_menu('help')" id="button_help">Get started</td>
|
||||
<td onclick="toggle_menu('faq')" id="button_faq">FAQ</td>
|
||||
</tr></table>
|
||||
<br>
|
||||
<table id="menu_pool" class="menu_page">
|
||||
<tr><td></td><td style="width:17rem;">Pool</td><td>Network</td></tr>
|
||||
<tr><td style="padding-bottom: 1rem;"></td><td></td><td></td></tr>
|
||||
<tr><td>Hashrate</td><td><span id="pool_hashrate">N/A</span></td><td><span id="monero_hashrate">N/A</span></td></tr>
|
||||
<tr><td>Miners</td><td><span id="pool_miners">N/A</span></td><td></td></tr>
|
||||
<tr><td>PPLNS window</td><td><span id="pplns_duration">N/A</span></td><td></td></tr>
|
||||
<tr><td>Last block</td><td><span id="pool_last_block">N/A</span></td><td><span id="monero_last_block">N/A</span></td></tr>
|
||||
<tr><td>Total blocks</td><td><span id="pool_total_blocks">N/A</span></td><td></td></tr>
|
||||
<tr><td>Current effort</td><td><span id="current_effort">N/A</span></td><td></td></tr>
|
||||
<tr><td>Average effort<br><div style="text-align:center;font-size:0.9rem">last 50 blocks</div></td><td><span id="average_effort">N/A</span></td><td></td></tr>
|
||||
<tr><td> </td><td></td><td></td></tr>
|
||||
<tr><td>Fee</td><td>0%</td><td></td></tr>
|
||||
<tr><td>Min payout</td><td><span id="min_payout">0.00027 XMR</span></td><td></td></tr>
|
||||
<tr><td>Payout scheme</td><td><a href="https://en.wikipedia.org/wiki/Mining_pool#Pay-per-last-N-shares" target="_blank">PPLNS</a></td><td></td></tr>
|
||||
<tr><td> </td><td></td><td></td></tr>
|
||||
<tr><td>Statistics</td><td><a href="https://p2pool.observer/" target="_blank">P2Pool observer</a></td><td></td></tr>
|
||||
</table>
|
||||
<table id="menu_blocks" class="menu_page">
|
||||
<tr><td style="padding-right:5rem;">Height</td><td style="padding-right:5rem;">Effort</td><td>Age</td></tr>
|
||||
</table>
|
||||
<table id="menu_help" class="menu_page"><tr><td>
|
||||
|
||||
<details><summary>P2Pool video guide</summary>
|
||||
<ul>
|
||||
<li>A detailed <a href="https://www.youtube.com/watch?v=NbxbRu-2GWI" target="_blank">video guide</a> to install P2Pool and start mining
|
||||
</ul>
|
||||
</details>
|
||||
|
||||
<details><summary>Setup Monero wallet</summary>
|
||||
Wallets with confirmed P2Pool support<br>
|
||||
<span style="font-size:0.9rem;color:#e09000;">You might not see P2Pool payouts in other wallets if they're not updated!</span>
|
||||
<ul>
|
||||
<li>Official <a href="https://www.getmonero.org/downloads/" target="_blank">Monero CLI and GUI v0.18.1.0</a> and newer
|
||||
<li><a href="https://play.google.com/store/apps/details?id=com.m2049r.xmrwallet" target="_blank">Monerujo v3.0.2 "Fluorine Fermi"</a> and newer
|
||||
<li><a href="https://play.google.com/store/apps/details?id=com.cakewallet.cake_wallet" target="_blank">Cake Wallet v4.4.5</a> and newer
|
||||
<li><a href="https://featherwallet.org/" target="_blank">Feather Wallet v2.1.0</a> and newer
|
||||
<li><a href="https://mymonero.com/" target="_blank">MyMonero</a>
|
||||
</ul>
|
||||
It's highly recommended to create a new wallet for mining because wallet addresses are public on p2pool. You have to use the primary wallet address for mining. Subaddresses and integrated addresses are not supported, just like with monerod solo mining.
|
||||
</details>
|
||||
|
||||
<details><summary>Setup Monero node</summary>
|
||||
<ul>
|
||||
<li>Download the latest Monero <a href="https://www.getmonero.org/downloads/" target="_blank">release</a>
|
||||
<li>[Optional] Open port <span>18080</span> (Monero p2p port) in your firewall to ensure better connectivity
|
||||
<li>Run <span>./monerod --zmq-pub tcp://127.0.0.1:18083 --out-peers 32 --in-peers 64 --add-priority-node=p2pmd.xmrvsbeast.com:18080 --add-priority-node=nodes.hashvault.pro:18080 --disable-dns-checkpoints --enable-dns-blocklist</span>
|
||||
<li>If your network connection's upload bandwidth is less than 10 Mbit, use <span>--out-peers 8 --in-peers 16</span> instead.
|
||||
<li>Wait until it's fully synchronized. If you didn't run Monero node before, it can take up to several days to synchronize (5-6 hours on a modern PC with fast SSD and fast Internet connection). You can add <span>--prune-blockchain</span> argument to the command line to run a pruned node (3-4 times less disk usage)
|
||||
</ul></details>
|
||||
|
||||
<details><summary>Setup P2Pool node</summary>
|
||||
<ul>
|
||||
<li>Download the latest P2Pool <a href="https://github.com/SChernykh/p2pool/releases/latest" target="_blank">release</a>
|
||||
<li>[Optional] Open port <span>37889</span> (P2Pool port) or <span>37888</span> (P2Pool mini port) in your firewall to ensure better connectivity
|
||||
<li>Run <span>./p2pool --host 127.0.0.1 --wallet YOUR_WALLET_ADDRESS</span>
|
||||
<li>It should take no more than 5-10 minutes to synchronize
|
||||
</ul></details>
|
||||
|
||||
<details><summary>Miner software</summary>
|
||||
<ul>
|
||||
<li><a href="https://xmrig.com/" target="_blank">XMRig</a> is recommended. <a href="https://xmrig.com/proxy" target="_blank">XMRig Proxy</a> is fully supported.
|
||||
<li>Once P2Pool sync is complete, XMRig should be able to connect to the stratum server on port <span>3333</span>
|
||||
<li>Run <span>./xmrig -o 127.0.0.1:3333</span>. Note that you don't need to specify wallet address for xmrig. Wallet address set in xmrig config will be ignored!
|
||||
<li>To set custom fixed difficulty for your miner (for example, <span>10000</span>), run <span>./xmrig -u x+10000 -o 127.0.0.1:3333</span>
|
||||
<li>To connect another mining rig to your P2Pool node, run <span>./xmrig -o YOUR_P2POOL_NODE_IP:3333</span> on that mining rig
|
||||
</ul></details>
|
||||
|
||||
<details><summary>Checking your progress</summary>
|
||||
<ul>
|
||||
<li>You can enter your wallet address at <a href="https://p2pool.observer/" target="_blank">P2Pool Observer</a>
|
||||
<li>P2Pool Observer for P2Pool mini can be found <a href="https://mini.p2pool.observer/" target="_blank">here</a>
|
||||
<li>You will find your wallet's statistics there only after you've mined at least 1 P2Pool share
|
||||
</ul>
|
||||
</details>
|
||||
|
||||
<details><summary>Help and support</summary>
|
||||
P2Pool is a decentralized community, there is no dedicated support. You can reach and get help from other miners on:
|
||||
<ul>
|
||||
<li>IRC channels: <span>#monero-pools</span> and <span>#p2pool-log</span> (<span>#p2pool-mini</span> for P2Pool mini) on <a href="https://libera.chat/" target="_blank">Libera.Chat</a>
|
||||
<li>Reddit: <a href="https://reddit.com/r/MoneroMining/" target="_blank">r/MoneroMining</a>
|
||||
</ul></details>
|
||||
</td></tr></table>
|
||||
<table id="menu_faq" class="menu_page"><tr><td>
|
||||
<ul>
|
||||
<li><span style="font-size:2rem;color:#e09000;">What are system requirements to run P2Pool?</span>
|
||||
<ul><li>P2Pool needs 0.5 GB disc space and 2.6 GB RAM to run (0.6 GB RAM in light mode). Add this to monerod requirements if you run both on the same machine. Add <span style="color:#808080;">--light-mode</span> to p2pool command line to reduce the memory usage to 0.6 GB, or <span style="color:#808080;">--no-randomx --no-cache</span> to reduce the memory usage to less than 100 MB.</ul><br>
|
||||
<li><span style="font-size:2rem;color:#e09000;">Does P2Pool work with XMRig Proxy?</span>
|
||||
<ul><li>Yes, P2Pool fully supports <a href="https://xmrig.com/proxy" target="_blank">XMRig Proxy</a>.</ul><br>
|
||||
<li><span style="font-size:2rem;color:#e09000;">Does monerod have to be run on the same machine as P2Pool?</span>
|
||||
<ul><li>No, you can run them on different machines and even connect multiple p2pool instances to a single server running monerod</ul><br>
|
||||
<li><span style="font-size:2rem;color:#e09000;">Does P2Pool work with pruned Monero node?</span>
|
||||
<ul><li>Yes, you can use pruned Monero node to mine on P2Pool</ul><br>
|
||||
<li><span style="font-size:2rem;color:#e09000;">Does P2Pool require incoming connections to work properly?</span>
|
||||
<ul><li>P2Pool (and Monero) can work with only outgoing connections, but it's recommended to open ports 18080 (Monero) and 37889/37888 (P2Pool/P2Pool mini) for better connectivity with the rest of the network.</ul><br>
|
||||
<li><span style="font-size:2rem;color:#e09000;">I have been mining for several hours and still got no rewards?</span>
|
||||
<ul><li>P2Pool doesn't work exactly like regular pools - there's no "pending balance" here. You need to find a pool share first and then wait for P2Pool to find a Monero block. You'll get a payout to your XMR wallet as soon as a block is found and you have shares in PPLNS window. It can take several days to a week to find a share if your hashrate is low. Type "status" command in P2Pool console or visit <a href="https://p2pool.observer/" target="_blank">P2Pool observer</a> to check your progress.</ul><br>
|
||||
<li><span style="font-size:2rem;color:#e09000;">I am mining but I can't find any shares</span>
|
||||
<ul><li>First check for any warnings and errors in P2Pool console and logs. If everything works fine, you can check the <a href="https://p2pool.observer/calculate-share-time" target="_blank">average share time calculator</a> to get an idea how often you should find a share with your hashrate. If this time is more than 1 day, it's recommended to switch to P2Pool mini by adding <span style="color:#808080;">--mini</span> to P2Pool command line.</ul><br>
|
||||
<li><span style="font-size:2rem;color:#e09000;">I get an error "monerod RPC ... is incompatible, update to RPC >= v3.8"</span>
|
||||
<ul><li>Use monerod v0.18.0.0 or newer</ul><br>
|
||||
<li><span style="font-size:2rem;color:#e09000;">I get warnings "peer ... is ahead on mainchain (height ..., your height ...). Is your monerod stuck or lagging?"</span>
|
||||
<ul><li>Make sure you add these arguments to monerod command line: <span style="color:#808080;">--zmq-pub tcp://127.0.0.1:18083 --disable-dns-checkpoints --enable-dns-blocklist</span></ul><br>
|
||||
</ul>
|
||||
</td></tr></table>
|
||||
<br><br>
|
||||
<div style="position:fixed;width:100%;bottom:0;background-color:#383838;font-size:1rem;text-align:center;color:#b0b0b0;">
|
||||
<a href="api/" target="_blank">Pool API</a> | <a href="https://github.com/SChernykh/p2pool" target="_blank">Source</a> | <a href="http://yucmgsbw7nknw7oi3bkuwudvc657g2xcqahhbjyewazusyytapqo4xid.onion/" target="_blank">Onion URL</a><br>
|
||||
Donate to support the project:<br><a href="monero:44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg?tx_description=Donation%20to%20P2Pool" style="font-size:0.9rem;color:#b0b0b0;">44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg</a><br>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 671 B |
@@ -0,0 +1,317 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>P2Pool mini - Decentralized Monero mining pool</title>
|
||||
<link rel="shortcut icon" type="image/png" href="favicon-32x32.png"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.5">
|
||||
<style>
|
||||
a {
|
||||
color: #e09000;
|
||||
-ms-touch-action: none;
|
||||
touch-action: none;
|
||||
}
|
||||
|
||||
a:visited {
|
||||
color: #808080;
|
||||
-ms-touch-action: none;
|
||||
touch-action: none;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: #383838;
|
||||
color: #e0e0e0;
|
||||
font-family: Arial, sans-serif;
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
table {
|
||||
color: #c0c0c0;
|
||||
border-spacing:15px 5px;
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
table.menu_page {
|
||||
width: 100%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
details > summary {
|
||||
padding: 0.25rem;
|
||||
font-size: 2.5rem;
|
||||
-ms-touch-action: none;
|
||||
touch-action: none;
|
||||
}
|
||||
|
||||
details > ul > li > span {
|
||||
color: #e09000;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
function elapsedTimeStr(ts1, ts2, short_form) {
|
||||
let s = ts2 - ts1;
|
||||
if (s < 0) s = 0;
|
||||
let m = Math.floor(s / 60) % 60;
|
||||
let h = Math.floor(s / 3600) % 24;
|
||||
let d = Math.floor(s / 86400);
|
||||
if (short_form) {
|
||||
if (s >= 86400) return d + 'd';
|
||||
if (s >= 3600) return h + 'h';
|
||||
return m + 'm';
|
||||
}
|
||||
else {
|
||||
let result = m + 'm';
|
||||
if (s >= 3600) result = h + 'h ' + result;
|
||||
if (s >= 86400) result = d + 'd ' + h + 'h';
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
function set_effort(el, value) {
|
||||
el.innerHTML = value.toFixed(2) + '%';
|
||||
el.style = (value < 100.0) ? "color:#00C000;" : (value < 200.0) ? "color:#E0E000;" : "color:#FF0000;";
|
||||
}
|
||||
|
||||
async function load_data() {
|
||||
init_menu();
|
||||
window.onresize = init_menu;
|
||||
|
||||
let pool_stats_req = await fetch('api/pool/stats');
|
||||
let pool_blocks_req = await fetch('api/pool/blocks');
|
||||
let network_stats_req = await fetch('api/network/stats');
|
||||
let latest_release_req = await fetch('api/latest_release');
|
||||
|
||||
let pool_stats = JSON.parse(await pool_stats_req.text());
|
||||
let pool_blocks = JSON.parse(await pool_blocks_req.text());
|
||||
let network_stats = JSON.parse(await network_stats_req.text());
|
||||
let latest_release = JSON.parse(await latest_release_req.text());
|
||||
|
||||
let pool_hashrate = pool_stats.pool_statistics.hashRate / 1e6;
|
||||
let pplns_duration = pool_stats.pool_statistics.pplnsWeight / pool_stats.pool_statistics.hashRate;
|
||||
let min_payout = 0.6 * pool_stats.pool_statistics.sidechainDifficulty / pool_stats.pool_statistics.pplnsWeight;
|
||||
|
||||
document.getElementById("pool_hashrate").innerHTML = pool_hashrate.toFixed(3) + ' MH/s';
|
||||
document.getElementById("pplns_duration").innerHTML = elapsedTimeStr(0, pplns_duration, 0) + ' ' + Math.floor(pplns_duration % 60) + 's';
|
||||
document.getElementById("pool_miners").innerHTML = pool_stats.pool_statistics.miners;
|
||||
document.getElementById("min_payout").innerHTML = min_payout.toFixed(5) + ' XMR';
|
||||
document.getElementById("latest_release").innerHTML = '<a href="' + latest_release.html_url + '" target="_blank">' + latest_release.name + '</a>';
|
||||
|
||||
let ts = Math.floor(Date.now() / 1000);
|
||||
|
||||
let n = pool_stats.pool_statistics.lastBlockFound;
|
||||
document.getElementById("pool_last_block").innerHTML = n ? ('<a href="/explorer/block/' + n + '" target="_blank">' + n + '</a> (' + elapsedTimeStr(pool_stats.pool_statistics.lastBlockFoundTime, ts, 0) + ' ago)') : 'N/A';
|
||||
document.getElementById("pool_total_blocks").innerHTML = pool_stats.pool_statistics.totalBlocksFound;
|
||||
|
||||
let t = document.getElementById('menu_blocks');
|
||||
let cur_effort = (pool_stats.pool_statistics.totalHashes - ((pool_blocks.length > 0) ? pool_blocks[0].totalHashes : 0)) * 100.0 / network_stats.difficulty;
|
||||
set_effort(document.getElementById("current_effort"), (cur_effort >= 0) ? cur_effort : 0);
|
||||
let total_effort = 0.0;
|
||||
let num_blocks_with_effort = 0;
|
||||
for (let i = 0, m = Math.min(pool_blocks.length, 50); i < m; ++i) {
|
||||
if (t.rows.length <= i + 1) t.insertRow(-1);
|
||||
let row = t.rows[i + 1];
|
||||
while (row.cells.length < 3) row.insertCell(-1);
|
||||
|
||||
let height = row.cells[0];
|
||||
let effort = row.cells[1];
|
||||
let age = row.cells[2];
|
||||
|
||||
n = pool_blocks[i].height;
|
||||
height.innerHTML = '<a href="/explorer/block/' + pool_blocks[i].hash + '" target="_blank">' + n + '</a>';
|
||||
|
||||
if ((i + 1 < pool_blocks.length) && (pool_blocks[i + 1].totalHashes > 0)) {
|
||||
let value = (pool_blocks[i].totalHashes - pool_blocks[i + 1].totalHashes) * 100.0 / pool_blocks[i].difficulty;
|
||||
total_effort += value;
|
||||
++num_blocks_with_effort;
|
||||
set_effort(effort, value);
|
||||
}
|
||||
else {
|
||||
effort.innerHTML = "N/A";
|
||||
}
|
||||
|
||||
age.innerHTML = elapsedTimeStr(pool_blocks[i].ts, ts, 1);
|
||||
}
|
||||
if (num_blocks_with_effort > 0) {
|
||||
let average_effort = total_effort / num_blocks_with_effort;
|
||||
set_effort(document.getElementById("average_effort"), average_effort);
|
||||
}
|
||||
|
||||
let network_hashrate = network_stats.difficulty / 120e6;
|
||||
document.getElementById("monero_hashrate").innerHTML = network_hashrate.toFixed(3) + ' MH/s';
|
||||
document.getElementById("monero_last_block").innerHTML = network_stats.height + ' (' + elapsedTimeStr(network_stats.timestamp, ts, 0) + ' ago)';
|
||||
}
|
||||
|
||||
const menu = ['pool', 'blocks', 'help', 'faq'];
|
||||
|
||||
function init_menu()
|
||||
{
|
||||
let is_mobile = false;
|
||||
|
||||
if (navigator.userAgentData) {
|
||||
is_mobile = navigator.userAgentData.mobile;
|
||||
}
|
||||
else {
|
||||
const mobile_preg = /Android|webOS|iPhone|iPad|iPod|BlackBerry/i;
|
||||
is_mobile = mobile_preg.test(navigator.userAgent) || mobile_preg.test(navigator.platform);
|
||||
}
|
||||
|
||||
let e = document.getElementById('main_menu');
|
||||
|
||||
if (!is_mobile) {
|
||||
e.style.cursor = "pointer";
|
||||
document.querySelectorAll("details > summary").forEach(el => { el.style.cursor = "pointer"; });
|
||||
}
|
||||
|
||||
e.style.width = (window.innerWidth > 1600) ? "1600px" : "100%";
|
||||
|
||||
menu.forEach(element => {
|
||||
let e2 = document.getElementById('menu_' + element);
|
||||
e2.style.width = e.style.width;
|
||||
});
|
||||
}
|
||||
|
||||
function toggle_menu(name) {
|
||||
if (!name) {
|
||||
name = 'pool';
|
||||
}
|
||||
|
||||
menu.forEach(element => {
|
||||
let e = document.getElementById('menu_' + element);
|
||||
let b = document.getElementById('button_' + element);
|
||||
if (element == name) {
|
||||
e.style.display = 'block';
|
||||
b.style.backgroundColor = '#646464';
|
||||
window.location.hash = '#' + name;
|
||||
}
|
||||
else {
|
||||
e.style.display = 'none';
|
||||
b.style.backgroundColor = '#404040';
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body onload="load_data();setInterval(load_data, 2000);toggle_menu(window.location.hash.substr(1));">
|
||||
<div style="font-size:3rem;text-align:center;">P2Pool mini</div><div style="font-size:1.1rem;text-align:center;">Decentralized Monero mining pool</div>
|
||||
<div style="font-size:1rem;text-align:center;">Latest release: <span id="latest_release"><a href="https://github.com/SChernykh/p2pool/releases/latest" target="_blank">P2Pool</a></span></div>
|
||||
<br>
|
||||
<table id="main_menu" style="width:100%;margin-left:auto;margin-right:auto;table-layout:fixed;text-align:center;-ms-touch-action:none;touch-action:none;"><tr>
|
||||
<td onclick="toggle_menu('pool')" id="button_pool">Pool</td>
|
||||
<td onclick="toggle_menu('blocks')" id="button_blocks">Blocks</td>
|
||||
<td onclick="toggle_menu('help')" id="button_help">Get started</td>
|
||||
<td onclick="toggle_menu('faq')" id="button_faq">FAQ</td>
|
||||
</tr></table>
|
||||
<br>
|
||||
<table id="menu_pool" class="menu_page">
|
||||
<tr><td></td><td style="width:17rem;">Pool</td><td>Network</td></tr>
|
||||
<tr><td style="padding-bottom: 1rem;"></td><td></td><td></td></tr>
|
||||
<tr><td>Hashrate</td><td><span id="pool_hashrate">N/A</span></td><td><span id="monero_hashrate">N/A</span></td></tr>
|
||||
<tr><td>Miners</td><td><span id="pool_miners">N/A</span></td><td></td></tr>
|
||||
<tr><td>PPLNS window</td><td><span id="pplns_duration">N/A</span></td><td></td></tr>
|
||||
<tr><td>Last block</td><td><span id="pool_last_block">N/A</span></td><td><span id="monero_last_block">N/A</span></td></tr>
|
||||
<tr><td>Total blocks</td><td><span id="pool_total_blocks">N/A</span></td><td></td></tr>
|
||||
<tr><td>Current effort</td><td><span id="current_effort">N/A</span></td><td></td></tr>
|
||||
<tr><td>Average effort<br><div style="text-align:center;font-size:0.9rem">last 50 blocks</div></td><td><span id="average_effort">N/A</span></td><td></td></tr>
|
||||
<tr><td> </td><td></td><td></td></tr>
|
||||
<tr><td>Fee</td><td>0%</td><td></td></tr>
|
||||
<tr><td>Min payout</td><td><span id="min_payout">0.00027 XMR</span></td><td></td></tr>
|
||||
<tr><td>Payout scheme</td><td><a href="https://en.wikipedia.org/wiki/Mining_pool#Pay-per-last-N-shares" target="_blank">PPLNS</a></td><td></td></tr>
|
||||
<tr><td> </td><td></td><td></td></tr>
|
||||
<tr><td>Statistics</td><td><a href="https://mini.p2pool.observer/" target="_blank">P2Pool observer</a></td><td></td></tr>
|
||||
</table>
|
||||
<table id="menu_blocks" class="menu_page">
|
||||
<tr><td style="padding-right:5rem;">Height</td><td style="padding-right:5rem;">Effort</td><td>Age</td></tr>
|
||||
</table>
|
||||
<table id="menu_help" class="menu_page"><tr><td>
|
||||
|
||||
<details><summary>P2Pool video guide</summary>
|
||||
<ul>
|
||||
<li>A detailed <a href="https://www.youtube.com/watch?v=NbxbRu-2GWI" target="_blank">video guide</a> to install P2Pool and start mining
|
||||
</ul>
|
||||
</details>
|
||||
|
||||
<details><summary>Setup Monero wallet</summary>
|
||||
Wallets with confirmed P2Pool support<br>
|
||||
<span style="font-size:0.9rem;color:#e09000;">You might not see P2Pool payouts in other wallets if they're not updated!</span>
|
||||
<ul>
|
||||
<li>Official <a href="https://www.getmonero.org/downloads/" target="_blank">Monero CLI and GUI v0.18.1.0</a> and newer
|
||||
<li><a href="https://play.google.com/store/apps/details?id=com.m2049r.xmrwallet" target="_blank">Monerujo v3.0.2 "Fluorine Fermi"</a> and newer
|
||||
<li><a href="https://play.google.com/store/apps/details?id=com.cakewallet.cake_wallet" target="_blank">Cake Wallet v4.4.5</a> and newer
|
||||
<li><a href="https://featherwallet.org/" target="_blank">Feather Wallet v2.1.0</a> and newer
|
||||
<li><a href="https://mymonero.com/" target="_blank">MyMonero</a>
|
||||
</ul>
|
||||
It's highly recommended to create a new wallet for mining because wallet addresses are public on p2pool. You have to use the primary wallet address for mining. Subaddresses and integrated addresses are not supported, just like with monerod solo mining.
|
||||
</details>
|
||||
|
||||
<details><summary>Setup Monero node</summary>
|
||||
<ul>
|
||||
<li>Download the latest Monero <a href="https://www.getmonero.org/downloads/" target="_blank">release</a>
|
||||
<li>[Optional] Open port <span>18080</span> (Monero p2p port) in your firewall to ensure better connectivity
|
||||
<li>Run <span>./monerod --zmq-pub tcp://127.0.0.1:18083 --out-peers 32 --in-peers 64 --add-priority-node=p2pmd.xmrvsbeast.com:18080 --add-priority-node=nodes.hashvault.pro:18080 --disable-dns-checkpoints --enable-dns-blocklist</span>
|
||||
<li>If your network connection's upload bandwidth is less than 10 Mbit, use <span>--out-peers 8 --in-peers 16</span> instead.
|
||||
<li>Wait until it's fully synchronized. If you didn't run Monero node before, it can take up to several days to synchronize (5-6 hours on a modern PC with fast SSD and fast Internet connection). You can add <span>--prune-blockchain</span> argument to the command line to run a pruned node (3-4 times less disk usage)
|
||||
</ul></details>
|
||||
|
||||
<details><summary>Setup P2Pool node</summary>
|
||||
<ul>
|
||||
<li>Download the latest P2Pool <a href="https://github.com/SChernykh/p2pool/releases/latest" target="_blank">release</a>
|
||||
<li>[Optional] Open port <span>37889</span> (P2Pool port) or <span>37888</span> (P2Pool mini port) in your firewall to ensure better connectivity
|
||||
<li>Run <span>./p2pool --host 127.0.0.1 --wallet YOUR_WALLET_ADDRESS --mini</span>
|
||||
<li>It should take no more than 5-10 minutes to synchronize
|
||||
</ul></details>
|
||||
|
||||
<details><summary>Miner software</summary>
|
||||
<ul>
|
||||
<li><a href="https://xmrig.com/" target="_blank">XMRig</a> is recommended. <a href="https://xmrig.com/proxy" target="_blank">XMRig Proxy</a> is fully supported.
|
||||
<li>Once P2Pool sync is complete, XMRig should be able to connect to the stratum server on port <span>3333</span>
|
||||
<li>Run <span>./xmrig -o 127.0.0.1:3333</span>. Note that you don't need to specify wallet address for xmrig. Wallet address set in xmrig config will be ignored!
|
||||
<li>To set custom fixed difficulty for your miner (for example, <span>10000</span>), run <span>./xmrig -u x+10000 -o 127.0.0.1:3333</span>
|
||||
<li>To connect another mining rig to your P2Pool node, run <span>./xmrig -o YOUR_P2POOL_NODE_IP:3333</span> on that mining rig
|
||||
</ul></details>
|
||||
|
||||
<details><summary>Checking your progress</summary>
|
||||
<ul>
|
||||
<li>You can enter your wallet address at <a href="https://p2pool.observer/" target="_blank">P2Pool Observer</a>
|
||||
<li>P2Pool Observer for P2Pool mini can be found <a href="https://mini.p2pool.observer/" target="_blank">here</a>
|
||||
<li>You will find your wallet's statistics there only after you've mined at least 1 P2Pool share
|
||||
</ul>
|
||||
</details>
|
||||
|
||||
<details><summary>Help and support</summary>
|
||||
P2Pool is a decentralized community, there is no dedicated support. You can reach and get help from other miners on:
|
||||
<ul>
|
||||
<li>IRC channels: <span>#monero-pools</span> and <span>#p2pool-log</span> (<span>#p2pool-mini</span> for P2Pool mini) on <a href="https://libera.chat/" target="_blank">Libera.Chat</a>
|
||||
<li>Reddit: <a href="https://reddit.com/r/MoneroMining/" target="_blank">r/MoneroMining</a>
|
||||
</ul></details>
|
||||
</td></tr></table>
|
||||
<table id="menu_faq" class="menu_page"><tr><td>
|
||||
<ul>
|
||||
<li><span style="font-size:2rem;color:#e09000;">What are system requirements to run P2Pool?</span>
|
||||
<ul><li>P2Pool needs 0.5 GB disc space and 2.6 GB RAM to run (0.6 GB RAM in light mode). Add this to monerod requirements if you run both on the same machine. Add <span style="color:#808080;">--light-mode</span> to p2pool command line to reduce the memory usage to 0.6 GB, or <span style="color:#808080;">--no-randomx --no-cache</span> to reduce the memory usage to less than 100 MB.</ul><br>
|
||||
<li><span style="font-size:2rem;color:#e09000;">Does P2Pool work with XMRig Proxy?</span>
|
||||
<ul><li>Yes, P2Pool fully supports <a href="https://xmrig.com/proxy" target="_blank">XMRig Proxy</a>.</ul><br>
|
||||
<li><span style="font-size:2rem;color:#e09000;">Does monerod have to be run on the same machine as P2Pool?</span>
|
||||
<ul><li>No, you can run them on different machines and even connect multiple p2pool instances to a single server running monerod</ul><br>
|
||||
<li><span style="font-size:2rem;color:#e09000;">Does P2Pool work with pruned Monero node?</span>
|
||||
<ul><li>Yes, you can use pruned Monero node to mine on P2Pool</ul><br>
|
||||
<li><span style="font-size:2rem;color:#e09000;">Does P2Pool require incoming connections to work properly?</span>
|
||||
<ul><li>P2Pool (and Monero) can work with only outgoing connections, but it's recommended to open ports 18080 (Monero) and 37889/37888 (P2Pool/P2Pool mini) for better connectivity with the rest of the network.</ul><br>
|
||||
<li><span style="font-size:2rem;color:#e09000;">I have been mining for several hours and still got no rewards?</span>
|
||||
<ul><li>P2Pool doesn't work exactly like regular pools - there's no "pending balance" here. You need to find a pool share first and then wait for P2Pool to find a Monero block. You'll get a payout to your XMR wallet as soon as a block is found and you have shares in PPLNS window. It can take several days to a week to find a share if your hashrate is low. Type "status" command in P2Pool console or visit <a href="https://mini.p2pool.observer/" target="_blank">P2Pool observer</a> to check your progress.</ul><br>
|
||||
<li><span style="font-size:2rem;color:#e09000;">I am mining but I can't find any shares</span>
|
||||
<ul><li>First check for any warnings and errors in P2Pool console and logs. If everything works fine, you can check the <a href="https://p2pool.observer/calculate-share-time" target="_blank">average share time calculator</a> to get an idea how often you should find a share with your hashrate. If this time is more than 1 day, it's recommended to switch to P2Pool mini by adding <span style="color:#808080;">--mini</span> to P2Pool command line.</ul><br>
|
||||
<li><span style="font-size:2rem;color:#e09000;">I get an error "monerod RPC ... is incompatible, update to RPC >= v3.8"</span>
|
||||
<ul><li>Use monerod v0.18.0.0 or newer</ul><br>
|
||||
<li><span style="font-size:2rem;color:#e09000;">I get warnings "peer ... is ahead on mainchain (height ..., your height ...). Is your monerod stuck or lagging?"</span>
|
||||
<ul><li>Make sure you add these arguments to monerod command line: <span style="color:#808080;">--zmq-pub tcp://127.0.0.1:18083 --disable-dns-checkpoints --enable-dns-blocklist</span></ul><br>
|
||||
</ul>
|
||||
</td></tr></table>
|
||||
<br><br>
|
||||
<div style="position:fixed;width:100%;bottom:0;background-color:#383838;font-size:1rem;text-align:center;color:#b0b0b0;">
|
||||
<a href="api/" target="_blank">Pool API</a> | <a href="https://github.com/SChernykh/p2pool" target="_blank">Source</a> | <a href="http://yucmgsbw7nknw7oi3bkuwudvc657g2xcqahhbjyewazusyytapqo4xid.onion/mini/" target="_blank">Onion URL</a><br>
|
||||
Donate to support the project:<br><a href="monero:44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg?tx_description=Donation%20to%20P2Pool" style="font-size:0.9rem;color:#b0b0b0;">44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg</a><br>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Vendored
+1
-1
Submodule external/src/RandomX updated: 1adc7d8efd...80d9f08b4f
Vendored
+1
-1
Submodule external/src/cppzmq updated: a98fa4a91d...c94c20743e
Vendored
+44
-8
@@ -3831,15 +3831,51 @@ int sc_isnonzero(const unsigned char *s) {
|
||||
s[27] | s[28] | s[29] | s[30] | s[31]) - 1) >> 8) + 1;
|
||||
}
|
||||
|
||||
int ge_p3_is_point_at_infinity(const ge_p3 *p) {
|
||||
// X = 0 and Y == Z
|
||||
int n;
|
||||
for (n = 0; n < 10; ++n)
|
||||
int ge_p3_is_point_at_infinity_vartime(const ge_p3 *p) {
|
||||
// https://eprint.iacr.org/2008/522
|
||||
// X == T == 0 and Y/Z == 1
|
||||
// note: convert all pieces to canonical bytes in case rounding is required (i.e. an element is > q)
|
||||
// note2: even though T = XY/Z is true for valid point representations (implying it isn't necessary to
|
||||
// test T == 0), the input to this function might NOT be valid, so we must test T == 0
|
||||
char result_X_bytes[32];
|
||||
fe_tobytes((unsigned char*)&result_X_bytes, p->X);
|
||||
|
||||
// X != 0
|
||||
for (int i = 0; i < 32; ++i)
|
||||
{
|
||||
if (p->X[n] | p->T[n])
|
||||
return 0;
|
||||
if (p->Y[n] != p->Z[n])
|
||||
if (result_X_bytes[i])
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
|
||||
char result_T_bytes[32];
|
||||
fe_tobytes((unsigned char*)&result_T_bytes, p->T);
|
||||
|
||||
// T != 0
|
||||
for (int i = 0; i < 32; ++i)
|
||||
{
|
||||
if (result_T_bytes[i])
|
||||
return 0;
|
||||
}
|
||||
|
||||
char result_Y_bytes[32];
|
||||
char result_Z_bytes[32];
|
||||
fe_tobytes((unsigned char*)&result_Y_bytes, p->Y);
|
||||
fe_tobytes((unsigned char*)&result_Z_bytes, p->Z);
|
||||
|
||||
// Y != Z
|
||||
for (int i = 0; i < 32; ++i)
|
||||
{
|
||||
if (result_Y_bytes[i] != result_Z_bytes[i])
|
||||
return 0;
|
||||
}
|
||||
|
||||
// is Y nonzero? then Y/Z == 1
|
||||
for (int i = 0; i < 32; ++i)
|
||||
{
|
||||
if (result_Y_bytes[i] != 0)
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Y/Z = 0/0
|
||||
return 0;
|
||||
}
|
||||
|
||||
Vendored
+1
-1
@@ -162,4 +162,4 @@ void fe_add(fe h, const fe f, const fe g);
|
||||
void fe_tobytes(unsigned char *, const fe);
|
||||
void fe_invert(fe out, const fe z);
|
||||
|
||||
int ge_p3_is_point_at_infinity(const ge_p3 *p);
|
||||
int ge_p3_is_point_at_infinity_vartime(const ge_p3 *p);
|
||||
|
||||
+1
Submodule external/src/curl added at 50490c0679
Vendored
+132
@@ -0,0 +1,132 @@
|
||||
// Copyright (c) 2014-2022, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4514 4820)
|
||||
#endif
|
||||
|
||||
#include "hardforks.h"
|
||||
|
||||
#undef MONERO_DEFAULT_LOG_CATEGORY
|
||||
#define MONERO_DEFAULT_LOG_CATEGORY "blockchain.hardforks"
|
||||
|
||||
const hardfork_t mainnet_hard_forks[] = {
|
||||
// version 1 from the start of the blockchain
|
||||
{ 1, 1, 0, 1341378000 },
|
||||
|
||||
// version 2 starts from block 1009827, which is on or around the 20th of March, 2016. Fork time finalised on 2015-09-20. No fork voting occurs for the v2 fork.
|
||||
{ 2, 1009827, 0, 1442763710 },
|
||||
|
||||
// version 3 starts from block 1141317, which is on or around the 24th of September, 2016. Fork time finalised on 2016-03-21.
|
||||
{ 3, 1141317, 0, 1458558528 },
|
||||
|
||||
// version 4 starts from block 1220516, which is on or around the 5th of January, 2017. Fork time finalised on 2016-09-18.
|
||||
{ 4, 1220516, 0, 1483574400 },
|
||||
|
||||
// version 5 starts from block 1288616, which is on or around the 15th of April, 2017. Fork time finalised on 2017-03-14.
|
||||
{ 5, 1288616, 0, 1489520158 },
|
||||
|
||||
// version 6 starts from block 1400000, which is on or around the 16th of September, 2017. Fork time finalised on 2017-08-18.
|
||||
{ 6, 1400000, 0, 1503046577 },
|
||||
|
||||
// version 7 starts from block 1546000, which is on or around the 6th of April, 2018. Fork time finalised on 2018-03-17.
|
||||
{ 7, 1546000, 0, 1521303150 },
|
||||
|
||||
// version 8 starts from block 1685555, which is on or around the 18th of October, 2018. Fork time finalised on 2018-09-02.
|
||||
{ 8, 1685555, 0, 1535889547 },
|
||||
|
||||
// version 9 starts from block 1686275, which is on or around the 19th of October, 2018. Fork time finalised on 2018-09-02.
|
||||
{ 9, 1686275, 0, 1535889548 },
|
||||
|
||||
// version 10 starts from block 1788000, which is on or around the 9th of March, 2019. Fork time finalised on 2019-02-10.
|
||||
{ 10, 1788000, 0, 1549792439 },
|
||||
|
||||
// version 11 starts from block 1788720, which is on or around the 10th of March, 2019. Fork time finalised on 2019-02-15.
|
||||
{ 11, 1788720, 0, 1550225678 },
|
||||
|
||||
// version 12 starts from block 1978433, which is on or around the 30th of November, 2019. Fork time finalised on 2019-10-18.
|
||||
{ 12, 1978433, 0, 1571419280 },
|
||||
|
||||
{ 13, 2210000, 0, 1598180817 },
|
||||
{ 14, 2210720, 0, 1598180818 },
|
||||
|
||||
{ 15, 2688888, 0, 1656629117 },
|
||||
{ 16, 2689608, 0, 1656629118 },
|
||||
};
|
||||
const size_t num_mainnet_hard_forks = sizeof(mainnet_hard_forks) / sizeof(mainnet_hard_forks[0]);
|
||||
const uint64_t mainnet_hard_fork_version_1_till = 1009826;
|
||||
|
||||
const hardfork_t testnet_hard_forks[] = {
|
||||
// version 1 from the start of the blockchain
|
||||
{ 1, 1, 0, 1341378000 },
|
||||
|
||||
// version 2 starts from block 624634, which is on or around the 23rd of November, 2015. Fork time finalised on 2015-11-20. No fork voting occurs for the v2 fork.
|
||||
{ 2, 624634, 0, 1445355000 },
|
||||
|
||||
// versions 3-5 were passed in rapid succession from September 18th, 2016
|
||||
{ 3, 800500, 0, 1472415034 },
|
||||
{ 4, 801219, 0, 1472415035 },
|
||||
{ 5, 802660, 0, 1472415036 + 86400*180 }, // add 5 months on testnet to shut the update warning up since there's a large gap to v6
|
||||
|
||||
{ 6, 971400, 0, 1501709789 },
|
||||
{ 7, 1057027, 0, 1512211236 },
|
||||
{ 8, 1057058, 0, 1533211200 },
|
||||
{ 9, 1057778, 0, 1533297600 },
|
||||
{ 10, 1154318, 0, 1550153694 },
|
||||
{ 11, 1155038, 0, 1550225678 },
|
||||
{ 12, 1308737, 0, 1569582000 },
|
||||
{ 13, 1543939, 0, 1599069376 },
|
||||
{ 14, 1544659, 0, 1599069377 },
|
||||
{ 15, 1982800, 0, 1652727000 },
|
||||
{ 16, 1983520, 0, 1652813400 },
|
||||
};
|
||||
const size_t num_testnet_hard_forks = sizeof(testnet_hard_forks) / sizeof(testnet_hard_forks[0]);
|
||||
const uint64_t testnet_hard_fork_version_1_till = 624633;
|
||||
|
||||
const hardfork_t stagenet_hard_forks[] = {
|
||||
// version 1 from the start of the blockchain
|
||||
{ 1, 1, 0, 1341378000 },
|
||||
|
||||
// versions 2-7 in rapid succession from March 13th, 2018
|
||||
{ 2, 32000, 0, 1521000000 },
|
||||
{ 3, 33000, 0, 1521120000 },
|
||||
{ 4, 34000, 0, 1521240000 },
|
||||
{ 5, 35000, 0, 1521360000 },
|
||||
{ 6, 36000, 0, 1521480000 },
|
||||
{ 7, 37000, 0, 1521600000 },
|
||||
{ 8, 176456, 0, 1537821770 },
|
||||
{ 9, 177176, 0, 1537821771 },
|
||||
{ 10, 269000, 0, 1550153694 },
|
||||
{ 11, 269720, 0, 1550225678 },
|
||||
{ 12, 454721, 0, 1571419280 },
|
||||
{ 13, 675405, 0, 1598180817 },
|
||||
{ 14, 676125, 0, 1598180818 },
|
||||
{ 15, 1151000, 0, 1656629117 },
|
||||
{ 16, 1151720, 0, 1656629118 },
|
||||
};
|
||||
const size_t num_stagenet_hard_forks = sizeof(stagenet_hard_forks) / sizeof(stagenet_hard_forks[0]);
|
||||
Vendored
+52
@@ -0,0 +1,52 @@
|
||||
// Copyright (c) 2014-2022, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
|
||||
struct hardfork_t
|
||||
{
|
||||
uint8_t version;
|
||||
uint64_t height;
|
||||
uint8_t threshold;
|
||||
time_t time;
|
||||
hardfork_t(uint8_t version, uint64_t height, uint8_t threshold, time_t time): version(version), height(height), threshold(threshold), time(time) {}
|
||||
};
|
||||
|
||||
extern const hardfork_t mainnet_hard_forks[];
|
||||
extern const uint64_t mainnet_hard_fork_version_1_till;
|
||||
extern const size_t num_mainnet_hard_forks;
|
||||
|
||||
extern const hardfork_t testnet_hard_forks[];
|
||||
extern const uint64_t testnet_hard_fork_version_1_till;
|
||||
extern const size_t num_testnet_hard_forks;
|
||||
|
||||
extern const hardfork_t stagenet_hard_forks[];
|
||||
extern const size_t num_stagenet_hard_forks;
|
||||
Vendored
-1
Submodule external/src/libsodium deleted from dce3bca3ba
Vendored
+1
-1
Submodule external/src/libuv updated: bb0b4bb783...26d43f49ff
Vendored
+1
-1
Submodule external/src/libzmq updated: a01d259db3...ec013f3a17
Vendored
-22
@@ -1,22 +0,0 @@
|
||||
This software is licensed under the MIT License.
|
||||
|
||||
Copyright Fedor Indutny, 2018.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
persons to whom the Software is furnished to do so, subject to the
|
||||
following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
Vendored
-375
@@ -1,375 +0,0 @@
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4100 4668 4710 4711 4820)
|
||||
#elif defined __GNUC__
|
||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "llhttp.h"
|
||||
|
||||
#define CALLBACK_MAYBE(PARSER, NAME) \
|
||||
do { \
|
||||
const llhttp_settings_t* settings; \
|
||||
settings = (const llhttp_settings_t*) (PARSER)->settings; \
|
||||
if (settings == NULL || settings->NAME == NULL) { \
|
||||
err = 0; \
|
||||
break; \
|
||||
} \
|
||||
err = settings->NAME((PARSER)); \
|
||||
} while (0)
|
||||
|
||||
#define SPAN_CALLBACK_MAYBE(PARSER, NAME, START, LEN) \
|
||||
do { \
|
||||
const llhttp_settings_t* settings; \
|
||||
settings = (const llhttp_settings_t*) (PARSER)->settings; \
|
||||
if (settings == NULL || settings->NAME == NULL) { \
|
||||
err = 0; \
|
||||
break; \
|
||||
} \
|
||||
err = settings->NAME((PARSER), (START), (LEN)); \
|
||||
if (err == -1) { \
|
||||
err = HPE_USER; \
|
||||
llhttp_set_error_reason((PARSER), "Span callback error in " #NAME); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
void llhttp_init(llhttp_t* parser, llhttp_type_t type,
|
||||
const llhttp_settings_t* settings) {
|
||||
llhttp__internal_init(parser);
|
||||
|
||||
parser->type = type;
|
||||
parser->settings = (void*) settings;
|
||||
}
|
||||
|
||||
|
||||
#if defined(__wasm__)
|
||||
|
||||
extern int wasm_on_message_begin(llhttp_t * p);
|
||||
extern int wasm_on_url(llhttp_t* p, const char* at, size_t length);
|
||||
extern int wasm_on_status(llhttp_t* p, const char* at, size_t length);
|
||||
extern int wasm_on_header_field(llhttp_t* p, const char* at, size_t length);
|
||||
extern int wasm_on_header_value(llhttp_t* p, const char* at, size_t length);
|
||||
extern int wasm_on_headers_complete(llhttp_t * p, int status_code,
|
||||
uint8_t upgrade, int should_keep_alive);
|
||||
extern int wasm_on_body(llhttp_t* p, const char* at, size_t length);
|
||||
extern int wasm_on_message_complete(llhttp_t * p);
|
||||
|
||||
static int wasm_on_headers_complete_wrap(llhttp_t* p) {
|
||||
return wasm_on_headers_complete(p, p->status_code, p->upgrade,
|
||||
llhttp_should_keep_alive(p));
|
||||
}
|
||||
|
||||
const llhttp_settings_t wasm_settings = {
|
||||
wasm_on_message_begin,
|
||||
wasm_on_url,
|
||||
wasm_on_status,
|
||||
wasm_on_header_field,
|
||||
wasm_on_header_value,
|
||||
wasm_on_headers_complete_wrap,
|
||||
wasm_on_body,
|
||||
wasm_on_message_complete,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
||||
llhttp_t* llhttp_alloc(llhttp_type_t type) {
|
||||
llhttp_t* parser = malloc(sizeof(llhttp_t));
|
||||
llhttp_init(parser, type, &wasm_settings);
|
||||
return parser;
|
||||
}
|
||||
|
||||
void llhttp_free(llhttp_t* parser) {
|
||||
free(parser);
|
||||
}
|
||||
|
||||
/* Some getters required to get stuff from the parser */
|
||||
|
||||
uint8_t llhttp_get_type(llhttp_t* parser) {
|
||||
return parser->type;
|
||||
}
|
||||
|
||||
uint8_t llhttp_get_http_major(llhttp_t* parser) {
|
||||
return parser->http_major;
|
||||
}
|
||||
|
||||
uint8_t llhttp_get_http_minor(llhttp_t* parser) {
|
||||
return parser->http_minor;
|
||||
}
|
||||
|
||||
uint8_t llhttp_get_method(llhttp_t* parser) {
|
||||
return parser->method;
|
||||
}
|
||||
|
||||
int llhttp_get_status_code(llhttp_t* parser) {
|
||||
return parser->status_code;
|
||||
}
|
||||
|
||||
uint8_t llhttp_get_upgrade(llhttp_t* parser) {
|
||||
return parser->upgrade;
|
||||
}
|
||||
|
||||
#endif // defined(__wasm__)
|
||||
|
||||
|
||||
void llhttp_reset(llhttp_t* parser) {
|
||||
llhttp_type_t type = parser->type;
|
||||
const llhttp_settings_t* settings = parser->settings;
|
||||
void* data = parser->data;
|
||||
uint8_t lenient_flags = parser->lenient_flags;
|
||||
|
||||
llhttp__internal_init(parser);
|
||||
|
||||
parser->type = type;
|
||||
parser->settings = (void*) settings;
|
||||
parser->data = data;
|
||||
parser->lenient_flags = lenient_flags;
|
||||
}
|
||||
|
||||
|
||||
llhttp_errno_t llhttp_execute(llhttp_t* parser, const char* data, size_t len) {
|
||||
return llhttp__internal_execute(parser, data, data + len);
|
||||
}
|
||||
|
||||
|
||||
void llhttp_settings_init(llhttp_settings_t* settings) {
|
||||
memset(settings, 0, sizeof(*settings));
|
||||
}
|
||||
|
||||
|
||||
llhttp_errno_t llhttp_finish(llhttp_t* parser) {
|
||||
int err;
|
||||
|
||||
/* We're in an error state. Don't bother doing anything. */
|
||||
if (parser->error != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (parser->finish) {
|
||||
case HTTP_FINISH_SAFE_WITH_CB:
|
||||
CALLBACK_MAYBE(parser, on_message_complete);
|
||||
if (err != HPE_OK) return err;
|
||||
|
||||
/* FALLTHROUGH */
|
||||
case HTTP_FINISH_SAFE:
|
||||
return HPE_OK;
|
||||
case HTTP_FINISH_UNSAFE:
|
||||
parser->reason = "Invalid EOF state";
|
||||
return HPE_INVALID_EOF_STATE;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void llhttp_pause(llhttp_t* parser) {
|
||||
if (parser->error != HPE_OK) {
|
||||
return;
|
||||
}
|
||||
|
||||
parser->error = HPE_PAUSED;
|
||||
parser->reason = "Paused";
|
||||
}
|
||||
|
||||
|
||||
void llhttp_resume(llhttp_t* parser) {
|
||||
if (parser->error != HPE_PAUSED) {
|
||||
return;
|
||||
}
|
||||
|
||||
parser->error = 0;
|
||||
}
|
||||
|
||||
|
||||
void llhttp_resume_after_upgrade(llhttp_t* parser) {
|
||||
if (parser->error != HPE_PAUSED_UPGRADE) {
|
||||
return;
|
||||
}
|
||||
|
||||
parser->error = 0;
|
||||
}
|
||||
|
||||
|
||||
llhttp_errno_t llhttp_get_errno(const llhttp_t* parser) {
|
||||
return parser->error;
|
||||
}
|
||||
|
||||
|
||||
const char* llhttp_get_error_reason(const llhttp_t* parser) {
|
||||
return parser->reason;
|
||||
}
|
||||
|
||||
|
||||
void llhttp_set_error_reason(llhttp_t* parser, const char* reason) {
|
||||
parser->reason = reason;
|
||||
}
|
||||
|
||||
|
||||
const char* llhttp_get_error_pos(const llhttp_t* parser) {
|
||||
return parser->error_pos;
|
||||
}
|
||||
|
||||
|
||||
const char* llhttp_errno_name(llhttp_errno_t err) {
|
||||
#define HTTP_ERRNO_GEN(CODE, NAME, _) case HPE_##NAME: return "HPE_" #NAME;
|
||||
switch (err) {
|
||||
HTTP_ERRNO_MAP(HTTP_ERRNO_GEN)
|
||||
default: abort();
|
||||
}
|
||||
#undef HTTP_ERRNO_GEN
|
||||
}
|
||||
|
||||
|
||||
const char* llhttp_method_name(llhttp_method_t method) {
|
||||
#define HTTP_METHOD_GEN(NUM, NAME, STRING) case HTTP_##NAME: return #STRING;
|
||||
switch (method) {
|
||||
HTTP_ALL_METHOD_MAP(HTTP_METHOD_GEN)
|
||||
default: abort();
|
||||
}
|
||||
#undef HTTP_METHOD_GEN
|
||||
}
|
||||
|
||||
|
||||
void llhttp_set_lenient_headers(llhttp_t* parser, int enabled) {
|
||||
if (enabled) {
|
||||
parser->lenient_flags |= LENIENT_HEADERS;
|
||||
} else {
|
||||
parser->lenient_flags &= ~LENIENT_HEADERS;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void llhttp_set_lenient_chunked_length(llhttp_t* parser, int enabled) {
|
||||
if (enabled) {
|
||||
parser->lenient_flags |= LENIENT_CHUNKED_LENGTH;
|
||||
} else {
|
||||
parser->lenient_flags &= ~LENIENT_CHUNKED_LENGTH;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void llhttp_set_lenient_keep_alive(llhttp_t* parser, int enabled) {
|
||||
if (enabled) {
|
||||
parser->lenient_flags |= LENIENT_KEEP_ALIVE;
|
||||
} else {
|
||||
parser->lenient_flags &= ~LENIENT_KEEP_ALIVE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Callbacks */
|
||||
|
||||
|
||||
int llhttp__on_message_begin(llhttp_t* s, const char* p, const char* endp) {
|
||||
int err;
|
||||
CALLBACK_MAYBE(s, on_message_begin);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
int llhttp__on_url(llhttp_t* s, const char* p, const char* endp) {
|
||||
int err;
|
||||
SPAN_CALLBACK_MAYBE(s, on_url, p, endp - p);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
int llhttp__on_url_complete(llhttp_t* s, const char* p, const char* endp) {
|
||||
int err;
|
||||
CALLBACK_MAYBE(s, on_url_complete);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
int llhttp__on_status(llhttp_t* s, const char* p, const char* endp) {
|
||||
int err;
|
||||
SPAN_CALLBACK_MAYBE(s, on_status, p, endp - p);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
int llhttp__on_status_complete(llhttp_t* s, const char* p, const char* endp) {
|
||||
int err;
|
||||
CALLBACK_MAYBE(s, on_status_complete);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
int llhttp__on_header_field(llhttp_t* s, const char* p, const char* endp) {
|
||||
int err;
|
||||
SPAN_CALLBACK_MAYBE(s, on_header_field, p, endp - p);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
int llhttp__on_header_field_complete(llhttp_t* s, const char* p, const char* endp) {
|
||||
int err;
|
||||
CALLBACK_MAYBE(s, on_header_field_complete);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
int llhttp__on_header_value(llhttp_t* s, const char* p, const char* endp) {
|
||||
int err;
|
||||
SPAN_CALLBACK_MAYBE(s, on_header_value, p, endp - p);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
int llhttp__on_header_value_complete(llhttp_t* s, const char* p, const char* endp) {
|
||||
int err;
|
||||
CALLBACK_MAYBE(s, on_header_value_complete);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
int llhttp__on_headers_complete(llhttp_t* s, const char* p, const char* endp) {
|
||||
int err;
|
||||
CALLBACK_MAYBE(s, on_headers_complete);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
int llhttp__on_message_complete(llhttp_t* s, const char* p, const char* endp) {
|
||||
int err;
|
||||
CALLBACK_MAYBE(s, on_message_complete);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
int llhttp__on_body(llhttp_t* s, const char* p, const char* endp) {
|
||||
int err;
|
||||
SPAN_CALLBACK_MAYBE(s, on_body, p, endp - p);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
int llhttp__on_chunk_header(llhttp_t* s, const char* p, const char* endp) {
|
||||
int err;
|
||||
CALLBACK_MAYBE(s, on_chunk_header);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
int llhttp__on_chunk_complete(llhttp_t* s, const char* p, const char* endp) {
|
||||
int err;
|
||||
CALLBACK_MAYBE(s, on_chunk_complete);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/* Private */
|
||||
|
||||
|
||||
void llhttp__debug(llhttp_t* s, const char* p, const char* endp,
|
||||
const char* msg) {
|
||||
if (p == endp) {
|
||||
fprintf(stderr, "p=%p type=%d flags=%02x next=null debug=%s\n", s, s->type,
|
||||
s->flags, msg);
|
||||
} else {
|
||||
fprintf(stderr, "p=%p type=%d flags=%02x next=%02x debug=%s\n", s,
|
||||
s->type, s->flags, *p, msg);
|
||||
}
|
||||
}
|
||||
Vendored
-155
@@ -1,155 +0,0 @@
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4100 4668 4710 4711 4820)
|
||||
#elif defined __GNUC__
|
||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#ifndef LLHTTP__TEST
|
||||
# include "llhttp.h"
|
||||
#else
|
||||
# define llhttp_t llparse_t
|
||||
#endif /* */
|
||||
|
||||
int llhttp_message_needs_eof(const llhttp_t* parser);
|
||||
int llhttp_should_keep_alive(const llhttp_t* parser);
|
||||
|
||||
int llhttp__before_headers_complete(llhttp_t* parser, const char* p,
|
||||
const char* endp) {
|
||||
/* Set this here so that on_headers_complete() callbacks can see it */
|
||||
if ((parser->flags & F_UPGRADE) &&
|
||||
(parser->flags & F_CONNECTION_UPGRADE)) {
|
||||
/* For responses, "Upgrade: foo" and "Connection: upgrade" are
|
||||
* mandatory only when it is a 101 Switching Protocols response,
|
||||
* otherwise it is purely informational, to announce support.
|
||||
*/
|
||||
parser->upgrade =
|
||||
(parser->type == HTTP_REQUEST || parser->status_code == 101);
|
||||
} else {
|
||||
parser->upgrade = (parser->method == HTTP_CONNECT);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Return values:
|
||||
* 0 - No body, `restart`, message_complete
|
||||
* 1 - CONNECT request, `restart`, message_complete, and pause
|
||||
* 2 - chunk_size_start
|
||||
* 3 - body_identity
|
||||
* 4 - body_identity_eof
|
||||
* 5 - invalid transfer-encoding for request
|
||||
*/
|
||||
int llhttp__after_headers_complete(llhttp_t* parser, const char* p,
|
||||
const char* endp) {
|
||||
int hasBody;
|
||||
|
||||
hasBody = parser->flags & F_CHUNKED || parser->content_length > 0;
|
||||
if (parser->upgrade && (parser->method == HTTP_CONNECT ||
|
||||
(parser->flags & F_SKIPBODY) || !hasBody)) {
|
||||
/* Exit, the rest of the message is in a different protocol. */
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (parser->flags & F_SKIPBODY) {
|
||||
return 0;
|
||||
} else if (parser->flags & F_CHUNKED) {
|
||||
/* chunked encoding - ignore Content-Length header, prepare for a chunk */
|
||||
return 2;
|
||||
} else if (parser->flags & F_TRANSFER_ENCODING) {
|
||||
if (parser->type == HTTP_REQUEST &&
|
||||
(parser->lenient_flags & LENIENT_CHUNKED_LENGTH) == 0) {
|
||||
/* RFC 7230 3.3.3 */
|
||||
|
||||
/* If a Transfer-Encoding header field
|
||||
* is present in a request and the chunked transfer coding is not
|
||||
* the final encoding, the message body length cannot be determined
|
||||
* reliably; the server MUST respond with the 400 (Bad Request)
|
||||
* status code and then close the connection.
|
||||
*/
|
||||
return 5;
|
||||
} else {
|
||||
/* RFC 7230 3.3.3 */
|
||||
|
||||
/* If a Transfer-Encoding header field is present in a response and
|
||||
* the chunked transfer coding is not the final encoding, the
|
||||
* message body length is determined by reading the connection until
|
||||
* it is closed by the server.
|
||||
*/
|
||||
return 4;
|
||||
}
|
||||
} else {
|
||||
if (!(parser->flags & F_CONTENT_LENGTH)) {
|
||||
if (!llhttp_message_needs_eof(parser)) {
|
||||
/* Assume content-length 0 - read the next */
|
||||
return 0;
|
||||
} else {
|
||||
/* Read body until EOF */
|
||||
return 4;
|
||||
}
|
||||
} else if (parser->content_length == 0) {
|
||||
/* Content-Length header given but zero: Content-Length: 0\r\n */
|
||||
return 0;
|
||||
} else {
|
||||
/* Content-Length header given and non-zero */
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int llhttp__after_message_complete(llhttp_t* parser, const char* p,
|
||||
const char* endp) {
|
||||
int should_keep_alive;
|
||||
|
||||
should_keep_alive = llhttp_should_keep_alive(parser);
|
||||
parser->finish = HTTP_FINISH_SAFE;
|
||||
parser->flags = 0;
|
||||
|
||||
/* NOTE: this is ignored in loose parsing mode */
|
||||
return should_keep_alive;
|
||||
}
|
||||
|
||||
|
||||
int llhttp_message_needs_eof(const llhttp_t* parser) {
|
||||
if (parser->type == HTTP_REQUEST) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* See RFC 2616 section 4.4 */
|
||||
if (parser->status_code / 100 == 1 || /* 1xx e.g. Continue */
|
||||
parser->status_code == 204 || /* No Content */
|
||||
parser->status_code == 304 || /* Not Modified */
|
||||
(parser->flags & F_SKIPBODY)) { /* response to a HEAD request */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* RFC 7230 3.3.3, see `llhttp__after_headers_complete` */
|
||||
if ((parser->flags & F_TRANSFER_ENCODING) &&
|
||||
(parser->flags & F_CHUNKED) == 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (parser->flags & (F_CHUNKED | F_CONTENT_LENGTH)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int llhttp_should_keep_alive(const llhttp_t* parser) {
|
||||
if (parser->http_major > 0 && parser->http_minor > 0) {
|
||||
/* HTTP/1.1 */
|
||||
if (parser->flags & F_CONNECTION_CLOSE) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
/* HTTP/1.0 or earlier */
|
||||
if (!(parser->flags & F_CONNECTION_KEEP_ALIVE)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return !llhttp_message_needs_eof(parser);
|
||||
}
|
||||
Vendored
-14933
File diff suppressed because it is too large
Load Diff
Vendored
-564
@@ -1,564 +0,0 @@
|
||||
#ifndef INCLUDE_LLHTTP_H_
|
||||
#define INCLUDE_LLHTTP_H_
|
||||
|
||||
#define LLHTTP_VERSION_MAJOR 6
|
||||
#define LLHTTP_VERSION_MINOR 0
|
||||
#define LLHTTP_VERSION_PATCH 4
|
||||
|
||||
#ifndef LLHTTP_STRICT_MODE
|
||||
# define LLHTTP_STRICT_MODE 0
|
||||
#endif
|
||||
|
||||
#ifndef INCLUDE_LLHTTP_ITSELF_H_
|
||||
#define INCLUDE_LLHTTP_ITSELF_H_
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct llhttp__internal_s llhttp__internal_t;
|
||||
struct llhttp__internal_s {
|
||||
int32_t _index;
|
||||
void* _span_pos0;
|
||||
void* _span_cb0;
|
||||
int32_t error;
|
||||
const char* reason;
|
||||
const char* error_pos;
|
||||
void* data;
|
||||
void* _current;
|
||||
uint64_t content_length;
|
||||
uint8_t type;
|
||||
uint8_t method;
|
||||
uint8_t http_major;
|
||||
uint8_t http_minor;
|
||||
uint8_t header_state;
|
||||
uint8_t lenient_flags;
|
||||
uint8_t upgrade;
|
||||
uint8_t finish;
|
||||
uint16_t flags;
|
||||
uint16_t status_code;
|
||||
void* settings;
|
||||
};
|
||||
|
||||
int llhttp__internal_init(llhttp__internal_t* s);
|
||||
int llhttp__internal_execute(llhttp__internal_t* s, const char* p, const char* endp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
#endif /* INCLUDE_LLHTTP_ITSELF_H_ */
|
||||
|
||||
#ifndef LLLLHTTP_C_HEADERS_
|
||||
#define LLLLHTTP_C_HEADERS_
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum llhttp_errno {
|
||||
HPE_OK = 0,
|
||||
HPE_INTERNAL = 1,
|
||||
HPE_STRICT = 2,
|
||||
HPE_LF_EXPECTED = 3,
|
||||
HPE_UNEXPECTED_CONTENT_LENGTH = 4,
|
||||
HPE_CLOSED_CONNECTION = 5,
|
||||
HPE_INVALID_METHOD = 6,
|
||||
HPE_INVALID_URL = 7,
|
||||
HPE_INVALID_CONSTANT = 8,
|
||||
HPE_INVALID_VERSION = 9,
|
||||
HPE_INVALID_HEADER_TOKEN = 10,
|
||||
HPE_INVALID_CONTENT_LENGTH = 11,
|
||||
HPE_INVALID_CHUNK_SIZE = 12,
|
||||
HPE_INVALID_STATUS = 13,
|
||||
HPE_INVALID_EOF_STATE = 14,
|
||||
HPE_INVALID_TRANSFER_ENCODING = 15,
|
||||
HPE_CB_MESSAGE_BEGIN = 16,
|
||||
HPE_CB_HEADERS_COMPLETE = 17,
|
||||
HPE_CB_MESSAGE_COMPLETE = 18,
|
||||
HPE_CB_CHUNK_HEADER = 19,
|
||||
HPE_CB_CHUNK_COMPLETE = 20,
|
||||
HPE_PAUSED = 21,
|
||||
HPE_PAUSED_UPGRADE = 22,
|
||||
HPE_PAUSED_H2_UPGRADE = 23,
|
||||
HPE_USER = 24
|
||||
};
|
||||
typedef enum llhttp_errno llhttp_errno_t;
|
||||
|
||||
enum llhttp_flags {
|
||||
F_CONNECTION_KEEP_ALIVE = 0x1,
|
||||
F_CONNECTION_CLOSE = 0x2,
|
||||
F_CONNECTION_UPGRADE = 0x4,
|
||||
F_CHUNKED = 0x8,
|
||||
F_UPGRADE = 0x10,
|
||||
F_CONTENT_LENGTH = 0x20,
|
||||
F_SKIPBODY = 0x40,
|
||||
F_TRAILING = 0x80,
|
||||
F_TRANSFER_ENCODING = 0x200
|
||||
};
|
||||
typedef enum llhttp_flags llhttp_flags_t;
|
||||
|
||||
enum llhttp_lenient_flags {
|
||||
LENIENT_HEADERS = 0x1,
|
||||
LENIENT_CHUNKED_LENGTH = 0x2,
|
||||
LENIENT_KEEP_ALIVE = 0x4
|
||||
};
|
||||
typedef enum llhttp_lenient_flags llhttp_lenient_flags_t;
|
||||
|
||||
enum llhttp_type {
|
||||
HTTP_BOTH = 0,
|
||||
HTTP_REQUEST = 1,
|
||||
HTTP_RESPONSE = 2
|
||||
};
|
||||
typedef enum llhttp_type llhttp_type_t;
|
||||
|
||||
enum llhttp_finish {
|
||||
HTTP_FINISH_SAFE = 0,
|
||||
HTTP_FINISH_SAFE_WITH_CB = 1,
|
||||
HTTP_FINISH_UNSAFE = 2
|
||||
};
|
||||
typedef enum llhttp_finish llhttp_finish_t;
|
||||
|
||||
enum llhttp_method {
|
||||
HTTP_DELETE = 0,
|
||||
HTTP_GET = 1,
|
||||
HTTP_HEAD = 2,
|
||||
HTTP_POST = 3,
|
||||
HTTP_PUT = 4,
|
||||
HTTP_CONNECT = 5,
|
||||
HTTP_OPTIONS = 6,
|
||||
HTTP_TRACE = 7,
|
||||
HTTP_COPY = 8,
|
||||
HTTP_LOCK = 9,
|
||||
HTTP_MKCOL = 10,
|
||||
HTTP_MOVE = 11,
|
||||
HTTP_PROPFIND = 12,
|
||||
HTTP_PROPPATCH = 13,
|
||||
HTTP_SEARCH = 14,
|
||||
HTTP_UNLOCK = 15,
|
||||
HTTP_BIND = 16,
|
||||
HTTP_REBIND = 17,
|
||||
HTTP_UNBIND = 18,
|
||||
HTTP_ACL = 19,
|
||||
HTTP_REPORT = 20,
|
||||
HTTP_MKACTIVITY = 21,
|
||||
HTTP_CHECKOUT = 22,
|
||||
HTTP_MERGE = 23,
|
||||
HTTP_MSEARCH = 24,
|
||||
HTTP_NOTIFY = 25,
|
||||
HTTP_SUBSCRIBE = 26,
|
||||
HTTP_UNSUBSCRIBE = 27,
|
||||
HTTP_PATCH = 28,
|
||||
HTTP_PURGE = 29,
|
||||
HTTP_MKCALENDAR = 30,
|
||||
HTTP_LINK = 31,
|
||||
HTTP_UNLINK = 32,
|
||||
HTTP_SOURCE = 33,
|
||||
HTTP_PRI = 34,
|
||||
HTTP_DESCRIBE = 35,
|
||||
HTTP_ANNOUNCE = 36,
|
||||
HTTP_SETUP = 37,
|
||||
HTTP_PLAY = 38,
|
||||
HTTP_PAUSE = 39,
|
||||
HTTP_TEARDOWN = 40,
|
||||
HTTP_GET_PARAMETER = 41,
|
||||
HTTP_SET_PARAMETER = 42,
|
||||
HTTP_REDIRECT = 43,
|
||||
HTTP_RECORD = 44,
|
||||
HTTP_FLUSH = 45
|
||||
};
|
||||
typedef enum llhttp_method llhttp_method_t;
|
||||
|
||||
#define HTTP_ERRNO_MAP(XX) \
|
||||
XX(0, OK, OK) \
|
||||
XX(1, INTERNAL, INTERNAL) \
|
||||
XX(2, STRICT, STRICT) \
|
||||
XX(3, LF_EXPECTED, LF_EXPECTED) \
|
||||
XX(4, UNEXPECTED_CONTENT_LENGTH, UNEXPECTED_CONTENT_LENGTH) \
|
||||
XX(5, CLOSED_CONNECTION, CLOSED_CONNECTION) \
|
||||
XX(6, INVALID_METHOD, INVALID_METHOD) \
|
||||
XX(7, INVALID_URL, INVALID_URL) \
|
||||
XX(8, INVALID_CONSTANT, INVALID_CONSTANT) \
|
||||
XX(9, INVALID_VERSION, INVALID_VERSION) \
|
||||
XX(10, INVALID_HEADER_TOKEN, INVALID_HEADER_TOKEN) \
|
||||
XX(11, INVALID_CONTENT_LENGTH, INVALID_CONTENT_LENGTH) \
|
||||
XX(12, INVALID_CHUNK_SIZE, INVALID_CHUNK_SIZE) \
|
||||
XX(13, INVALID_STATUS, INVALID_STATUS) \
|
||||
XX(14, INVALID_EOF_STATE, INVALID_EOF_STATE) \
|
||||
XX(15, INVALID_TRANSFER_ENCODING, INVALID_TRANSFER_ENCODING) \
|
||||
XX(16, CB_MESSAGE_BEGIN, CB_MESSAGE_BEGIN) \
|
||||
XX(17, CB_HEADERS_COMPLETE, CB_HEADERS_COMPLETE) \
|
||||
XX(18, CB_MESSAGE_COMPLETE, CB_MESSAGE_COMPLETE) \
|
||||
XX(19, CB_CHUNK_HEADER, CB_CHUNK_HEADER) \
|
||||
XX(20, CB_CHUNK_COMPLETE, CB_CHUNK_COMPLETE) \
|
||||
XX(21, PAUSED, PAUSED) \
|
||||
XX(22, PAUSED_UPGRADE, PAUSED_UPGRADE) \
|
||||
XX(23, PAUSED_H2_UPGRADE, PAUSED_H2_UPGRADE) \
|
||||
XX(24, USER, USER) \
|
||||
|
||||
|
||||
#define HTTP_METHOD_MAP(XX) \
|
||||
XX(0, DELETE, DELETE) \
|
||||
XX(1, GET, GET) \
|
||||
XX(2, HEAD, HEAD) \
|
||||
XX(3, POST, POST) \
|
||||
XX(4, PUT, PUT) \
|
||||
XX(5, CONNECT, CONNECT) \
|
||||
XX(6, OPTIONS, OPTIONS) \
|
||||
XX(7, TRACE, TRACE) \
|
||||
XX(8, COPY, COPY) \
|
||||
XX(9, LOCK, LOCK) \
|
||||
XX(10, MKCOL, MKCOL) \
|
||||
XX(11, MOVE, MOVE) \
|
||||
XX(12, PROPFIND, PROPFIND) \
|
||||
XX(13, PROPPATCH, PROPPATCH) \
|
||||
XX(14, SEARCH, SEARCH) \
|
||||
XX(15, UNLOCK, UNLOCK) \
|
||||
XX(16, BIND, BIND) \
|
||||
XX(17, REBIND, REBIND) \
|
||||
XX(18, UNBIND, UNBIND) \
|
||||
XX(19, ACL, ACL) \
|
||||
XX(20, REPORT, REPORT) \
|
||||
XX(21, MKACTIVITY, MKACTIVITY) \
|
||||
XX(22, CHECKOUT, CHECKOUT) \
|
||||
XX(23, MERGE, MERGE) \
|
||||
XX(24, MSEARCH, M-SEARCH) \
|
||||
XX(25, NOTIFY, NOTIFY) \
|
||||
XX(26, SUBSCRIBE, SUBSCRIBE) \
|
||||
XX(27, UNSUBSCRIBE, UNSUBSCRIBE) \
|
||||
XX(28, PATCH, PATCH) \
|
||||
XX(29, PURGE, PURGE) \
|
||||
XX(30, MKCALENDAR, MKCALENDAR) \
|
||||
XX(31, LINK, LINK) \
|
||||
XX(32, UNLINK, UNLINK) \
|
||||
XX(33, SOURCE, SOURCE) \
|
||||
|
||||
|
||||
#define RTSP_METHOD_MAP(XX) \
|
||||
XX(1, GET, GET) \
|
||||
XX(3, POST, POST) \
|
||||
XX(6, OPTIONS, OPTIONS) \
|
||||
XX(35, DESCRIBE, DESCRIBE) \
|
||||
XX(36, ANNOUNCE, ANNOUNCE) \
|
||||
XX(37, SETUP, SETUP) \
|
||||
XX(38, PLAY, PLAY) \
|
||||
XX(39, PAUSE, PAUSE) \
|
||||
XX(40, TEARDOWN, TEARDOWN) \
|
||||
XX(41, GET_PARAMETER, GET_PARAMETER) \
|
||||
XX(42, SET_PARAMETER, SET_PARAMETER) \
|
||||
XX(43, REDIRECT, REDIRECT) \
|
||||
XX(44, RECORD, RECORD) \
|
||||
XX(45, FLUSH, FLUSH) \
|
||||
|
||||
|
||||
#define HTTP_ALL_METHOD_MAP(XX) \
|
||||
XX(0, DELETE, DELETE) \
|
||||
XX(1, GET, GET) \
|
||||
XX(2, HEAD, HEAD) \
|
||||
XX(3, POST, POST) \
|
||||
XX(4, PUT, PUT) \
|
||||
XX(5, CONNECT, CONNECT) \
|
||||
XX(6, OPTIONS, OPTIONS) \
|
||||
XX(7, TRACE, TRACE) \
|
||||
XX(8, COPY, COPY) \
|
||||
XX(9, LOCK, LOCK) \
|
||||
XX(10, MKCOL, MKCOL) \
|
||||
XX(11, MOVE, MOVE) \
|
||||
XX(12, PROPFIND, PROPFIND) \
|
||||
XX(13, PROPPATCH, PROPPATCH) \
|
||||
XX(14, SEARCH, SEARCH) \
|
||||
XX(15, UNLOCK, UNLOCK) \
|
||||
XX(16, BIND, BIND) \
|
||||
XX(17, REBIND, REBIND) \
|
||||
XX(18, UNBIND, UNBIND) \
|
||||
XX(19, ACL, ACL) \
|
||||
XX(20, REPORT, REPORT) \
|
||||
XX(21, MKACTIVITY, MKACTIVITY) \
|
||||
XX(22, CHECKOUT, CHECKOUT) \
|
||||
XX(23, MERGE, MERGE) \
|
||||
XX(24, MSEARCH, M-SEARCH) \
|
||||
XX(25, NOTIFY, NOTIFY) \
|
||||
XX(26, SUBSCRIBE, SUBSCRIBE) \
|
||||
XX(27, UNSUBSCRIBE, UNSUBSCRIBE) \
|
||||
XX(28, PATCH, PATCH) \
|
||||
XX(29, PURGE, PURGE) \
|
||||
XX(30, MKCALENDAR, MKCALENDAR) \
|
||||
XX(31, LINK, LINK) \
|
||||
XX(32, UNLINK, UNLINK) \
|
||||
XX(33, SOURCE, SOURCE) \
|
||||
XX(34, PRI, PRI) \
|
||||
XX(35, DESCRIBE, DESCRIBE) \
|
||||
XX(36, ANNOUNCE, ANNOUNCE) \
|
||||
XX(37, SETUP, SETUP) \
|
||||
XX(38, PLAY, PLAY) \
|
||||
XX(39, PAUSE, PAUSE) \
|
||||
XX(40, TEARDOWN, TEARDOWN) \
|
||||
XX(41, GET_PARAMETER, GET_PARAMETER) \
|
||||
XX(42, SET_PARAMETER, SET_PARAMETER) \
|
||||
XX(43, REDIRECT, REDIRECT) \
|
||||
XX(44, RECORD, RECORD) \
|
||||
XX(45, FLUSH, FLUSH) \
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
#endif /* LLLLHTTP_C_HEADERS_ */
|
||||
|
||||
#ifndef INCLUDE_LLHTTP_API_H_
|
||||
#define INCLUDE_LLHTTP_API_H_
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include <stddef.h>
|
||||
|
||||
#if defined(__wasm__)
|
||||
#define LLHTTP_EXPORT __attribute__((visibility("default")))
|
||||
#else
|
||||
#define LLHTTP_EXPORT
|
||||
#endif
|
||||
|
||||
typedef llhttp__internal_t llhttp_t;
|
||||
typedef struct llhttp_settings_s llhttp_settings_t;
|
||||
|
||||
typedef int (*llhttp_data_cb)(llhttp_t*, const char *at, size_t length);
|
||||
typedef int (*llhttp_cb)(llhttp_t*);
|
||||
|
||||
struct llhttp_settings_s {
|
||||
/* Possible return values 0, -1, `HPE_PAUSED` */
|
||||
llhttp_cb on_message_begin;
|
||||
|
||||
/* Possible return values 0, -1, HPE_USER */
|
||||
llhttp_data_cb on_url;
|
||||
llhttp_data_cb on_status;
|
||||
llhttp_data_cb on_header_field;
|
||||
llhttp_data_cb on_header_value;
|
||||
|
||||
/* Possible return values:
|
||||
* 0 - Proceed normally
|
||||
* 1 - Assume that request/response has no body, and proceed to parsing the
|
||||
* next message
|
||||
* 2 - Assume absence of body (as above) and make `llhttp_execute()` return
|
||||
* `HPE_PAUSED_UPGRADE`
|
||||
* -1 - Error
|
||||
* `HPE_PAUSED`
|
||||
*/
|
||||
llhttp_cb on_headers_complete;
|
||||
|
||||
/* Possible return values 0, -1, HPE_USER */
|
||||
llhttp_data_cb on_body;
|
||||
|
||||
/* Possible return values 0, -1, `HPE_PAUSED` */
|
||||
llhttp_cb on_message_complete;
|
||||
|
||||
/* When on_chunk_header is called, the current chunk length is stored
|
||||
* in parser->content_length.
|
||||
* Possible return values 0, -1, `HPE_PAUSED`
|
||||
*/
|
||||
llhttp_cb on_chunk_header;
|
||||
llhttp_cb on_chunk_complete;
|
||||
|
||||
/* Information-only callbacks, return value is ignored */
|
||||
llhttp_cb on_url_complete;
|
||||
llhttp_cb on_status_complete;
|
||||
llhttp_cb on_header_field_complete;
|
||||
llhttp_cb on_header_value_complete;
|
||||
};
|
||||
|
||||
/* Initialize the parser with specific type and user settings.
|
||||
*
|
||||
* NOTE: lifetime of `settings` has to be at least the same as the lifetime of
|
||||
* the `parser` here. In practice, `settings` has to be either a static
|
||||
* variable or be allocated with `malloc`, `new`, etc.
|
||||
*/
|
||||
LLHTTP_EXPORT
|
||||
void llhttp_init(llhttp_t* parser, llhttp_type_t type,
|
||||
const llhttp_settings_t* settings);
|
||||
|
||||
#if defined(__wasm__)
|
||||
|
||||
LLHTTP_EXPORT
|
||||
llhttp_t* llhttp_alloc(llhttp_type_t type);
|
||||
|
||||
LLHTTP_EXPORT
|
||||
void llhttp_free(llhttp_t* parser);
|
||||
|
||||
LLHTTP_EXPORT
|
||||
uint8_t llhttp_get_type(llhttp_t* parser);
|
||||
|
||||
LLHTTP_EXPORT
|
||||
uint8_t llhttp_get_http_major(llhttp_t* parser);
|
||||
|
||||
LLHTTP_EXPORT
|
||||
uint8_t llhttp_get_http_minor(llhttp_t* parser);
|
||||
|
||||
LLHTTP_EXPORT
|
||||
uint8_t llhttp_get_method(llhttp_t* parser);
|
||||
|
||||
LLHTTP_EXPORT
|
||||
int llhttp_get_status_code(llhttp_t* parser);
|
||||
|
||||
LLHTTP_EXPORT
|
||||
uint8_t llhttp_get_upgrade(llhttp_t* parser);
|
||||
|
||||
#endif // defined(__wasm__)
|
||||
|
||||
/* Reset an already initialized parser back to the start state, preserving the
|
||||
* existing parser type, callback settings, user data, and lenient flags.
|
||||
*/
|
||||
LLHTTP_EXPORT
|
||||
void llhttp_reset(llhttp_t* parser);
|
||||
|
||||
/* Initialize the settings object */
|
||||
LLHTTP_EXPORT
|
||||
void llhttp_settings_init(llhttp_settings_t* settings);
|
||||
|
||||
/* Parse full or partial request/response, invoking user callbacks along the
|
||||
* way.
|
||||
*
|
||||
* If any of `llhttp_data_cb` returns errno not equal to `HPE_OK` - the parsing
|
||||
* interrupts, and such errno is returned from `llhttp_execute()`. If
|
||||
* `HPE_PAUSED` was used as a errno, the execution can be resumed with
|
||||
* `llhttp_resume()` call.
|
||||
*
|
||||
* In a special case of CONNECT/Upgrade request/response `HPE_PAUSED_UPGRADE`
|
||||
* is returned after fully parsing the request/response. If the user wishes to
|
||||
* continue parsing, they need to invoke `llhttp_resume_after_upgrade()`.
|
||||
*
|
||||
* NOTE: if this function ever returns a non-pause type error, it will continue
|
||||
* to return the same error upon each successive call up until `llhttp_init()`
|
||||
* is called.
|
||||
*/
|
||||
LLHTTP_EXPORT
|
||||
llhttp_errno_t llhttp_execute(llhttp_t* parser, const char* data, size_t len);
|
||||
|
||||
/* This method should be called when the other side has no further bytes to
|
||||
* send (e.g. shutdown of readable side of the TCP connection.)
|
||||
*
|
||||
* Requests without `Content-Length` and other messages might require treating
|
||||
* all incoming bytes as the part of the body, up to the last byte of the
|
||||
* connection. This method will invoke `on_message_complete()` callback if the
|
||||
* request was terminated safely. Otherwise a error code would be returned.
|
||||
*/
|
||||
LLHTTP_EXPORT
|
||||
llhttp_errno_t llhttp_finish(llhttp_t* parser);
|
||||
|
||||
/* Returns `1` if the incoming message is parsed until the last byte, and has
|
||||
* to be completed by calling `llhttp_finish()` on EOF
|
||||
*/
|
||||
LLHTTP_EXPORT
|
||||
int llhttp_message_needs_eof(const llhttp_t* parser);
|
||||
|
||||
/* Returns `1` if there might be any other messages following the last that was
|
||||
* successfully parsed.
|
||||
*/
|
||||
LLHTTP_EXPORT
|
||||
int llhttp_should_keep_alive(const llhttp_t* parser);
|
||||
|
||||
/* Make further calls of `llhttp_execute()` return `HPE_PAUSED` and set
|
||||
* appropriate error reason.
|
||||
*
|
||||
* Important: do not call this from user callbacks! User callbacks must return
|
||||
* `HPE_PAUSED` if pausing is required.
|
||||
*/
|
||||
LLHTTP_EXPORT
|
||||
void llhttp_pause(llhttp_t* parser);
|
||||
|
||||
/* Might be called to resume the execution after the pause in user's callback.
|
||||
* See `llhttp_execute()` above for details.
|
||||
*
|
||||
* Call this only if `llhttp_execute()` returns `HPE_PAUSED`.
|
||||
*/
|
||||
LLHTTP_EXPORT
|
||||
void llhttp_resume(llhttp_t* parser);
|
||||
|
||||
/* Might be called to resume the execution after the pause in user's callback.
|
||||
* See `llhttp_execute()` above for details.
|
||||
*
|
||||
* Call this only if `llhttp_execute()` returns `HPE_PAUSED_UPGRADE`
|
||||
*/
|
||||
LLHTTP_EXPORT
|
||||
void llhttp_resume_after_upgrade(llhttp_t* parser);
|
||||
|
||||
/* Returns the latest return error */
|
||||
LLHTTP_EXPORT
|
||||
llhttp_errno_t llhttp_get_errno(const llhttp_t* parser);
|
||||
|
||||
/* Returns the verbal explanation of the latest returned error.
|
||||
*
|
||||
* Note: User callback should set error reason when returning the error. See
|
||||
* `llhttp_set_error_reason()` for details.
|
||||
*/
|
||||
LLHTTP_EXPORT
|
||||
const char* llhttp_get_error_reason(const llhttp_t* parser);
|
||||
|
||||
/* Assign verbal description to the returned error. Must be called in user
|
||||
* callbacks right before returning the errno.
|
||||
*
|
||||
* Note: `HPE_USER` error code might be useful in user callbacks.
|
||||
*/
|
||||
LLHTTP_EXPORT
|
||||
void llhttp_set_error_reason(llhttp_t* parser, const char* reason);
|
||||
|
||||
/* Returns the pointer to the last parsed byte before the returned error. The
|
||||
* pointer is relative to the `data` argument of `llhttp_execute()`.
|
||||
*
|
||||
* Note: this method might be useful for counting the number of parsed bytes.
|
||||
*/
|
||||
LLHTTP_EXPORT
|
||||
const char* llhttp_get_error_pos(const llhttp_t* parser);
|
||||
|
||||
/* Returns textual name of error code */
|
||||
LLHTTP_EXPORT
|
||||
const char* llhttp_errno_name(llhttp_errno_t err);
|
||||
|
||||
/* Returns textual name of HTTP method */
|
||||
LLHTTP_EXPORT
|
||||
const char* llhttp_method_name(llhttp_method_t method);
|
||||
|
||||
|
||||
/* Enables/disables lenient header value parsing (disabled by default).
|
||||
*
|
||||
* Lenient parsing disables header value token checks, extending llhttp's
|
||||
* protocol support to highly non-compliant clients/server. No
|
||||
* `HPE_INVALID_HEADER_TOKEN` will be raised for incorrect header values when
|
||||
* lenient parsing is "on".
|
||||
*
|
||||
* **(USE AT YOUR OWN RISK)**
|
||||
*/
|
||||
LLHTTP_EXPORT
|
||||
void llhttp_set_lenient_headers(llhttp_t* parser, int enabled);
|
||||
|
||||
|
||||
/* Enables/disables lenient handling of conflicting `Transfer-Encoding` and
|
||||
* `Content-Length` headers (disabled by default).
|
||||
*
|
||||
* Normally `llhttp` would error when `Transfer-Encoding` is present in
|
||||
* conjunction with `Content-Length`. This error is important to prevent HTTP
|
||||
* request smuggling, but may be less desirable for small number of cases
|
||||
* involving legacy servers.
|
||||
*
|
||||
* **(USE AT YOUR OWN RISK)**
|
||||
*/
|
||||
LLHTTP_EXPORT
|
||||
void llhttp_set_lenient_chunked_length(llhttp_t* parser, int enabled);
|
||||
|
||||
|
||||
/* Enables/disables lenient handling of `Connection: close` and HTTP/1.0
|
||||
* requests responses.
|
||||
*
|
||||
* Normally `llhttp` would error on (in strict mode) or discard (in loose mode)
|
||||
* the HTTP request/response after the request/response with `Connection: close`
|
||||
* and `Content-Length`. This is important to prevent cache poisoning attacks,
|
||||
* but might interact badly with outdated and insecure clients. With this flag
|
||||
* the extra request/response will be parsed normally.
|
||||
*
|
||||
* **(USE AT YOUR OWN RISK)**
|
||||
*/
|
||||
void llhttp_set_lenient_keep_alive(llhttp_t* parser, int enabled);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
#endif /* INCLUDE_LLHTTP_API_H_ */
|
||||
|
||||
#endif /* INCLUDE_LLHTTP_H_ */
|
||||
+1
Submodule external/src/miniupnp added at f7b437772b
Vendored
+1
-1
Submodule external/src/rapidjson updated: a115f5d775...128cc9359f
Vendored
+1
-1
Submodule external/src/robin-hood-hashing updated: 90687c508a...4213dd109f
Generated
+6
-6
@@ -2,11 +2,11 @@
|
||||
"nodes": {
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1631368560,
|
||||
"narHash": "sha256-JUx+2uf1C2dZ1n56hcy5gjPGh4UP0nQwIr+WbjaWaP4=",
|
||||
"lastModified": 1678349056,
|
||||
"narHash": "sha256-kcL7Ap6IfUQRmGFeE2F0SkzIbQaPvZiylIuL2dD6mL0=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "91333fe5c9212e1a0c587c8ce70b0571bf0b18bd",
|
||||
"rev": "6a231a6eb788a345b265e1f26e04b96d8a402bf5",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -23,11 +23,11 @@
|
||||
},
|
||||
"utils": {
|
||||
"locked": {
|
||||
"lastModified": 1629481132,
|
||||
"narHash": "sha256-JHgasjPR0/J1J3DRm4KxM4zTyAj4IOJY8vIl75v/kPI=",
|
||||
"lastModified": 1676283394,
|
||||
"narHash": "sha256-XX2f9c3iySLCw54rJ/CZs+ZK6IQy7GXNY4nSOyu2QG4=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "997f7efcb746a9c140ce1f13c72263189225f482",
|
||||
"rev": "3db36a8b464d0c4532ba1c7dda728f4576d6d073",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
||||
@@ -23,9 +23,11 @@
|
||||
};
|
||||
|
||||
buildInputs = builtins.attrValues {
|
||||
inherit (pkgs) libuv zeromq libsodium gss;
|
||||
inherit (pkgs) libuv zeromq libsodium gss curl;
|
||||
};
|
||||
|
||||
cmakeFlags = ["-DWITH_LTO=OFF"];
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out/bin
|
||||
cp -r ./p2pool $out/bin/
|
||||
|
||||
+21
-11
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
|
||||
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright (c) 2021-2023 SChernykh <https://github.com/SChernykh>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -20,7 +20,7 @@
|
||||
#include "pool_block.h"
|
||||
#include "p2p_server.h"
|
||||
|
||||
static constexpr char log_category_prefix[] = "BlockCache ";
|
||||
LOG_CATEGORY(BlockCache)
|
||||
|
||||
static constexpr uint32_t BLOCK_SIZE = 96 * 1024;
|
||||
static constexpr uint32_t NUM_BLOCKS = 4608;
|
||||
@@ -145,7 +145,7 @@ struct BlockCache::Impl : public nocopy_nomove
|
||||
|
||||
#else
|
||||
// Not implemented on other platforms
|
||||
void flush() {}
|
||||
void flush() { m_data = nullptr; }
|
||||
#endif
|
||||
|
||||
uint8_t* m_data = nullptr;
|
||||
@@ -154,6 +154,8 @@ struct BlockCache::Impl : public nocopy_nomove
|
||||
BlockCache::BlockCache()
|
||||
: m_impl(new Impl())
|
||||
, m_flushRunning(0)
|
||||
, m_storeIndex(0)
|
||||
, m_loadingStarted(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -164,26 +166,34 @@ BlockCache::~BlockCache()
|
||||
|
||||
void BlockCache::store(const PoolBlock& block)
|
||||
{
|
||||
const size_t n1 = block.m_mainChainData.size();
|
||||
const size_t n2 = block.m_sideChainData.size();
|
||||
const std::vector<uint8_t> mainchain_data = block.serialize_mainchain_data();
|
||||
const std::vector<uint8_t> sidechain_data = block.serialize_sidechain_data();
|
||||
|
||||
const size_t n1 = mainchain_data.size();
|
||||
const size_t n2 = sidechain_data.size();
|
||||
|
||||
if (!m_impl->m_data || (sizeof(uint32_t) + n1 + n2 > BLOCK_SIZE)) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t* data = m_impl->m_data + (static_cast<size_t>(block.m_sidechainHeight % NUM_BLOCKS) * BLOCK_SIZE);
|
||||
uint8_t* data = m_impl->m_data + (static_cast<size_t>((m_storeIndex++) % NUM_BLOCKS) * BLOCK_SIZE);
|
||||
|
||||
*reinterpret_cast<uint32_t*>(data) = static_cast<uint32_t>(n1 + n2);
|
||||
memcpy(data + sizeof(uint32_t), block.m_mainChainData.data(), n1);
|
||||
memcpy(data + sizeof(uint32_t) + n1, block.m_sideChainData.data(), n2);
|
||||
memcpy(data + sizeof(uint32_t), mainchain_data.data(), n1);
|
||||
memcpy(data + sizeof(uint32_t) + n1, sidechain_data.data(), n2);
|
||||
}
|
||||
|
||||
void BlockCache::load_all(SideChain& side_chain, P2PServer& server)
|
||||
void BlockCache::load_all(const SideChain& side_chain, P2PServer& server)
|
||||
{
|
||||
if (!m_impl->m_data) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Can be only called once
|
||||
if (m_loadingStarted.exchange(1)) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOGINFO(1, "loading cached blocks");
|
||||
|
||||
PoolBlock block;
|
||||
@@ -197,7 +207,7 @@ void BlockCache::load_all(SideChain& side_chain, P2PServer& server)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (block.deserialize(data + sizeof(uint32_t), n, side_chain) == 0) {
|
||||
if (block.deserialize(data + sizeof(uint32_t), n, side_chain, uv_default_loop_checked(), false) == 0) {
|
||||
server.add_cached_block(block);
|
||||
++blocks_loaded;
|
||||
}
|
||||
@@ -208,7 +218,7 @@ void BlockCache::load_all(SideChain& side_chain, P2PServer& server)
|
||||
|
||||
void BlockCache::flush()
|
||||
{
|
||||
if (m_flushRunning.exchange(1) == 0) {
|
||||
if (m_flushRunning.exchange(1)) {
|
||||
m_impl->flush();
|
||||
m_flushRunning.store(0);
|
||||
}
|
||||
|
||||
+4
-2
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
|
||||
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright (c) 2021-2023 SChernykh <https://github.com/SChernykh>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -30,13 +30,15 @@ public:
|
||||
~BlockCache();
|
||||
|
||||
void store(const PoolBlock& block);
|
||||
void load_all(SideChain& side_chain, P2PServer& server);
|
||||
void load_all(const SideChain& side_chain, P2PServer& server);
|
||||
void flush();
|
||||
|
||||
private:
|
||||
struct Impl;
|
||||
Impl* m_impl;
|
||||
std::atomic<uint32_t> m_flushRunning;
|
||||
std::atomic<uint32_t> m_storeIndex;
|
||||
std::atomic<uint32_t> m_loadingStarted;
|
||||
};
|
||||
|
||||
} // namespace p2pool
|
||||
|
||||
+523
-217
File diff suppressed because it is too large
Load Diff
+38
-19
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
|
||||
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright (c) 2021-2023 SChernykh <https://github.com/SChernykh>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -23,7 +23,8 @@
|
||||
|
||||
namespace p2pool {
|
||||
|
||||
class p2pool;
|
||||
class SideChain;
|
||||
class RandomX_Hasher_Base;
|
||||
class Mempool;
|
||||
class Wallet;
|
||||
struct PoolBlock;
|
||||
@@ -32,37 +33,43 @@ struct MinerShare;
|
||||
class BlockTemplate
|
||||
{
|
||||
public:
|
||||
explicit BlockTemplate(p2pool* pool);
|
||||
explicit BlockTemplate(SideChain* sidechain, RandomX_Hasher_Base* hasher);
|
||||
~BlockTemplate();
|
||||
|
||||
BlockTemplate(const BlockTemplate& b);
|
||||
BlockTemplate& operator=(const BlockTemplate& b);
|
||||
|
||||
void update(const MinerData& data, const Mempool& mempool, Wallet* miner_wallet);
|
||||
void update(const MinerData& data, const Mempool& mempool, const Wallet* miner_wallet);
|
||||
uint64_t last_updated() const { return m_lastUpdated.load(); }
|
||||
|
||||
bool get_difficulties(const uint32_t template_id, difficulty_type& mainchain_difficulty, difficulty_type& sidechain_difficulty) const;
|
||||
bool get_difficulties(const uint32_t template_id, uint64_t& height, uint64_t& sidechain_height, difficulty_type& mainchain_difficulty, difficulty_type& sidechain_difficulty) const;
|
||||
uint32_t get_hashing_blob(const uint32_t template_id, uint32_t extra_nonce, uint8_t (&blob)[128], uint64_t& height, difficulty_type& difficulty, difficulty_type& sidechain_difficulty, hash& seed_hash, size_t& nonce_offset) const;
|
||||
|
||||
uint32_t get_hashing_blob(uint32_t extra_nonce, uint8_t (&blob)[128], uint64_t& height, difficulty_type& difficulty, difficulty_type& sidechain_difficulty, hash& seed_hash, size_t& nonce_offset, uint32_t& template_id) const;
|
||||
uint32_t get_hashing_blob(uint32_t extra_nonce, uint8_t (&blob)[128], uint64_t& height, uint64_t& sidechain_height, difficulty_type& difficulty, difficulty_type& sidechain_difficulty, hash& seed_hash, size_t& nonce_offset, uint32_t& template_id) const;
|
||||
uint32_t get_hashing_blobs(uint32_t extra_nonce_start, uint32_t count, std::vector<uint8_t>& blobs, uint64_t& height, difficulty_type& difficulty, difficulty_type& sidechain_difficulty, hash& seed_hash, size_t& nonce_offset, uint32_t& template_id) const;
|
||||
|
||||
std::vector<uint8_t> get_block_template_blob(uint32_t template_id, size_t& nonce_offset, size_t& extra_nonce_offset) const;
|
||||
void update_tx_keys();
|
||||
std::vector<uint8_t> get_block_template_blob(uint32_t template_id, uint32_t sidechain_extra_nonce, size_t& nonce_offset, size_t& extra_nonce_offset, size_t& sidechain_id_offset, hash& sidechain_id) const;
|
||||
|
||||
FORCEINLINE uint64_t height() const { return m_height; }
|
||||
FORCEINLINE time_t timestamp() const { return m_timestamp; }
|
||||
FORCEINLINE difficulty_type difficulty() const { return m_difficulty; }
|
||||
|
||||
void submit_sidechain_block(uint32_t template_id, uint32_t nonce, uint32_t extra_nonce);
|
||||
bool submit_sidechain_block(uint32_t template_id, uint32_t nonce, uint32_t extra_nonce);
|
||||
|
||||
FORCEINLINE uint64_t final_reward() const { return m_finalReward; }
|
||||
FORCEINLINE const std::vector<MinerShare>& shares() const { return m_shares; }
|
||||
FORCEINLINE uint64_t get_reward() const { return m_finalReward; }
|
||||
|
||||
#ifdef P2POOL_UNIT_TESTS
|
||||
FORCEINLINE const PoolBlock* pool_block_template() const { return m_poolBlockTemplate; }
|
||||
FORCEINLINE std::mt19937_64& rng() { return m_rng; }
|
||||
#endif
|
||||
|
||||
private:
|
||||
p2pool* m_pool;
|
||||
SideChain* m_sidechain;
|
||||
RandomX_Hasher_Base* m_hasher;
|
||||
|
||||
private:
|
||||
bool create_miner_tx(const MinerData& data, const std::vector<MinerShare>& shares, uint64_t max_reward_amounts_weight, bool dry_run);
|
||||
hash calc_sidechain_hash() const;
|
||||
int create_miner_tx(const MinerData& data, const std::vector<MinerShare>& shares, uint64_t max_reward_amounts_weight, bool dry_run);
|
||||
hash calc_sidechain_hash(uint32_t sidechain_extra_nonce) const;
|
||||
hash calc_miner_tx_hash(uint32_t extra_nonce) const;
|
||||
void calc_merkle_tree_main_branch();
|
||||
|
||||
@@ -71,8 +78,10 @@ private:
|
||||
mutable uv_rwlock_t m_lock;
|
||||
|
||||
uint32_t m_templateId;
|
||||
std::atomic<uint64_t> m_lastUpdated;
|
||||
|
||||
std::vector<uint8_t> m_blockTemplateBlob;
|
||||
std::vector<uint8_t> m_fullDataBlob;
|
||||
std::vector<uint8_t> m_merkleTreeMainBranch;
|
||||
|
||||
size_t m_blockHeaderSize;
|
||||
@@ -83,31 +92,41 @@ private:
|
||||
|
||||
size_t m_numTransactionHashes;
|
||||
hash m_prevId;
|
||||
uint64_t m_height;
|
||||
std::atomic<uint64_t> m_height;
|
||||
difficulty_type m_difficulty;
|
||||
hash m_seedHash;
|
||||
|
||||
uint64_t m_timestamp;
|
||||
|
||||
hash m_txkeyPub;
|
||||
hash m_txkeySec;
|
||||
|
||||
PoolBlock* m_poolBlockTemplate;
|
||||
|
||||
BlockTemplate* m_oldTemplates[4] = {};
|
||||
|
||||
uint64_t m_finalReward;
|
||||
std::atomic<uint64_t> m_finalReward;
|
||||
|
||||
// Temp vectors, will be cleaned up after use and skipped in copy constructor/assignment operators
|
||||
std::vector<uint8_t> m_minerTx;
|
||||
uint64_t m_minerTxKeccakState[25];
|
||||
size_t m_minerTxKeccakStateInputLength;
|
||||
|
||||
std::vector<uint8_t> m_sidechainHashBlob;
|
||||
uint64_t m_sidechainHashKeccakState[25];
|
||||
size_t m_sidechainHashInputLength;
|
||||
|
||||
std::vector<uint8_t> m_blockHeader;
|
||||
std::vector<uint8_t> m_minerTxExtra;
|
||||
std::vector<uint8_t> m_transactionHashes;
|
||||
unordered_set<hash> m_transactionHashesSet;
|
||||
std::vector<uint64_t> m_rewards;
|
||||
std::vector<TxMempoolData> m_mempoolTxs;
|
||||
std::vector<int> m_mempoolTxsOrder;
|
||||
std::vector<int> m_mempoolTxsOrder2;
|
||||
std::vector<MinerShare> m_shares;
|
||||
|
||||
std::mt19937_64 m_rng;
|
||||
|
||||
void shuffle_tx_order();
|
||||
|
||||
#if TEST_MEMPOOL_PICKING_ALGORITHM
|
||||
void fill_optimal_knapsack(const MinerData& data, uint64_t base_reward, uint64_t miner_tx_weight, uint64_t& best_reward, uint64_t& final_fees, uint64_t& final_weight);
|
||||
|
||||
|
||||
+173
-18
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
|
||||
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright (c) 2021-2023 SChernykh <https://github.com/SChernykh>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -19,22 +19,25 @@
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
#pragma warning(disable : 4005 4061 4365 4464 4625 4626 4668 4710 4711 4804 4820 5039 5045 5220)
|
||||
#pragma warning(disable : 4005 4061 4324 4365 4464 4619 4625 4626 4668 4710 4711 4714 4804 4820 5039 5045 5220 5246 5264)
|
||||
#define FORCEINLINE __forceinline
|
||||
#define NOINLINE __declspec(noinline)
|
||||
#define LIKELY(expression) expression
|
||||
#define MSVC_PRAGMA(...) __pragma(__VA_ARGS__)
|
||||
|
||||
#elif __GNUC__
|
||||
|
||||
#define FORCEINLINE __attribute__((always_inline)) inline
|
||||
#define NOINLINE __attribute__((noinline))
|
||||
#define LIKELY(expression) __builtin_expect(expression, 1)
|
||||
#define MSVC_PRAGMA(...)
|
||||
|
||||
#else
|
||||
|
||||
#define FORCEINLINE inline
|
||||
#define NOINLINE
|
||||
#define LIKELY(expression) expression
|
||||
#define MSVC_PRAGMA(...)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -53,7 +56,7 @@
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
#include <random>
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
@@ -64,10 +67,18 @@
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32_WINNT
|
||||
#define _WIN32_WINNT 0x0600
|
||||
#endif
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
#elif defined(__linux__) || defined(__unix__) || defined(_POSIX_VERSION) || defined(__MACH__)
|
||||
@@ -77,16 +88,38 @@
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef __has_feature
|
||||
#define __has_feature(x) 0
|
||||
#endif
|
||||
|
||||
#if defined(_DEBUG) || defined(__SANITIZE_ADDRESS__) || __has_feature(address_sanitizer) || defined(__SANITIZE_THREAD__) || __has_feature(thread_sanitizer)
|
||||
#define P2POOL_DEBUGGING 1
|
||||
#endif
|
||||
|
||||
#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
|
||||
#define P2POOL_ASAN
|
||||
#define ASAN_POISON_MEMORY_REGION(addr, size) __asan_poison_memory_region((addr), (size))
|
||||
#define ASAN_UNPOISON_MEMORY_REGION(addr, size) __asan_unpoison_memory_region((addr), (size))
|
||||
extern "C" void __asan_poison_memory_region(void const volatile* addr, size_t size);
|
||||
extern "C" void __asan_unpoison_memory_region(void const volatile* addr, size_t size);
|
||||
#else
|
||||
#define ASAN_POISON_MEMORY_REGION(addr, size)
|
||||
#define ASAN_UNPOISON_MEMORY_REGION(addr, size)
|
||||
#endif
|
||||
|
||||
namespace p2pool {
|
||||
|
||||
constexpr size_t HASH_SIZE = 32;
|
||||
constexpr uint8_t HARDFORK_SUPPORTED_VERSION = 14;
|
||||
constexpr uint8_t HARDFORK_VIEW_TAGS_VERSION = 15;
|
||||
constexpr uint8_t HARDFORK_SUPPORTED_VERSION = 16;
|
||||
constexpr uint8_t MINER_REWARD_UNLOCK_TIME = 60;
|
||||
constexpr uint8_t NONCE_SIZE = 4;
|
||||
constexpr uint8_t EXTRA_NONCE_SIZE = 4;
|
||||
constexpr uint8_t EXTRA_NONCE_MAX_SIZE = EXTRA_NONCE_SIZE + 10;
|
||||
constexpr uint8_t TX_VERSION = 2;
|
||||
constexpr uint8_t TXIN_GEN = 0xFF;
|
||||
constexpr uint8_t TXOUT_TO_KEY = 2;
|
||||
constexpr uint8_t TXOUT_TO_TAGGED_KEY = 3;
|
||||
constexpr uint8_t TX_EXTRA_TAG_PUBKEY = 1;
|
||||
constexpr uint8_t TX_EXTRA_NONCE = 2;
|
||||
constexpr uint8_t TX_EXTRA_MERGE_MINING_TAG = 3;
|
||||
@@ -94,6 +127,8 @@ constexpr uint8_t TX_EXTRA_MERGE_MINING_TAG = 3;
|
||||
#ifdef _MSC_VER
|
||||
#define umul128 _umul128
|
||||
#define udiv128 _udiv128
|
||||
FORCEINLINE uint64_t shiftleft128(uint64_t lo, uint64_t hi, uint64_t shift) { return __shiftleft128(lo, hi, static_cast<unsigned char>(shift)); }
|
||||
FORCEINLINE uint64_t shiftright128(uint64_t lo, uint64_t hi, uint64_t shift) { return __shiftright128(lo, hi, static_cast<unsigned char>(shift)); }
|
||||
#else
|
||||
FORCEINLINE uint64_t umul128(uint64_t a, uint64_t b, uint64_t* hi)
|
||||
{
|
||||
@@ -111,18 +146,23 @@ FORCEINLINE uint64_t udiv128(uint64_t hi, uint64_t lo, uint64_t divisor, uint64_
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
FORCEINLINE uint64_t shiftleft128(uint64_t lo, uint64_t hi, uint64_t shift) { return (hi << shift) | (lo >> (64 - shift)); }
|
||||
FORCEINLINE uint64_t shiftright128(uint64_t lo, uint64_t hi, uint64_t shift) { return (hi << (64 - shift)) | (lo >> shift); }
|
||||
#endif
|
||||
|
||||
struct hash
|
||||
template<typename T> constexpr FORCEINLINE T round_up(T a, size_t granularity) { return static_cast<T>(((a + (granularity - static_cast<size_t>(1))) / granularity) * granularity); }
|
||||
|
||||
struct alignas(uint64_t) hash
|
||||
{
|
||||
alignas(8) uint8_t h[HASH_SIZE];
|
||||
uint8_t h[HASH_SIZE];
|
||||
|
||||
FORCEINLINE hash() : h{} {}
|
||||
|
||||
FORCEINLINE bool operator<(const hash& other) const
|
||||
{
|
||||
const uint64_t* a = reinterpret_cast<const uint64_t*>(h);
|
||||
const uint64_t* b = reinterpret_cast<const uint64_t*>(other.h);
|
||||
const uint64_t* a = u64();
|
||||
const uint64_t* b = other.u64();
|
||||
|
||||
if (a[3] < b[3]) return true;
|
||||
if (a[3] > b[3]) return false;
|
||||
@@ -138,18 +178,21 @@ struct hash
|
||||
|
||||
FORCEINLINE bool operator==(const hash& other) const
|
||||
{
|
||||
const uint64_t* a = reinterpret_cast<const uint64_t*>(h);
|
||||
const uint64_t* b = reinterpret_cast<const uint64_t*>(other.h);
|
||||
const uint64_t* a = u64();
|
||||
const uint64_t* b = other.u64();
|
||||
return (a[0] == b[0]) && (a[1] == b[1]) && (a[2] == b[2]) && (a[3] == b[3]);
|
||||
}
|
||||
|
||||
FORCEINLINE bool operator!=(const hash& other) const { return !operator==(other); }
|
||||
|
||||
FORCEINLINE bool empty() const {
|
||||
const uint64_t* a = reinterpret_cast<const uint64_t*>(h);
|
||||
const uint64_t* a = u64();
|
||||
return (a[0] == 0) && (a[1] == 0) && (a[2] == 0) && (a[3] == 0);
|
||||
}
|
||||
|
||||
FORCEINLINE uint64_t* u64() { return reinterpret_cast<uint64_t*>(h); }
|
||||
FORCEINLINE const uint64_t* u64() const { return reinterpret_cast<const uint64_t*>(h); }
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& s, const hash& d);
|
||||
friend std::istream& operator>>(std::istream& s, hash& d);
|
||||
};
|
||||
@@ -157,10 +200,14 @@ struct hash
|
||||
static_assert(sizeof(hash) == HASH_SIZE, "struct hash has invalid size, check your compiler options");
|
||||
static_assert(std::is_standard_layout<hash>::value, "struct hash is not a POD, check your compiler options");
|
||||
|
||||
struct difficulty_type
|
||||
struct
|
||||
#ifdef __GNUC__
|
||||
alignas(unsigned __int128)
|
||||
#endif
|
||||
difficulty_type
|
||||
{
|
||||
FORCEINLINE difficulty_type() : lo(0), hi(0) {}
|
||||
FORCEINLINE difficulty_type(uint64_t a, uint64_t b) : lo(a), hi(b) {}
|
||||
FORCEINLINE constexpr difficulty_type() : lo(0), hi(0) {}
|
||||
FORCEINLINE constexpr difficulty_type(uint64_t a, uint64_t b) : lo(a), hi(b) {}
|
||||
|
||||
uint64_t lo;
|
||||
uint64_t hi;
|
||||
@@ -169,7 +216,7 @@ struct difficulty_type
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
_addcarry_u64(_addcarry_u64(0, lo, b.lo, &lo), hi, b.hi, &hi);
|
||||
#elif __GNUC__
|
||||
#elif defined(__GNUC__) && !defined(DEV_CLANG_TIDY)
|
||||
*reinterpret_cast<unsigned __int128*>(this) += *reinterpret_cast<const unsigned __int128*>(&b);
|
||||
#else
|
||||
const uint64_t t = lo;
|
||||
@@ -180,6 +227,47 @@ struct difficulty_type
|
||||
return *this;
|
||||
}
|
||||
|
||||
FORCEINLINE difficulty_type& operator+=(uint64_t b) { return operator+=(difficulty_type{ b, 0 }); }
|
||||
|
||||
FORCEINLINE difficulty_type& operator-=(const difficulty_type& b)
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
_subborrow_u64(_subborrow_u64(0, lo, b.lo, &lo), hi, b.hi, &hi);
|
||||
#elif defined(__GNUC__) && !defined(DEV_CLANG_TIDY)
|
||||
*reinterpret_cast<unsigned __int128*>(this) -= *reinterpret_cast<const unsigned __int128*>(&b);
|
||||
#else
|
||||
const uint64_t t = b.lo;
|
||||
const uint64_t carry = (lo < t) ? 1 : 0;
|
||||
lo -= t;
|
||||
hi -= b.hi + carry;
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
FORCEINLINE difficulty_type& operator-=(uint64_t b) { return operator-=(difficulty_type{ b, 0 }); }
|
||||
|
||||
FORCEINLINE difficulty_type& operator*=(const uint64_t b)
|
||||
{
|
||||
uint64_t t;
|
||||
lo = umul128(lo, b, &t);
|
||||
hi = t + hi * b;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
FORCEINLINE difficulty_type& operator/=(const uint64_t b)
|
||||
{
|
||||
const uint64_t t = hi;
|
||||
hi = t / b;
|
||||
|
||||
uint64_t r;
|
||||
lo = udiv128(t % b, lo, b, &r);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
difficulty_type& operator/=(difficulty_type b);
|
||||
|
||||
FORCEINLINE bool operator<(const difficulty_type& other) const
|
||||
{
|
||||
if (hi < other.hi) return true;
|
||||
@@ -187,16 +275,24 @@ struct difficulty_type
|
||||
return (lo < other.lo);
|
||||
}
|
||||
|
||||
FORCEINLINE bool operator>(const difficulty_type& other) const { return other.operator<(*this); }
|
||||
|
||||
FORCEINLINE bool operator>=(const difficulty_type& other) const { return !operator<(other); }
|
||||
FORCEINLINE bool operator<=(const difficulty_type& other) const { return !operator>(other); }
|
||||
|
||||
FORCEINLINE bool operator==(const difficulty_type& other) const { return (lo == other.lo) && (hi == other.hi); }
|
||||
FORCEINLINE bool operator!=(const difficulty_type& other) const { return (lo != other.lo) || (hi != other.hi); }
|
||||
|
||||
FORCEINLINE bool operator==(uint64_t other) const { return (lo == other) && (hi == 0); }
|
||||
FORCEINLINE bool operator!=(uint64_t other) const { return (lo != other) || (hi != 0); }
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& s, const difficulty_type& d);
|
||||
friend std::istream& operator>>(std::istream& s, difficulty_type& d);
|
||||
|
||||
FORCEINLINE double to_double() const { return static_cast<double>(hi) * 18446744073709551616.0 + static_cast<double>(lo); }
|
||||
|
||||
FORCEINLINE bool empty() const { return (lo == 0) && (hi == 0); }
|
||||
|
||||
// Finds a 64-bit target for mining (target = 2^64 / difficulty) and rounds up the result of division
|
||||
// Because of that, there's a very small chance that miners will find a hash that meets the target but is still wrong (hash * difficulty >= 2^256)
|
||||
// A proper difficulty check is in check_pow()
|
||||
@@ -222,17 +318,65 @@ struct difficulty_type
|
||||
static_assert(sizeof(difficulty_type) == sizeof(uint64_t) * 2, "struct difficulty_type has invalid size, check your compiler options");
|
||||
static_assert(std::is_standard_layout<difficulty_type>::value, "struct difficulty_type is not a POD, check your compiler options");
|
||||
|
||||
difficulty_type operator+(const difficulty_type& a, const difficulty_type& b);
|
||||
static constexpr difficulty_type diff_max = { std::numeric_limits<uint64_t>::max(), std::numeric_limits<uint64_t>::max() };
|
||||
|
||||
template<typename T>
|
||||
FORCEINLINE difficulty_type operator+(const difficulty_type& a, const T& b)
|
||||
{
|
||||
difficulty_type result = a;
|
||||
result += b;
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
FORCEINLINE difficulty_type operator-(const difficulty_type& a, const T& b)
|
||||
{
|
||||
difficulty_type result = a;
|
||||
result -= b;
|
||||
return result;
|
||||
}
|
||||
|
||||
FORCEINLINE difficulty_type operator*(const difficulty_type& a, uint64_t b)
|
||||
{
|
||||
difficulty_type result = a;
|
||||
result *= b;
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
FORCEINLINE difficulty_type operator/(const difficulty_type& a, const T& b)
|
||||
{
|
||||
difficulty_type result = a;
|
||||
result /= b;
|
||||
return result;
|
||||
}
|
||||
|
||||
struct TxMempoolData
|
||||
{
|
||||
FORCEINLINE TxMempoolData() : id(), blob_size(0), weight(0), fee(0), time_received(0) {}
|
||||
|
||||
FORCEINLINE bool operator<(const TxMempoolData& tx) const
|
||||
{
|
||||
const uint64_t a = fee * tx.weight;
|
||||
const uint64_t b = tx.fee * weight;
|
||||
|
||||
// Prefer transactions with higher fee/byte
|
||||
if (a > b) return true;
|
||||
if (a < b) return false;
|
||||
|
||||
// If fee/byte is the same, prefer smaller transactions (they give smaller penalty when going above the median block size limit)
|
||||
if (weight < tx.weight) return true;
|
||||
if (weight > tx.weight) return false;
|
||||
|
||||
// If two transactions have exactly the same fee and weight, just order them by id
|
||||
return id < tx.id;
|
||||
}
|
||||
|
||||
hash id;
|
||||
uint64_t blob_size;
|
||||
uint64_t weight;
|
||||
uint64_t fee;
|
||||
time_t time_received;
|
||||
uint64_t time_received;
|
||||
};
|
||||
|
||||
struct MinerData
|
||||
@@ -258,7 +402,7 @@ struct MinerData
|
||||
uint64_t median_timestamp;
|
||||
std::vector<TxMempoolData> tx_backlog;
|
||||
|
||||
std::chrono::system_clock::time_point time_received;
|
||||
std::chrono::high_resolution_clock::time_point time_received;
|
||||
};
|
||||
|
||||
struct ChainMain
|
||||
@@ -303,6 +447,14 @@ struct raw_ip
|
||||
}
|
||||
|
||||
FORCEINLINE bool operator!=(const raw_ip& other) const { return !operator==(other); }
|
||||
|
||||
FORCEINLINE bool is_localhost() const { return (*this == localhost_ipv4) || (*this == localhost_ipv6); }
|
||||
FORCEINLINE bool is_ipv4_prefix() const { return memcmp(data, ipv4_prefix, sizeof(ipv4_prefix)) == 0; }
|
||||
|
||||
static const raw_ip localhost_ipv4;
|
||||
static const raw_ip localhost_ipv6;
|
||||
|
||||
alignas(8) static const uint8_t ipv4_prefix[12];
|
||||
};
|
||||
|
||||
static_assert(sizeof(raw_ip) == 16, "struct raw_ip has invalid size");
|
||||
@@ -311,6 +463,9 @@ void* malloc_hook(size_t n) noexcept;
|
||||
void* realloc_hook(void* ptr, size_t size) noexcept;
|
||||
void* calloc_hook(size_t count, size_t size) noexcept;
|
||||
void free_hook(void* p) noexcept;
|
||||
char* strdup_hook(const char* s) noexcept;
|
||||
|
||||
extern const char* BLOCK_FOUND;
|
||||
|
||||
} // namespace p2pool
|
||||
|
||||
|
||||
+252
-72
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
|
||||
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright (c) 2021-2023 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright (c) 2021 hyc <https://github.com/hyc>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
@@ -21,36 +21,126 @@
|
||||
#include "p2pool.h"
|
||||
#include "stratum_server.h"
|
||||
#include "p2p_server.h"
|
||||
#ifdef WITH_RANDOMX
|
||||
#include "miner.h"
|
||||
#endif
|
||||
#include "side_chain.h"
|
||||
#include <iostream>
|
||||
#include "p2pool_api.h"
|
||||
#include "params.h"
|
||||
|
||||
static constexpr char log_category_prefix[] = "ConsoleCommands ";
|
||||
LOG_CATEGORY(ConsoleCommands)
|
||||
|
||||
static constexpr int DEFAULT_BACKLOG = 1;
|
||||
|
||||
namespace p2pool {
|
||||
|
||||
bool ConsoleCommands::stopped = false;
|
||||
|
||||
ConsoleCommands::ConsoleCommands(p2pool* pool)
|
||||
: m_pool(pool)
|
||||
: TCPServer(DEFAULT_BACKLOG, ConsoleClient::allocate)
|
||||
, m_pool(pool)
|
||||
, m_tty{}
|
||||
, m_stdin_pipe{}
|
||||
, m_stdin_handle(nullptr)
|
||||
, m_readBuf{}
|
||||
, m_readBufInUse(false)
|
||||
{
|
||||
m_worker = new std::thread(&ConsoleCommands::run, this);
|
||||
const uv_handle_type stdin_type = uv_guess_handle(0);
|
||||
LOGINFO(3, "uv_guess_handle returned " << static_cast<int>(stdin_type));
|
||||
if (stdin_type != UV_TTY && stdin_type != UV_NAMED_PIPE) {
|
||||
LOGERR(1, "tty or named pipe is not available");
|
||||
}
|
||||
|
||||
int err;
|
||||
|
||||
if (stdin_type == UV_TTY) {
|
||||
LOGINFO(3, "processing stdin as UV_TTY");
|
||||
err = uv_tty_init(&m_loop, &m_tty, 0, 1);
|
||||
if (err) {
|
||||
LOGERR(1, "uv_tty_init failed, error " << uv_err_name(err));
|
||||
throw std::exception();
|
||||
}
|
||||
m_stdin_handle = reinterpret_cast<uv_stream_t*>(&m_tty);
|
||||
}
|
||||
else if (stdin_type == UV_NAMED_PIPE) {
|
||||
LOGINFO(3, "processing stdin as UV_NAMED_PIPE");
|
||||
err = uv_pipe_init(&m_loop, &m_stdin_pipe, 0);
|
||||
if (err) {
|
||||
LOGERR(1, "uv_pipe_init failed, error " << uv_err_name(err));
|
||||
throw std::exception();
|
||||
}
|
||||
m_stdin_handle = reinterpret_cast<uv_stream_t*>(&m_stdin_pipe);
|
||||
err = uv_pipe_open(&m_stdin_pipe, 0);
|
||||
if (err) {
|
||||
LOGERR(1, "uv_pipe_open failed, error " << uv_err_name(err));
|
||||
throw std::exception();
|
||||
}
|
||||
}
|
||||
|
||||
if (m_stdin_handle) {
|
||||
m_stdin_handle->data = this;
|
||||
err = uv_read_start(m_stdin_handle, allocCallback, stdinReadCallback);
|
||||
if (err) {
|
||||
LOGERR(1, "uv_read_start failed, error " << uv_err_name(err));
|
||||
throw std::exception();
|
||||
}
|
||||
}
|
||||
|
||||
std::random_device rd;
|
||||
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
if (start_listening(false, "127.0.0.1", 49152 + (rd() % 16384))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_listenPort < 0) {
|
||||
LOGERR(1, "failed to listen on TCP port");
|
||||
throw std::exception();
|
||||
}
|
||||
|
||||
if (m_pool->api() && m_pool->params().m_localStats) {
|
||||
m_pool->api()->set(p2pool_api::Category::LOCAL, "console",
|
||||
[stdin_type, this](log::Stream& s)
|
||||
{
|
||||
s << "{\"mode\":\"";
|
||||
|
||||
if (stdin_type == UV_TTY) {
|
||||
s << "tty";
|
||||
}
|
||||
else if (stdin_type == UV_NAMED_PIPE) {
|
||||
s << "pipe";
|
||||
}
|
||||
else {
|
||||
s << static_cast<int>(stdin_type);
|
||||
}
|
||||
|
||||
s << "\",\"tcp_port\":" << m_listenPort << '}';
|
||||
});
|
||||
}
|
||||
|
||||
err = uv_thread_create(&m_loopThread, loop, this);
|
||||
if (err) {
|
||||
LOGERR(1, "failed to start event loop thread, error " << uv_err_name(err));
|
||||
throw std::exception();
|
||||
}
|
||||
|
||||
m_loopThreadCreated = true;
|
||||
}
|
||||
|
||||
ConsoleCommands::~ConsoleCommands()
|
||||
{
|
||||
stopped = true;
|
||||
shutdown_tcp();
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
TerminateThread(reinterpret_cast<HANDLE>(m_worker->native_handle()), 0);
|
||||
#else
|
||||
pthread_cancel(m_worker->native_handle());
|
||||
#endif
|
||||
void ConsoleCommands::on_shutdown()
|
||||
{
|
||||
if (m_stdin_handle) {
|
||||
uv_close(reinterpret_cast<uv_handle_t*>(m_stdin_handle), nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
m_worker->join();
|
||||
delete m_worker;
|
||||
|
||||
LOGINFO(1, "stopped");
|
||||
const char* ConsoleCommands::get_log_category() const
|
||||
{
|
||||
return log_category_prefix;
|
||||
}
|
||||
|
||||
typedef struct strconst {
|
||||
@@ -61,7 +151,7 @@ typedef struct strconst {
|
||||
#define STRCONST(x) {x, sizeof(x)-1}
|
||||
#define STRCNULL {NULL, 0}
|
||||
|
||||
typedef int (cmdfunc)(p2pool *pool, const char *args);
|
||||
typedef void (cmdfunc)(p2pool *pool, const char *args);
|
||||
|
||||
typedef struct cmd {
|
||||
strconst name;
|
||||
@@ -70,7 +160,11 @@ typedef struct cmd {
|
||||
cmdfunc *func;
|
||||
} cmd;
|
||||
|
||||
static cmdfunc do_help, do_status, do_loglevel, do_addpeers, do_droppeers, do_showpeers, do_outpeers, do_inpeers, do_start_mining, do_stop_mining, do_exit;
|
||||
static cmdfunc do_help, do_status, do_loglevel, do_addpeers, do_droppeers, do_showpeers, do_showworkers, do_showbans, do_showhosts, do_nexthost, do_outpeers, do_inpeers, do_exit, do_version;
|
||||
|
||||
#ifdef WITH_RANDOMX
|
||||
static cmdfunc do_start_mining, do_stop_mining;
|
||||
#endif
|
||||
|
||||
static cmd cmds[] = {
|
||||
{ STRCONST("help"), "", "display list of commands", do_help },
|
||||
@@ -79,147 +173,233 @@ static cmd cmds[] = {
|
||||
{ STRCONST("addpeers"), "<peeraddr>", "add peer", do_addpeers },
|
||||
{ STRCONST("droppeers"), "", "disconnect all peers", do_droppeers },
|
||||
{ STRCONST("peers"), "", "show all peers", do_showpeers },
|
||||
{ STRCONST("outpeers"), "", "set maximum number of outgoing connections", do_outpeers },
|
||||
{ STRCONST("inpeers"), "", "set maximum number of incoming connections", do_inpeers },
|
||||
{ STRCONST("workers"), "", "show all connected workers", do_showworkers },
|
||||
{ STRCONST("bans"), "", "show all banned IPs", do_showbans },
|
||||
{ STRCONST("hosts"), "", "show Monero hosts", do_showhosts },
|
||||
{ STRCONST("next_host"), "", "switch to the next Monero host", do_nexthost },
|
||||
{ STRCONST("outpeers"), "<N>", "set maximum number of outgoing connections", do_outpeers },
|
||||
{ STRCONST("inpeers"), "<N>", "set maximum number of incoming connections", do_inpeers },
|
||||
#ifdef WITH_RANDOMX
|
||||
{ STRCONST("start_mining"), "<threads>", "start mining", do_start_mining },
|
||||
{ STRCONST("stop_mining"), "", "stop mining", do_stop_mining },
|
||||
#endif
|
||||
{ STRCONST("exit"), "", "terminate p2pool", do_exit },
|
||||
{ STRCONST("version"), "", "show p2pool version", do_version },
|
||||
{ STRCNULL, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
static int do_help(p2pool * /* m_pool */, const char * /* args */)
|
||||
static void do_help(p2pool * /* m_pool */, const char * /* args */)
|
||||
{
|
||||
LOGINFO(0, "List of commands");
|
||||
for (int i = 0; cmds[i].name.len; ++i) {
|
||||
LOGINFO(0, cmds[i].name.str << " " << cmds[i].arg << "\t" << cmds[i].descr);
|
||||
LOGINFO(0, log::pad_right(cmds[i].name.str, 20) << log::pad_right(cmds[i].arg, 12) << cmds[i].descr);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_status(p2pool *m_pool, const char * /* args */)
|
||||
static void do_status(p2pool *m_pool, const char * /* args */)
|
||||
{
|
||||
m_pool->side_chain().print_status();
|
||||
if (m_pool->stratum_server()) {
|
||||
m_pool->stratum_server()->print_status();
|
||||
}
|
||||
if (m_pool->p2p_server()) {
|
||||
m_pool->p2p_server()->print_status();
|
||||
}
|
||||
if (m_pool->miner()) {
|
||||
m_pool->miner()->print_status();
|
||||
|
||||
P2PServer* p2p = m_pool->p2p_server();
|
||||
if (p2p) {
|
||||
p2p->print_status();
|
||||
}
|
||||
|
||||
#ifdef WITH_RANDOMX
|
||||
m_pool->print_miner_status();
|
||||
#endif
|
||||
bkg_jobs_tracker.print_status();
|
||||
return 0;
|
||||
|
||||
if (p2p) {
|
||||
p2p->check_for_updates(true);
|
||||
}
|
||||
}
|
||||
|
||||
static int do_loglevel(p2pool * /* m_pool */, const char *args)
|
||||
static void do_loglevel(p2pool * /* m_pool */, const char *args)
|
||||
{
|
||||
int level = strtol(args, nullptr, 10);
|
||||
level = std::min(std::max(level, 0), log::MAX_GLOBAL_LOG_LEVEL);
|
||||
log::GLOBAL_LOG_LEVEL = level;
|
||||
LOGINFO(0, "log level set to " << level);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_addpeers(p2pool *m_pool, const char *args)
|
||||
// cppcheck-suppress constParameterCallback
|
||||
static void do_addpeers(p2pool *m_pool, const char *args)
|
||||
{
|
||||
if (m_pool->p2p_server()) {
|
||||
m_pool->p2p_server()->connect_to_peers(args);
|
||||
m_pool->p2p_server()->connect_to_peers_async(args);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_droppeers(p2pool *m_pool, const char * /* args */)
|
||||
// cppcheck-suppress constParameterCallback
|
||||
static void do_droppeers(p2pool *m_pool, const char * /* args */)
|
||||
{
|
||||
if (m_pool->p2p_server()) {
|
||||
m_pool->p2p_server()->drop_connections();
|
||||
m_pool->p2p_server()->drop_connections_async();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_showpeers(p2pool* m_pool, const char* /* args */)
|
||||
// cppcheck-suppress constParameterCallback
|
||||
static void do_showpeers(p2pool* m_pool, const char* /* args */)
|
||||
{
|
||||
if (m_pool->p2p_server()) {
|
||||
m_pool->p2p_server()->show_peers();
|
||||
m_pool->p2p_server()->show_peers_async();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_outpeers(p2pool* m_pool, const char* args)
|
||||
// cppcheck-suppress constParameterCallback
|
||||
static void do_showworkers(p2pool* m_pool, const char* /* args */)
|
||||
{
|
||||
if (m_pool->stratum_server()) {
|
||||
m_pool->stratum_server()->show_workers_async();
|
||||
}
|
||||
}
|
||||
|
||||
// cppcheck-suppress constParameterCallback
|
||||
static void do_showbans(p2pool* m_pool, const char* /* args */)
|
||||
{
|
||||
if (m_pool->stratum_server()) {
|
||||
m_pool->stratum_server()->print_bans();
|
||||
}
|
||||
if (m_pool->p2p_server()) {
|
||||
m_pool->p2p_server()->print_bans();
|
||||
}
|
||||
}
|
||||
|
||||
// cppcheck-suppress constParameterCallback
|
||||
static void do_showhosts(p2pool* m_pool, const char* /* args */)
|
||||
{
|
||||
m_pool->print_hosts();
|
||||
}
|
||||
|
||||
// cppcheck-suppress constParameterCallback
|
||||
static void do_nexthost(p2pool* m_pool, const char* /* args */)
|
||||
{
|
||||
m_pool->reconnect_to_host();
|
||||
}
|
||||
|
||||
// cppcheck-suppress constParameterCallback
|
||||
static void do_outpeers(p2pool* m_pool, const char* args)
|
||||
{
|
||||
if (m_pool->p2p_server()) {
|
||||
m_pool->p2p_server()->set_max_outgoing_peers(strtoul(args, nullptr, 10));
|
||||
LOGINFO(0, "max outgoing peers set to " << m_pool->p2p_server()->max_outgoing_peers());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_inpeers(p2pool* m_pool, const char* args)
|
||||
// cppcheck-suppress constParameterCallback
|
||||
static void do_inpeers(p2pool* m_pool, const char* args)
|
||||
{
|
||||
if (m_pool->p2p_server()) {
|
||||
m_pool->p2p_server()->set_max_incoming_peers(strtoul(args, nullptr, 10));
|
||||
LOGINFO(0, "max incoming peers set to " << m_pool->p2p_server()->max_incoming_peers());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_start_mining(p2pool* m_pool, const char* args)
|
||||
#ifdef WITH_RANDOMX
|
||||
static void do_start_mining(p2pool* m_pool, const char* args)
|
||||
{
|
||||
uint32_t threads = strtoul(args, nullptr, 10);
|
||||
threads = std::min(std::max(threads, 1u), 64u);
|
||||
m_pool->start_mining(threads);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_stop_mining(p2pool* m_pool, const char* /*args*/)
|
||||
static void do_stop_mining(p2pool* m_pool, const char* /*args*/)
|
||||
{
|
||||
m_pool->stop_mining();
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int do_exit(p2pool *m_pool, const char * /* args */)
|
||||
static void do_exit(p2pool *m_pool, const char * /* args */)
|
||||
{
|
||||
bkg_jobs_tracker.wait();
|
||||
m_pool->stop();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ConsoleCommands::run()
|
||||
// cppcheck-suppress constParameterCallback
|
||||
static void do_version(p2pool* m_pool, const char* /* args */)
|
||||
{
|
||||
LOGINFO(1, "started");
|
||||
LOGINFO(0, log::LightCyan() << VERSION);
|
||||
|
||||
std::string command;
|
||||
command.reserve(1024);
|
||||
const P2PServer* p2p = m_pool->p2p_server();
|
||||
if (p2p) {
|
||||
p2p->check_for_updates(true);
|
||||
}
|
||||
}
|
||||
|
||||
void ConsoleCommands::allocCallback(uv_handle_t* handle, size_t /*suggested_size*/, uv_buf_t* buf)
|
||||
{
|
||||
ConsoleCommands* pThis = static_cast<ConsoleCommands*>(handle->data);
|
||||
|
||||
if (pThis->m_readBufInUse) {
|
||||
buf->len = 0;
|
||||
buf->base = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
buf->len = sizeof(pThis->m_readBuf);
|
||||
buf->base = pThis->m_readBuf;
|
||||
pThis->m_readBufInUse = true;
|
||||
}
|
||||
|
||||
void ConsoleCommands::stdinReadCallback(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf)
|
||||
{
|
||||
ConsoleCommands* pThis = static_cast<ConsoleCommands*>(stream->data);
|
||||
|
||||
if (nread > 0) {
|
||||
pThis->process_input(pThis->m_command, buf->base, static_cast<uint32_t>(nread));
|
||||
}
|
||||
else if (nread < 0) {
|
||||
LOGWARN(4, "read error " << uv_err_name(static_cast<int>(nread)));
|
||||
}
|
||||
|
||||
pThis->m_readBufInUse = false;
|
||||
}
|
||||
|
||||
|
||||
void ConsoleCommands::process_input(std::string& command, char* data, uint32_t size)
|
||||
{
|
||||
command.append(data, size);
|
||||
|
||||
do {
|
||||
std::getline(std::cin, command);
|
||||
|
||||
if (std::cin.eof()) {
|
||||
LOGINFO(1, "EOF, stopping");
|
||||
return;
|
||||
}
|
||||
|
||||
if (stopped) {
|
||||
LOGINFO(1, "stopping");
|
||||
return;
|
||||
size_t k = command.find_first_of("\r\n");
|
||||
if (k == std::string::npos) {
|
||||
break;
|
||||
}
|
||||
command[k] = '\0';
|
||||
|
||||
cmd* c = cmds;
|
||||
for (; c->name.len; ++c) {
|
||||
if (!strncmp(command.c_str(), c->name.str, c->name.len)) {
|
||||
const char *args = command.c_str() + c->name.len + 1;
|
||||
if (c->func(m_pool, args)) {
|
||||
LOGINFO(1, "exit requested, stopping");
|
||||
return;
|
||||
const char* args = (c->name.len + 1 <= k) ? (command.c_str() + c->name.len + 1) : "";
|
||||
|
||||
// Skip spaces
|
||||
while ((args[0] == ' ') || (args[0] == '\t')) {
|
||||
++args;
|
||||
}
|
||||
|
||||
// Check if an argument is required
|
||||
if (strlen(c->arg) && !strlen(args)) {
|
||||
LOGWARN(0, c->name.str << " requires arguments");
|
||||
do_help(nullptr, nullptr);
|
||||
break;
|
||||
}
|
||||
|
||||
c->func(m_pool, args);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!c->name.len) {
|
||||
LOGWARN(0, "Unknown command " << command);
|
||||
LOGWARN(0, "Unknown command " << command.c_str());
|
||||
do_help(nullptr, nullptr);
|
||||
}
|
||||
|
||||
k = command.find_first_not_of("\r\n", k + 1);
|
||||
command.erase(0, k);
|
||||
} while (true);
|
||||
}
|
||||
|
||||
|
||||
+40
-8
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
|
||||
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright (c) 2021-2023 SChernykh <https://github.com/SChernykh>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -17,24 +17,56 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <thread>
|
||||
#include "uv_util.h"
|
||||
#include "tcp_server.h"
|
||||
|
||||
namespace p2pool {
|
||||
|
||||
class p2pool;
|
||||
|
||||
class ConsoleCommands : public nocopy_nomove
|
||||
class ConsoleCommands : public TCPServer
|
||||
{
|
||||
public:
|
||||
explicit ConsoleCommands(p2pool* pool);
|
||||
~ConsoleCommands();
|
||||
|
||||
private:
|
||||
p2pool* m_pool;
|
||||
std::thread* m_worker;
|
||||
struct ConsoleClient : public Client
|
||||
{
|
||||
ConsoleClient() : Client(m_consoleReadBuf, sizeof(m_consoleReadBuf)) {}
|
||||
~ConsoleClient() {}
|
||||
|
||||
static bool stopped;
|
||||
void run();
|
||||
static Client* allocate() { return new ConsoleClient(); }
|
||||
|
||||
size_t size() const override { return sizeof(ConsoleClient); }
|
||||
|
||||
bool on_connect() override { return true; };
|
||||
bool on_read(char* data, uint32_t size) override { static_cast<ConsoleCommands*>(m_owner)->process_input(m_command, data, size); return true; };
|
||||
|
||||
char m_consoleReadBuf[1024] = {};
|
||||
|
||||
std::string m_command;
|
||||
};
|
||||
|
||||
void on_shutdown() override;
|
||||
|
||||
private:
|
||||
const char* get_log_category() const override;
|
||||
|
||||
p2pool* m_pool;
|
||||
|
||||
uv_tty_t m_tty;
|
||||
uv_pipe_t m_stdin_pipe;
|
||||
uv_stream_t* m_stdin_handle;
|
||||
|
||||
char m_readBuf[1024];
|
||||
bool m_readBufInUse;
|
||||
|
||||
std::string m_command;
|
||||
|
||||
static void allocCallback(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf);
|
||||
static void stdinReadCallback(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf);
|
||||
|
||||
void process_input(std::string& command, char* data, uint32_t size);
|
||||
};
|
||||
|
||||
} // namespace p2pool
|
||||
|
||||
+272
-72
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
|
||||
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright (c) 2021-2023 SChernykh <https://github.com/SChernykh>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -19,12 +19,15 @@
|
||||
#include "crypto.h"
|
||||
#include "keccak.h"
|
||||
#include "uv_util.h"
|
||||
#include <random>
|
||||
|
||||
extern "C" {
|
||||
#include "crypto-ops.h"
|
||||
}
|
||||
|
||||
// l = 2^252 + 27742317777372353535851937790883648493.
|
||||
// l fits 15 times in 32 bytes (iow, 15 l is the highest multiple of l that fits in 32 bytes)
|
||||
static constexpr uint8_t limit[32] = { 0xe3, 0x6a, 0x67, 0x72, 0x8b, 0xce, 0x13, 0x29, 0x8f, 0x30, 0x82, 0x8c, 0x0b, 0xa4, 0x10, 0x39, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0 };
|
||||
|
||||
namespace p2pool {
|
||||
|
||||
namespace {
|
||||
@@ -32,7 +35,7 @@ namespace {
|
||||
class RandomBytes
|
||||
{
|
||||
public:
|
||||
RandomBytes() : rng(s), dist(0, 255)
|
||||
RandomBytes() : rng(RandomDeviceSeed::instance), dist(0, 255)
|
||||
{
|
||||
uv_mutex_init_checked(&m);
|
||||
|
||||
@@ -57,22 +60,6 @@ public:
|
||||
private:
|
||||
uv_mutex_t m;
|
||||
|
||||
// Fills the whole initial MT19937-64 state with non-deterministic random numbers
|
||||
struct SeedSequence
|
||||
{
|
||||
using result_type = std::random_device::result_type;
|
||||
|
||||
template<typename T>
|
||||
static void generate(T begin, T end)
|
||||
{
|
||||
std::random_device rd;
|
||||
for (T i = begin; i != end; ++i) {
|
||||
*i = rd();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
SeedSequence s;
|
||||
std::mt19937_64 rng;
|
||||
std::uniform_int_distribution<> dist;
|
||||
};
|
||||
@@ -93,13 +80,9 @@ static FORCEINLINE bool less32(const uint8_t* k0, const uint8_t* k1)
|
||||
return false;
|
||||
}
|
||||
|
||||
// cppcheck-suppress constParameter
|
||||
// cppcheck-suppress constParameterReference
|
||||
void generate_keys(hash& pub, hash& sec)
|
||||
{
|
||||
// l = 2^252 + 27742317777372353535851937790883648493.
|
||||
// l fits 15 times in 32 bytes (iow, 15 l is the highest multiple of l that fits in 32 bytes)
|
||||
static constexpr uint8_t limit[32] = { 0xe3, 0x6a, 0x67, 0x72, 0x8b, 0xce, 0x13, 0x29, 0x8f, 0x30, 0x82, 0x8c, 0x0b, 0xa4, 0x10, 0x39, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0 };
|
||||
|
||||
do {
|
||||
do { randomBytes(sec.h); } while (!less32(sec.h, limit));
|
||||
sc_reduce32(sec.h);
|
||||
@@ -110,6 +93,30 @@ void generate_keys(hash& pub, hash& sec)
|
||||
ge_p3_tobytes(pub.h, &point);
|
||||
}
|
||||
|
||||
// cppcheck-suppress constParameterReference
|
||||
void generate_keys_deterministic(hash& pub, hash& sec, const uint8_t* entropy, size_t len)
|
||||
{
|
||||
uint32_t counter = 0;
|
||||
|
||||
do {
|
||||
do {
|
||||
++counter;
|
||||
keccak_custom([entropy, len, counter](int offset)
|
||||
{
|
||||
if (offset < static_cast<int>(len)) {
|
||||
return entropy[offset];
|
||||
}
|
||||
return static_cast<uint8_t>(counter >> ((offset - len) * 8));
|
||||
}, static_cast<int>(len + sizeof(counter)), sec.h, HASH_SIZE);
|
||||
} while (!less32(sec.h, limit));
|
||||
sc_reduce32(sec.h);
|
||||
} while (!sc_isnonzero(sec.h));
|
||||
|
||||
ge_p3 point;
|
||||
ge_scalarmult_base(&point, sec.h);
|
||||
ge_p3_tobytes(pub.h, &point);
|
||||
}
|
||||
|
||||
bool check_keys(const hash& pub, const hash& sec)
|
||||
{
|
||||
// From ge_scalarmult_base's comment: "preconditions a[31] <= 127"
|
||||
@@ -126,9 +133,9 @@ bool check_keys(const hash& pub, const hash& sec)
|
||||
return pub == pub_check;
|
||||
}
|
||||
|
||||
static FORCEINLINE void hash_to_scalar(const uint8_t* data, size_t length, uint8_t(&res)[HASH_SIZE])
|
||||
static FORCEINLINE void hash_to_scalar(const uint8_t* data, int length, uint8_t (&res)[HASH_SIZE])
|
||||
{
|
||||
keccak(data, static_cast<int>(length), res, HASH_SIZE);
|
||||
keccak(data, length, res);
|
||||
sc_reduce32(res);
|
||||
}
|
||||
|
||||
@@ -139,64 +146,81 @@ static FORCEINLINE void derivation_to_scalar(const hash& derivation, size_t outp
|
||||
uint8_t output_index[(sizeof(size_t) * 8 + 6) / 7];
|
||||
} buf;
|
||||
|
||||
uint8_t* begin = buf.derivation;
|
||||
uint8_t* end = buf.output_index;
|
||||
memcpy(buf.derivation, derivation.h, sizeof(buf.derivation));
|
||||
|
||||
size_t k = output_index;
|
||||
while (k >= 0x80) {
|
||||
*(end++) = (static_cast<uint8_t>(k) & 0x7F) | 0x80;
|
||||
k >>= 7;
|
||||
}
|
||||
*(end++) = static_cast<uint8_t>(k);
|
||||
uint8_t* p = buf.output_index;
|
||||
writeVarint(output_index, [&p](uint8_t b) { *(p++) = b; });
|
||||
|
||||
hash_to_scalar(begin, end - begin, res);
|
||||
const uint8_t* data = buf.derivation;
|
||||
hash_to_scalar(data, static_cast<int>(p - data), res);
|
||||
}
|
||||
|
||||
class Cache
|
||||
class Cache : public nocopy_nomove
|
||||
{
|
||||
public:
|
||||
Cache()
|
||||
: derivations(new DerivationsMap())
|
||||
, public_keys(new PublicKeysMap())
|
||||
, tx_keys(new TxKeysMap())
|
||||
{
|
||||
uv_mutex_init_checked(&m);
|
||||
uv_rwlock_init_checked(&derivations_lock);
|
||||
uv_rwlock_init_checked(&public_keys_lock);
|
||||
uv_rwlock_init_checked(&tx_keys_lock);
|
||||
}
|
||||
|
||||
~Cache()
|
||||
{
|
||||
uv_mutex_destroy(&m);
|
||||
delete derivations;
|
||||
delete public_keys;
|
||||
delete tx_keys;
|
||||
|
||||
uv_rwlock_destroy(&derivations_lock);
|
||||
uv_rwlock_destroy(&public_keys_lock);
|
||||
uv_rwlock_destroy(&tx_keys_lock);
|
||||
}
|
||||
|
||||
bool get_derivation(const hash& key1, const hash& key2, hash& derivation)
|
||||
bool get_derivation(const hash& key1, const hash& key2, size_t output_index, hash& derivation, uint8_t& view_tag)
|
||||
{
|
||||
std::array<uint8_t, HASH_SIZE * 2> index;
|
||||
memcpy(index.data(), key1.h, HASH_SIZE);
|
||||
memcpy(index.data() + HASH_SIZE, key2.h, HASH_SIZE);
|
||||
|
||||
derivation = {};
|
||||
{
|
||||
MutexLock lock(m);
|
||||
auto it = derivations.find(index);
|
||||
if (it != derivations.end()) {
|
||||
derivation = it->second;
|
||||
return true;
|
||||
ReadLock lock(derivations_lock);
|
||||
auto it = derivations->find(index);
|
||||
if (it != derivations->end()) {
|
||||
const DerivationEntry& entry = it->second;
|
||||
derivation = entry.m_derivation;
|
||||
if (entry.find_view_tag(output_index, view_tag)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ge_p3 point;
|
||||
ge_p2 point2;
|
||||
ge_p1p1 point3;
|
||||
if (derivation.empty()) {
|
||||
ge_p3 point;
|
||||
ge_p2 point2;
|
||||
ge_p1p1 point3;
|
||||
|
||||
if (ge_frombytes_vartime(&point, key1.h) != 0) {
|
||||
return false;
|
||||
if (ge_frombytes_vartime(&point, key1.h) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ge_scalarmult(&point2, key2.h, &point);
|
||||
ge_mul8(&point3, &point2);
|
||||
ge_p1p1_to_p2(&point2, &point3);
|
||||
ge_tobytes(reinterpret_cast<uint8_t*>(&derivation), &point2);
|
||||
}
|
||||
|
||||
ge_scalarmult(&point2, key2.h, &point);
|
||||
ge_mul8(&point3, &point2);
|
||||
ge_p1p1_to_p2(&point2, &point3);
|
||||
ge_tobytes(reinterpret_cast<uint8_t*>(&derivation), &point2);
|
||||
derive_view_tag(derivation, output_index, view_tag);
|
||||
|
||||
const uint64_t t = seconds_since_epoch();
|
||||
{
|
||||
MutexLock lock(m);
|
||||
derivations.emplace(index, derivation);
|
||||
WriteLock lock(derivations_lock);
|
||||
|
||||
DerivationEntry& entry = derivations->emplace(index, DerivationEntry{ derivation, { 0xFFFFFFFFUL, 0xFFFFFFFFUL }, {}, t }).first->second;
|
||||
entry.add_view_tag(static_cast<uint32_t>(output_index << 8) | view_tag);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -210,10 +234,10 @@ public:
|
||||
memcpy(index.data() + HASH_SIZE * 2, &output_index, sizeof(size_t));
|
||||
|
||||
{
|
||||
MutexLock lock(m);
|
||||
auto it = public_keys.find(index);
|
||||
if (it != public_keys.end()) {
|
||||
derived_key = it->second;
|
||||
ReadLock lock(public_keys_lock);
|
||||
auto it = public_keys->find(index);
|
||||
if (it != public_keys->end()) {
|
||||
derived_key = it->second.m_key;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -236,33 +260,186 @@ public:
|
||||
ge_p1p1_to_p2(&point5, &point4);
|
||||
ge_tobytes(derived_key.h, &point5);
|
||||
|
||||
const uint64_t t = seconds_since_epoch();
|
||||
{
|
||||
MutexLock lock(m);
|
||||
public_keys.emplace(index, derived_key);
|
||||
WriteLock lock(public_keys_lock);
|
||||
public_keys->emplace(index, PublicKeyEntry{ derived_key, t });
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void clear()
|
||||
void get_tx_keys(hash& pub, hash& sec, const hash& seed, const hash& monero_block_id)
|
||||
{
|
||||
MutexLock lock(m);
|
||||
std::array<uint8_t, HASH_SIZE * 2> index;
|
||||
memcpy(index.data(), seed.h, HASH_SIZE);
|
||||
memcpy(index.data() + HASH_SIZE, monero_block_id.h, HASH_SIZE);
|
||||
|
||||
derivations.clear();
|
||||
public_keys.clear();
|
||||
{
|
||||
ReadLock lock(tx_keys_lock);
|
||||
auto it = tx_keys->find(index);
|
||||
if (it != tx_keys->end()) {
|
||||
pub = it->second.m_pub;
|
||||
sec = it->second.m_sec;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr char domain[] = "tx_secret_key";
|
||||
static constexpr size_t N = sizeof(domain) - 1;
|
||||
uint8_t entropy[N + HASH_SIZE * 2];
|
||||
|
||||
memcpy(entropy, domain, N);
|
||||
memcpy(entropy + N, seed.h, HASH_SIZE);
|
||||
memcpy(entropy + N + HASH_SIZE, monero_block_id.h, HASH_SIZE);
|
||||
|
||||
generate_keys_deterministic(pub, sec, entropy, sizeof(entropy));
|
||||
|
||||
const uint64_t t = seconds_since_epoch();
|
||||
{
|
||||
WriteLock lock(tx_keys_lock);
|
||||
tx_keys->emplace(index, TxKeyEntry{ pub, sec, t });
|
||||
}
|
||||
}
|
||||
|
||||
void clear(uint64_t timestamp)
|
||||
{
|
||||
if (timestamp) {
|
||||
auto clean_old = [timestamp](auto* table) {
|
||||
for (auto it = table->begin(); it != table->end();) {
|
||||
if (it->second.m_timestamp < timestamp) {
|
||||
it = table->erase(it);
|
||||
}
|
||||
else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
{
|
||||
WriteLock lock(derivations_lock);
|
||||
clean_old(derivations);
|
||||
}
|
||||
{
|
||||
WriteLock lock(public_keys_lock);
|
||||
clean_old(public_keys);
|
||||
}
|
||||
{
|
||||
WriteLock lock(tx_keys_lock);
|
||||
clean_old(tx_keys);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
WriteLock lock(derivations_lock);
|
||||
delete derivations;
|
||||
derivations = new DerivationsMap();
|
||||
derivations->reserve(5000);
|
||||
}
|
||||
{
|
||||
WriteLock lock(public_keys_lock);
|
||||
delete public_keys;
|
||||
public_keys = new PublicKeysMap();
|
||||
public_keys->reserve(5000);
|
||||
}
|
||||
{
|
||||
WriteLock lock(tx_keys_lock);
|
||||
delete tx_keys;
|
||||
tx_keys = new TxKeysMap();
|
||||
tx_keys->reserve(50);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
uv_mutex_t m;
|
||||
unordered_map<std::array<uint8_t, HASH_SIZE * 2>, hash> derivations;
|
||||
unordered_map<std::array<uint8_t, HASH_SIZE * 2 + sizeof(size_t)>, hash> public_keys;
|
||||
struct DerivationEntry
|
||||
{
|
||||
hash m_derivation;
|
||||
uint32_t m_viewTags1[2] = { 0xFFFFFFFFUL, 0xFFFFFFFFUL };
|
||||
std::vector<uint32_t> m_viewTags2;
|
||||
// cppcheck-suppress unusedStructMember
|
||||
uint64_t m_timestamp;
|
||||
|
||||
FORCEINLINE bool find_view_tag(size_t output_index, uint8_t& view_tag) const
|
||||
{
|
||||
#define ITER(i) do { \
|
||||
const uint32_t k = m_viewTags1[i]; \
|
||||
if ((k >> 8) == output_index) { \
|
||||
view_tag = static_cast<uint8_t>(k); \
|
||||
return true; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
ITER(0);
|
||||
ITER(1);
|
||||
#undef ITER
|
||||
|
||||
for (const uint32_t k : m_viewTags2) {
|
||||
if ((k >> 8) == output_index) {
|
||||
view_tag = static_cast<uint8_t>(k);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
FORCEINLINE void add_view_tag(uint32_t k)
|
||||
{
|
||||
#define ITER(i) do { \
|
||||
const uint32_t t = m_viewTags1[i]; \
|
||||
if (t == 0xFFFFFFFFUL) { \
|
||||
m_viewTags1[i] = k; \
|
||||
return; \
|
||||
} \
|
||||
else if (t == k) { \
|
||||
return; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
ITER(0);
|
||||
ITER(1);
|
||||
#undef ITER
|
||||
|
||||
if (std::find(m_viewTags2.begin(), m_viewTags2.end(), k) == m_viewTags2.end()) {
|
||||
m_viewTags2.emplace_back(k);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct PublicKeyEntry
|
||||
{
|
||||
hash m_key;
|
||||
// cppcheck-suppress unusedStructMember
|
||||
uint64_t m_timestamp;
|
||||
};
|
||||
|
||||
struct TxKeyEntry
|
||||
{
|
||||
hash m_pub;
|
||||
hash m_sec;
|
||||
// cppcheck-suppress unusedStructMember
|
||||
uint64_t m_timestamp;
|
||||
};
|
||||
|
||||
typedef unordered_map<std::array<uint8_t, HASH_SIZE * 2>, DerivationEntry> DerivationsMap;
|
||||
typedef unordered_map<std::array<uint8_t, HASH_SIZE * 2 + sizeof(size_t)>, PublicKeyEntry> PublicKeysMap;
|
||||
typedef unordered_map<std::array<uint8_t, HASH_SIZE * 2>, TxKeyEntry> TxKeysMap;
|
||||
|
||||
uv_rwlock_t derivations_lock;
|
||||
DerivationsMap* derivations;
|
||||
|
||||
uv_rwlock_t public_keys_lock;
|
||||
PublicKeysMap* public_keys;
|
||||
|
||||
uv_rwlock_t tx_keys_lock;
|
||||
TxKeysMap* tx_keys;
|
||||
};
|
||||
|
||||
static Cache* cache = nullptr;
|
||||
|
||||
bool generate_key_derivation(const hash& key1, const hash& key2, hash& derivation)
|
||||
bool generate_key_derivation(const hash& key1, const hash& key2, size_t output_index, hash& derivation, uint8_t& view_tag)
|
||||
{
|
||||
return cache->get_derivation(key1, key2, derivation);
|
||||
return cache->get_derivation(key1, key2, output_index, derivation, view_tag);
|
||||
}
|
||||
|
||||
bool derive_public_key(const hash& derivation, size_t output_index, const hash& base, hash& derived_key)
|
||||
@@ -270,6 +447,27 @@ bool derive_public_key(const hash& derivation, size_t output_index, const hash&
|
||||
return cache->get_public_key(derivation, output_index, base, derived_key);
|
||||
}
|
||||
|
||||
void get_tx_keys(hash& pub, hash& sec, const hash& seed, const hash& monero_block_id)
|
||||
{
|
||||
cache->get_tx_keys(pub, sec, seed, monero_block_id);
|
||||
}
|
||||
|
||||
void derive_view_tag(const hash& derivation, size_t output_index, uint8_t& view_tag)
|
||||
{
|
||||
constexpr uint8_t salt[] = "view_tag";
|
||||
constexpr size_t SALT_SIZE = sizeof(salt) - 1;
|
||||
|
||||
uint8_t buf[64];
|
||||
memcpy(buf, salt, SALT_SIZE);
|
||||
memcpy(buf + SALT_SIZE, derivation.h, HASH_SIZE);
|
||||
uint8_t* p = buf + SALT_SIZE + HASH_SIZE;
|
||||
writeVarint(output_index, [&p](uint8_t b) { *(p++) = b; });
|
||||
|
||||
hash view_tag_full;
|
||||
keccak(buf, static_cast<int>(p - buf), view_tag_full.h);
|
||||
view_tag = view_tag_full.h[0];
|
||||
}
|
||||
|
||||
void init_crypto_cache()
|
||||
{
|
||||
if (!cache) {
|
||||
@@ -285,9 +483,11 @@ void destroy_crypto_cache()
|
||||
}
|
||||
}
|
||||
|
||||
void clear_crypto_cache()
|
||||
void clear_crypto_cache(uint64_t timestamp)
|
||||
{
|
||||
cache->clear();
|
||||
if (cache) {
|
||||
cache->clear(timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace p2pool
|
||||
|
||||
+6
-3
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
|
||||
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright (c) 2021-2023 SChernykh <https://github.com/SChernykh>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -20,12 +20,15 @@
|
||||
namespace p2pool {
|
||||
|
||||
void generate_keys(hash& pub, hash& sec);
|
||||
void generate_keys_deterministic(hash& pub, hash& sec, const uint8_t* entropy, size_t len);
|
||||
void get_tx_keys(hash& pub, hash& sec, const hash& seed, const hash& monero_block_id);
|
||||
bool check_keys(const hash& pub, const hash& sec);
|
||||
bool generate_key_derivation(const hash& key1, const hash& key2, hash& derivation);
|
||||
bool generate_key_derivation(const hash& key1, const hash& key2, size_t output_index, hash& derivation, uint8_t& view_tag);
|
||||
bool derive_public_key(const hash& derivation, size_t output_index, const hash& base, hash& derived_key);
|
||||
void derive_view_tag(const hash& derivation, size_t output_index, uint8_t& view_tag);
|
||||
|
||||
void init_crypto_cache();
|
||||
void destroy_crypto_cache();
|
||||
void clear_crypto_cache();
|
||||
void clear_crypto_cache(uint64_t timestamp = 0);
|
||||
|
||||
} // namespace p2pool
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
|
||||
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright (c) 2021-2023 SChernykh <https://github.com/SChernykh>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -104,7 +104,7 @@ struct parse_wrapper<T, difficulty_type>
|
||||
if (!from_hex(s[i], d)) {
|
||||
return false;
|
||||
}
|
||||
out_value.hi = (out_value.hi << 4) || (out_value.lo >> 60);
|
||||
out_value.hi = (out_value.hi << 4) | (out_value.lo >> 60);
|
||||
out_value.lo = (out_value.lo << 4) | d;
|
||||
}
|
||||
|
||||
|
||||
+452
-185
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
|
||||
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright (c) 2021-2023 SChernykh <https://github.com/SChernykh>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -18,223 +18,490 @@
|
||||
#include "common.h"
|
||||
#include "uv_util.h"
|
||||
#include "json_rpc_request.h"
|
||||
#include "llhttp.h"
|
||||
#include <string>
|
||||
#include <curl/curl.h>
|
||||
|
||||
static constexpr char log_category_prefix[] = "JSONRPCRequest ";
|
||||
LOG_CATEGORY(JSONRPCRequest)
|
||||
|
||||
namespace p2pool {
|
||||
namespace JSONRPCRequest {
|
||||
|
||||
JSONRPCRequest::JSONRPCRequest(const char* address, int port, const char* req, CallbackBase* cb, CallbackBase* close_cb, uv_loop_t* loop)
|
||||
: m_socket{}
|
||||
, m_connect{}
|
||||
, m_write{}
|
||||
, m_callback(cb)
|
||||
, m_closeCallback(close_cb)
|
||||
, m_contentLength(0)
|
||||
, m_contentLengthHeader(false)
|
||||
, m_readBufInUse(false)
|
||||
, m_valid(true)
|
||||
struct CurlContext
|
||||
{
|
||||
m_readBuf[0] = '\0';
|
||||
CurlContext(const std::string& address, int port, const std::string& req, const std::string& auth, const std::string& proxy, CallbackBase* cb, CallbackBase* close_cb, uv_loop_t* loop);
|
||||
~CurlContext();
|
||||
|
||||
uv_tcp_init(loop ? loop : uv_default_loop_checked(), &m_socket);
|
||||
uv_tcp_nodelay(&m_socket, 1);
|
||||
static int socket_func(CURL* easy, curl_socket_t s, int action, void* userp, void* socketp)
|
||||
{
|
||||
CurlContext* ctx = reinterpret_cast<CurlContext*>(socketp ? socketp : userp);
|
||||
return ctx->on_socket(easy, s, action);
|
||||
}
|
||||
|
||||
sockaddr_storage addr;
|
||||
if (uv_ip4_addr(address, port, reinterpret_cast<sockaddr_in*>(&addr)) != 0) {
|
||||
const int err = uv_ip6_addr(address, port, reinterpret_cast<sockaddr_in6*>(&addr));
|
||||
if (err) {
|
||||
LOGERR(1, "invalid IP address " << address << " or port " << port);
|
||||
m_valid = false;
|
||||
static int timer_func(CURLM* multi, long timeout_ms, void* ctx)
|
||||
{
|
||||
return reinterpret_cast<CurlContext*>(ctx)->on_timer(multi, timeout_ms);
|
||||
}
|
||||
|
||||
static size_t write_func(const void* buffer, size_t size, size_t count, void* ctx)
|
||||
{
|
||||
return reinterpret_cast<CurlContext*>(ctx)->on_write(buffer, size, count);
|
||||
}
|
||||
|
||||
int on_socket(CURL* easy, curl_socket_t s, int action);
|
||||
int on_timer(CURLM* multi, long timeout_ms);
|
||||
|
||||
static void on_timeout(uv_handle_t* req);
|
||||
|
||||
size_t on_write(const void* buffer, size_t size, size_t count);
|
||||
|
||||
static void curl_perform(uv_poll_t* req, int status, int events);
|
||||
void check_multi_info();
|
||||
|
||||
static void on_close(uv_handle_t* h);
|
||||
|
||||
void shutdown();
|
||||
|
||||
std::vector<std::pair<curl_socket_t, uv_poll_t*>> m_pollHandles;
|
||||
|
||||
CallbackBase* m_callback;
|
||||
CallbackBase* m_closeCallback;
|
||||
|
||||
uv_loop_t* m_loop;
|
||||
uv_timer_t m_timer;
|
||||
uv_async_t m_async;
|
||||
CURLM* m_multiHandle;
|
||||
CURL* m_handle;
|
||||
|
||||
std::string m_url;
|
||||
std::string m_req;
|
||||
|
||||
std::vector<char> m_response;
|
||||
std::string m_error;
|
||||
|
||||
curl_slist* m_headers;
|
||||
|
||||
uint64_t m_startTime;
|
||||
uint64_t m_connectedTime;
|
||||
};
|
||||
|
||||
CurlContext::CurlContext(const std::string& address, int port, const std::string& req, const std::string& auth, const std::string& proxy, CallbackBase* cb, CallbackBase* close_cb, uv_loop_t* loop)
|
||||
: m_callback(cb)
|
||||
, m_closeCallback(close_cb)
|
||||
, m_loop(loop)
|
||||
, m_timer{}
|
||||
, m_async{}
|
||||
, m_multiHandle(nullptr)
|
||||
, m_handle(nullptr)
|
||||
, m_req(req)
|
||||
, m_headers(nullptr)
|
||||
, m_startTime(0)
|
||||
, m_connectedTime(0)
|
||||
{
|
||||
m_pollHandles.reserve(2);
|
||||
|
||||
{
|
||||
char buf[log::Stream::BUF_SIZE + 1];
|
||||
buf[0] = '\0';
|
||||
|
||||
log::Stream s(buf);
|
||||
s << "http://" << address << ':' << port;
|
||||
|
||||
if (!m_req.empty() && (m_req.front() == '/')) {
|
||||
s << m_req.c_str() << '\0';
|
||||
m_req.clear();
|
||||
}
|
||||
else {
|
||||
s << "/json_rpc\0";
|
||||
}
|
||||
|
||||
m_url = buf;
|
||||
}
|
||||
|
||||
int err = uv_timer_init(m_loop, &m_timer);
|
||||
if (err) {
|
||||
LOGERR(1, "uv_timer_init failed, error " << uv_err_name(err));
|
||||
throw std::runtime_error("uv_timer_init failed");
|
||||
}
|
||||
m_timer.data = this;
|
||||
|
||||
err = uv_async_init(m_loop, &m_async, reinterpret_cast<uv_async_cb>(on_timeout));
|
||||
if (err) {
|
||||
LOGERR(1, "uv_async_init failed, error " << uv_err_name(err));
|
||||
uv_close(reinterpret_cast<uv_handle_t*>(&m_timer), nullptr);
|
||||
throw std::runtime_error("uv_async_init failed");
|
||||
}
|
||||
m_async.data = this;
|
||||
|
||||
m_multiHandle = curl_multi_init();
|
||||
if (!m_multiHandle) {
|
||||
static constexpr char msg[] = "curl_multi_init() failed";
|
||||
LOGERR(1, msg);
|
||||
uv_close(reinterpret_cast<uv_handle_t*>(&m_async), nullptr);
|
||||
uv_close(reinterpret_cast<uv_handle_t*>(&m_timer), nullptr);
|
||||
throw std::runtime_error(msg);
|
||||
}
|
||||
|
||||
#define curl_multi_setopt_checked(...) \
|
||||
do { \
|
||||
const CURLMcode r = curl_multi_setopt(__VA_ARGS__); \
|
||||
if (r != CURLM_OK) { \
|
||||
static constexpr char msg[] = "curl_multi_setopt(" #__VA_ARGS__ ") failed"; \
|
||||
LOGERR(1, msg << ": " << curl_multi_strerror(r)); \
|
||||
throw std::runtime_error(msg); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
curl_multi_setopt_checked(m_multiHandle, CURLMOPT_SOCKETFUNCTION, socket_func);
|
||||
curl_multi_setopt_checked(m_multiHandle, CURLMOPT_SOCKETDATA, this);
|
||||
|
||||
curl_multi_setopt_checked(m_multiHandle, CURLMOPT_TIMERFUNCTION, timer_func);
|
||||
curl_multi_setopt_checked(m_multiHandle, CURLMOPT_TIMERDATA, this);
|
||||
|
||||
m_handle = curl_easy_init();
|
||||
if (!m_handle) {
|
||||
static constexpr char msg[] = "curl_easy_init() failed";
|
||||
LOGERR(1, msg);
|
||||
curl_multi_cleanup(m_multiHandle);
|
||||
uv_close(reinterpret_cast<uv_handle_t*>(&m_async), nullptr);
|
||||
uv_close(reinterpret_cast<uv_handle_t*>(&m_timer), nullptr);
|
||||
throw std::runtime_error(msg);
|
||||
}
|
||||
|
||||
#define curl_easy_setopt_checked(...) \
|
||||
do { \
|
||||
const CURLcode r = curl_easy_setopt(__VA_ARGS__); \
|
||||
if (r != CURLE_OK) { \
|
||||
static constexpr char msg[] = "curl_easy_setopt(" #__VA_ARGS__ ") failed"; \
|
||||
LOGERR(1, msg << ": " << curl_easy_strerror(r)); \
|
||||
throw std::runtime_error(msg); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
curl_easy_setopt_checked(m_handle, CURLOPT_BUFFERSIZE, 102400L);
|
||||
|
||||
curl_easy_setopt_checked(m_handle, CURLOPT_WRITEFUNCTION, write_func);
|
||||
curl_easy_setopt_checked(m_handle, CURLOPT_WRITEDATA, this);
|
||||
|
||||
#ifdef DEV_TEST_SYNC
|
||||
const int timeout = 10;
|
||||
#else
|
||||
const int timeout = proxy.empty() ? 1 : 5;
|
||||
#endif
|
||||
|
||||
curl_easy_setopt_checked(m_handle, CURLOPT_URL, m_url.c_str());
|
||||
curl_easy_setopt_checked(m_handle, CURLOPT_POSTFIELDS, m_req.c_str());
|
||||
curl_easy_setopt_checked(m_handle, CURLOPT_CONNECTTIMEOUT, timeout);
|
||||
curl_easy_setopt_checked(m_handle, CURLOPT_TIMEOUT, timeout * 10);
|
||||
|
||||
m_headers = curl_slist_append(m_headers, "Content-Type: application/json");
|
||||
if (m_headers) {
|
||||
curl_easy_setopt_checked(m_handle, CURLOPT_HTTPHEADER, m_headers);
|
||||
}
|
||||
|
||||
if (!auth.empty()) {
|
||||
curl_easy_setopt_checked(m_handle, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST | CURLAUTH_ONLY);
|
||||
curl_easy_setopt_checked(m_handle, CURLOPT_USERPWD, auth.c_str());
|
||||
}
|
||||
|
||||
if (!proxy.empty()) {
|
||||
if (is_localhost(address)) {
|
||||
LOGINFO(5, "not using proxy to connect to localhost address " << log::Gray() << address);
|
||||
}
|
||||
else {
|
||||
curl_easy_setopt_checked(m_handle, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5_HOSTNAME);
|
||||
curl_easy_setopt_checked(m_handle, CURLOPT_PROXY, proxy.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
CURLMcode curl_err = curl_multi_add_handle(m_multiHandle, m_handle);
|
||||
if (curl_err != CURLM_OK) {
|
||||
LOGERR(1, "curl_multi_add_handle failed, error " << curl_multi_strerror(curl_err));
|
||||
curl_easy_cleanup(m_handle);
|
||||
curl_multi_cleanup(m_multiHandle);
|
||||
uv_close(reinterpret_cast<uv_handle_t*>(&m_async), nullptr);
|
||||
uv_close(reinterpret_cast<uv_handle_t*>(&m_timer), nullptr);
|
||||
throw std::runtime_error("curl_multi_add_handle failed");
|
||||
}
|
||||
|
||||
m_startTime = microseconds_since_epoch();
|
||||
}
|
||||
|
||||
CurlContext::~CurlContext()
|
||||
{
|
||||
double tcp_ping = 0.0;
|
||||
|
||||
if (m_error.empty() && !m_response.empty()) {
|
||||
if (m_connectedTime) {
|
||||
tcp_ping = static_cast<double>(m_connectedTime - m_startTime) / 1000.0;
|
||||
}
|
||||
(*m_callback)(m_response.data(), m_response.size(), tcp_ping);
|
||||
}
|
||||
delete m_callback;
|
||||
|
||||
if (m_response.empty()) {
|
||||
if (m_error.empty()) {
|
||||
m_error = "empty response";
|
||||
}
|
||||
else {
|
||||
m_error += " (empty response)";
|
||||
}
|
||||
}
|
||||
|
||||
(*m_closeCallback)(m_error.c_str(), m_error.length(), tcp_ping);
|
||||
delete m_closeCallback;
|
||||
|
||||
curl_slist_free_all(m_headers);
|
||||
}
|
||||
|
||||
int CurlContext::on_socket(CURL* /*easy*/, curl_socket_t s, int action)
|
||||
{
|
||||
auto it = std::find_if(m_pollHandles.begin(), m_pollHandles.end(), [s](const auto& value) { return value.first == s; });
|
||||
|
||||
switch (action) {
|
||||
case CURL_POLL_IN:
|
||||
case CURL_POLL_OUT:
|
||||
case CURL_POLL_INOUT:
|
||||
{
|
||||
uv_poll_t* h = nullptr;
|
||||
|
||||
if (it != m_pollHandles.end()) {
|
||||
h = it->second;
|
||||
}
|
||||
else {
|
||||
h = new uv_poll_t{};
|
||||
|
||||
// cppcheck-suppress nullPointer
|
||||
h->data = this;
|
||||
|
||||
const int result = uv_poll_init_socket(m_loop, h, s);
|
||||
if (result < 0) {
|
||||
LOGERR(1, "uv_poll_init_socket failed: " << uv_err_name(result));
|
||||
delete h;
|
||||
h = nullptr;
|
||||
}
|
||||
else {
|
||||
m_pollHandles.emplace_back(s, h);
|
||||
}
|
||||
}
|
||||
|
||||
if (h) {
|
||||
const CURLMcode err = curl_multi_assign(m_multiHandle, s, this);
|
||||
if (err != CURLM_OK) {
|
||||
LOGERR(1, "curl_multi_assign(action = " << action << ") failed: " << curl_multi_strerror(err));
|
||||
}
|
||||
|
||||
int events = 0;
|
||||
if (action != CURL_POLL_IN) events |= UV_WRITABLE;
|
||||
if (action != CURL_POLL_OUT) events |= UV_READABLE;
|
||||
|
||||
const int result = uv_poll_start(h, events, curl_perform);
|
||||
if (result < 0) {
|
||||
LOGERR(1, "uv_poll_start failed with error " << uv_err_name(result));
|
||||
}
|
||||
}
|
||||
else {
|
||||
LOGERR(1, "failed to start polling on socket " << static_cast<int>(s));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case CURL_POLL_REMOVE:
|
||||
default:
|
||||
{
|
||||
if (it != m_pollHandles.end()) {
|
||||
uv_poll_t* h = it->second;
|
||||
m_pollHandles.erase(it);
|
||||
|
||||
uv_poll_stop(h);
|
||||
uv_close(reinterpret_cast<uv_handle_t*>(h), [](uv_handle_t* h) { delete reinterpret_cast<uv_poll_t*>(h); });
|
||||
}
|
||||
|
||||
const CURLMcode err = curl_multi_assign(m_multiHandle, s, nullptr);
|
||||
if (err != CURLM_OK) {
|
||||
LOGERR(1, "curl_multi_assign(action = " << action << ") failed: " << curl_multi_strerror(err));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CurlContext::on_timer(CURLM* /*multi*/, long timeout_ms)
|
||||
{
|
||||
if (timeout_ms < 0) {
|
||||
uv_timer_stop(&m_timer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((timeout_ms == 0) && !uv_is_closing(reinterpret_cast<uv_handle_t*>(&m_async))) {
|
||||
// 0 ms timeout, but we can't just call on_timeout() here - we have to kick the UV loop
|
||||
const int result = uv_async_send(&m_async);
|
||||
if (result < 0) {
|
||||
LOGERR(1, "uv_async_send failed with error " << uv_err_name(result));
|
||||
|
||||
// if async call didn't work, try to use the timer with 1 ms timeout
|
||||
timeout_ms = 1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
const int result = uv_timer_start(&m_timer, reinterpret_cast<uv_timer_cb>(on_timeout), timeout_ms, 0);
|
||||
if (result < 0) {
|
||||
LOGERR(1, "uv_timer_start failed with error " << uv_err_name(result));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CurlContext::on_timeout(uv_handle_t* req)
|
||||
{
|
||||
CurlContext* ctx = reinterpret_cast<CurlContext*>(req->data);
|
||||
|
||||
int running_handles = 0;
|
||||
const CURLMcode err = curl_multi_socket_action(ctx->m_multiHandle, CURL_SOCKET_TIMEOUT, 0, &running_handles);
|
||||
if (err != CURLM_OK) {
|
||||
LOGERR(1, "curl_multi_socket_action failed, error " << curl_multi_strerror(err));
|
||||
}
|
||||
|
||||
ctx->check_multi_info();
|
||||
|
||||
if (running_handles == 0) {
|
||||
ctx->shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
size_t CurlContext::on_write(const void* buffer, size_t size, size_t count)
|
||||
{
|
||||
if (!m_connectedTime) {
|
||||
m_connectedTime = microseconds_since_epoch();
|
||||
}
|
||||
|
||||
const size_t realsize = size * count;
|
||||
const char* p = reinterpret_cast<const char*>(buffer);
|
||||
m_response.insert(m_response.end(), p, p + realsize);
|
||||
return realsize;
|
||||
}
|
||||
|
||||
void CurlContext::curl_perform(uv_poll_t* req, int status, int events)
|
||||
{
|
||||
CurlContext* ctx = reinterpret_cast<CurlContext*>(req->data);
|
||||
|
||||
int flags = 0;
|
||||
if (status < 0) {
|
||||
flags |= CURL_CSELECT_ERR;
|
||||
LOGERR(1, "uv_poll_start returned error " << uv_err_name(status));
|
||||
}
|
||||
else {
|
||||
if (events & UV_READABLE) flags |= CURL_CSELECT_IN;
|
||||
if (events & UV_WRITABLE) {
|
||||
flags |= CURL_CSELECT_OUT;
|
||||
if (!ctx->m_connectedTime) {
|
||||
ctx->m_connectedTime = microseconds_since_epoch();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int running_handles = 0;
|
||||
auto it = std::find_if(ctx->m_pollHandles.begin(), ctx->m_pollHandles.end(), [req](const auto& value) { return value.second == req; });
|
||||
if (it != ctx->m_pollHandles.end()) {
|
||||
const CURLMcode err = curl_multi_socket_action(ctx->m_multiHandle, it->first, flags, &running_handles);
|
||||
if (err != CURLM_OK) {
|
||||
LOGERR(1, "curl_multi_socket_action failed, error " << curl_multi_strerror(err));
|
||||
}
|
||||
}
|
||||
|
||||
ctx->check_multi_info();
|
||||
|
||||
if (running_handles == 0) {
|
||||
ctx->shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
void CurlContext::check_multi_info()
|
||||
{
|
||||
int pending;
|
||||
while (CURLMsg* message = curl_multi_info_read(m_multiHandle, &pending)) {
|
||||
if (message->msg == CURLMSG_DONE) {
|
||||
if (message->data.result != CURLE_OK) {
|
||||
m_error = curl_easy_strerror(message->data.result);
|
||||
}
|
||||
else {
|
||||
long http_code = 0;
|
||||
curl_easy_getinfo(message->easy_handle, CURLINFO_RESPONSE_CODE, &http_code);
|
||||
|
||||
if (http_code != 200) {
|
||||
char buf[32] = {};
|
||||
log::Stream s(buf);
|
||||
s << "HTTP error " << static_cast<int>(http_code) << '\0';
|
||||
m_error = buf;
|
||||
}
|
||||
else if (m_response.empty()) {
|
||||
m_error = "empty response";
|
||||
}
|
||||
}
|
||||
|
||||
curl_multi_remove_handle(m_multiHandle, m_handle);
|
||||
curl_easy_cleanup(m_handle);
|
||||
curl_multi_cleanup(m_multiHandle);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
m_socket.data = this;
|
||||
m_connect.data = this;
|
||||
m_write.data = this;
|
||||
|
||||
const size_t len = strlen(req);
|
||||
|
||||
m_request.reserve(std::max<size_t>(len + 128, log::Stream::BUF_SIZE + 1));
|
||||
m_request.resize(log::Stream::BUF_SIZE + 1);
|
||||
|
||||
log::Stream s(m_request.data());
|
||||
s << "POST /json_rpc HTTP/1.1\nContent-Type: application/json\nContent-Length: " << len << "\n\n";
|
||||
|
||||
m_request.resize(s.m_pos);
|
||||
m_request.insert(m_request.end(), req, req + len);
|
||||
|
||||
m_response.reserve(sizeof(m_readBuf));
|
||||
|
||||
const int err = uv_tcp_connect(&m_connect, &m_socket, reinterpret_cast<const sockaddr*>(&addr), on_connect);
|
||||
if (err) {
|
||||
LOGERR(1, "failed to initiate tcp connection to " << address << ", error " << uv_err_name(err));
|
||||
m_valid = false;
|
||||
}
|
||||
}
|
||||
|
||||
void JSONRPCRequest::on_connect(uv_connect_t* req, int status)
|
||||
void CurlContext::on_close(uv_handle_t* h)
|
||||
{
|
||||
JSONRPCRequest* pThis = static_cast<JSONRPCRequest*>(req->data);
|
||||
CurlContext* ctx = reinterpret_cast<CurlContext*>(h->data);
|
||||
h->data = nullptr;
|
||||
|
||||
if (status != 0) {
|
||||
pThis->m_error = uv_err_name(status);
|
||||
LOGERR(1, "failed to connect, error " << pThis->m_error);
|
||||
pThis->close();
|
||||
if (ctx->m_timer.data || ctx->m_async.data) {
|
||||
return;
|
||||
}
|
||||
|
||||
uv_buf_t buf[1];
|
||||
buf[0].base = pThis->m_request.data();
|
||||
buf[0].len = static_cast<uint32_t>(pThis->m_request.size());
|
||||
|
||||
uv_write(&pThis->m_write, reinterpret_cast<uv_stream_t*>(&pThis->m_socket), buf, 1, on_write);
|
||||
delete ctx;
|
||||
}
|
||||
|
||||
void JSONRPCRequest::on_write(uv_write_t* handle, int status)
|
||||
void CurlContext::shutdown()
|
||||
{
|
||||
JSONRPCRequest* pThis = static_cast<JSONRPCRequest*>(handle->data);
|
||||
for (const auto& p : m_pollHandles) {
|
||||
uv_poll_stop(p.second);
|
||||
uv_close(reinterpret_cast<uv_handle_t*>(p.second), [](uv_handle_t* h) { delete reinterpret_cast<uv_poll_t*>(h); });
|
||||
}
|
||||
m_pollHandles.clear();
|
||||
|
||||
if (status != 0) {
|
||||
pThis->m_error = uv_err_name(status);
|
||||
LOGERR(1, "failed to send request, error " << pThis->m_error);
|
||||
pThis->close();
|
||||
return;
|
||||
if (m_async.data && !uv_is_closing(reinterpret_cast<uv_handle_t*>(&m_async))) {
|
||||
uv_close(reinterpret_cast<uv_handle_t*>(&m_async), on_close);
|
||||
}
|
||||
|
||||
uv_read_start(reinterpret_cast<uv_stream_t*>(&pThis->m_socket), on_alloc, on_read);
|
||||
}
|
||||
|
||||
void JSONRPCRequest::on_alloc(uv_handle_t* handle, size_t /*suggested_size*/, uv_buf_t* buf)
|
||||
{
|
||||
JSONRPCRequest* pThis = static_cast<JSONRPCRequest*>(handle->data);
|
||||
|
||||
if (pThis->m_readBufInUse) {
|
||||
LOGERR(1, "read buffer is already in use");
|
||||
}
|
||||
|
||||
buf->len = sizeof(pThis->m_readBuf);
|
||||
buf->base = pThis->m_readBuf;
|
||||
pThis->m_readBufInUse = true;
|
||||
}
|
||||
|
||||
void JSONRPCRequest::on_read(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf)
|
||||
{
|
||||
JSONRPCRequest* pThis = static_cast<JSONRPCRequest*>(stream->data);
|
||||
pThis->m_readBufInUse = false;
|
||||
|
||||
if (nread > 0) {
|
||||
pThis->on_read(buf->base, nread);
|
||||
}
|
||||
else if (nread < 0) {
|
||||
if (nread != UV_EOF){
|
||||
pThis->m_error = uv_err_name(static_cast<int>(nread));
|
||||
LOGERR(1, "failed to read response, error " << pThis->m_error);
|
||||
}
|
||||
pThis->close();
|
||||
if (m_timer.data && !uv_is_closing(reinterpret_cast<uv_handle_t*>(&m_timer))) {
|
||||
uv_close(reinterpret_cast<uv_handle_t*>(&m_timer), on_close);
|
||||
}
|
||||
}
|
||||
|
||||
void JSONRPCRequest::on_read(const char* data, size_t size)
|
||||
void Call(const std::string& address, int port, const std::string& req, const std::string& auth, const std::string& proxy, CallbackBase* cb, CallbackBase* close_cb, uv_loop_t* loop)
|
||||
{
|
||||
m_response.append(data, size);
|
||||
|
||||
static constexpr char headers_end[] = "\r\n\r\n";
|
||||
if (m_response.find(headers_end) == std::string::npos) {
|
||||
return;
|
||||
if (!loop) {
|
||||
loop = uv_default_loop();
|
||||
}
|
||||
|
||||
llhttp_settings_t settings{};
|
||||
|
||||
settings.on_status = [](llhttp_t*, const char* at, size_t length)
|
||||
{
|
||||
if ((length == 2) && (!memcmp(at, "Ok", 2) || !memcmp(at, "OK", 2))) {
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
|
||||
settings.on_header_field = [](llhttp_t* parser, const char* at, size_t length)
|
||||
{
|
||||
JSONRPCRequest* pThis = static_cast<JSONRPCRequest*>(parser->data);
|
||||
static const char header[] = "Content-Length";
|
||||
pThis->m_contentLengthHeader = ((length == sizeof(header) - 1) && (memcmp(at, header, length) == 0));
|
||||
return 0;
|
||||
};
|
||||
|
||||
settings.on_header_value = [](llhttp_t* parser, const char* at, size_t length)
|
||||
{
|
||||
JSONRPCRequest* pThis = static_cast<JSONRPCRequest*>(parser->data);
|
||||
if (pThis->m_contentLengthHeader) {
|
||||
uint32_t k = 0;
|
||||
for (const char* p = at; p < at + length; ++p) {
|
||||
if ('0' <= *p && *p <= '9') {
|
||||
k = k * 10 + (*p - '0');
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
const bool result = CallOnLoop(loop,
|
||||
[=]()
|
||||
{
|
||||
try {
|
||||
new CurlContext(address, port, req, auth, proxy, cb, close_cb, loop);
|
||||
}
|
||||
if (!k) {
|
||||
return -1;
|
||||
catch (const std::exception& e) {
|
||||
const char* msg = e.what();
|
||||
(*close_cb)(msg, strlen(msg), 0.0);
|
||||
}
|
||||
pThis->m_contentLength = k;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
});
|
||||
|
||||
settings.on_body = [](llhttp_t* parser, const char* at, size_t length)
|
||||
{
|
||||
JSONRPCRequest* pThis = static_cast<JSONRPCRequest*>(parser->data);
|
||||
if (pThis->m_contentLength && (length >= pThis->m_contentLength) && pThis->m_callback) {
|
||||
(*pThis->m_callback)(at, length);
|
||||
delete pThis->m_callback;
|
||||
pThis->m_callback = nullptr;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
|
||||
llhttp_t parser;
|
||||
llhttp_init(&parser, HTTP_RESPONSE, &settings);
|
||||
|
||||
parser.data = this;
|
||||
|
||||
const llhttp_errno result = llhttp_execute(&parser, m_response.c_str(), m_response.length());
|
||||
if (result != HPE_OK) {
|
||||
m_error = "failed to parse response";
|
||||
LOGERR(1, m_error << ", result = " << static_cast<int>(result));
|
||||
close();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_callback) {
|
||||
close();
|
||||
if (!result) {
|
||||
LOGERR(1, "JSON RPC \"" << req << "\" failed");
|
||||
}
|
||||
}
|
||||
|
||||
void JSONRPCRequest::close()
|
||||
{
|
||||
uv_handle_t* h = reinterpret_cast<uv_handle_t*>(&m_socket);
|
||||
if (!uv_is_closing(h)) {
|
||||
uv_close(h, on_close);
|
||||
}
|
||||
}
|
||||
|
||||
void JSONRPCRequest::on_close(uv_handle_t* handle)
|
||||
{
|
||||
JSONRPCRequest* req = static_cast<JSONRPCRequest*>(handle->data);
|
||||
if (req->m_closeCallback) {
|
||||
(*req->m_closeCallback)(req->m_error.c_str(), req->m_error.length());
|
||||
}
|
||||
delete req;
|
||||
}
|
||||
|
||||
JSONRPCRequest::~JSONRPCRequest()
|
||||
{
|
||||
delete m_callback;
|
||||
delete m_closeCallback;
|
||||
}
|
||||
|
||||
} // namespace JSONRPCRequest
|
||||
} // namespace p2pool
|
||||
|
||||
+13
-70
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
|
||||
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright (c) 2021-2023 SChernykh <https://github.com/SChernykh>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -18,77 +18,20 @@
|
||||
#pragma once
|
||||
|
||||
namespace p2pool {
|
||||
namespace JSONRPCRequest {
|
||||
|
||||
class JSONRPCRequest
|
||||
typedef Callback<void, const char*, size_t, double>::Base CallbackBase;
|
||||
|
||||
void Call(const std::string& address, int port, const std::string& req, const std::string& auth, const std::string& proxy, CallbackBase* cb, CallbackBase* close_cb, uv_loop_t* loop);
|
||||
|
||||
template<typename T, typename U>
|
||||
FORCEINLINE void call(const std::string& address, int port, const std::string& req, const std::string& auth, const std::string& proxy, T&& cb, U&& close_cb, uv_loop_t* loop = nullptr)
|
||||
{
|
||||
public:
|
||||
template<typename T>
|
||||
static FORCEINLINE void call(const char* address, int port, const char* req, T&& cb)
|
||||
{
|
||||
// It will be deleted in one of the tcp callbacks eventually
|
||||
JSONRPCRequest* r = new JSONRPCRequest(address, port, req, new Callback<T>(std::move(cb)), nullptr, nullptr);
|
||||
if (!r->m_valid) {
|
||||
delete r;
|
||||
}
|
||||
}
|
||||
typedef Callback<void, const char*, size_t, double>::Derived<T> CallbackT;
|
||||
typedef Callback<void, const char*, size_t, double>::Derived<U> CallbackU;
|
||||
|
||||
template<typename T, typename U>
|
||||
static FORCEINLINE void call(const char* address, int port, const char* req, T&& cb, U&& close_cb, uv_loop_t* loop = nullptr)
|
||||
{
|
||||
// It will be deleted in one of the tcp callbacks eventually
|
||||
CallbackBase* close_callback = new Callback<U>(std::move(close_cb));
|
||||
JSONRPCRequest* r = new JSONRPCRequest(address, port, req, new Callback<T>(std::move(cb)), close_callback, loop);
|
||||
if (!r->m_valid) {
|
||||
constexpr char err[] = "internal error";
|
||||
(*close_callback)(err, sizeof(err) - 1);
|
||||
delete r;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
struct CallbackBase
|
||||
{
|
||||
virtual ~CallbackBase() {}
|
||||
virtual void operator()(const char* data, size_t size) = 0;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct Callback : public CallbackBase
|
||||
{
|
||||
explicit FORCEINLINE Callback(T&& cb) : m_cb(std::move(cb)) {}
|
||||
void operator()(const char* data, size_t size) override { m_cb(data, size); }
|
||||
|
||||
private:
|
||||
Callback& operator=(Callback&&) = delete;
|
||||
T m_cb;
|
||||
};
|
||||
|
||||
JSONRPCRequest(const char* address, int port, const char* req, CallbackBase* cb, CallbackBase* close_cb, uv_loop_t* loop);
|
||||
~JSONRPCRequest();
|
||||
|
||||
static void on_connect(uv_connect_t* req, int status);
|
||||
static void on_write(uv_write_t* handle, int status);
|
||||
static void on_alloc(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf);
|
||||
static void on_read(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf);
|
||||
void on_read(const char* data, size_t size);
|
||||
void close();
|
||||
static void on_close(uv_handle_t* handle);
|
||||
|
||||
uv_tcp_t m_socket;
|
||||
uv_connect_t m_connect;
|
||||
uv_write_t m_write;
|
||||
|
||||
CallbackBase* m_callback;
|
||||
CallbackBase* m_closeCallback;
|
||||
uint32_t m_contentLength;
|
||||
bool m_contentLengthHeader;
|
||||
|
||||
std::vector<char> m_request;
|
||||
std::string m_response;
|
||||
char m_readBuf[65536];
|
||||
bool m_readBufInUse;
|
||||
bool m_valid;
|
||||
std::string m_error;
|
||||
};
|
||||
Call(address, port, req, auth, proxy, new CallbackT(std::move(cb)), new CallbackU(std::move(close_cb)), loop);
|
||||
}
|
||||
|
||||
} // namespace JSONRPCRequest
|
||||
} // namespace p2pool
|
||||
|
||||
+47
-79
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
|
||||
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright (c) 2021-2023 SChernykh <https://github.com/SChernykh>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -24,7 +24,7 @@ namespace p2pool {
|
||||
#define ROTL64(x, y) (((x) << (y)) | ((x) >> (64 - (y))))
|
||||
#endif
|
||||
|
||||
const uint64_t keccakf_rndc[24] =
|
||||
static const uint64_t keccakf_rndc[24] =
|
||||
{
|
||||
0x0000000000000001, 0x0000000000008082, 0x800000000000808a,
|
||||
0x8000000080008000, 0x000000000000808b, 0x0000000080000001,
|
||||
@@ -36,7 +36,7 @@ const uint64_t keccakf_rndc[24] =
|
||||
0x8000000000008080, 0x0000000080000001, 0x8000000080008008
|
||||
};
|
||||
|
||||
NOINLINE void keccakf(uint64_t* st)
|
||||
NOINLINE void keccakf(uint64_t (&st)[25])
|
||||
{
|
||||
for (int round = 0; round < KeccakParams::ROUNDS; ++round) {
|
||||
uint64_t bc[5];
|
||||
@@ -48,17 +48,23 @@ NOINLINE void keccakf(uint64_t* st)
|
||||
bc[3] = st[3] ^ st[8] ^ st[13] ^ st[18] ^ st[23];
|
||||
bc[4] = st[4] ^ st[9] ^ st[14] ^ st[19] ^ st[24];
|
||||
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
uint64_t t = bc[(i + 4) % 5] ^ ROTL64(bc[(i + 1) % 5], 1);
|
||||
st[i + 0 ] ^= t;
|
||||
st[i + 5] ^= t;
|
||||
st[i + 10] ^= t;
|
||||
st[i + 15] ^= t;
|
||||
st[i + 20] ^= t;
|
||||
#define THETA(i) { \
|
||||
const uint64_t t = bc[(i + 4) % 5] ^ ROTL64(bc[(i + 1) % 5], 1); \
|
||||
st[i + 0 ] ^= t; \
|
||||
st[i + 5] ^= t; \
|
||||
st[i + 10] ^= t; \
|
||||
st[i + 15] ^= t; \
|
||||
st[i + 20] ^= t; \
|
||||
}
|
||||
|
||||
THETA(0);
|
||||
THETA(1);
|
||||
THETA(2);
|
||||
THETA(3);
|
||||
THETA(4);
|
||||
|
||||
// Rho Pi
|
||||
uint64_t t = st[1];
|
||||
const uint64_t t = st[1];
|
||||
st[ 1] = ROTL64(st[ 6], 44);
|
||||
st[ 6] = ROTL64(st[ 9], 20);
|
||||
st[ 9] = ROTL64(st[22], 61);
|
||||
@@ -85,80 +91,49 @@ NOINLINE void keccakf(uint64_t* st)
|
||||
st[10] = ROTL64(t, 1);
|
||||
|
||||
// Chi
|
||||
// unrolled loop, where only last iteration is different
|
||||
int j = 0;
|
||||
bc[0] = st[j + 0];
|
||||
bc[1] = st[j + 1];
|
||||
#define CHI(j) { \
|
||||
const uint64_t st0 = st[j ]; \
|
||||
const uint64_t st1 = st[j + 1]; \
|
||||
const uint64_t st2 = st[j + 2]; \
|
||||
const uint64_t st3 = st[j + 3]; \
|
||||
const uint64_t st4 = st[j + 4]; \
|
||||
st[j ] ^= ~st1 & st2; \
|
||||
st[j + 1] ^= ~st2 & st3; \
|
||||
st[j + 2] ^= ~st3 & st4; \
|
||||
st[j + 3] ^= ~st4 & st0; \
|
||||
st[j + 4] ^= ~st0 & st1; \
|
||||
}
|
||||
|
||||
st[j + 0] ^= (~st[j + 1]) & st[j + 2];
|
||||
st[j + 1] ^= (~st[j + 2]) & st[j + 3];
|
||||
st[j + 2] ^= (~st[j + 3]) & st[j + 4];
|
||||
st[j + 3] ^= (~st[j + 4]) & bc[0];
|
||||
st[j + 4] ^= (~bc[0]) & bc[1];
|
||||
CHI( 0);
|
||||
CHI( 5);
|
||||
CHI(10);
|
||||
CHI(15);
|
||||
CHI(20);
|
||||
|
||||
j = 5;
|
||||
bc[0] = st[j + 0];
|
||||
bc[1] = st[j + 1];
|
||||
|
||||
st[j + 0] ^= (~st[j + 1]) & st[j + 2];
|
||||
st[j + 1] ^= (~st[j + 2]) & st[j + 3];
|
||||
st[j + 2] ^= (~st[j + 3]) & st[j + 4];
|
||||
st[j + 3] ^= (~st[j + 4]) & bc[0];
|
||||
st[j + 4] ^= (~bc[0]) & bc[1];
|
||||
|
||||
j = 10;
|
||||
bc[0] = st[j + 0];
|
||||
bc[1] = st[j + 1];
|
||||
|
||||
st[j + 0] ^= (~st[j + 1]) & st[j + 2];
|
||||
st[j + 1] ^= (~st[j + 2]) & st[j + 3];
|
||||
st[j + 2] ^= (~st[j + 3]) & st[j + 4];
|
||||
st[j + 3] ^= (~st[j + 4]) & bc[0];
|
||||
st[j + 4] ^= (~bc[0]) & bc[1];
|
||||
|
||||
j = 15;
|
||||
bc[0] = st[j + 0];
|
||||
bc[1] = st[j + 1];
|
||||
|
||||
st[j + 0] ^= (~st[j + 1]) & st[j + 2];
|
||||
st[j + 1] ^= (~st[j + 2]) & st[j + 3];
|
||||
st[j + 2] ^= (~st[j + 3]) & st[j + 4];
|
||||
st[j + 3] ^= (~st[j + 4]) & bc[0];
|
||||
st[j + 4] ^= (~bc[0]) & bc[1];
|
||||
|
||||
j = 20;
|
||||
bc[0] = st[j + 0];
|
||||
bc[1] = st[j + 1];
|
||||
bc[2] = st[j + 2];
|
||||
bc[3] = st[j + 3];
|
||||
bc[4] = st[j + 4];
|
||||
|
||||
st[j + 0] ^= (~bc[1]) & bc[2];
|
||||
st[j + 1] ^= (~bc[2]) & bc[3];
|
||||
st[j + 2] ^= (~bc[3]) & bc[4];
|
||||
st[j + 3] ^= (~bc[4]) & bc[0];
|
||||
st[j + 4] ^= (~bc[0]) & bc[1];
|
||||
|
||||
// Iota
|
||||
st[0] ^= keccakf_rndc[round];
|
||||
}
|
||||
}
|
||||
|
||||
NOINLINE void keccak(const uint8_t* in, int inlen, uint8_t* md, int mdlen)
|
||||
NOINLINE void keccak_step(const uint8_t* &in, int &inlen, uint64_t (&st)[25])
|
||||
{
|
||||
uint64_t st[25];
|
||||
|
||||
const int rsiz = sizeof(st) == mdlen ? KeccakParams::HASH_DATA_AREA : 200 - 2 * mdlen;
|
||||
const int rsizw = rsiz / 8;
|
||||
|
||||
memset(st, 0, sizeof(st));
|
||||
constexpr int rsiz = KeccakParams::HASH_DATA_AREA;
|
||||
constexpr int rsizw = rsiz / 8;
|
||||
|
||||
for (; inlen >= rsiz; inlen -= rsiz, in += rsiz) {
|
||||
for (int i = 0; i < rsizw; i++) {
|
||||
st[i] ^= ((uint64_t*)in)[i];
|
||||
st[i] ^= read_unaligned(reinterpret_cast<const uint64_t*>(in) + i);
|
||||
}
|
||||
keccakf(st);
|
||||
}
|
||||
}
|
||||
|
||||
NOINLINE void keccak_finish(const uint8_t* in, int inlen, uint64_t (&st)[25])
|
||||
{
|
||||
constexpr int rsiz = KeccakParams::HASH_DATA_AREA;
|
||||
constexpr int rsizw = rsiz / 8;
|
||||
|
||||
keccak_step(in, inlen, st);
|
||||
|
||||
// last block and padding
|
||||
alignas(8) uint8_t temp[144];
|
||||
@@ -169,17 +144,10 @@ NOINLINE void keccak(const uint8_t* in, int inlen, uint8_t* md, int mdlen)
|
||||
temp[rsiz - 1] |= 0x80;
|
||||
|
||||
for (int i = 0; i < rsizw; i++) {
|
||||
st[i] ^= ((uint64_t*)temp)[i];
|
||||
st[i] ^= reinterpret_cast<uint64_t*>(temp)[i];
|
||||
}
|
||||
|
||||
keccakf(st);
|
||||
|
||||
memcpy(md, st, mdlen);
|
||||
}
|
||||
|
||||
void keccak(const uint8_t *in, int inlen, uint8_t (&md)[200])
|
||||
{
|
||||
keccak(in, inlen, md, 200);
|
||||
}
|
||||
|
||||
} // namespace p2pool
|
||||
|
||||
+16
-7
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
|
||||
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright (c) 2021-2023 SChernykh <https://github.com/SChernykh>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -24,20 +24,29 @@ enum KeccakParams {
|
||||
ROUNDS = 24,
|
||||
};
|
||||
|
||||
void keccakf(uint64_t* st);
|
||||
void keccak(const uint8_t *in, int inlen, uint8_t *md, int mdlen);
|
||||
void keccak(const uint8_t* in, int inlen, uint8_t (&md)[200]);
|
||||
void keccakf(uint64_t (&st)[25]);
|
||||
void keccak_step(const uint8_t* &in, int &inlen, uint64_t (&st)[25]);
|
||||
void keccak_finish(const uint8_t* in, int inlen, uint64_t (&st)[25]);
|
||||
|
||||
template<size_t N>
|
||||
FORCEINLINE void keccak(const uint8_t* in, int inlen, uint8_t (&md)[N])
|
||||
{
|
||||
static_assert((N == 32) || (N == 200), "invalid size");
|
||||
|
||||
uint64_t st[25] = {};
|
||||
keccak_step(in, inlen, st);
|
||||
keccak_finish(in, inlen, st);
|
||||
memcpy(md, st, N);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
FORCEINLINE void keccak_custom(T&& in, int inlen, uint8_t* md, int mdlen)
|
||||
{
|
||||
uint64_t st[25];
|
||||
uint64_t st[25] = {};
|
||||
|
||||
const int rsiz = sizeof(st) == mdlen ? KeccakParams::HASH_DATA_AREA : 200 - 2 * mdlen;
|
||||
const int rsizw = rsiz / 8;
|
||||
|
||||
memset(st, 0, sizeof(st));
|
||||
|
||||
int offset = 0;
|
||||
|
||||
for (; inlen >= rsiz; inlen -= rsiz, offset += rsiz) {
|
||||
|
||||
+223
-64
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
|
||||
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright (c) 2021-2023 SChernykh <https://github.com/SChernykh>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -17,10 +17,19 @@
|
||||
|
||||
#include "common.h"
|
||||
#include "uv_util.h"
|
||||
#include "wallet.h"
|
||||
#include <ctime>
|
||||
#include <fstream>
|
||||
#include <thread>
|
||||
#include <stdlib.h>
|
||||
#include <clocale>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4996)
|
||||
#endif
|
||||
|
||||
LOG_CATEGORY(Log)
|
||||
|
||||
static constexpr char log_category_prefix[] = "Log ";
|
||||
static constexpr char log_file_name[] = "p2pool.log";
|
||||
|
||||
namespace p2pool {
|
||||
@@ -32,14 +41,69 @@ bool CONSOLE_COLORS = true;
|
||||
|
||||
#ifndef P2POOL_LOG_DISABLE
|
||||
|
||||
static volatile bool stopped = false;
|
||||
static volatile bool worker_started = false;
|
||||
|
||||
#ifdef _WIN32
|
||||
static const HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE);
|
||||
static const HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
static const HANDLE hStdErr = GetStdHandle(STD_ERROR_HANDLE);
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && !defined(NDEBUG)
|
||||
|
||||
#include <DbgHelp.h>
|
||||
|
||||
#pragma comment(lib, "Dbghelp.lib")
|
||||
|
||||
LONG WINAPI UnhandledExceptionFilter(_In_ _EXCEPTION_POINTERS* exception_pointers)
|
||||
{
|
||||
constexpr size_t MAX_FRAMES = 32;
|
||||
|
||||
void* stack_trace[MAX_FRAMES] = {};
|
||||
DWORD hash;
|
||||
CaptureStackBackTrace(1, MAX_FRAMES, stack_trace, &hash);
|
||||
|
||||
char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)] = {};
|
||||
PSYMBOL_INFO pSymbol = reinterpret_cast<PSYMBOL_INFO>(buffer);
|
||||
|
||||
pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
|
||||
pSymbol->MaxNameLen = MAX_SYM_NAME;
|
||||
|
||||
IMAGEHLP_LINE64 line{};
|
||||
line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
|
||||
|
||||
const HANDLE h = GetCurrentProcess();
|
||||
|
||||
const uint32_t code = (exception_pointers && exception_pointers->ExceptionRecord) ? exception_pointers->ExceptionRecord->ExceptionCode : 0;
|
||||
|
||||
fprintf(stderr, "\n\nUnhandled exception %X at:\n", code);
|
||||
fflush(stderr);
|
||||
|
||||
for (size_t j = 0; j < MAX_FRAMES; ++j) {
|
||||
const DWORD64 address = reinterpret_cast<DWORD64>(stack_trace[j]);
|
||||
DWORD t = 0;
|
||||
if (SymFromAddr(h, address, nullptr, pSymbol) && SymGetLineFromAddr64(h, address, &t, &line)) {
|
||||
fprintf(stderr, "%s (%s, line %lu)\n", line.FileName, pSymbol->Name, line.LineNumber);
|
||||
fflush(stderr);
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "\n\n");
|
||||
fflush(stderr);
|
||||
|
||||
// Normal logging might be broken at this point, but try to log it anyway
|
||||
LOGERR(0, "Unhandled exception " << log::Hex(code) << " at:");
|
||||
|
||||
for (size_t j = 0; j < MAX_FRAMES; ++j) {
|
||||
const DWORD64 address = reinterpret_cast<DWORD64>(stack_trace[j]);
|
||||
DWORD t = 0;
|
||||
if (SymFromAddr(h, address, nullptr, pSymbol) && SymGetLineFromAddr64(h, address, &t, &line)) {
|
||||
LOGERR(0, line.FileName << " (" << static_cast<const char*>(pSymbol->Name) << ", line " << static_cast<size_t>(line.LineNumber) << ')');
|
||||
}
|
||||
}
|
||||
|
||||
Sleep(1000);
|
||||
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
#endif // _MSC_VER && !NDEBUG
|
||||
#endif // _WIN32
|
||||
|
||||
class Worker
|
||||
{
|
||||
@@ -47,15 +111,24 @@ public:
|
||||
enum params : int
|
||||
{
|
||||
SLOT_SIZE = 1024,
|
||||
BUF_SIZE = SLOT_SIZE * 16384,
|
||||
BUF_SIZE = SLOT_SIZE * 8192,
|
||||
};
|
||||
|
||||
FORCEINLINE Worker()
|
||||
: m_writePos(0)
|
||||
, m_readPos(0)
|
||||
, m_started{ false }
|
||||
, m_stopped(false)
|
||||
{
|
||||
#if defined(_WIN32) && defined(_MSC_VER) && !defined(NDEBUG)
|
||||
SetUnhandledExceptionFilter(UnhandledExceptionFilter);
|
||||
SymInitialize(GetCurrentProcess(), NULL, TRUE);
|
||||
#endif
|
||||
|
||||
set_main_thread();
|
||||
|
||||
std::setlocale(LC_ALL, "en_001");
|
||||
|
||||
m_logFile.open(log_file_name, std::ios::app | std::ios::binary);
|
||||
|
||||
m_buf.resize(BUF_SIZE);
|
||||
@@ -72,44 +145,68 @@ public:
|
||||
abort();
|
||||
}
|
||||
|
||||
do {} while (!worker_started);
|
||||
while (m_started.load() == false) {
|
||||
std::this_thread::yield();
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
SetConsoleMode(hStdIn, ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_EXTENDED_FLAGS);
|
||||
|
||||
DWORD dwConsoleMode;
|
||||
if (GetConsoleMode(hStdIn, &dwConsoleMode)) {
|
||||
SetConsoleMode(hStdIn, dwConsoleMode & ~ENABLE_QUICK_EDIT_MODE);
|
||||
}
|
||||
if (GetConsoleMode(hStdOut, &dwConsoleMode)) {
|
||||
SetConsoleMode(hStdOut, dwConsoleMode | ENABLE_VIRTUAL_TERMINAL_PROCESSING);
|
||||
}
|
||||
#endif
|
||||
|
||||
const char* no_color = getenv("NO_COLOR");
|
||||
if (no_color && *no_color) {
|
||||
CONSOLE_COLORS = false;
|
||||
}
|
||||
|
||||
LOGINFO(0, "started");
|
||||
|
||||
if (!m_logFile.is_open()) {
|
||||
LOGERR(0, "failed to open " << log_file_name);
|
||||
}
|
||||
|
||||
init_uv_threadpool();
|
||||
}
|
||||
|
||||
FORCEINLINE ~Worker()
|
||||
~Worker()
|
||||
{
|
||||
stop();
|
||||
try {
|
||||
stop();
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
}
|
||||
|
||||
FORCEINLINE void stop()
|
||||
{
|
||||
if (stopped) {
|
||||
return;
|
||||
{
|
||||
MutexLock lock(m_mutex);
|
||||
if (m_stopped) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_stopped = true;
|
||||
LOGINFO(0, "stopped");
|
||||
}
|
||||
|
||||
stopped = true;
|
||||
LOGINFO(0, "stopped");
|
||||
uv_thread_join(&m_worker);
|
||||
uv_cond_destroy(&m_cond);
|
||||
uv_mutex_destroy(&m_mutex);
|
||||
uv_loop_close(uv_default_loop());
|
||||
|
||||
#if ((UV_VERSION_MAJOR > 1) || ((UV_VERSION_MAJOR == 1) && (UV_VERSION_MINOR >= 38)))
|
||||
uv_library_shutdown();
|
||||
#endif
|
||||
|
||||
m_logFile.close();
|
||||
|
||||
#if defined(_WIN32) && defined(_MSC_VER) && !defined(NDEBUG)
|
||||
SymCleanup(GetCurrentProcess());
|
||||
#endif
|
||||
}
|
||||
|
||||
FORCEINLINE void write(const char* buf, uint32_t size)
|
||||
@@ -127,7 +224,10 @@ public:
|
||||
|
||||
memcpy(p + 1, buf + 1, size - 1);
|
||||
|
||||
// Ensure memory order in the writer thread
|
||||
#ifndef DEV_WITH_TSAN
|
||||
std::atomic_thread_fence(std::memory_order_seq_cst);
|
||||
#endif
|
||||
|
||||
// Mark that everything is written into this log slot
|
||||
p[0] = buf[0] + 1;
|
||||
@@ -136,27 +236,67 @@ public:
|
||||
uv_cond_signal(&m_cond);
|
||||
}
|
||||
|
||||
private:
|
||||
static void init_uv_threadpool()
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
#define putenv _putenv
|
||||
#endif
|
||||
|
||||
const uint32_t N = std::min(std::max(std::thread::hardware_concurrency(), 4U), 8U);
|
||||
|
||||
static char buf[40] = {};
|
||||
log::Stream s(buf);
|
||||
s << "UV_THREADPOOL_SIZE=" << N << '\0';
|
||||
|
||||
int err = putenv(buf);
|
||||
if (err != 0) {
|
||||
err = errno;
|
||||
LOGWARN(0, "Couldn't set UV thread pool size to " << N << " threads, putenv returned error " << err);
|
||||
}
|
||||
|
||||
static uv_work_t dummy;
|
||||
err = uv_queue_work(uv_default_loop_checked(), &dummy, [](uv_work_t*) {}, nullptr);
|
||||
if (err) {
|
||||
LOGERR(0, "init_uv_threadpool: uv_queue_work failed, error " << uv_err_name(err));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
static void run_wrapper(void* arg) { reinterpret_cast<Worker*>(arg)->run(); }
|
||||
|
||||
NOINLINE void run()
|
||||
{
|
||||
worker_started = true;
|
||||
m_started.exchange(true);
|
||||
|
||||
do {
|
||||
uv_mutex_lock(&m_mutex);
|
||||
uv_cond_wait(&m_cond, &m_mutex);
|
||||
if (m_readPos == m_writePos.load()) {
|
||||
// Nothing to do, wait for the signal or exit if stopped
|
||||
if (m_stopped) {
|
||||
uv_mutex_unlock(&m_mutex);
|
||||
return;
|
||||
}
|
||||
uv_cond_wait(&m_cond, &m_mutex);
|
||||
}
|
||||
uv_mutex_unlock(&m_mutex);
|
||||
|
||||
for (uint32_t writePos = m_writePos.load(); m_readPos < writePos; writePos = m_writePos.load()) {
|
||||
for (uint32_t writePos = m_writePos.load(); m_readPos != writePos; writePos = m_writePos.load()) {
|
||||
// We have at least one log slot pending, possibly more than one
|
||||
// Process everything in a loop before reading m_writePos again
|
||||
do {
|
||||
char* p = m_buf.data() + (m_readPos % BUF_SIZE);
|
||||
|
||||
// Wait until everything is written into this log slot
|
||||
volatile char& severity = *p;
|
||||
while (!severity) {}
|
||||
volatile char& severity = p[0];
|
||||
while (!severity) {
|
||||
std::this_thread::yield();
|
||||
}
|
||||
|
||||
// Ensure memory order in the reader thread
|
||||
#ifndef DEV_WITH_TSAN
|
||||
std::atomic_thread_fence(std::memory_order_seq_cst);
|
||||
#endif
|
||||
|
||||
uint32_t size = static_cast<uint8_t>(p[2]);
|
||||
size = (size << 8) + static_cast<uint8_t>(p[1]);
|
||||
@@ -172,21 +312,7 @@ private:
|
||||
strip_colors(p, size);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
DWORD k;
|
||||
WriteConsole((severity == 1) ? hStdOut : hStdErr, p, size, &k, nullptr);
|
||||
#else
|
||||
fwrite(p, 1, size, (severity == 1) ? stdout : stderr);
|
||||
#endif
|
||||
|
||||
// Reopen the log file if it's been moved (logrotate support)
|
||||
if (m_logFile.is_open()) {
|
||||
struct stat buf;
|
||||
if (stat(log_file_name, &buf) != 0) {
|
||||
m_logFile.close();
|
||||
m_logFile.open(log_file_name, std::ios::app | std::ios::binary);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_logFile.is_open()) {
|
||||
if (c) {
|
||||
@@ -204,7 +330,6 @@ private:
|
||||
}
|
||||
|
||||
m_logFile.write(p, size);
|
||||
m_logFile.flush();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -212,16 +337,31 @@ private:
|
||||
severity = '\0';
|
||||
|
||||
m_readPos += SLOT_SIZE;
|
||||
} while (m_readPos < writePos);
|
||||
} while (m_readPos != writePos);
|
||||
}
|
||||
} while (!stopped);
|
||||
|
||||
// Flush the log file only after all pending log lines have been written
|
||||
if (m_logFile.is_open()) {
|
||||
m_logFile.flush();
|
||||
|
||||
// Reopen the log file if it's been moved (logrotate support)
|
||||
struct stat buf;
|
||||
if (stat(log_file_name, &buf) != 0) {
|
||||
m_logFile.close();
|
||||
m_logFile.open(log_file_name, std::ios::app | std::ios::binary);
|
||||
}
|
||||
}
|
||||
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
} while (1);
|
||||
}
|
||||
|
||||
static FORCEINLINE void strip_colors(char* buf, uint32_t& size)
|
||||
{
|
||||
char* p_read = buf;
|
||||
const char* p_read = buf;
|
||||
char* p_write = buf;
|
||||
char* buf_end = buf + size;
|
||||
const char* buf_end = buf + size;
|
||||
|
||||
bool is_color = false;
|
||||
|
||||
@@ -252,6 +392,9 @@ private:
|
||||
uv_mutex_t m_mutex;
|
||||
uv_thread_t m_worker;
|
||||
|
||||
std::atomic<bool> m_started;
|
||||
bool m_stopped;
|
||||
|
||||
std::ofstream m_logFile;
|
||||
};
|
||||
|
||||
@@ -259,14 +402,39 @@ static Worker worker;
|
||||
|
||||
#endif // P2POOL_LOG_DISABLE
|
||||
|
||||
// cppcheck-suppress uninitMemberVar
|
||||
static FORCEINLINE void writeCurrentTime(Stream& s)
|
||||
{
|
||||
using namespace std::chrono;
|
||||
|
||||
const system_clock::time_point now = system_clock::now();
|
||||
const time_t t0 = system_clock::to_time_t(now);
|
||||
|
||||
tm t;
|
||||
|
||||
#ifdef _WIN32
|
||||
gmtime_s(&t, &t0);
|
||||
#else
|
||||
gmtime_r(&t0, &t);
|
||||
#endif
|
||||
|
||||
s.setNumberWidth(2);
|
||||
s << (t.tm_year + 1900) << '-' << (t.tm_mon + 1) << '-' << t.tm_mday << ' ' << t.tm_hour << ':' << t.tm_min << ':' << t.tm_sec << '.';
|
||||
|
||||
const int32_t mcs = time_point_cast<microseconds>(now).time_since_epoch().count() % 1000000;
|
||||
|
||||
s.setNumberWidth(4);
|
||||
s << (mcs / 100);
|
||||
s.setNumberWidth(1);
|
||||
}
|
||||
|
||||
NOINLINE Writer::Writer(Severity severity) : Stream(m_stackBuf)
|
||||
{
|
||||
m_stackBuf[BUF_SIZE] = '\0';
|
||||
m_buf[0] = static_cast<char>(severity);
|
||||
m_pos = 3;
|
||||
|
||||
*this << Cyan();
|
||||
writeCurrentTime();
|
||||
writeCurrentTime(*this);
|
||||
*this << NoColor() << ' ';
|
||||
}
|
||||
|
||||
@@ -294,30 +462,21 @@ void stop()
|
||||
#endif
|
||||
}
|
||||
|
||||
NOINLINE void Stream::writeCurrentTime()
|
||||
NOINLINE void Stream::Entry<raw_ip>::put(const raw_ip& value, Stream* wrapper)
|
||||
{
|
||||
using namespace std::chrono;
|
||||
const bool is_ipv4 = value.is_ipv4_prefix();
|
||||
|
||||
const system_clock::time_point now = system_clock::now();
|
||||
const time_t t0 = system_clock::to_time_t(now);
|
||||
char addr_str_buf[64];
|
||||
const char* addr_str = inet_ntop(is_ipv4 ? AF_INET : AF_INET6, value.data + (is_ipv4 ? 12 : 0), addr_str_buf, sizeof(addr_str_buf));
|
||||
|
||||
tm t;
|
||||
*wrapper << (addr_str ? addr_str : "N/A");
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
gmtime_s(&t, &t0);
|
||||
#else
|
||||
gmtime_r(&t0, &t);
|
||||
#endif
|
||||
|
||||
m_numberWidth = 2;
|
||||
*this << (t.tm_year + 1900) << '-' << (t.tm_mon + 1) << '-' << t.tm_mday << ' ' << t.tm_hour << ':' << t.tm_min << ':' << t.tm_sec << '.';
|
||||
|
||||
const int32_t mcs = time_point_cast<microseconds>(now).time_since_epoch().count() % 1000000;
|
||||
|
||||
m_numberWidth = 4;
|
||||
*this << (mcs / 100);
|
||||
// cppcheck-suppress redundantAssignment
|
||||
m_numberWidth = 1;
|
||||
NOINLINE void Stream::Entry<Wallet>::put(const Wallet& w, Stream* wrapper)
|
||||
{
|
||||
char buf[Wallet::ADDRESS_LENGTH];
|
||||
w.encode(buf);
|
||||
wrapper->writeBuf(buf, Wallet::ADDRESS_LENGTH);
|
||||
}
|
||||
|
||||
} // namespace log
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
|
||||
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright (c) 2021-2023 SChernykh <https://github.com/SChernykh>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -19,6 +19,8 @@
|
||||
|
||||
namespace p2pool {
|
||||
|
||||
class Wallet;
|
||||
|
||||
namespace log {
|
||||
|
||||
extern int GLOBAL_LOG_LEVEL;
|
||||
@@ -35,8 +37,19 @@ struct Stream
|
||||
{
|
||||
enum params : int { BUF_SIZE = 1024 - 1 };
|
||||
|
||||
explicit FORCEINLINE Stream(char* buf) : m_pos(0), m_numberWidth(1), m_buf(buf), m_bufSize(BUF_SIZE) {}
|
||||
FORCEINLINE Stream(char* buf, size_t size) : m_pos(0), m_numberWidth(1), m_buf(buf), m_bufSize(static_cast<int>(size) - 1) {}
|
||||
template<size_t N>
|
||||
explicit FORCEINLINE Stream(char (&buf)[N]) : m_pos(0), m_numberWidth(1), m_buf(buf), m_bufSize(N - 1), m_spilled(0) {}
|
||||
|
||||
FORCEINLINE Stream(void* buf, size_t size) { reset(buf, size); }
|
||||
|
||||
FORCEINLINE void reset(void* buf, size_t size)
|
||||
{
|
||||
m_pos = 0;
|
||||
m_numberWidth = 1;
|
||||
m_buf = reinterpret_cast<char*>(buf);
|
||||
m_bufSize = static_cast<int>(size) - 1;
|
||||
m_spilled = 0;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct Entry
|
||||
@@ -61,24 +74,23 @@ struct Stream
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T, int base = 10>
|
||||
template<typename T, unsigned int base = 10>
|
||||
NOINLINE void writeInt(T data)
|
||||
{
|
||||
static_assert(1 < base && base <= 64, "Invalid base");
|
||||
|
||||
const T data_with_sign = data;
|
||||
data = abs(data);
|
||||
const bool negative = (data != data_with_sign);
|
||||
const bool negative = is_negative(data);
|
||||
std::make_unsigned_t<T> udata = abs(data);
|
||||
|
||||
char buf[32];
|
||||
size_t k = sizeof(buf);
|
||||
int w = m_numberWidth;
|
||||
|
||||
do {
|
||||
buf[--k] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+/"[data % base];
|
||||
data /= base;
|
||||
buf[--k] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+/"[udata % base];
|
||||
udata /= base;
|
||||
--w;
|
||||
} while ((data > 0) || (w > 0));
|
||||
} while (udata || (w > 0));
|
||||
|
||||
if (negative) {
|
||||
buf[--k] = '-';
|
||||
@@ -92,6 +104,7 @@ struct Stream
|
||||
const int n = static_cast<int>(n0);
|
||||
const int pos = m_pos;
|
||||
if (pos + n > m_bufSize) {
|
||||
m_spilled += n;
|
||||
return;
|
||||
}
|
||||
memcpy(m_buf + pos, buf, n);
|
||||
@@ -101,12 +114,11 @@ struct Stream
|
||||
FORCEINLINE int getNumberWidth() const { return m_numberWidth; }
|
||||
FORCEINLINE void setNumberWidth(int width) { m_numberWidth = width; }
|
||||
|
||||
NOINLINE void writeCurrentTime();
|
||||
|
||||
int m_pos;
|
||||
int m_numberWidth;
|
||||
char* m_buf;
|
||||
int m_bufSize;
|
||||
int m_spilled;
|
||||
};
|
||||
|
||||
struct Writer : public Stream
|
||||
@@ -142,7 +154,13 @@ COLOR_ENTRY(LightCyan, "\x1b[0;96m")
|
||||
|
||||
template<size_t N> struct Stream::Entry<char[N]>
|
||||
{
|
||||
static FORCEINLINE void put(const char (&data)[N], Stream* wrapper) { wrapper->writeBuf(data, N - 1); }
|
||||
template<typename T>
|
||||
// cppcheck-suppress constParameterReference
|
||||
static FORCEINLINE void put(T (&data)[N], Stream* wrapper)
|
||||
{
|
||||
static_assert(std::is_same<T, const char>::value, "Non-const char buffer must be cast to \"const char*\"");
|
||||
wrapper->writeBuf(data, N - 1);
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct Stream::Entry<const char*>
|
||||
@@ -152,6 +170,7 @@ template<> struct Stream::Entry<const char*>
|
||||
|
||||
template<> struct Stream::Entry<char*>
|
||||
{
|
||||
// cppcheck-suppress constParameterPointer
|
||||
static FORCEINLINE void put(char* data, Stream* wrapper) { wrapper->writeBuf(data, strlen(data)); }
|
||||
};
|
||||
|
||||
@@ -172,7 +191,7 @@ INT_ENTRY(uint16_t)
|
||||
INT_ENTRY(uint32_t)
|
||||
INT_ENTRY(uint64_t)
|
||||
|
||||
#ifdef __APPLE__
|
||||
#if defined(__APPLE__) || defined(__OpenBSD__)
|
||||
INT_ENTRY(long)
|
||||
INT_ENTRY(unsigned long)
|
||||
#endif
|
||||
@@ -182,7 +201,10 @@ INT_ENTRY(unsigned long)
|
||||
template<typename T, int base>
|
||||
struct BasedValue
|
||||
{
|
||||
explicit FORCEINLINE BasedValue(T value) : m_value(value) {}
|
||||
explicit FORCEINLINE BasedValue(T value) : m_value(value)
|
||||
{
|
||||
static_assert(std::is_integral<T>::value, "Must be an integer type here");
|
||||
}
|
||||
|
||||
T m_value;
|
||||
};
|
||||
@@ -190,7 +212,7 @@ struct BasedValue
|
||||
template<typename T, int base>
|
||||
struct Stream::Entry<BasedValue<T, base>>
|
||||
{
|
||||
static FORCEINLINE void put(BasedValue<T, base>&& data, Stream* wrapper)
|
||||
static FORCEINLINE void put(BasedValue<T, base> data, Stream* wrapper)
|
||||
{
|
||||
wrapper->writeInt<T, base>(data.m_value);
|
||||
}
|
||||
@@ -274,7 +296,10 @@ template<> struct log::Stream::Entry<const_buf>
|
||||
|
||||
struct hex_buf
|
||||
{
|
||||
FORCEINLINE hex_buf(const uint8_t* data, size_t size) : m_data(data), m_size(size) {}
|
||||
FORCEINLINE hex_buf(const void* data, size_t size) : m_data(reinterpret_cast<const uint8_t*>(data)), m_size(size) {}
|
||||
|
||||
template<typename T>
|
||||
explicit FORCEINLINE hex_buf(const T* data) : m_data(reinterpret_cast<const uint8_t*>(data)), m_size(sizeof(T)) {}
|
||||
|
||||
const uint8_t* m_data;
|
||||
size_t m_size;
|
||||
@@ -302,6 +327,7 @@ struct Hashrate
|
||||
{
|
||||
FORCEINLINE Hashrate() : m_data(0), m_valid(false) {}
|
||||
explicit FORCEINLINE Hashrate(uint64_t data) : m_data(data), m_valid(true) {}
|
||||
FORCEINLINE Hashrate(uint64_t data, bool valid) : m_data(data), m_valid(valid) {}
|
||||
|
||||
uint64_t m_data;
|
||||
bool m_valid;
|
||||
@@ -309,7 +335,7 @@ struct Hashrate
|
||||
|
||||
template<> struct log::Stream::Entry<Hashrate>
|
||||
{
|
||||
static NOINLINE void put(Hashrate&& value, Stream* wrapper)
|
||||
static NOINLINE void put(const Hashrate& value, Stream* wrapper)
|
||||
{
|
||||
if (!value.m_valid) {
|
||||
return;
|
||||
@@ -354,7 +380,7 @@ struct XMRAmount
|
||||
|
||||
template<> struct log::Stream::Entry<XMRAmount>
|
||||
{
|
||||
static NOINLINE void put(XMRAmount&& value, Stream* wrapper)
|
||||
static NOINLINE void put(XMRAmount value, Stream* wrapper)
|
||||
{
|
||||
constexpr uint64_t denomination = 1000000000000ULL;
|
||||
|
||||
@@ -372,8 +398,7 @@ template<> struct log::Stream::Entry<XMRAmount>
|
||||
|
||||
template<> struct log::Stream::Entry<NetworkType>
|
||||
{
|
||||
// cppcheck-suppress constParameter
|
||||
static NOINLINE void put(const NetworkType& value, Stream* wrapper)
|
||||
static NOINLINE void put(NetworkType value, Stream* wrapper)
|
||||
{
|
||||
switch (value) {
|
||||
case NetworkType::Invalid: *wrapper << "invalid"; break;
|
||||
@@ -384,6 +409,71 @@ template<> struct log::Stream::Entry<NetworkType>
|
||||
}
|
||||
};
|
||||
|
||||
struct Duration
|
||||
{
|
||||
explicit FORCEINLINE Duration(uint64_t data) : m_data(data) {}
|
||||
|
||||
uint64_t m_data;
|
||||
};
|
||||
|
||||
template<> struct log::Stream::Entry<Duration>
|
||||
{
|
||||
static NOINLINE void put(Duration value, Stream* wrapper)
|
||||
{
|
||||
const uint64_t uptime = value.m_data;
|
||||
|
||||
const int64_t s = uptime % 60;
|
||||
const int64_t m = (uptime / 60) % 60;
|
||||
const int64_t h = (uptime / 3600) % 24;
|
||||
const int64_t d = uptime / 86400;
|
||||
|
||||
if (d > 0) {
|
||||
*wrapper << d << "d ";
|
||||
}
|
||||
*wrapper << h << "h " << m << "m " << s << 's';
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct PadRight
|
||||
{
|
||||
FORCEINLINE PadRight(const T& value, int len) : m_value(value), m_len(len) {}
|
||||
|
||||
const T& m_value;
|
||||
int m_len;
|
||||
|
||||
// Declare it to make compiler happy
|
||||
PadRight(const PadRight&);
|
||||
|
||||
private:
|
||||
PadRight& operator=(const PadRight&) = delete;
|
||||
PadRight& operator=(PadRight&&) = delete;
|
||||
};
|
||||
|
||||
template<typename T> FORCEINLINE PadRight<T> pad_right(const T& value, int len) { return PadRight<T>(value, len); }
|
||||
|
||||
template<typename T>
|
||||
struct log::Stream::Entry<PadRight<T>>
|
||||
{
|
||||
static NOINLINE void put(PadRight<T>&& data, Stream* wrapper)
|
||||
{
|
||||
char buf[log::Stream::BUF_SIZE + 1];
|
||||
log::Stream s(buf);
|
||||
s << data.m_value;
|
||||
|
||||
const int len = std::min<int>(data.m_len, log::Stream::BUF_SIZE);
|
||||
if (s.m_pos < len) {
|
||||
memset(buf + s.m_pos, ' ', static_cast<size_t>(len) - s.m_pos);
|
||||
s.m_pos = len;
|
||||
}
|
||||
|
||||
wrapper->writeBuf(buf, s.m_pos);
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct log::Stream::Entry<raw_ip> { static NOINLINE void put(const raw_ip& value, Stream* wrapper); };
|
||||
template<> struct log::Stream::Entry<Wallet> { static NOINLINE void put(const Wallet& w, Stream* wrapper); };
|
||||
|
||||
namespace {
|
||||
template<log::Severity severity> void apply_severity(log::Stream&);
|
||||
|
||||
@@ -395,17 +485,53 @@ namespace {
|
||||
#define CONCAT(a, b) CONCAT2(a, b)
|
||||
#define CONCAT2(a, b) a##b
|
||||
|
||||
// This is to check that LOG() call doesn't modify variables in scope, making program behavior dependent on the log level:
|
||||
//
|
||||
// int some_func(int& n) { return ++n; }
|
||||
// ...
|
||||
// LOGINFO(1, "Some important value: " << some_func(n));
|
||||
//
|
||||
// will not compile because the dummy lambda capture uses const-qualified copies of all variables.
|
||||
//
|
||||
// The check is "free": compiler will remove it entirely in release builds.
|
||||
|
||||
struct DummyStream
|
||||
{
|
||||
template<typename T>
|
||||
FORCEINLINE DummyStream& operator<<(const T&)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef __COVERITY__
|
||||
// Coverity doesn't like this macro - CID 393138: Big parameter passed by value (PASS_BY_VALUE)
|
||||
#define SIDE_EFFECT_CHECK(level, ...)
|
||||
#else
|
||||
#define SIDE_EFFECT_CHECK(level, ...) \
|
||||
if (0) { \
|
||||
MSVC_PRAGMA(warning(suppress:26444)) \
|
||||
[=]() { \
|
||||
log::DummyStream x; \
|
||||
x << (level) << __VA_ARGS__; \
|
||||
}; \
|
||||
}
|
||||
#endif
|
||||
|
||||
#define LOG_CATEGORY(category) static constexpr char log_category_prefix[] = #category " ";
|
||||
|
||||
#ifdef P2POOL_LOG_DISABLE
|
||||
|
||||
#define LOGINFO(level, ...)
|
||||
#define LOGWARN(level, ...)
|
||||
#define LOGERR(level, ...)
|
||||
#define LOGINFO(level, ...) SIDE_EFFECT_CHECK(level, log_category_prefix << __VA_ARGS__)
|
||||
#define LOGWARN(level, ...) SIDE_EFFECT_CHECK(level, log_category_prefix << __VA_ARGS__)
|
||||
#define LOGERR(level, ...) SIDE_EFFECT_CHECK(level, log_category_prefix << __VA_ARGS__)
|
||||
|
||||
#else
|
||||
|
||||
#define LOG(level, severity, ...) \
|
||||
do { \
|
||||
if (level <= log::GLOBAL_LOG_LEVEL) { \
|
||||
SIDE_EFFECT_CHECK(level, log_category_prefix << __VA_ARGS__); \
|
||||
if ((level) <= log::GLOBAL_LOG_LEVEL) { \
|
||||
log::Writer CONCAT(log_wrapper_, __LINE__)(severity); \
|
||||
CONCAT(log_wrapper_, __LINE__) << log::Gray() << log_category_prefix; \
|
||||
log::apply_severity<severity>(CONCAT(log_wrapper_, __LINE__)); \
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user