mirror of
https://github.com/bisq-network/bisq.git
synced 2024-11-19 09:52:23 +01:00
Merge pull request #7136 from HenrikJannsen/re-integrate-inventory-module
Reintegrate inventory module
This commit is contained in:
commit
ae240719ff
@ -43,9 +43,12 @@ natpryce-make-it-easy = { strictly = '4.0.1' }
|
||||
netlayer = { strictly = '2b459dc' }
|
||||
openjfx-javafx-plugin = { strictly = '0.0.10' }
|
||||
protobuf = { strictly = '3.19.1' }
|
||||
pushy = { strictly = '0.13.10' }
|
||||
qrgen = { strictly = '1.3' }
|
||||
javacv = { strictly = '1.5.10' }
|
||||
slf4j = { strictly = '1.7.30' }
|
||||
spark = { strictly = '2.9.4' }
|
||||
|
||||
|
||||
[libraries]
|
||||
apache-httpclient = { module = "org.apache.httpcomponents:httpclient", version.ref = "apache-httpclient" }
|
||||
@ -75,6 +78,7 @@ grpc-core = { module = "io.grpc:grpc-core", version.ref = "grpc" }
|
||||
grpc-netty-shaded = { module = "io.grpc:grpc-netty-shaded", version.ref = "grpc" }
|
||||
grpc-protobuf = { module = "io.grpc:grpc-protobuf", version.ref = "grpc" }
|
||||
grpc-stub = { module = "io.grpc:grpc-stub", version.ref = "grpc" }
|
||||
grpc-auth = { module = "io.grpc:grpc-auth", version.ref = "grpc" }
|
||||
|
||||
hamcrest = { module = "org.hamcrest:hamcrest", version.ref = "hamcrest" }
|
||||
|
||||
@ -108,6 +112,9 @@ netlayer-tor-native = { module = "com.github.bisq-network.netlayer:tor.native",
|
||||
|
||||
openjfx-javafx-plugin = { module = "org.openjfx:javafx-plugin", version.ref = "openjfx-javafx-plugin" }
|
||||
protobuf-java = { module = "com.google.protobuf:protobuf-java", version.ref = "protobuf" }
|
||||
pushy = { module = "com.turo:pushy", version.ref = "pushy" }
|
||||
qrgen = { module = "net.glxn:qrgen", version.ref = "qrgen" }
|
||||
javacv = { module = "org.bytedeco:javacv-platform", version.ref = "javacv" }
|
||||
slf4j-api = { module = "org.slf4j:slf4j-api", version.ref = "slf4j" }
|
||||
spark-core = { module = "com.sparkjava:spark-core", version.ref = "spark" }
|
||||
|
||||
|
@ -38,6 +38,14 @@
|
||||
<sha256 value="ec6a3b1ccb21e66c02e36899735c0c2171c5bd3a4ea269a28be95f9f2e8a822b" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.eatthepath" name="fast-uuid" version="0.1">
|
||||
<artifact name="fast-uuid-0.1.jar">
|
||||
<sha256 value="670976cae3f41609128f647388791f43af361f3e7403ef0e3f0529c23fa1bccc" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="fast-uuid-0.1.pom">
|
||||
<sha256 value="8f51f3c717831493529c962e65dde7a4d51762a1818d7bb8777123635b669d9d" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.fasterxml" name="oss-parent" version="41">
|
||||
<artifact name="oss-parent-41.pom">
|
||||
<sha256 value="af650fa4dd400bc5769320bcef08ed93813f349cabe8213d469acafbbd945d8a" origin="Generated by Gradle"/>
|
||||
@ -280,6 +288,19 @@
|
||||
<sha256 value="8b62bfd85d693ebcffd828232af7424f34fd212c5e28e5ed99b0dc5d2bc7d4f5" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.google.auth" name="google-auth-library-credentials" version="0.22.2">
|
||||
<artifact name="google-auth-library-credentials-0.22.2.jar">
|
||||
<sha256 value="e42c2cbe642744f55bd2a081e6f60f126e691129e7148daec3af79deab4ac65a" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="google-auth-library-credentials-0.22.2.pom">
|
||||
<sha256 value="c6094e9b3875421e8f4433d624b80df29f2aefc224f1238ffbf5e86cc89c1760" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.google.auth" name="google-auth-library-parent" version="0.22.2">
|
||||
<artifact name="google-auth-library-parent-0.22.2.pom">
|
||||
<sha256 value="6ea6b8eb596209e74d5a82b67e13f717ad6d788abe137f361d5137d457794e87" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.google.code.findbugs" name="jsr305" version="3.0.2">
|
||||
<artifact name="jsr305-3.0.2.jar">
|
||||
<sha256 value="766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7" origin="Generated by Gradle"/>
|
||||
@ -288,6 +309,14 @@
|
||||
<sha256 value="19889dbdf1b254b2601a5ee645b8147a974644882297684c798afe5d63d78dfe" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.google.code.gson" name="gson" version="2.8.0">
|
||||
<artifact name="gson-2.8.0.jar">
|
||||
<sha256 value="c6221763bd79c4f1c3dc7f750b5f29a0bb38b367b81314c4f71896e340c40825" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="gson-2.8.0.pom">
|
||||
<sha256 value="a5331a0ecb548f9942ab5b93c7ac43c38a21e897763dde1bcdbf0774f416ca6f" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.google.code.gson" name="gson" version="2.8.5">
|
||||
<artifact name="gson-2.8.5.jar">
|
||||
<sha256 value="233a0149fc365c9f6edbd683cfe266b19bdc773be98eabdaf6b3c924b48e7d81" origin="Generated by Gradle"/>
|
||||
@ -320,6 +349,11 @@
|
||||
<sha256 value="e5966323d7142570b37a4be979e21bc2dae848107e4dc416d8f44d9aa3f02903" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.google.code.gson" name="gson-parent" version="2.8.0">
|
||||
<artifact name="gson-parent-2.8.0.pom">
|
||||
<sha256 value="0f1d8369b1e9f1bc4b467c8dcfdd8b59733aad5b5c8419c3a59b2f9abaf04cd2" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.google.code.gson" name="gson-parent" version="2.8.5">
|
||||
<artifact name="gson-parent-2.8.5.pom">
|
||||
<sha256 value="8f1fec72b91a71ea39ec39f5f778c4d1124b6b097c6d55b3a50b554a52237b27" origin="Generated by Gradle"/>
|
||||
@ -502,6 +536,11 @@
|
||||
<sha256 value="18d4b1db26153d4e55079ce1f76bb1fe05cdb862ef9954a88cbcc4ff38b8679b" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.google.http-client" name="google-http-client-bom" version="1.38.0">
|
||||
<artifact name="google-http-client-bom-1.38.0.pom">
|
||||
<sha256 value="c443a88cd51ce7714e7df9598267eb7d1c429caa56db4df016c8d3cef98d274d" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.google.inject" name="guice" version="5.0.1">
|
||||
<artifact name="guice-5.0.1.jar">
|
||||
<sha256 value="3bae18be3e0f0940375d1ebdd2f3b84d87ae16026ae663b2f5d4667fe5b04036" origin="Generated by Gradle"/>
|
||||
@ -635,6 +674,27 @@
|
||||
<sha256 value="1526287fb2372207be56c8e98b6a1621db9a88774331ba0c603b2710ed365f7d" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.sparkjava" name="spark-core" version="2.9.4">
|
||||
<artifact name="spark-core-2.9.4.jar">
|
||||
<sha256 value="99f4717695184e29ace24735bc539a7497775452b381b8080335adae3a985c3a" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="spark-core-2.9.4.pom">
|
||||
<sha256 value="02c4d68a8d9f8d34f11b2c9750006591959f5222887fcbe6c70dcf2bb4b76219" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.turo" name="pushy" version="0.13.10">
|
||||
<artifact name="pushy-0.13.10.jar">
|
||||
<sha256 value="0dfd827e8244354b987bf454854636e7a8b851aad66bfdb1138f73783b7852a7" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="pushy-0.13.10.pom">
|
||||
<sha256 value="4a5a4ab8ab1e36695e7d241618fd27cb2031b7c45623b1a058fd49b0aa0799e7" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.turo" name="pushy-parent" version="0.13.10">
|
||||
<artifact name="pushy-parent-0.13.10.pom">
|
||||
<sha256 value="94cad20a9255ae7c948ab5cbb9b02076c0c7c5166f6234996d2c8da744671692" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="commons-codec" name="commons-codec" version="1.13">
|
||||
<artifact name="commons-codec-1.13.jar">
|
||||
<sha256 value="61f7a3079e92b9fdd605238d0295af5fd11ac411a0a0af48deace1f6c5ffa072" origin="Generated by Gradle"/>
|
||||
@ -720,6 +780,14 @@
|
||||
<sha256 value="e371abe8a43de8416afa1a970466d833d1974f86ed620a5f548ab5aac4610188" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="io.grpc" name="grpc-auth" version="1.42.1">
|
||||
<artifact name="grpc-auth-1.42.1.jar">
|
||||
<sha256 value="fbfeae9b1b8b913f82a8ed5c20d4536a404464bfd385fd8ecd5a7dac9207ce30" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="grpc-auth-1.42.1.pom">
|
||||
<sha256 value="a9dc9340d89c6ebc1f4534cc911f129bb9413bccdbd95f76122e119e9dfdaab5" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="io.grpc" name="grpc-context" version="1.42.1">
|
||||
<artifact name="grpc-context-1.42.1.jar">
|
||||
<sha256 value="8810d6dc294b8c025c152a0093a2c62406ed79778f52ebbb28ab51640c1a4504" origin="Generated by Gradle"/>
|
||||
@ -785,6 +853,107 @@
|
||||
<sha256 value="9856d0a3e07df312825e698082b6ec6401cd15814ca74092ae58084f4925e784" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="io.netty" name="netty-buffer" version="4.1.37.Final">
|
||||
<artifact name="netty-buffer-4.1.37.Final.jar">
|
||||
<sha256 value="83805671c27e388976de74fe477a246bea5b8a71f228fcfefee32fc2593725cf" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="netty-buffer-4.1.37.Final.pom">
|
||||
<sha256 value="807f0e6454a5756add9decebf5e7e647a832b61cdcb51cce599fbe3c01289f58" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="io.netty" name="netty-codec" version="4.1.37.Final">
|
||||
<artifact name="netty-codec-4.1.37.Final.jar">
|
||||
<sha256 value="7ed9b1a4dcd2abebd6fb80971a87262bb32799bf3a0cfe73287439e8be0bb456" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="netty-codec-4.1.37.Final.pom">
|
||||
<sha256 value="9748cd2c2c7438351e38123b7a8cdf696f9ccce5f622bf6c5f28deb8a8817fee" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="io.netty" name="netty-codec-dns" version="4.1.37.Final">
|
||||
<artifact name="netty-codec-dns-4.1.37.Final.jar">
|
||||
<sha256 value="d35babd57e48cf5dd5709b5c11073fe4834a07804e7824478f13e8d3106d4b12" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="netty-codec-dns-4.1.37.Final.pom">
|
||||
<sha256 value="723745f5e1bcfc6a110f1ef7e6bdfc6bad57d3683bb06c52d8b0c5b08cd62289" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="io.netty" name="netty-codec-http" version="4.1.37.Final">
|
||||
<artifact name="netty-codec-http-4.1.37.Final.jar">
|
||||
<sha256 value="334bf6b2929d1ea6b951a3ae44ffc6fcea5d7f7c5a1ff1dc023a7e57e4c8ad48" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="netty-codec-http-4.1.37.Final.pom">
|
||||
<sha256 value="b9c5db0be9208ebf75c336bc19141bc5feda2353a7675ad68a43cf0b4e7d8fc4" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="io.netty" name="netty-codec-http2" version="4.1.37.Final">
|
||||
<artifact name="netty-codec-http2-4.1.37.Final.jar">
|
||||
<sha256 value="42b42d0d08a3ab4e1bec058c1d4a442324cc105a40800798006ba67cd46b9c0f" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="netty-codec-http2-4.1.37.Final.pom">
|
||||
<sha256 value="72e34f48a1e128b7a8faf9652b03fbd7b722f5067f519132bcd58a6527ea62ee" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="io.netty" name="netty-codec-socks" version="4.1.37.Final">
|
||||
<artifact name="netty-codec-socks-4.1.37.Final.jar">
|
||||
<sha256 value="b2955422bb167caad2eb4008fcb49410928227f31f924a92f450eccb8b1e7fd5" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="netty-codec-socks-4.1.37.Final.pom">
|
||||
<sha256 value="fbd64714407434d20de6b494e5ba6654212010bfb59e11f46902edc911ccbb71" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="io.netty" name="netty-common" version="4.1.37.Final">
|
||||
<artifact name="netty-common-4.1.37.Final.jar">
|
||||
<sha256 value="4b1a4d670b5b8be99779588aa6677b9e78ffbd774fbb2a1311e0b3fa037773e6" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="netty-common-4.1.37.Final.pom">
|
||||
<sha256 value="20ba81332f5d248cf204a814129a18eb6369d36585538ce403b019b7b35ed8b2" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="io.netty" name="netty-handler" version="4.1.37.Final">
|
||||
<artifact name="netty-handler-4.1.37.Final.jar">
|
||||
<sha256 value="0e51521918e84cfb11a381fec7b598649e6cd4669b2284e168c5155f247e3a4c" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="netty-handler-4.1.37.Final.pom">
|
||||
<sha256 value="a98458c0c49245ffdc3af4c6f730c5c2f87c2c63f35fa4ab1906f21428b98f2e" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="io.netty" name="netty-handler-proxy" version="4.1.37.Final">
|
||||
<artifact name="netty-handler-proxy-4.1.37.Final.jar">
|
||||
<sha256 value="30c206f82d5d9eca38aab94a99be909d2b9ca290dc5588a19b350d0983ce0350" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="netty-handler-proxy-4.1.37.Final.pom">
|
||||
<sha256 value="be08a4329fb1379f922b33060e96440123a89f14c153ce9f13cd1cbb5d7cca21" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="io.netty" name="netty-parent" version="4.1.37.Final">
|
||||
<artifact name="netty-parent-4.1.37.Final.pom">
|
||||
<sha256 value="4327c907e2354558c37587dd6605b4d46b2fb578ede43fa68cc23dba4ac5d673" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="io.netty" name="netty-resolver" version="4.1.37.Final">
|
||||
<artifact name="netty-resolver-4.1.37.Final.jar">
|
||||
<sha256 value="ebaf963b7194f70039b11d74657d09161b0729e97ea4460bf1ba312c7d84ca7e" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="netty-resolver-4.1.37.Final.pom">
|
||||
<sha256 value="e7e8cbe66b019e3bc07c7a881c91ecc6a3c1ded70dd88f0b8f19ea3ab20ec788" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="io.netty" name="netty-resolver-dns" version="4.1.37.Final">
|
||||
<artifact name="netty-resolver-dns-4.1.37.Final.jar">
|
||||
<sha256 value="ae20a2607cb004b5e73e0a28c35902a251bdadaec96b8a520ab5569d4f88b8b7" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="netty-resolver-dns-4.1.37.Final.pom">
|
||||
<sha256 value="aaa1e8da71648c499be96e2661dc4ff33cb5c374054671454e89abd5b890822b" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="io.netty" name="netty-transport" version="4.1.37.Final">
|
||||
<artifact name="netty-transport-4.1.37.Final.jar">
|
||||
<sha256 value="962279abbdc58a261fbb39b55838225efb62771dc6ea938490567142135bd1fc" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="netty-transport-4.1.37.Final.pom">
|
||||
<sha256 value="af469d1995aca14fd56e61aca1220ca8803dd71d70d3be1e5293ccf66278638a" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="io.perfmark" name="perfmark-api" version="0.23.0">
|
||||
<artifact name="perfmark-api-0.23.0.jar">
|
||||
<sha256 value="c705b5c10c18ff3032b9e81742bc2f6b0e5607f6a6dfc0c8ad0cff75d4913042" origin="Generated by Gradle"/>
|
||||
@ -809,6 +978,14 @@
|
||||
<sha256 value="943e12b100627804638fa285805a0ab788a680266531e650921ebfe4621a8bfa" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="javax.servlet" name="javax.servlet-api" version="3.1.0">
|
||||
<artifact name="javax.servlet-api-3.1.0.jar">
|
||||
<sha256 value="af456b2dd41c4e82cf54f3e743bc678973d9fe35bd4d3071fa05c7e5333b8482" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="javax.servlet-api-3.1.0.pom">
|
||||
<sha256 value="b31109e22ea3f2df1ad7955432e718a35def50ae6c19698034afa8a0cf9e9069" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="junit" name="junit" version="4.12">
|
||||
<artifact name="junit-4.12.jar">
|
||||
<sha256 value="59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a" origin="Generated by Gradle"/>
|
||||
@ -1832,6 +2009,136 @@
|
||||
<sha256 value="11067f6a75fded12bcdc8daf7a66ddd942ce289c3daf88a3fe0f8b12858a2ee6" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="org.eclipse.jetty" name="jetty-client" version="9.4.48.v20220622">
|
||||
<artifact name="jetty-client-9.4.48.v20220622.jar">
|
||||
<sha256 value="7f89fe0900d36b296275999992a6ad76d523be35487d613d8fb56434c34d1d15" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="jetty-client-9.4.48.v20220622.pom">
|
||||
<sha256 value="39203691dd95811c0f1be86618cfd64c5028d69eb927d93727c79d0bea3148be" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="org.eclipse.jetty" name="jetty-http" version="9.4.48.v20220622">
|
||||
<artifact name="jetty-http-9.4.48.v20220622.jar">
|
||||
<sha256 value="c99914804c25288fde0470530411258ee4bab83b69ad764149c816c984f8175e" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="jetty-http-9.4.48.v20220622.pom">
|
||||
<sha256 value="29166bedbd82f620b94b944b4a6f43cef9170ddd22161924b717da90a5c2bd27" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="org.eclipse.jetty" name="jetty-io" version="9.4.48.v20220622">
|
||||
<artifact name="jetty-io-9.4.48.v20220622.jar">
|
||||
<sha256 value="4d2f60a0348905a0a70bb266d1eb23a29959281391aba54d17d4a3a0460b8b47" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="jetty-io-9.4.48.v20220622.pom">
|
||||
<sha256 value="234cb237e4daa47e5190e9de1c685fb02dcea2c4eb4705b85e0306dede91cf34" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="org.eclipse.jetty" name="jetty-project" version="9.4.48.v20220622">
|
||||
<artifact name="jetty-project-9.4.48.v20220622.pom">
|
||||
<sha256 value="15b74d56c3e55664b02d24d38158e7d1fbf798d072522906168ac8356bb53314" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="org.eclipse.jetty" name="jetty-security" version="9.4.48.v20220622">
|
||||
<artifact name="jetty-security-9.4.48.v20220622.jar">
|
||||
<sha256 value="43039b0f58a156a7f1b9b7750ad82f7fcdd5dba81717b970c381cb1b8618ff73" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="jetty-security-9.4.48.v20220622.pom">
|
||||
<sha256 value="eee196593347cfee21c912b49a26a13dd87d5d27bdcc25de2b9a81e1d5d3395c" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="org.eclipse.jetty" name="jetty-server" version="9.4.48.v20220622">
|
||||
<artifact name="jetty-server-9.4.48.v20220622.jar">
|
||||
<sha256 value="dbb2b64216b0f10db591319c313979c1389249a196afb9690c022a923c0f0f77" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="jetty-server-9.4.48.v20220622.pom">
|
||||
<sha256 value="f4f48d40182eec66b08ae3914afe9f73038cd0786bd4863e4372dbe92d5d43c2" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="org.eclipse.jetty" name="jetty-servlet" version="9.4.48.v20220622">
|
||||
<artifact name="jetty-servlet-9.4.48.v20220622.jar">
|
||||
<sha256 value="eabc36f43fb4080b7d02e1fbcad0b437e035d3adc7bfd7a89b3cdeb22247e682" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="jetty-servlet-9.4.48.v20220622.pom">
|
||||
<sha256 value="5f583667c8d0e281464ad020282fcb2992f0010633276c23803753c6fd4a076b" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="org.eclipse.jetty" name="jetty-util" version="9.4.48.v20220622">
|
||||
<artifact name="jetty-util-9.4.48.v20220622.jar">
|
||||
<sha256 value="24cafd449ca4b4bea9c2792b28fc6fe1c43beb628c0c1a0a72ee33afeac82b87" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="jetty-util-9.4.48.v20220622.pom">
|
||||
<sha256 value="c55cbf31473dbc489e09a9ce1cfb0c69b63596bb9a5ed9feb23bdbe98a669802" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="org.eclipse.jetty" name="jetty-util-ajax" version="9.4.48.v20220622">
|
||||
<artifact name="jetty-util-ajax-9.4.48.v20220622.jar">
|
||||
<sha256 value="b5d4b40be3cf9f48b3d5f8e5918066724a620cb901684939c9f1dd7ec1b930cb" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="jetty-util-ajax-9.4.48.v20220622.pom">
|
||||
<sha256 value="700afb62d38b4ab798113b7ca93f797a7e7f088748d1351cc72a961d98f3b1c7" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="org.eclipse.jetty" name="jetty-webapp" version="9.4.48.v20220622">
|
||||
<artifact name="jetty-webapp-9.4.48.v20220622.jar">
|
||||
<sha256 value="bdb33dd7e9a30ea428f301010d08c7f69b37ec75dda340b79a86e95149fec0b2" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="jetty-webapp-9.4.48.v20220622.pom">
|
||||
<sha256 value="27cd28cd52122d7aa05c0189f0d1384f6a43fb46b578d20416e680edda5737aa" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="org.eclipse.jetty" name="jetty-xml" version="9.4.48.v20220622">
|
||||
<artifact name="jetty-xml-9.4.48.v20220622.jar">
|
||||
<sha256 value="fe94705c7f49fe56194abfc16050fafc44be0faf691a2e6dca13c5d343a2bea5" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="jetty-xml-9.4.48.v20220622.pom">
|
||||
<sha256 value="6396c29c8881a6fa2487085e6930dc7ff5c9d8b04cb18176cf11dba5f0484136" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="org.eclipse.jetty.websocket" name="websocket-api" version="9.4.48.v20220622">
|
||||
<artifact name="websocket-api-9.4.48.v20220622.jar">
|
||||
<sha256 value="87fb052324d6c5e22f58fb729169913bb318d97921115640c3dca453c7eb19e1" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="websocket-api-9.4.48.v20220622.pom">
|
||||
<sha256 value="d82f8e6e227a414bc260884836b7234682be89bf6776d46f7200d0abf33f2816" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="org.eclipse.jetty.websocket" name="websocket-client" version="9.4.48.v20220622">
|
||||
<artifact name="websocket-client-9.4.48.v20220622.jar">
|
||||
<sha256 value="432d9d85734be8acbdbc3656200d2b1d540574c9bebe0b4f75a3f8bbe402a2f1" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="websocket-client-9.4.48.v20220622.pom">
|
||||
<sha256 value="57a16d3850de59f43c12c03f668c2db76e71b6496a492150a158d7bffdd0e3f7" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="org.eclipse.jetty.websocket" name="websocket-common" version="9.4.48.v20220622">
|
||||
<artifact name="websocket-common-9.4.48.v20220622.jar">
|
||||
<sha256 value="1f630339e7e7f6de5d7f47f9496495d7689ad41fc11565aaf11ce9e22ff6ccda" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="websocket-common-9.4.48.v20220622.pom">
|
||||
<sha256 value="6ed1f928f89af9f808a65637ec429ff0a0151f9fd29d76259d1fa1b3def57ea7" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="org.eclipse.jetty.websocket" name="websocket-parent" version="9.4.48.v20220622">
|
||||
<artifact name="websocket-parent-9.4.48.v20220622.pom">
|
||||
<sha256 value="7ef6aa037919ea930772f468e13c3f3fc67343ded79ee2b7dd469d589cf6b50d" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="org.eclipse.jetty.websocket" name="websocket-server" version="9.4.48.v20220622">
|
||||
<artifact name="websocket-server-9.4.48.v20220622.jar">
|
||||
<sha256 value="32ad18b3c610a5036c33d2e6bdf76eb46759fb8e067483d7a96f94e3909a4285" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="websocket-server-9.4.48.v20220622.pom">
|
||||
<sha256 value="26f12bf6adfc658aef4ce62ed2e3e8279d344d8418ffeb7d5ba105deadeb2d07" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="org.eclipse.jetty.websocket" name="websocket-servlet" version="9.4.48.v20220622">
|
||||
<artifact name="websocket-servlet-9.4.48.v20220622.jar">
|
||||
<sha256 value="28aeea9ac33a3f6d22e31ed2a6079abc35ce3ec1d5c80e1cc13859f536680b25" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="websocket-servlet-9.4.48.v20220622.pom">
|
||||
<sha256 value="92168e50de653cdb2dbc6916e054594aeb72d0a2b0b94d0d50b3e06b56d5f4b7" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="org.fxmisc.easybind" name="easybind" version="1.0.3">
|
||||
<artifact name="easybind-1.0.3.jar">
|
||||
<sha256 value="666af296dda6de68751668a62661571b5238ac6f1c07c8a204fc6f902b222aaf" origin="Generated by Gradle"/>
|
||||
@ -1874,6 +2181,16 @@
|
||||
<sha256 value="b36137376c4b3fcf76dc337e2a1bc5b691a2ac1aa966ab5d26209a93812fa57d" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="org.infinispan" name="infinispan-bom" version="11.0.15.Final">
|
||||
<artifact name="infinispan-bom-11.0.15.Final.pom">
|
||||
<sha256 value="07386ee62c8464618770d209f8c060da8e51f56e76314d1b29caec9c302130e9" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="org.infinispan" name="infinispan-build-configuration-parent" version="11.0.15.Final">
|
||||
<artifact name="infinispan-build-configuration-parent-11.0.15.Final.pom">
|
||||
<sha256 value="b2f82dd670e70f378a780efea1053f0e660a825dbbfe8c6ca8ca996dfde3aaa0" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="org.jacoco" name="org.jacoco.agent" version="0.8.8">
|
||||
<artifact name="org.jacoco.agent-0.8.8.jar">
|
||||
<sha256 value="072ecbd496896623899a696fff12c01c1615f737616d2792e6d0e10cdf8a610d" origin="Generated by Gradle"/>
|
||||
@ -1927,6 +2244,11 @@
|
||||
<sha256 value="c9d3790f030276541d118a11be67fd271bf81e301b962780e542c2e5f636c1b1" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="org.jboss" name="jboss-parent" version="36">
|
||||
<artifact name="jboss-parent-36.pom">
|
||||
<sha256 value="000dd616298aebd21a9d5731874df083d7298424b91e037b73cbdd07ebc83e0e" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="org.jdom" name="jdom2" version="2.0.6">
|
||||
<artifact name="jdom2-2.0.6.jar">
|
||||
<sha256 value="1345f11ba606d15603d6740551a8c21947c0215640770ec67271fe78bea97cf5" origin="Generated by Gradle"/>
|
||||
@ -2255,6 +2577,14 @@
|
||||
<sha256 value="35fb15f8d0bee2b5900a22832762366552f9a349c56ced60ba123ce47738ff00" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="org.junit" name="junit-bom" version="5.8.2">
|
||||
<artifact name="junit-bom-5.8.2.module">
|
||||
<sha256 value="40cfad993fa70ecdf2af74d0c56da1484ee220964be8f932cfe632be9a2733fa" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="junit-bom-5.8.2.pom">
|
||||
<sha256 value="836069ca9e8ee3c56e48376222da291263f137bd3fd16d84fdd47efcc3f286e2" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="org.junit.jupiter" name="junit-jupiter-api" version="5.7.0">
|
||||
<artifact name="junit-jupiter-api-5.7.0.jar">
|
||||
<sha256 value="b03f78e0daeed2d77a0af9bcd662b4cdb9693f7ee72e01a539b508b84c63d182" origin="Generated by Gradle"/>
|
||||
@ -2539,6 +2869,11 @@
|
||||
<sha256 value="fb40265f982548212ff82e362e59732b2187ec6f0d80182885c14ef1f982827a" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="org.testcontainers" name="testcontainers-bom" version="1.16.1">
|
||||
<artifact name="testcontainers-bom-1.16.1.pom">
|
||||
<sha256 value="5061ba84c98536e5a6b4ce280fbcecb00e335f3b04c5d484629162fcb4624778" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="org.tukaani" name="xz" version="1.6">
|
||||
<artifact name="xz-1.6.jar">
|
||||
<sha256 value="a594643d73cc01928cf6ca5ce100e094ea9d73af760a5d4fb6b75fa673ecec96" origin="Generated by Gradle"/>
|
||||
|
44
inventory/README.md
Normal file
44
inventory/README.md
Normal file
@ -0,0 +1,44 @@
|
||||
## Inventory monitor
|
||||
|
||||
This is a simple headless node with a http server which requests periodically from the seed nodes their inventory (not
|
||||
the full data but just the information about their network data).
|
||||
|
||||
### Run inventory monitor
|
||||
|
||||
Run the Gradle task:
|
||||
|
||||
```sh
|
||||
./gradlew inventory:run
|
||||
```
|
||||
|
||||
Or create a run scrip by:
|
||||
|
||||
```sh
|
||||
./gradlew inventory:startBisqApp
|
||||
```
|
||||
|
||||
And then run:
|
||||
|
||||
```sh
|
||||
./bisq-inventory
|
||||
```
|
||||
|
||||
### Customize inventory monitor
|
||||
|
||||
To configure it with custom parameters append optional program arguments in the following order:
|
||||
|
||||
Arguments: `port cleanupTorFiles intervalSec shutdownIntervalDays useLocalhostForP2P network`
|
||||
If `shutdownIntervalDays` is 0 the app will not be shut down. Otherwise, it's the number of days for shutting down (run
|
||||
script need to ensure the node gets started again).
|
||||
|
||||
Values: `Integer 0|1 Integer Integer 0|1 BTC_MAINNET|BTC_TESTNET|BTC_REGTEST`
|
||||
|
||||
Example for localhost, regtest on port 8080: `8080 0 10 5 1 BTC_REGTEST`
|
||||
|
||||
Example for production node with cleanupTorFiles=true: `80 1`
|
||||
|
||||
Append the program arguments to the run script:
|
||||
|
||||
```sh
|
||||
./bisq-inventory 8080 0 10 1 BTC_REGTEST
|
||||
```
|
31
inventory/build.gradle
Normal file
31
inventory/build.gradle
Normal file
@ -0,0 +1,31 @@
|
||||
plugins {
|
||||
id 'bisq.application'
|
||||
id 'bisq.gradle.app_start_plugin.AppStartPlugin'
|
||||
}
|
||||
mainClassName = 'bisq.inventory.InventoryMonitorMain'
|
||||
|
||||
distTar.enabled = true
|
||||
|
||||
dependencies {
|
||||
implementation enforcedPlatform(project(':platform'))
|
||||
implementation project(':common')
|
||||
implementation project(':proto')
|
||||
implementation project(':p2p')
|
||||
implementation project(':core')
|
||||
implementation libs.protobuf.java
|
||||
annotationProcessor libs.lombok
|
||||
compileOnly libs.lombok
|
||||
implementation libs.jetbrains.annotations
|
||||
implementation libs.logback.classic
|
||||
implementation libs.logback.core
|
||||
implementation libs.google.guava
|
||||
implementation libs.slf4j.api
|
||||
implementation(libs.google.guice) {
|
||||
exclude(module: 'guava')
|
||||
}
|
||||
|
||||
implementation libs.spark.core
|
||||
implementation libs.pushy
|
||||
implementation libs.commons.codec
|
||||
implementation libs.grpc.auth
|
||||
}
|
288
inventory/src/main/java/bisq/inventory/InventoryMonitor.java
Normal file
288
inventory/src/main/java/bisq/inventory/InventoryMonitor.java
Normal file
@ -0,0 +1,288 @@
|
||||
/*
|
||||
* This file is part of Bisq.
|
||||
*
|
||||
* Bisq is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bisq is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package bisq.inventory;
|
||||
|
||||
|
||||
import bisq.core.app.TorSetup;
|
||||
import bisq.core.network.p2p.inventory.GetInventoryRequestManager;
|
||||
import bisq.core.network.p2p.inventory.model.Average;
|
||||
import bisq.core.network.p2p.inventory.model.DeviationSeverity;
|
||||
import bisq.core.network.p2p.inventory.model.InventoryItem;
|
||||
import bisq.core.network.p2p.inventory.model.RequestInfo;
|
||||
import bisq.core.network.p2p.seed.DefaultSeedNodeRepository;
|
||||
import bisq.core.proto.network.CoreNetworkProtoResolver;
|
||||
import bisq.core.util.JsonUtil;
|
||||
|
||||
import bisq.network.p2p.NetworkNodeProvider;
|
||||
import bisq.network.p2p.NodeAddress;
|
||||
import bisq.network.p2p.network.NetworkNode;
|
||||
import bisq.network.p2p.network.SetupListener;
|
||||
|
||||
import bisq.common.UserThread;
|
||||
import bisq.common.config.BaseCurrencyNetwork;
|
||||
import bisq.common.file.JsonFileManager;
|
||||
import bisq.common.util.Tuple2;
|
||||
|
||||
import java.time.Clock;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@Slf4j
|
||||
public class InventoryMonitor implements SetupListener {
|
||||
private final Map<NodeAddress, JsonFileManager> jsonFileManagerByNodeAddress = new HashMap<>();
|
||||
private final Map<NodeAddress, List<RequestInfo>> requestInfoListByNode = new HashMap<>();
|
||||
private final File appDir;
|
||||
private final boolean useLocalhostForP2P;
|
||||
private final int intervalSec;
|
||||
private final NetworkNode networkNode;
|
||||
private final GetInventoryRequestManager getInventoryRequestManager;
|
||||
|
||||
private final List<NodeAddress> seedNodes;
|
||||
private InventoryWebServer inventoryWebServer;
|
||||
private int requestCounter = 0;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public InventoryMonitor(File appDir,
|
||||
boolean useLocalhostForP2P,
|
||||
BaseCurrencyNetwork network,
|
||||
int intervalSec,
|
||||
boolean cleanupTorFiles) {
|
||||
this.appDir = appDir;
|
||||
this.useLocalhostForP2P = useLocalhostForP2P;
|
||||
this.intervalSec = intervalSec;
|
||||
|
||||
File torDir = new File(appDir, "tor");
|
||||
if (!torDir.exists() && !torDir.mkdir()) {
|
||||
log.warn("make torDir failed");
|
||||
}
|
||||
|
||||
networkNode = getNetworkNode(torDir);
|
||||
getInventoryRequestManager = new GetInventoryRequestManager(networkNode);
|
||||
|
||||
String networkName = network.name().toLowerCase();
|
||||
String fileName = network.isMainnet() ? "inv_" + networkName : networkName;
|
||||
seedNodes = new ArrayList<>(DefaultSeedNodeRepository.getSeedNodeAddressesFromPropertyFile(fileName));
|
||||
addJsonFileManagers(seedNodes);
|
||||
|
||||
BufferedReader bufferedReader = DefaultSeedNodeRepository.readSeedNodePropertyFile(fileName).orElseThrow();
|
||||
inventoryWebServer = new InventoryWebServer(seedNodes, bufferedReader);
|
||||
|
||||
TorSetup torSetup = new TorSetup(torDir);
|
||||
if (cleanupTorFiles) {
|
||||
torSetup.cleanupTorFiles(() -> log.info("Tor directory cleaned up"), log::error);
|
||||
}
|
||||
}
|
||||
|
||||
void start(int port) {
|
||||
networkNode.start(this);
|
||||
inventoryWebServer.start(port);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// API
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void shutDown(Runnable shutDownCompleteHandler) {
|
||||
networkNode.shutDown(shutDownCompleteHandler);
|
||||
inventoryWebServer.shutDown();
|
||||
jsonFileManagerByNodeAddress.values().forEach(JsonFileManager::shutDown);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// SetupListener
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public void onTorNodeReady() {
|
||||
UserThread.runPeriodically(this::requestFromAllSeeds, intervalSec);
|
||||
requestFromAllSeeds();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHiddenServicePublished() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSetupFailed(Throwable throwable) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestCustomBridges() {
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Private
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void requestFromAllSeeds() {
|
||||
requestCounter++;
|
||||
seedNodes.forEach(nodeAddress -> {
|
||||
RequestInfo requestInfo = new RequestInfo(System.currentTimeMillis());
|
||||
new Thread(() -> {
|
||||
Thread.currentThread().setName("request @ " + getShortAddress(nodeAddress, useLocalhostForP2P));
|
||||
getInventoryRequestManager.request(nodeAddress,
|
||||
result -> processResponse(nodeAddress, requestInfo, result, null),
|
||||
errorMessage -> processResponse(nodeAddress, requestInfo, null, errorMessage));
|
||||
}).start();
|
||||
});
|
||||
}
|
||||
|
||||
private void processResponse(NodeAddress nodeAddress,
|
||||
RequestInfo requestInfo,
|
||||
@Nullable Map<InventoryItem, String> result,
|
||||
@Nullable String errorMessage) {
|
||||
if (errorMessage != null && !errorMessage.isEmpty()) {
|
||||
log.warn("Error at connection to peer {}: {}", nodeAddress, errorMessage);
|
||||
requestInfo.setErrorMessage(errorMessage);
|
||||
} else {
|
||||
requestInfo.setResponseTime(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
boolean ignoreDeviationAtStartup;
|
||||
if (result != null) {
|
||||
log.info("nodeAddress={}, result={}", nodeAddress, result.toString());
|
||||
|
||||
// If seed just started up we ignore the deviation as it can be expected that seed is still syncing
|
||||
// DAO state/blocks. P2P data should be ready but as we received it from other seeds it is not that
|
||||
// valuable information either, so we apply the ignore to all data.
|
||||
if (result.containsKey(InventoryItem.jvmStartTime)) {
|
||||
String jvmStartTimeString = result.get(InventoryItem.jvmStartTime);
|
||||
long jvmStartTime = Long.parseLong(jvmStartTimeString);
|
||||
ignoreDeviationAtStartup = jvmStartTime < TimeUnit.MINUTES.toMillis(2);
|
||||
} else {
|
||||
ignoreDeviationAtStartup = false;
|
||||
}
|
||||
} else {
|
||||
ignoreDeviationAtStartup = false;
|
||||
}
|
||||
|
||||
requestInfoListByNode.putIfAbsent(nodeAddress, new ArrayList<>());
|
||||
List<RequestInfo> requestInfoList = requestInfoListByNode.get(nodeAddress);
|
||||
|
||||
|
||||
// We create average of all nodes latest results. It might be that the nodes last result is
|
||||
// from a previous request as the response has not arrived yet.
|
||||
//TODO might be not a good idea to use the last result if its not a recent one. a faulty node would distort
|
||||
// the average calculation.
|
||||
// As we add at the end our own result the average is excluding our own value
|
||||
Collection<List<RequestInfo>> requestInfoListByNodeValues = requestInfoListByNode.values();
|
||||
Set<RequestInfo> requestInfoSet = requestInfoListByNodeValues.stream()
|
||||
.filter(list -> !list.isEmpty())
|
||||
.map(list -> list.get(list.size() - 1))
|
||||
.collect(Collectors.toSet());
|
||||
Map<InventoryItem, Double> averageValues = Average.of(requestInfoSet);
|
||||
|
||||
String daoStateChainHeight = result != null &&
|
||||
result.containsKey(InventoryItem.daoStateChainHeight) ?
|
||||
result.get(InventoryItem.daoStateChainHeight) :
|
||||
null;
|
||||
List.of(InventoryItem.values()).forEach(inventoryItem -> {
|
||||
String value = result != null ? result.get(inventoryItem) : null;
|
||||
Tuple2<Double, Double> tuple = inventoryItem.getDeviationAndAverage(averageValues, value);
|
||||
Double deviation = tuple != null ? tuple.first : null;
|
||||
Double average = tuple != null ? tuple.second : null;
|
||||
DeviationSeverity deviationSeverity = ignoreDeviationAtStartup ? DeviationSeverity.IGNORED :
|
||||
inventoryItem.getDeviationSeverity(deviation,
|
||||
requestInfoListByNodeValues,
|
||||
value,
|
||||
daoStateChainHeight);
|
||||
int endIndex = Math.max(0, requestInfoList.size() - 1);
|
||||
int deviationTolerance = inventoryItem.getDeviationTolerance();
|
||||
int fromIndex = Math.max(0, endIndex - deviationTolerance);
|
||||
List<DeviationSeverity> lastDeviationSeverityEntries = requestInfoList.subList(fromIndex, endIndex).stream()
|
||||
.filter(e -> e.getDataMap().containsKey(inventoryItem))
|
||||
.map(e -> e.getDataMap().get(inventoryItem).getDeviationSeverity())
|
||||
.collect(Collectors.toList());
|
||||
long numWarnings = lastDeviationSeverityEntries.stream()
|
||||
.filter(e -> e == DeviationSeverity.WARN)
|
||||
.count();
|
||||
long numAlerts = lastDeviationSeverityEntries.stream()
|
||||
.filter(e -> e == DeviationSeverity.ALERT)
|
||||
.count();
|
||||
boolean persistentWarning = numWarnings == deviationTolerance;
|
||||
boolean persistentAlert = numAlerts == deviationTolerance;
|
||||
RequestInfo.Data data = new RequestInfo.Data(value, average, deviation, deviationSeverity, persistentWarning, persistentAlert);
|
||||
requestInfo.getDataMap().put(inventoryItem, data);
|
||||
});
|
||||
|
||||
requestInfoList.add(requestInfo);
|
||||
|
||||
inventoryWebServer.onNewRequestInfo(requestInfoListByNode, requestCounter);
|
||||
|
||||
String json = JsonUtil.objectToJson(requestInfo);
|
||||
jsonFileManagerByNodeAddress.get(nodeAddress).writeToDisc(json, String.valueOf(requestInfo.getRequestStartTime()));
|
||||
}
|
||||
|
||||
private void addJsonFileManagers(List<NodeAddress> seedNodes) {
|
||||
File jsonDir = new File(appDir, "json");
|
||||
if (!jsonDir.exists() && !jsonDir.mkdir()) {
|
||||
log.warn("make jsonDir failed");
|
||||
}
|
||||
seedNodes.forEach(nodeAddress -> {
|
||||
JsonFileManager jsonFileManager = new JsonFileManager(new File(jsonDir, getShortAddress(nodeAddress, useLocalhostForP2P)));
|
||||
jsonFileManagerByNodeAddress.put(nodeAddress, jsonFileManager);
|
||||
});
|
||||
}
|
||||
|
||||
private NetworkNode getNetworkNode(File torDir) {
|
||||
CoreNetworkProtoResolver networkProtoResolver = new CoreNetworkProtoResolver(Clock.systemDefaultZone());
|
||||
return new NetworkNodeProvider(networkProtoResolver,
|
||||
() -> null,
|
||||
null,
|
||||
12,
|
||||
useLocalhostForP2P,
|
||||
9999,
|
||||
torDir,
|
||||
null,
|
||||
"",
|
||||
"",
|
||||
-1,
|
||||
"",
|
||||
null,
|
||||
false,
|
||||
false)
|
||||
.get();
|
||||
}
|
||||
|
||||
private String getShortAddress(NodeAddress nodeAddress, boolean useLocalhostForP2P) {
|
||||
return useLocalhostForP2P ?
|
||||
nodeAddress.getFullAddress().replace(":", "_") :
|
||||
nodeAddress.getFullAddress().substring(0, 10);
|
||||
}
|
||||
}
|
138
inventory/src/main/java/bisq/inventory/InventoryMonitorMain.java
Normal file
138
inventory/src/main/java/bisq/inventory/InventoryMonitorMain.java
Normal file
@ -0,0 +1,138 @@
|
||||
/*
|
||||
* This file is part of Bisq.
|
||||
*
|
||||
* Bisq is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bisq is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package bisq.inventory;
|
||||
|
||||
|
||||
import bisq.core.locale.Res;
|
||||
|
||||
import bisq.common.UserThread;
|
||||
import bisq.common.app.AsciiLogo;
|
||||
import bisq.common.app.Log;
|
||||
import bisq.common.app.Version;
|
||||
import bisq.common.config.BaseCurrencyNetwork;
|
||||
import bisq.common.util.SingleThreadExecutorUtils;
|
||||
import bisq.common.util.Utilities;
|
||||
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import ch.qos.logback.classic.Level;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import static bisq.core.app.BisqExecutable.EXIT_SUCCESS;
|
||||
|
||||
|
||||
|
||||
import sun.misc.Signal;
|
||||
|
||||
@Slf4j
|
||||
public class InventoryMonitorMain {
|
||||
|
||||
private static InventoryMonitor inventoryMonitor;
|
||||
private static boolean stopped;
|
||||
|
||||
// Example prog args:
|
||||
// 8080 0 10 5 1 BTC_REGTEST
|
||||
public static void main(String[] args) {
|
||||
// Default values
|
||||
int port = 80;
|
||||
boolean cleanupTorFiles = false;
|
||||
int intervalSec = 120;
|
||||
int shutdownIntervalDays = 5;
|
||||
boolean useLocalhostForP2P = false;
|
||||
BaseCurrencyNetwork network = BaseCurrencyNetwork.BTC_MAINNET;
|
||||
|
||||
/* port = 8080;
|
||||
useLocalhostForP2P = true;
|
||||
network = BaseCurrencyNetwork.BTC_REGTEST;*/
|
||||
|
||||
if (args.length > 0) {
|
||||
port = Integer.parseInt(args[0]);
|
||||
}
|
||||
if (args.length > 1) {
|
||||
cleanupTorFiles = args[1].equals("1");
|
||||
}
|
||||
if (args.length > 2) {
|
||||
intervalSec = Integer.parseInt(args[2]);
|
||||
}
|
||||
if (args.length > 3) {
|
||||
shutdownIntervalDays = Integer.parseInt(args[3]);
|
||||
}
|
||||
if (args.length > 4) {
|
||||
useLocalhostForP2P = args[4].equals("1");
|
||||
}
|
||||
if (args.length > 5) {
|
||||
network = BaseCurrencyNetwork.valueOf(args[5]);
|
||||
}
|
||||
|
||||
String appName = "bisq-inventory-monitor-" + network;
|
||||
File appDir = new File(Utilities.getUserDataDir(), appName);
|
||||
if (!appDir.exists() && !appDir.mkdir()) {
|
||||
log.warn("make appDir failed");
|
||||
}
|
||||
|
||||
setup(network, appDir);
|
||||
|
||||
inventoryMonitor = new InventoryMonitor(appDir, useLocalhostForP2P, network, intervalSec, cleanupTorFiles);
|
||||
inventoryMonitor.start(port);
|
||||
// We shut down after 5 days to avoid potential memory leak issue.
|
||||
// The start script will restart the app.
|
||||
if (shutdownIntervalDays > 0) {
|
||||
UserThread.runAfter(InventoryMonitorMain::shutDown, TimeUnit.DAYS.toSeconds(shutdownIntervalDays));
|
||||
}
|
||||
|
||||
keepRunning();
|
||||
}
|
||||
|
||||
private static void setup(BaseCurrencyNetwork network, File appDir) {
|
||||
String logPath = Paths.get(appDir.getPath(), "bisq").toString();
|
||||
Log.setup(logPath);
|
||||
Log.setLevel(Level.INFO);
|
||||
AsciiLogo.showAsciiLogo();
|
||||
Version.setBaseCryptoNetworkId(network.ordinal());
|
||||
|
||||
Res.setup(); // Used for some formatting in the webserver
|
||||
|
||||
// We do not set any capabilities as we don't want to receive any network data beside our response.
|
||||
// We also do not use capabilities for the request/response messages as we only connect to seeds nodes
|
||||
ExecutorService executorService = SingleThreadExecutorUtils.getSingleThreadExecutor(InventoryMonitorMain.class);
|
||||
UserThread.setExecutor(executorService);
|
||||
|
||||
Signal.handle(new Signal("INT"), signal -> UserThread.execute(InventoryMonitorMain::shutDown));
|
||||
Signal.handle(new Signal("TERM"), signal -> UserThread.execute(InventoryMonitorMain::shutDown));
|
||||
}
|
||||
|
||||
private static void shutDown() {
|
||||
stopped = true;
|
||||
inventoryMonitor.shutDown(() -> System.exit(EXIT_SUCCESS));
|
||||
}
|
||||
|
||||
private static void keepRunning() {
|
||||
while (!stopped) {
|
||||
try {
|
||||
Thread.sleep(Long.MAX_VALUE);
|
||||
} catch (InterruptedException ignore) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
552
inventory/src/main/java/bisq/inventory/InventoryWebServer.java
Normal file
552
inventory/src/main/java/bisq/inventory/InventoryWebServer.java
Normal file
@ -0,0 +1,552 @@
|
||||
/*
|
||||
* This file is part of Bisq.
|
||||
*
|
||||
* Bisq is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bisq is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package bisq.inventory;
|
||||
|
||||
import bisq.core.network.p2p.inventory.model.DeviationByIntegerDiff;
|
||||
import bisq.core.network.p2p.inventory.model.DeviationByPercentage;
|
||||
import bisq.core.network.p2p.inventory.model.DeviationSeverity;
|
||||
import bisq.core.network.p2p.inventory.model.InventoryItem;
|
||||
import bisq.core.network.p2p.inventory.model.RequestInfo;
|
||||
import bisq.core.util.FormattingUtils;
|
||||
|
||||
import bisq.network.p2p.NodeAddress;
|
||||
|
||||
import bisq.common.app.Version;
|
||||
import bisq.common.util.MathUtils;
|
||||
import bisq.common.util.Utilities;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Function;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
|
||||
|
||||
import spark.Spark;
|
||||
|
||||
@Slf4j
|
||||
public class InventoryWebServer {
|
||||
private final static String CLOSE_TAG = "</font><br/>";
|
||||
private final static String WARNING_ICON = "⚠ ";
|
||||
private final static String ALERT_ICON = "☠ "; // ⚡ ⚡
|
||||
|
||||
private final List<NodeAddress> seedNodes;
|
||||
private final Map<String, String> operatorByNodeAddress = new HashMap<>();
|
||||
|
||||
private String html;
|
||||
private int requestCounter;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public InventoryWebServer(List<NodeAddress> seedNodes, BufferedReader seedNodeFile) {
|
||||
this.seedNodes = seedNodes;
|
||||
setupOperatorMap(seedNodeFile);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// API
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void start(int port) {
|
||||
Spark.port(port);
|
||||
Spark.get("/", (req, res) -> {
|
||||
log.info("Incoming request from: {}", req.userAgent());
|
||||
return html == null ? "Starting up..." : html;
|
||||
});
|
||||
}
|
||||
|
||||
public void shutDown() {
|
||||
Spark.stop();
|
||||
}
|
||||
|
||||
public void onNewRequestInfo(Map<NodeAddress, List<RequestInfo>> requestInfoListByNode, int requestCounter) {
|
||||
this.requestCounter = requestCounter;
|
||||
html = generateHtml(requestInfoListByNode);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// HTML
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private String generateHtml(Map<NodeAddress, List<RequestInfo>> map) {
|
||||
StringBuilder html = new StringBuilder();
|
||||
html.append("<html>" +
|
||||
"<head>" +
|
||||
"<style type=\"text/css\">" +
|
||||
" a {" +
|
||||
" text-decoration:none; color: black;" +
|
||||
" }" +
|
||||
" #warn { color: #ff7700; } " +
|
||||
" #alert { color: #ff0000; } " +
|
||||
"table, th, td {border: 1px solid black;}" +
|
||||
"</style></head>" +
|
||||
"<body><h3>")
|
||||
.append("Current time: ").append(new Date().toString()).append("<br/>")
|
||||
.append("Request cycle: ").append(requestCounter).append("<br/>")
|
||||
.append("Version/commit: ").append(Version.VERSION).append(" / ").append("TODO RequestInfo.COMMIT_HASH").append("<br/>")
|
||||
.append("<table style=\"width:100%\">")
|
||||
.append("<tr>")
|
||||
.append("<th align=\"left\">Seed node info</th>")
|
||||
.append("<th align=\"left\">Request info</th>")
|
||||
.append("<th align=\"left\">Data inventory</th>")
|
||||
.append("<th align=\"left\">DAO data</th>")
|
||||
.append("<th align=\"left\">Network info</th>").append("</tr>");
|
||||
|
||||
seedNodes.forEach(seedNode -> {
|
||||
html.append("<tr valign=\"top\">");
|
||||
if (map.containsKey(seedNode) && !map.get(seedNode).isEmpty()) {
|
||||
List<RequestInfo> list = map.get(seedNode);
|
||||
int numRequests = list.size();
|
||||
RequestInfo requestInfo = list.get(numRequests - 1);
|
||||
html.append("<td>").append(getSeedNodeInfo(seedNode, requestInfo)).append("</td>")
|
||||
.append("<td>").append(getRequestInfo(seedNode, requestInfo, numRequests, map)).append("</td>")
|
||||
.append("<td>").append(getDataInfo(seedNode, requestInfo, map)).append("</td>")
|
||||
.append("<td>").append(getDaoInfo(seedNode, requestInfo, map)).append("</td>")
|
||||
.append("<td>").append(getNetworkInfo(seedNode, requestInfo, map)).append("</td>");
|
||||
} else {
|
||||
html.append("<td>").append(getSeedNodeInfo(seedNode, null)).append("</td>")
|
||||
.append("<td>").append("n/a").append("</td>")
|
||||
.append("<td>").append("n/a").append("</td>")
|
||||
.append("<td>").append("n/a").append("</td>")
|
||||
.append("<td>").append("n/a").append("</td>");
|
||||
}
|
||||
html.append("</tr>");
|
||||
});
|
||||
|
||||
html.append("</table></body></html>");
|
||||
return html.toString();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Sub sections
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private String getSeedNodeInfo(NodeAddress nodeAddress,
|
||||
@Nullable RequestInfo requestInfo) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
String operator = operatorByNodeAddress.get(nodeAddress.getFullAddress());
|
||||
sb.append("Operator: ").append(operator).append("<br/>");
|
||||
|
||||
String address = nodeAddress.getFullAddress();
|
||||
|
||||
String filteredSeeds = requestInfo != null ? requestInfo.getValue(InventoryItem.filteredSeeds) : null;
|
||||
if (filteredSeeds != null && filteredSeeds.contains(address)) {
|
||||
sb.append(getColorTagByDeviationSeverity(DeviationSeverity.ALERT)).append("Node address: ")
|
||||
.append(address).append(" (is filtered!)").append(CLOSE_TAG);
|
||||
} else {
|
||||
sb.append("Node address: ").append(address).append("<br/>");
|
||||
}
|
||||
|
||||
if (requestInfo != null) {
|
||||
sb.append("Version: ").append(requestInfo.getDisplayValue(InventoryItem.version)).append("<br/>");
|
||||
sb.append("Commit hash: ").append(requestInfo.getDisplayValue(InventoryItem.commitHash)).append("<br/>");
|
||||
String memory = requestInfo.getValue(InventoryItem.usedMemory);
|
||||
String memoryString = memory != null ? Utilities.readableFileSize(Long.parseLong(memory)) : "n/a";
|
||||
sb.append("Memory used: ")
|
||||
.append(memoryString)
|
||||
.append("<br/>");
|
||||
|
||||
String jvmStartTimeString = requestInfo.getValue(InventoryItem.jvmStartTime);
|
||||
long jvmStartTime = jvmStartTimeString != null ? Long.parseLong(jvmStartTimeString) : 0;
|
||||
sb.append("Node started at: ")
|
||||
.append(new Date(jvmStartTime).toString())
|
||||
.append("<br/>");
|
||||
|
||||
String duration = jvmStartTime > 0 ?
|
||||
FormattingUtils.formatDurationAsWords(System.currentTimeMillis() - jvmStartTime,
|
||||
true, true) :
|
||||
"n/a";
|
||||
sb.append("Run duration: ").append(duration).append("<br/>");
|
||||
|
||||
String filteredSeedNodes = requestInfo.getDisplayValue(InventoryItem.filteredSeeds)
|
||||
.replace(System.getProperty("line.separator"), "<br/>");
|
||||
if (filteredSeedNodes.isEmpty()) {
|
||||
filteredSeedNodes = "-";
|
||||
}
|
||||
sb.append("Filtered seed nodes: ")
|
||||
.append(filteredSeedNodes)
|
||||
.append("<br/>");
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private String getRequestInfo(NodeAddress seedNode,
|
||||
RequestInfo requestInfo,
|
||||
int numRequests,
|
||||
Map<NodeAddress, List<RequestInfo>> map) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
DeviationSeverity deviationSeverity = numRequests == requestCounter ?
|
||||
DeviationSeverity.OK :
|
||||
requestCounter - numRequests > 4 ?
|
||||
DeviationSeverity.ALERT :
|
||||
DeviationSeverity.WARN;
|
||||
sb.append("Number of requests: ").append(getColorTagByDeviationSeverity(deviationSeverity))
|
||||
.append(numRequests).append(CLOSE_TAG);
|
||||
|
||||
DeviationSeverity rrtDeviationSeverity = DeviationSeverity.OK;
|
||||
String rrtString = "n/a";
|
||||
if (requestInfo.getResponseTime() > 0) {
|
||||
long rrt = requestInfo.getResponseTime() - requestInfo.getRequestStartTime();
|
||||
if (rrt > 20_000) {
|
||||
rrtDeviationSeverity = DeviationSeverity.ALERT;
|
||||
} else if (rrt > 10_000) {
|
||||
rrtDeviationSeverity = DeviationSeverity.WARN;
|
||||
}
|
||||
rrtString = MathUtils.roundDouble(rrt / 1000d, 3) + " sec";
|
||||
|
||||
}
|
||||
sb.append("Round trip time: ").append(getColorTagByDeviationSeverity(rrtDeviationSeverity))
|
||||
.append(rrtString).append(CLOSE_TAG);
|
||||
|
||||
Date requestStartTime = new Date(requestInfo.getRequestStartTime());
|
||||
sb.append("Requested at: ").append(requestStartTime).append("<br/>");
|
||||
|
||||
String responseTime = requestInfo.getResponseTime() > 0 ?
|
||||
new Date(requestInfo.getResponseTime()).toString() :
|
||||
"n/a";
|
||||
sb.append("Response received at: ").append(responseTime).append("<br/>");
|
||||
|
||||
sb.append(getErrorMsgLine(seedNode, requestInfo, map));
|
||||
|
||||
sb.append(getLastSuccessfulResponseLine(seedNode, map));
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private String getDataInfo(NodeAddress seedNode,
|
||||
RequestInfo requestInfo,
|
||||
Map<NodeAddress, List<RequestInfo>> map) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append(getLine(InventoryItem.OfferPayload, seedNode, requestInfo, map));
|
||||
sb.append(getLine(InventoryItem.MailboxStoragePayload, seedNode, requestInfo, map));
|
||||
sb.append(getLine(InventoryItem.TradeStatistics3, seedNode, requestInfo, map));
|
||||
sb.append(getLine(InventoryItem.AccountAgeWitness, seedNode, requestInfo, map));
|
||||
sb.append(getLine(InventoryItem.SignedWitness, seedNode, requestInfo, map));
|
||||
|
||||
sb.append(getLine(InventoryItem.Alert, seedNode, requestInfo, map));
|
||||
sb.append(getLine(InventoryItem.Filter, seedNode, requestInfo, map));
|
||||
sb.append(getLine(InventoryItem.Mediator, seedNode, requestInfo, map));
|
||||
sb.append(getLine(InventoryItem.RefundAgent, seedNode, requestInfo, map));
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private String getDaoInfo(NodeAddress seedNode,
|
||||
RequestInfo requestInfo,
|
||||
Map<NodeAddress, List<RequestInfo>> map) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append(getLine("Number of BSQ blocks: ", InventoryItem.numBsqBlocks, seedNode, requestInfo, map));
|
||||
sb.append(getLine(InventoryItem.TempProposalPayload, seedNode, requestInfo, map));
|
||||
sb.append(getLine(InventoryItem.ProposalPayload, seedNode, requestInfo, map));
|
||||
sb.append(getLine(InventoryItem.BlindVotePayload, seedNode, requestInfo, map));
|
||||
sb.append(getLine("DAO state block height: ", InventoryItem.daoStateChainHeight, seedNode, requestInfo, map));
|
||||
|
||||
sb.append(getLine("DAO state hash: ", InventoryItem.daoStateHash, seedNode, requestInfo, map));
|
||||
|
||||
// The hash for proposal changes only at first block of blind vote phase but as we do not want to initialize the
|
||||
// dao domain we cannot check that. But we also don't need that as we can just compare that all hashes at all
|
||||
// blocks from all seeds are the same. Same for blindVoteHash.
|
||||
sb.append(getLine("Proposal state hash: ", InventoryItem.proposalHash, seedNode, requestInfo, map));
|
||||
sb.append(getLine("Blind vote state hash: ", InventoryItem.blindVoteHash, seedNode, requestInfo, map));
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private String getNetworkInfo(NodeAddress seedNode,
|
||||
RequestInfo requestInfo,
|
||||
Map<NodeAddress, List<RequestInfo>> map) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append(getLine("Max. connections: ",
|
||||
InventoryItem.maxConnections, seedNode, requestInfo, map));
|
||||
sb.append(getLine("Number of connections: ",
|
||||
InventoryItem.numConnections, seedNode, requestInfo, map));
|
||||
sb.append(getLine("Peak number of connections: ",
|
||||
InventoryItem.peakNumConnections, seedNode, requestInfo, map));
|
||||
sb.append(getLine("Number of 'All connections lost' events: ",
|
||||
InventoryItem.numAllConnectionsLostEvents, seedNode, requestInfo, map));
|
||||
|
||||
sb.append(getLine("Sent messages/sec: ",
|
||||
InventoryItem.sentMessagesPerSec, seedNode, requestInfo, map, this::getRounded));
|
||||
sb.append(getLine("Received messages/sec: ",
|
||||
InventoryItem.receivedMessagesPerSec, seedNode, requestInfo, map, this::getRounded));
|
||||
sb.append(getLine("Sent kB/sec: ",
|
||||
InventoryItem.sentBytesPerSec, seedNode, requestInfo, map, this::getKbRounded));
|
||||
sb.append(getLine("Received kB/sec: ",
|
||||
InventoryItem.receivedBytesPerSec, seedNode, requestInfo, map, this::getKbRounded));
|
||||
sb.append(getLine("Sent data: ",
|
||||
InventoryItem.sentBytes, seedNode, requestInfo, map,
|
||||
value -> Utilities.readableFileSize(Long.parseLong(value))));
|
||||
sb.append(getLine("Received data: ",
|
||||
InventoryItem.receivedBytes, seedNode, requestInfo, map,
|
||||
value -> Utilities.readableFileSize(Long.parseLong(value))));
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Utils
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private String getLine(InventoryItem inventoryItem,
|
||||
NodeAddress seedNode,
|
||||
RequestInfo requestInfo,
|
||||
Map<NodeAddress, List<RequestInfo>> map) {
|
||||
return getLine(getTitle(inventoryItem),
|
||||
inventoryItem,
|
||||
seedNode,
|
||||
requestInfo,
|
||||
map);
|
||||
}
|
||||
|
||||
private String getLine(String title,
|
||||
InventoryItem inventoryItem,
|
||||
NodeAddress seedNode,
|
||||
RequestInfo requestInfo,
|
||||
Map<NodeAddress, List<RequestInfo>> map) {
|
||||
return getLine(title,
|
||||
inventoryItem,
|
||||
seedNode,
|
||||
requestInfo,
|
||||
map,
|
||||
null);
|
||||
}
|
||||
|
||||
private String getLine(String title,
|
||||
InventoryItem inventoryItem,
|
||||
NodeAddress seedNode,
|
||||
RequestInfo requestInfo,
|
||||
Map<NodeAddress, List<RequestInfo>> map,
|
||||
@Nullable Function<String, String> formatter) {
|
||||
String displayValue = requestInfo.getDisplayValue(inventoryItem);
|
||||
String value = requestInfo.getValue(inventoryItem);
|
||||
if (formatter != null && value != null) {
|
||||
displayValue = formatter.apply(value);
|
||||
}
|
||||
|
||||
String deviationAsPercentString = "";
|
||||
DeviationSeverity deviationSeverity = DeviationSeverity.OK;
|
||||
if (requestInfo.getDataMap().containsKey(inventoryItem)) {
|
||||
RequestInfo.Data data = requestInfo.getDataMap().get(inventoryItem);
|
||||
deviationAsPercentString = getDeviationAsPercentString(inventoryItem, data);
|
||||
deviationSeverity = data.getDeviationSeverity();
|
||||
}
|
||||
|
||||
List<RequestInfo> requestInfoList = map.get(seedNode);
|
||||
String historicalWarnings = "";
|
||||
String historicalAlerts = "";
|
||||
List<String> warningsAtRequestNumber = new ArrayList<>();
|
||||
List<String> alertsAtRequestNumber = new ArrayList<>();
|
||||
if (requestInfoList != null) {
|
||||
for (int i = 0; i < requestInfoList.size(); i++) {
|
||||
RequestInfo reqInfo = requestInfoList.get(i);
|
||||
Map<InventoryItem, RequestInfo.Data> deviationInfoMap = reqInfo.getDataMap();
|
||||
if (deviationInfoMap.containsKey(inventoryItem)) {
|
||||
RequestInfo.Data data = deviationInfoMap.get(inventoryItem);
|
||||
String deviationAsPercent = getDeviationAsPercentString(inventoryItem, data);
|
||||
if (data.isPersistentWarning()) {
|
||||
warningsAtRequestNumber.add((i + 1) + deviationAsPercent);
|
||||
} else if (data.isPersistentAlert()) {
|
||||
alertsAtRequestNumber.add((i + 1) + deviationAsPercent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!warningsAtRequestNumber.isEmpty()) {
|
||||
historicalWarnings = warningsAtRequestNumber.size() + " repeated warning(s) at request(s) " +
|
||||
Joiner.on(", ").join(warningsAtRequestNumber);
|
||||
}
|
||||
if (!alertsAtRequestNumber.isEmpty()) {
|
||||
historicalAlerts = alertsAtRequestNumber.size() + " repeated alert(s) at request(s): " +
|
||||
Joiner.on(", ").join(alertsAtRequestNumber);
|
||||
}
|
||||
}
|
||||
String historicalWarningsHtml = warningsAtRequestNumber.isEmpty() ? "" :
|
||||
", <b><a id=\"warn\" href=\"#\" title=\"" + historicalWarnings + "\">" + WARNING_ICON +
|
||||
warningsAtRequestNumber.size() + "</a></b>";
|
||||
String historicalAlertsHtml = alertsAtRequestNumber.isEmpty() ? "" :
|
||||
", <b><a id=\"alert\" href=\"#\" title=\"" + historicalAlerts + "\">" + ALERT_ICON +
|
||||
alertsAtRequestNumber.size() + "</a></b>";
|
||||
|
||||
return title +
|
||||
getColorTagByDeviationSeverity(deviationSeverity) +
|
||||
displayValue +
|
||||
deviationAsPercentString +
|
||||
historicalWarningsHtml +
|
||||
historicalAlertsHtml +
|
||||
CLOSE_TAG;
|
||||
}
|
||||
|
||||
private String getDeviationAsPercentString(InventoryItem inventoryItem, RequestInfo.Data data) {
|
||||
Double deviation = data.getDeviation();
|
||||
if (deviation == null || deviation == 1) {
|
||||
return "";
|
||||
}
|
||||
if (inventoryItem.getDeviationType() instanceof DeviationByPercentage) {
|
||||
return getDeviationInRoundedPercent(deviation);
|
||||
} else if (inventoryItem.getDeviationType() instanceof DeviationByIntegerDiff) {
|
||||
// For larger numbers like chain height we need to show all decimals as diff can be very small
|
||||
return getDeviationInExactPercent(deviation);
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
private String getDeviationInRoundedPercent(double deviation) {
|
||||
return " (" + MathUtils.roundDouble(100 * deviation, 2) + " %)";
|
||||
}
|
||||
|
||||
private String getDeviationInExactPercent(double deviation) {
|
||||
return " (" + 100 * deviation + " %)";
|
||||
}
|
||||
|
||||
private String getColorTagByDeviationSeverity(@Nullable DeviationSeverity deviationSeverity) {
|
||||
if (deviationSeverity == null) {
|
||||
return "<font color=\"black\">";
|
||||
}
|
||||
|
||||
switch (deviationSeverity) {
|
||||
case WARN:
|
||||
return "<font color=\"#0000cc\">";
|
||||
case ALERT:
|
||||
return "<font color=\"#cc0000\">";
|
||||
case IGNORED:
|
||||
return "<font color=\"#333333\">";
|
||||
case OK:
|
||||
default:
|
||||
return "<font color=\"black\">";
|
||||
}
|
||||
}
|
||||
|
||||
private String getTitle(InventoryItem inventoryItem) {
|
||||
return "Number of " + inventoryItem.getKey() + ": ";
|
||||
}
|
||||
|
||||
private String getRounded(String value) {
|
||||
return String.valueOf(MathUtils.roundDouble(Double.parseDouble(value), 2));
|
||||
}
|
||||
|
||||
private String getKbRounded(String bytes) {
|
||||
return String.valueOf(MathUtils.roundDouble(Double.parseDouble(bytes) / 1000, 2));
|
||||
}
|
||||
|
||||
private void setupOperatorMap(BufferedReader seedNodeFile) {
|
||||
seedNodeFile.lines().forEach(line -> {
|
||||
if (!line.startsWith("#")) {
|
||||
String[] strings = line.split(" \\(@");
|
||||
String node = strings.length > 0 ? strings[0] : "n/a";
|
||||
String operator = strings.length > 1 ? strings[1].replace(")", "") : "n/a";
|
||||
operatorByNodeAddress.put(node, operator);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// We use here a bit diff. model as with other historical data alerts/warnings as we do not store it in the data
|
||||
// object as we do with normal inventoryItems. So the historical error msg are not available in the json file.
|
||||
// If we need it we have to move that handling here to the InventoryMonitor and change the data model to support the
|
||||
// missing data for error messages.
|
||||
private String getErrorMsgLine(NodeAddress seedNode,
|
||||
RequestInfo requestInfo,
|
||||
Map<NodeAddress, List<RequestInfo>> map) {
|
||||
String errorMessage = requestInfo.hasError() ? requestInfo.getErrorMessage() : "-";
|
||||
List<RequestInfo> requestInfoList = map.get(seedNode);
|
||||
List<String> errorsAtRequestNumber = new ArrayList<>();
|
||||
String historicalErrorsHtml = "";
|
||||
if (requestInfoList != null) {
|
||||
for (int i = 0; i < requestInfoList.size(); i++) {
|
||||
RequestInfo requestInfo1 = requestInfoList.get(i);
|
||||
|
||||
// We ignore old errors as at startup timeouts are expected and each node restarts once a day
|
||||
long duration = System.currentTimeMillis() - requestInfo1.getRequestStartTime();
|
||||
if (requestInfo1.getRequestStartTime() > 0 && duration > TimeUnit.HOURS.toMillis(24)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (requestInfo1.hasError()) {
|
||||
errorsAtRequestNumber.add((i + 1) + " (" + requestInfo1.getErrorMessage() + ")");
|
||||
}
|
||||
}
|
||||
|
||||
if (!errorsAtRequestNumber.isEmpty()) {
|
||||
String errorIcon;
|
||||
String type;
|
||||
String style;
|
||||
if (errorsAtRequestNumber.size() > 4) {
|
||||
errorIcon = ALERT_ICON;
|
||||
type = "alert";
|
||||
style = "alert";
|
||||
} else {
|
||||
errorIcon = WARNING_ICON;
|
||||
type = "warning";
|
||||
style = "warn";
|
||||
}
|
||||
String historicalAlerts = errorsAtRequestNumber.size() + " repeated " + type + "(s) at request(s): " +
|
||||
Joiner.on(", ").join(errorsAtRequestNumber);
|
||||
historicalErrorsHtml = errorsAtRequestNumber.isEmpty() ? "" :
|
||||
", <b><a id=\"" + style + "\" href=\"#\" title=\"" + historicalAlerts + "\">" + errorIcon +
|
||||
errorsAtRequestNumber.size() + "</a></b>";
|
||||
}
|
||||
}
|
||||
DeviationSeverity deviationSeverity = requestInfo.hasError() ?
|
||||
errorsAtRequestNumber.size() > 4 ? DeviationSeverity.ALERT : DeviationSeverity.WARN
|
||||
: DeviationSeverity.OK;
|
||||
|
||||
return "Error message: " +
|
||||
getColorTagByDeviationSeverity(deviationSeverity) +
|
||||
errorMessage +
|
||||
historicalErrorsHtml +
|
||||
CLOSE_TAG;
|
||||
}
|
||||
|
||||
private String getLastSuccessfulResponseLine(NodeAddress seedNode,
|
||||
Map<NodeAddress, List<RequestInfo>> map) {
|
||||
long newestResponseTime = 0;
|
||||
List<RequestInfo> requestInfoList = map.get(seedNode);
|
||||
if (requestInfoList != null) {
|
||||
for (int i = 0; i < requestInfoList.size(); i++) {
|
||||
RequestInfo requestInfo1 = requestInfoList.get(i);
|
||||
newestResponseTime = Math.max(newestResponseTime, requestInfo1.getResponseTime());
|
||||
}
|
||||
}
|
||||
String responseMessage = newestResponseTime > 0 ? new Date(newestResponseTime).toString() : "none";
|
||||
return "Last response received: " +
|
||||
responseMessage +
|
||||
CLOSE_TAG;
|
||||
}
|
||||
}
|
10
inventory/src/main/resources/inv_btc_mainnet.seednodes
Normal file
10
inventory/src/main/resources/inv_btc_mainnet.seednodes
Normal file
@ -0,0 +1,10 @@
|
||||
# nodeaddress.onion:port [(@owner,@backup)]
|
||||
devinv3rhon24gqf5v6ondoqgyrbzyqihzyouzv7ptltsewhfmox2zqd.onion:8000 (@devinbileck)
|
||||
devinsn2teu33efff62bnvwbxmfgbfjlgqsu3ad4b4fudx3a725eqnyd.onion:8000 (@devinbileck)
|
||||
devinsn3xuzxhj6pmammrxpydhwwmwp75qkksedo5dn2tlmu7jggo7id.onion:8000 (@devinbileck)
|
||||
sn3emzy56u3mxzsr4geysc52feoq5qt7ja56km6gygwnszkshunn2sid.onion:8000 (@emzy)
|
||||
sn4emzywye3dhjouv7jig677qepg7fnusjidw74fbwneieruhmi7fuyd.onion:8000 (@emzy)
|
||||
sn5emzyvxuildv34n6jewfp2zeota4aq63fsl5yyilnvksezr3htveqd.onion:8000 (@emzy)
|
||||
y6mvobc6tfp7l3rq2rae7hayvkmy35su33cun2mfdbzd4uw536pqtlyd.onion:8000 (@jester4042)
|
||||
xaebw6lpcckkyb2anyzyfynthebek2abqzyhchenfrdqlfktezgtrtqd.onion:8000 (@jester4042)
|
||||
33ol66i7crfrnypjlpd7kem3imo6zmjkvxdr6ipcdx3e2skbpcrfzuqd.onion:8000 (@jester4042)
|
15
inventory/src/main/resources/logback.xml
Normal file
15
inventory/src/main/resources/logback.xml
Normal file
@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<appender name="CONSOLE_APPENDER" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%highlight(%d{MMM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{40}: %msg %xEx%n)</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root level="TRACE">
|
||||
<appender-ref ref="CONSOLE_APPENDER"/>
|
||||
</root>
|
||||
|
||||
<!-- <logger name="org.bitcoinj" level="WARN"/>-->
|
||||
<logger name="org.berndpruenster.netlayer.tor.Tor" level="WARN"/>
|
||||
</configuration>
|
@ -19,9 +19,6 @@ package bisq.network.p2p.network;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface BridgeAddressProvider {
|
||||
@Nullable
|
||||
List<String> getBridgeAddresses();
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ include 'core'
|
||||
include 'cli'
|
||||
include 'daemon'
|
||||
include 'desktop'
|
||||
include 'inventory'
|
||||
include 'persistence'
|
||||
include 'seednode'
|
||||
include 'statsnode'
|
||||
|
Loading…
Reference in New Issue
Block a user