diff --git a/Cargo.lock b/Cargo.lock index c6b9a412a..b863693a8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -149,6 +149,15 @@ name = "base32" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "base64" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "safemem 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "base64" version = "0.10.1" @@ -1541,6 +1550,24 @@ name = "humantime" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "hyper" +version = "0.10.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", + "httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "hyper" version = "0.12.35" @@ -1758,6 +1785,23 @@ dependencies = [ "wasm-bindgen 0.2.56 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "jsonrpc-client-transports" +version = "14.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-pubsub 14.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "websocket 0.24.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "jsonrpc-core" version = "14.0.5" @@ -1770,6 +1814,14 @@ dependencies = [ "serde_json 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "jsonrpc-core-client" +version = "14.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "jsonrpc-client-transports 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "jsonrpc-derive" version = "14.0.5" @@ -1877,6 +1929,11 @@ name = "lalrpop-util" version = "0.17.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "language-tags" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "lazy_static" version = "1.4.0" @@ -2020,6 +2077,14 @@ dependencies = [ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "mime" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "mime" version = "0.3.13" @@ -3227,6 +3292,11 @@ name = "ryu" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "safemem" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "same-file" version = "1.0.5" @@ -3410,6 +3480,11 @@ dependencies = [ "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "sha1" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "sha2" version = "0.7.1" @@ -3883,6 +3958,7 @@ dependencies = [ "indexmap 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-core 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core-client 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-derive 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-http-server 14.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-pubsub 14.0.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -5542,6 +5618,16 @@ dependencies = [ "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tokio-tls" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "tokio-udp" version = "0.1.3" @@ -5599,6 +5685,11 @@ name = "tower-service" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "traitobject" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "treeline" version = "0.1.0" @@ -5644,6 +5735,11 @@ dependencies = [ "utf-8 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "typeable" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "typed-arena" version = "1.6.1" @@ -5654,6 +5750,14 @@ name = "typenum" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "unicase" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "unicase" version = "2.4.0" @@ -5930,6 +6034,45 @@ dependencies = [ "webpki 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "websocket" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)", + "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tls 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "websocket-base 0.24.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "websocket-base" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tls 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "weedle" version = "0.10.0" @@ -6088,6 +6231,7 @@ dependencies = [ "checksum base32 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ce669cd6c8588f79e15cf450314f9638f967fc5770ff1c7c1deb0925ea7cfa" "checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" "checksum base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" +"checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" "checksum bech32 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "58946044516aa9dc922182e0d6e9d124a31aafe6b421614654eb27cf90cec09c" "checksum bincode 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5753e2a71534719bf3f4e57006c3a4f0d2c672a4b676eec84161f763eca87dbf" "checksum bindgen 0.49.2 (registry+https://github.com/rust-lang/crates.io-index)" = "846a1fba6535362a01487ef6b10f0275faa12e5c5d835c5c1c627aabc46ccbd6" @@ -6248,6 +6392,7 @@ dependencies = [ "checksum httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" "checksum humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" "checksum humantime 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b9b6c53306532d3c8e8087b44e6580e10db51a023cf9b433cea2ac38066b92da" +"checksum hyper 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)" = "0a0652d9a2609a968c14be1a9ea00bf4b1d64e2e1f53a1b51b6fff3a6e829273" "checksum hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)" = "9dbe6ed1438e1f8ad955a4701e9a944938e9519f6888d12d8558b645e247d5f6" "checksum hyper 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8bf49cfb32edee45d890537d9057d1b02ed55f53b7b6a30bae83a38c9231749e" "checksum hyper-rustls 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)" = "719d85c7df4a7f309a77d145340a063ea929dcb2e025bae46a80345cffec2952" @@ -6268,7 +6413,9 @@ dependencies = [ "checksum jemallocator 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "43ae63fcfc45e99ab3d1b29a46782ad679e98436c3169d15a167a1108a724b69" "checksum jobserver 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "f74e73053eaf95399bf926e48fc7a2a3ce50bd0eaaa2357d391e95b2dcdd4f10" "checksum js-sys 0.3.33 (registry+https://github.com/rust-lang/crates.io-index)" = "367647c532db6f1555d7151e619540ec5f713328235b8c062c6b4f63e84adfe3" +"checksum jsonrpc-client-transports 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0a9ae166c4d1f702d297cd76d4b55758ace80272ffc6dbb139fdc1bf810de40b" "checksum jsonrpc-core 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fe3b688648f1ef5d5072229e2d672ecb92cbff7d1c79bcf3fd5898f3f3df0970" +"checksum jsonrpc-core-client 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "080dc110be17701097df238fad3c816d4a478a1899dfbcf8ec8957dd40ec7304" "checksum jsonrpc-derive 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8609af8f63b626e8e211f52441fcdb6ec54f1a446606b10d5c89ae9bf8a20058" "checksum jsonrpc-http-server 14.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "816d63997ea45d3634608edbef83ddb35e661f7c0b27b5b72f237e321f0e9807" "checksum jsonrpc-pubsub 14.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "5b31c9b90731276fdd24d896f31bb10aecf2e5151733364ae81123186643d939" @@ -6278,6 +6425,7 @@ dependencies = [ "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lalrpop 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)" = "64dc3698e75d452867d9bd86f4a723f452ce9d01fe1d55990b79f0c790aa67db" "checksum lalrpop-util 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c277d18683b36349ab5cd030158b54856fca6bb2d5dc5263b06288f486958b7c" +"checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" "checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" "checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558" @@ -6297,6 +6445,7 @@ dependencies = [ "checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" "checksum memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ce6075db033bbbb7ee5a0bbd3a3186bbae616f57fb001c485c7ff77955f8177f" "checksum memsec 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ccabb92f665f997bcb4f3ade019a8e07315148d8bcef3e65fbc5dbd65a22eb04" +"checksum mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0" "checksum mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "3e27ca21f40a310bd06d9031785f4801710d566c184a6e15bad4f1d9b65f9425" "checksum mime_guess 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1a0ed03949aef72dbdf3116a383d7b38b4768e6f960528cd6a6044aa9ed68599" "checksum miniz_oxide 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7108aff85b876d06f22503dcce091e29f76733b2bfdd91eebce81f5e68203a10" @@ -6425,6 +6574,7 @@ dependencies = [ "checksum rustls-native-certs 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "51ffebdbb48c14f84eba0b715197d673aff1dd22cc1007ca647e28483bbcc307" "checksum rusty-fork 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3dd93264e10c577503e926bd1430193eeb5d21b059148910082245309b424fae" "checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997" +"checksum safemem 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" "checksum same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "585e8ddcedc187886a30fa705c47985c3fa88d06624095856b36ca0b82ff4421" "checksum schannel 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "87f550b06b6cba9c8b8be3ee73f391990116bf527450d2556e9b9ce263b9a021" "checksum scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" @@ -6446,6 +6596,7 @@ dependencies = [ "checksum serial_test_derive 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3c188479c8b700998829c168d7a4c21032660b0dd2ed87a0b166c85811750740" "checksum serial_test_derive 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d08338d8024b227c62bd68a12c7c9883f5c66780abaef15c550dc56f46ee6515" "checksum sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "23962131a91661d643c98940b20fcaffe62d776a823247be80a48fcb8b6fce68" +"checksum sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" "checksum sha2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9eb6be24e4c23a84d7184280d2722f7f2731fcdd4a9d886efbfe4413e4847ea0" "checksum sha2 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "27044adfd2e1f077f649f59deb9490d3941d674002f7d062870a60ebe9bd47a0" "checksum sha3 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd26bc0e7a2e3a7c959bc494caf58b72ee0c71d67704e9520f736ca7e4853ecf" @@ -6542,18 +6693,22 @@ dependencies = [ "checksum tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1d14b10654be682ac43efee27401d792507e30fd8d26389e1da3b185de2e4119" "checksum tokio-threadpool 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "90ca01319dea1e376a001e8dc192d42ebde6dd532532a5bad988ac37db365b19" "checksum tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "f2106812d500ed25a4f38235b9cae8f78a09edf43203e16e59c3b769a342a60e" +"checksum tokio-tls 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "354b8cd83825b3c20217a9dc174d6a0c67441a2fae5c41bcb1ea6679f6ae0f7c" "checksum tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "66268575b80f4a4a710ef83d087fdfeeabdce9b74c797535fbac18a2cb906e92" "checksum tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "037ffc3ba0e12a0ab4aca92e5234e0dedeb48fddf6ccd260f1f150a36a9f2445" "checksum tokio-util 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "571da51182ec208780505a32528fc5512a8fe1443ab960b3f2f3ef093cd16930" "checksum toml 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c04dffffeac90885436d23c692517bb5b8b3f8863e4afc15023628d067d667b7" "checksum tower-service 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e987b6bf443f4b5b3b6f38704195592cca41c5bb7aedd3c3693c7081f8289860" +"checksum traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" "checksum treeline 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a7f741b240f1a48843f9b8e0444fb55fb2a4ff67293b50a9179dfd5ea67f8d41" "checksum trees 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "afa1821e85be4f56cc5bd08bdbc32c0e26d105c90bed9c637992f6c7f747c180" "checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" "checksum try_from 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "283d3b89e1368717881a9d51dad843cc435380d8109c9e47d38780a324698d8b" "checksum tungstenite 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cfea31758bf674f990918962e8e5f07071a3161bd7c4138ed23e416e1ac4264e" +"checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" "checksum typed-arena 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9c0704a799d314795d3d847d519b284bae681ef9b1f3da99f7ebc7b47ba2e607" "checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" +"checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" "checksum unicase 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a84e5511b2a947f3ae965dcb29b13b7b1691b6e7332cf5dbc1744138d5acb7f6" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" "checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426" @@ -6589,6 +6744,8 @@ dependencies = [ "checksum web-sys 0.3.33 (registry+https://github.com/rust-lang/crates.io-index)" = "2fb60433d0dc12c803b9b017b3902d80c9451bab78d27bc3210bf2a7b96593f1" "checksum webpki 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d7e664e770ac0110e2384769bcc59ed19e329d81f555916a6e072714957b81b4" "checksum webpki-roots 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a262ae37dd9d60f60dd473d1158f9fbebf110ba7b6a5051c8160460f6043718b" +"checksum websocket 0.24.0 (registry+https://github.com/rust-lang/crates.io-index)" = "413b37840b9e27b340ce91b319ede10731de8c72f5bc4cb0206ec1ca4ce581d0" +"checksum websocket-base 0.24.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5e3810f0d00c4dccb54c30a4eee815e703232819dec7b007db115791c42aa374" "checksum weedle 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3bb43f70885151e629e2a19ce9e50bd730fd436cfd4b666894c9ce4de9141164" "checksum which 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b57acb10231b9493c8472b20cb57317d0679a49e0bdbee44b3b803a6473af164" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" diff --git a/cli/tests/deploy.rs b/cli/tests/deploy.rs index 66f9bc9df..e0e799d8a 100644 --- a/cli/tests/deploy.rs +++ b/cli/tests/deploy.rs @@ -1,7 +1,7 @@ use serde_json::Value; use solana_cli::cli::{process_command, CliCommand, CliConfig}; use solana_client::rpc_client::RpcClient; -use solana_core::validator::new_validator_for_tests; +use solana_core::validator::TestValidator; use solana_faucet::faucet::run_local_faucet; use solana_sdk::{bpf_loader, pubkey::Pubkey, signature::Keypair}; use std::{ @@ -22,7 +22,13 @@ fn test_cli_deploy_program() { pathbuf.push("noop"); pathbuf.set_extension("so"); - let (server, leader_data, alice, ledger_path) = new_validator_for_tests(); + let TestValidator { + server, + leader_data, + alice, + ledger_path, + .. + } = TestValidator::run(); let (sender, receiver) = channel(); run_local_faucet(alice, sender, None); diff --git a/cli/tests/nonce.rs b/cli/tests/nonce.rs index b5efc7a36..f2386854b 100644 --- a/cli/tests/nonce.rs +++ b/cli/tests/nonce.rs @@ -1,5 +1,6 @@ use solana_cli::cli::{process_command, request_and_confirm_airdrop, CliCommand, CliConfig}; use solana_client::rpc_client::RpcClient; +use solana_core::validator::TestValidator; use solana_faucet::faucet::run_local_faucet; use solana_sdk::{ hash::Hash, @@ -10,9 +11,6 @@ use solana_sdk::{ }; use std::{fs::remove_dir_all, sync::mpsc::channel, thread::sleep, time::Duration}; -#[cfg(test)] -use solana_core::validator::new_validator_for_tests; - fn check_balance(expected_balance: u64, client: &RpcClient, pubkey: &Pubkey) { (0..5).for_each(|tries| { let balance = client.retry_get_balance(pubkey, 1).unwrap().unwrap(); @@ -28,7 +26,13 @@ fn check_balance(expected_balance: u64, client: &RpcClient, pubkey: &Pubkey) { #[test] fn test_nonce() { - let (server, leader_data, alice, ledger_path) = new_validator_for_tests(); + let TestValidator { + server, + leader_data, + alice, + ledger_path, + .. + } = TestValidator::run(); let (sender, receiver) = channel(); run_local_faucet(alice, sender, None); let faucet_addr = receiver.recv().unwrap(); @@ -44,7 +48,13 @@ fn test_nonce() { #[test] fn test_nonce_with_seed() { - let (server, leader_data, alice, ledger_path) = new_validator_for_tests(); + let TestValidator { + server, + leader_data, + alice, + ledger_path, + .. + } = TestValidator::run(); let (sender, receiver) = channel(); run_local_faucet(alice, sender, None); let faucet_addr = receiver.recv().unwrap(); @@ -66,7 +76,13 @@ fn test_nonce_with_seed() { #[test] fn test_nonce_with_authority() { - let (server, leader_data, alice, ledger_path) = new_validator_for_tests(); + let TestValidator { + server, + leader_data, + alice, + ledger_path, + .. + } = TestValidator::run(); let (sender, receiver) = channel(); run_local_faucet(alice, sender, None); let faucet_addr = receiver.recv().unwrap(); diff --git a/cli/tests/pay.rs b/cli/tests/pay.rs index 2d30c6f11..de9770991 100644 --- a/cli/tests/pay.rs +++ b/cli/tests/pay.rs @@ -6,6 +6,7 @@ use solana_cli::{ offline::{parse_sign_only_reply_string, BlockhashQuery}, }; use solana_client::rpc_client::RpcClient; +use solana_core::validator::TestValidator; use solana_faucet::faucet::run_local_faucet; use solana_sdk::{ account_utils::StateMut, @@ -16,9 +17,6 @@ use solana_sdk::{ }; use std::{fs::remove_dir_all, sync::mpsc::channel, thread::sleep, time::Duration}; -#[cfg(test)] -use solana_core::validator::new_validator_for_tests; - fn check_balance(expected_balance: u64, client: &RpcClient, pubkey: &Pubkey) { (0..5).for_each(|tries| { let balance = client.retry_get_balance(pubkey, 1).unwrap().unwrap(); @@ -34,7 +32,13 @@ fn check_balance(expected_balance: u64, client: &RpcClient, pubkey: &Pubkey) { #[test] fn test_cli_timestamp_tx() { - let (server, leader_data, alice, ledger_path) = new_validator_for_tests(); + let TestValidator { + server, + leader_data, + alice, + ledger_path, + .. + } = TestValidator::run(); let bob_pubkey = Pubkey::new_rand(); let (sender, receiver) = channel(); @@ -113,7 +117,13 @@ fn test_cli_timestamp_tx() { #[test] fn test_cli_witness_tx() { - let (server, leader_data, alice, ledger_path) = new_validator_for_tests(); + let TestValidator { + server, + leader_data, + alice, + ledger_path, + .. + } = TestValidator::run(); let bob_pubkey = Pubkey::new_rand(); let (sender, receiver) = channel(); @@ -187,7 +197,13 @@ fn test_cli_witness_tx() { #[test] fn test_cli_cancel_tx() { - let (server, leader_data, alice, ledger_path) = new_validator_for_tests(); + let TestValidator { + server, + leader_data, + alice, + ledger_path, + .. + } = TestValidator::run(); let bob_pubkey = Pubkey::new_rand(); let (sender, receiver) = channel(); @@ -255,7 +271,13 @@ fn test_cli_cancel_tx() { #[test] fn test_offline_pay_tx() { - let (server, leader_data, alice, ledger_path) = new_validator_for_tests(); + let TestValidator { + server, + leader_data, + alice, + ledger_path, + .. + } = TestValidator::run(); let bob_pubkey = Pubkey::new_rand(); let (sender, receiver) = channel(); @@ -336,7 +358,13 @@ fn test_offline_pay_tx() { fn test_nonced_pay_tx() { solana_logger::setup(); - let (server, leader_data, alice, ledger_path) = new_validator_for_tests(); + let TestValidator { + server, + leader_data, + alice, + ledger_path, + .. + } = TestValidator::run(); let (sender, receiver) = channel(); run_local_faucet(alice, sender, None); let faucet_addr = receiver.recv().unwrap(); diff --git a/cli/tests/request_airdrop.rs b/cli/tests/request_airdrop.rs index ca92a6066..a7b5614ae 100644 --- a/cli/tests/request_airdrop.rs +++ b/cli/tests/request_airdrop.rs @@ -1,13 +1,19 @@ use solana_cli::cli::{process_command, CliCommand, CliConfig}; use solana_client::rpc_client::RpcClient; -use solana_core::validator::new_validator_for_tests; +use solana_core::validator::TestValidator; use solana_faucet::faucet::run_local_faucet; use solana_sdk::signature::Keypair; use std::{fs::remove_dir_all, sync::mpsc::channel}; #[test] fn test_cli_request_airdrop() { - let (server, leader_data, alice, ledger_path) = new_validator_for_tests(); + let TestValidator { + server, + leader_data, + alice, + ledger_path, + .. + } = TestValidator::run(); let (sender, receiver) = channel(); run_local_faucet(alice, sender, None); let faucet_addr = receiver.recv().unwrap(); diff --git a/cli/tests/stake.rs b/cli/tests/stake.rs index d2de68ed8..a6f0eeffb 100644 --- a/cli/tests/stake.rs +++ b/cli/tests/stake.rs @@ -4,6 +4,7 @@ use solana_cli::{ offline::{parse_sign_only_reply_string, BlockhashQuery}, }; use solana_client::rpc_client::RpcClient; +use solana_core::validator::{TestValidator, TestValidatorOptions}; use solana_faucet::faucet::run_local_faucet; use solana_sdk::{ account_utils::StateMut, @@ -16,11 +17,6 @@ use solana_sdk::{ use solana_stake_program::stake_state::{Lockup, StakeAuthorize, StakeState}; use std::{fs::remove_dir_all, sync::mpsc::channel, thread::sleep, time::Duration}; -#[cfg(test)] -use solana_core::validator::{ - new_validator_for_tests, new_validator_for_tests_ex, new_validator_for_tests_with_vote_pubkey, -}; - fn check_balance(expected_balance: u64, client: &RpcClient, pubkey: &Pubkey) { (0..5).for_each(|tries| { let balance = client.retry_get_balance(pubkey, 1).unwrap().unwrap(); @@ -36,7 +32,13 @@ fn check_balance(expected_balance: u64, client: &RpcClient, pubkey: &Pubkey) { #[test] fn test_stake_delegation_force() { - let (server, leader_data, alice, ledger_path) = new_validator_for_tests(); + let TestValidator { + server, + leader_data, + alice, + ledger_path, + .. + } = TestValidator::run(); let (sender, receiver) = channel(); run_local_faucet(alice, sender, None); let faucet_addr = receiver.recv().unwrap(); @@ -124,8 +126,14 @@ fn test_stake_delegation_force() { fn test_seed_stake_delegation_and_deactivation() { solana_logger::setup(); - let (server, leader_data, alice, ledger_path, vote_pubkey) = - new_validator_for_tests_with_vote_pubkey(); + let TestValidator { + server, + leader_data, + alice, + ledger_path, + vote_pubkey, + .. + } = TestValidator::run(); let (sender, receiver) = channel(); run_local_faucet(alice, sender, None); let faucet_addr = receiver.recv().unwrap(); @@ -206,8 +214,14 @@ fn test_seed_stake_delegation_and_deactivation() { fn test_stake_delegation_and_deactivation() { solana_logger::setup(); - let (server, leader_data, alice, ledger_path, vote_pubkey) = - new_validator_for_tests_with_vote_pubkey(); + let TestValidator { + server, + leader_data, + alice, + ledger_path, + vote_pubkey, + .. + } = TestValidator::run(); let (sender, receiver) = channel(); run_local_faucet(alice, sender, None); let faucet_addr = receiver.recv().unwrap(); @@ -284,8 +298,14 @@ fn test_stake_delegation_and_deactivation() { fn test_offline_stake_delegation_and_deactivation() { solana_logger::setup(); - let (server, leader_data, alice, ledger_path, vote_pubkey) = - new_validator_for_tests_with_vote_pubkey(); + let TestValidator { + server, + leader_data, + alice, + ledger_path, + vote_pubkey, + .. + } = TestValidator::run(); let (sender, receiver) = channel(); run_local_faucet(alice, sender, None); let faucet_addr = receiver.recv().unwrap(); @@ -414,8 +434,14 @@ fn test_offline_stake_delegation_and_deactivation() { fn test_nonced_stake_delegation_and_deactivation() { solana_logger::setup(); - let (server, leader_data, alice, ledger_path, vote_pubkey) = - new_validator_for_tests_with_vote_pubkey(); + let TestValidator { + server, + leader_data, + alice, + ledger_path, + vote_pubkey, + .. + } = TestValidator::run(); let (sender, receiver) = channel(); run_local_faucet(alice, sender, None); let faucet_addr = receiver.recv().unwrap(); @@ -520,7 +546,13 @@ fn test_nonced_stake_delegation_and_deactivation() { fn test_stake_authorize() { solana_logger::setup(); - let (server, leader_data, alice, ledger_path) = new_validator_for_tests(); + let TestValidator { + server, + leader_data, + alice, + ledger_path, + .. + } = TestValidator::run(); let (sender, receiver) = channel(); run_local_faucet(alice, sender, None); let faucet_addr = receiver.recv().unwrap(); @@ -744,8 +776,16 @@ fn test_stake_authorize_with_fee_payer() { solana_logger::setup(); const SIG_FEE: u64 = 42; - let (server, leader_data, alice, ledger_path, _voter) = - new_validator_for_tests_ex(SIG_FEE, 42_000); + let TestValidator { + server, + leader_data, + alice, + ledger_path, + .. + } = TestValidator::run_with_options(TestValidatorOptions { + fees: SIG_FEE, + bootstrap_validator_lamports: 42_000, + }); let (sender, receiver) = channel(); run_local_faucet(alice, sender, None); let faucet_addr = receiver.recv().unwrap(); @@ -867,7 +907,16 @@ fn test_stake_authorize_with_fee_payer() { fn test_stake_split() { solana_logger::setup(); - let (server, leader_data, alice, ledger_path, _voter) = new_validator_for_tests_ex(1, 42_000); + let TestValidator { + server, + leader_data, + alice, + ledger_path, + .. + } = TestValidator::run_with_options(TestValidatorOptions { + fees: 1, + bootstrap_validator_lamports: 42_000, + }); let (sender, receiver) = channel(); run_local_faucet(alice, sender, None); let faucet_addr = receiver.recv().unwrap(); @@ -1003,7 +1052,16 @@ fn test_stake_split() { fn test_stake_set_lockup() { solana_logger::setup(); - let (server, leader_data, alice, ledger_path, _voter) = new_validator_for_tests_ex(1, 42_000); + let TestValidator { + server, + leader_data, + alice, + ledger_path, + .. + } = TestValidator::run_with_options(TestValidatorOptions { + fees: 1, + bootstrap_validator_lamports: 42_000, + }); let (sender, receiver) = channel(); run_local_faucet(alice, sender, None); let faucet_addr = receiver.recv().unwrap(); @@ -1232,7 +1290,13 @@ fn test_stake_set_lockup() { fn test_offline_nonced_create_stake_account_and_withdraw() { solana_logger::setup(); - let (server, leader_data, alice, ledger_path) = new_validator_for_tests(); + let TestValidator { + server, + leader_data, + alice, + ledger_path, + .. + } = TestValidator::run(); let (sender, receiver) = channel(); run_local_faucet(alice, sender, None); let faucet_addr = receiver.recv().unwrap(); diff --git a/cli/tests/transfer.rs b/cli/tests/transfer.rs index a276128f1..7074a773f 100644 --- a/cli/tests/transfer.rs +++ b/cli/tests/transfer.rs @@ -4,6 +4,7 @@ use solana_cli::{ offline::{parse_sign_only_reply_string, BlockhashQuery}, }; use solana_client::rpc_client::RpcClient; +use solana_core::validator::{TestValidator, TestValidatorOptions}; use solana_faucet::faucet::run_local_faucet; use solana_sdk::{ account_utils::StateMut, @@ -14,9 +15,6 @@ use solana_sdk::{ }; use std::{fs::remove_dir_all, sync::mpsc::channel, thread::sleep, time::Duration}; -#[cfg(test)] -use solana_core::validator::new_validator_for_tests_ex; - fn check_balance(expected_balance: u64, client: &RpcClient, pubkey: &Pubkey) { (0..5).for_each(|tries| { let balance = client.retry_get_balance(pubkey, 1).unwrap().unwrap(); @@ -32,7 +30,16 @@ fn check_balance(expected_balance: u64, client: &RpcClient, pubkey: &Pubkey) { #[test] fn test_transfer() { - let (server, leader_data, mint_keypair, ledger_path, _) = new_validator_for_tests_ex(1, 42_000); + let TestValidator { + server, + leader_data, + alice: mint_keypair, + ledger_path, + .. + } = TestValidator::run_with_options(TestValidatorOptions { + fees: 1, + bootstrap_validator_lamports: 42_000, + }); let (sender, receiver) = channel(); run_local_faucet(mint_keypair, sender, None); diff --git a/core/Cargo.toml b/core/Cargo.toml index 5b5590aca..a226dd1df 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -25,6 +25,7 @@ fs_extra = "1.1.0" indexmap = "1.3" itertools = "0.8.2" jsonrpc-core = "14.0.5" +jsonrpc-core-client = { version = "14.0.5", features = ["ws"] } jsonrpc-derive = "14.0.5" jsonrpc-http-server = "14.0.6" jsonrpc-pubsub = "14.0.6" diff --git a/core/src/rpc_pubsub.rs b/core/src/rpc_pubsub.rs index 3be260b72..0288b3e07 100644 --- a/core/src/rpc_pubsub.rs +++ b/core/src/rpc_pubsub.rs @@ -12,7 +12,7 @@ use std::sync::{atomic, Arc}; // https://github.com/paritytech/jsonrpc/blob/2d38e6424d8461cdf72e78425ce67d51af9c6586/derive/src/lib.rs#L204 // Once https://github.com/paritytech/jsonrpc/issues/418 is resolved, try to remove this clippy allow #[allow(clippy::needless_return)] -#[rpc(server)] +#[rpc] pub trait RpcSolPubSub { type Metadata; diff --git a/core/src/rpc_subscriptions.rs b/core/src/rpc_subscriptions.rs index 1159e0157..cc3344429 100644 --- a/core/src/rpc_subscriptions.rs +++ b/core/src/rpc_subscriptions.rs @@ -17,14 +17,16 @@ use std::thread::{Builder, JoinHandle}; use std::time::Duration; use std::{ collections::{HashMap, HashSet}, + iter, sync::{Arc, Mutex, RwLock}, }; +use tokio::runtime::{Builder as RuntimeBuilder, Runtime, TaskExecutor}; const RECEIVE_DELAY_MILLIS: u64 = 100; pub type Confirmations = usize; -#[derive(Serialize, Clone, Copy, Debug)] +#[derive(Serialize, Deserialize, Clone, Copy, Debug)] pub struct SlotInfo { pub slot: Slot, pub parent: Slot, @@ -103,19 +105,20 @@ where found } -fn check_confirmations_and_notify( +fn check_confirmations_and_notify( subscriptions: &HashMap, Confirmations)>>, hashmap_key: &K, current_slot: Slot, bank_forks: &Arc>, - bank_method: F, - notify: N, + bank_method: B, + filter_results: F, + notifier: &RpcNotifier, ) -> HashSet where K: Eq + Hash + Clone + Copy, S: Clone + Serialize, - F: Fn(&Bank, &K) -> X, - N: Fn(X, &Sink, u64) -> bool, + B: Fn(&Bank, &K) -> X, + F: Fn(X, u64) -> Box>, X: Clone + Serialize, { let current_ancestors = bank_forks @@ -149,8 +152,9 @@ where .get(desired_slot[0]) .unwrap() .clone(); - let result = bank_method(&desired_bank, hashmap_key); - if notify(result, &sink, root) { + let results = bank_method(&desired_bank, hashmap_key); + for result in filter_results(results, root) { + notifier.notify(result, sink); notified_set.insert(bank_sub_id.clone()); } } @@ -159,41 +163,49 @@ where notified_set } -fn notify_account(result: Option<(Account, Slot)>, sink: &Sink, root: Slot) -> bool { +struct RpcNotifier(TaskExecutor); + +impl RpcNotifier { + fn notify(&self, value: T, sink: &Sink) + where + T: serde::Serialize, + { + self.0 + .spawn(sink.notify(Ok(value)).map(|_| ()).map_err(|_| ())); + } +} + +fn filter_account_result( + result: Option<(Account, Slot)>, + root: Slot, +) -> Box> { if let Some((account, fork)) = result { if fork >= root { - sink.notify(Ok(RpcAccount::encode(account))).wait().unwrap(); - return true; + return Box::new(iter::once(RpcAccount::encode(account))); } } - false + Box::new(iter::empty()) } -fn notify_signature(result: Option, sink: &Sink, _root: Slot) -> bool +fn filter_signature_result(result: Option, _root: Slot) -> Box> where - S: Clone + Serialize, + S: 'static + Clone + Serialize, { - if let Some(result) = result { - sink.notify(Ok(result)).wait().unwrap(); - return true; - } - false + Box::new(result.into_iter()) } -fn notify_program( +fn filter_program_results( accounts: Vec<(Pubkey, Account)>, - sink: &Sink, _root: Slot, -) -> bool { - for (pubkey, account) in accounts.iter() { - sink.notify(Ok(RpcKeyedAccount { - pubkey: pubkey.to_string(), - account: RpcAccount::encode(account.clone()), - })) - .wait() - .unwrap(); - } - !accounts.is_empty() +) -> Box> { + Box::new( + accounts + .into_iter() + .map(|(pubkey, account)| RpcKeyedAccount { + pubkey: pubkey.to_string(), + account: RpcAccount::encode(account), + }), + ) } pub struct RpcSubscriptions { @@ -203,6 +215,7 @@ pub struct RpcSubscriptions { slot_subscriptions: Arc, notification_sender: Arc>>, t_cleanup: Option>, + notifier_runtime: Option, exit: Arc, } @@ -239,11 +252,19 @@ impl RpcSubscriptions { let signature_subscriptions_clone = signature_subscriptions.clone(); let slot_subscriptions_clone = slot_subscriptions.clone(); + let notifier_runtime = RuntimeBuilder::new() + .core_threads(1) + .name_prefix("solana-rpc-notifier-") + .build() + .unwrap(); + + let notifier = RpcNotifier(notifier_runtime.executor()); let t_cleanup = Builder::new() .name("solana-rpc-notifications".to_string()) .spawn(move || { Self::process_notifications( exit_clone, + notifier, notification_receiver, account_subscriptions_clone, program_subscriptions_clone, @@ -259,6 +280,7 @@ impl RpcSubscriptions { signature_subscriptions, slot_subscriptions, notification_sender, + notifier_runtime: Some(notifier_runtime), t_cleanup: Some(t_cleanup), exit: exit.clone(), } @@ -269,6 +291,7 @@ impl RpcSubscriptions { current_slot: Slot, bank_forks: &Arc>, account_subscriptions: Arc, + notifier: &RpcNotifier, ) { let subscriptions = account_subscriptions.read().unwrap(); check_confirmations_and_notify( @@ -277,7 +300,8 @@ impl RpcSubscriptions { current_slot, bank_forks, Bank::get_account_modified_since_parent, - notify_account, + filter_account_result, + notifier, ); } @@ -286,6 +310,7 @@ impl RpcSubscriptions { current_slot: Slot, bank_forks: &Arc>, program_subscriptions: Arc, + notifier: &RpcNotifier, ) { let subscriptions = program_subscriptions.read().unwrap(); check_confirmations_and_notify( @@ -294,7 +319,8 @@ impl RpcSubscriptions { current_slot, bank_forks, Bank::get_program_accounts_modified_since_parent, - notify_program, + filter_program_results, + notifier, ); } @@ -303,6 +329,7 @@ impl RpcSubscriptions { current_slot: Slot, bank_forks: &Arc>, signature_subscriptions: Arc, + notifier: &RpcNotifier, ) { let mut subscriptions = signature_subscriptions.write().unwrap(); let notified_ids = check_confirmations_and_notify( @@ -311,7 +338,8 @@ impl RpcSubscriptions { current_slot, bank_forks, Bank::get_signature_status, - notify_signature, + filter_signature_result, + notifier, ); if let Some(subscription_ids) = subscriptions.get_mut(signature) { subscription_ids.retain(|k, _| !notified_ids.contains(k)); @@ -408,6 +436,7 @@ impl RpcSubscriptions { fn process_notifications( exit: Arc, + notifier: RpcNotifier, notification_receiver: Receiver, account_subscriptions: Arc, program_subscriptions: Arc, @@ -423,7 +452,7 @@ impl RpcSubscriptions { NotificationEntry::Slot(slot_info) => { let subscriptions = slot_subscriptions.read().unwrap(); for (_, sink) in subscriptions.iter() { - sink.notify(Ok(slot_info)).wait().unwrap(); + notifier.notify(slot_info, sink); } } NotificationEntry::Bank((current_slot, bank_forks)) => { @@ -437,6 +466,7 @@ impl RpcSubscriptions { current_slot, &bank_forks, account_subscriptions.clone(), + ¬ifier, ); } @@ -450,6 +480,7 @@ impl RpcSubscriptions { current_slot, &bank_forks, program_subscriptions.clone(), + ¬ifier, ); } @@ -463,6 +494,7 @@ impl RpcSubscriptions { current_slot, &bank_forks, signature_subscriptions.clone(), + ¬ifier, ); } } @@ -479,6 +511,12 @@ impl RpcSubscriptions { } fn shutdown(&mut self) -> std::thread::Result<()> { + if let Some(runtime) = self.notifier_runtime.take() { + info!("RPC Notifier runtime - shutting down"); + let _ = runtime.shutdown_now().wait(); + info!("RPC Notifier runtime - shut down"); + } + if self.t_cleanup.is_some() { info!("RPC Notification thread - shutting down"); self.exit.store(true, Ordering::Relaxed); diff --git a/core/src/validator.rs b/core/src/validator.rs index 16bda05a2..1f0ffeddf 100644 --- a/core/src/validator.rs +++ b/core/src/validator.rs @@ -642,74 +642,94 @@ fn wait_for_supermajority( } } -pub fn new_validator_for_tests() -> (Validator, ContactInfo, Keypair, PathBuf) { - let (node, contact_info, mint_keypair, ledger_path, _vote_pubkey) = - new_validator_for_tests_with_vote_pubkey(); - (node, contact_info, mint_keypair, ledger_path) +pub struct TestValidator { + pub server: Validator, + pub leader_data: ContactInfo, + pub alice: Keypair, + pub ledger_path: PathBuf, + pub genesis_hash: Hash, + pub vote_pubkey: Pubkey, } -pub fn new_validator_for_tests_with_vote_pubkey( -) -> (Validator, ContactInfo, Keypair, PathBuf, Pubkey) { - use crate::genesis_utils::BOOTSTRAP_VALIDATOR_LAMPORTS; - new_validator_for_tests_ex(0, BOOTSTRAP_VALIDATOR_LAMPORTS) +pub struct TestValidatorOptions { + pub fees: u64, + pub bootstrap_validator_lamports: u64, } -pub fn new_validator_for_tests_ex( - fees: u64, - bootstrap_validator_lamports: u64, -) -> (Validator, ContactInfo, Keypair, PathBuf, Pubkey) { - use crate::genesis_utils::{create_genesis_config_with_leader_ex, GenesisConfigInfo}; - use solana_sdk::fee_calculator::FeeCalculator; +impl Default for TestValidatorOptions { + fn default() -> Self { + use crate::genesis_utils::BOOTSTRAP_VALIDATOR_LAMPORTS; + TestValidatorOptions { + fees: 0, + bootstrap_validator_lamports: BOOTSTRAP_VALIDATOR_LAMPORTS, + } + } +} - let node_keypair = Arc::new(Keypair::new()); - let node = Node::new_localhost_with_pubkey(&node_keypair.pubkey()); - let contact_info = node.info.clone(); +impl TestValidator { + pub fn run() -> Self { + Self::run_with_options(TestValidatorOptions::default()) + } - let GenesisConfigInfo { - mut genesis_config, - mint_keypair, - voting_keypair, - } = create_genesis_config_with_leader_ex( - 1_000_000, - &contact_info.id, - 42, - bootstrap_validator_lamports, - ); - genesis_config - .native_instruction_processors - .push(solana_budget_program!()); + pub fn run_with_options(options: TestValidatorOptions) -> Self { + use crate::genesis_utils::{create_genesis_config_with_leader_ex, GenesisConfigInfo}; + use solana_sdk::fee_calculator::FeeCalculator; - genesis_config.rent.lamports_per_byte_year = 1; - genesis_config.rent.exemption_threshold = 1.0; - genesis_config.fee_calculator = FeeCalculator::new(fees, 0); + let TestValidatorOptions { + fees, + bootstrap_validator_lamports, + } = options; + let node_keypair = Arc::new(Keypair::new()); + let node = Node::new_localhost_with_pubkey(&node_keypair.pubkey()); + let contact_info = node.info.clone(); - let (ledger_path, _blockhash) = create_new_tmp_ledger!(&genesis_config); + let GenesisConfigInfo { + mut genesis_config, + mint_keypair, + voting_keypair, + } = create_genesis_config_with_leader_ex( + 1_000_000, + &contact_info.id, + 42, + bootstrap_validator_lamports, + ); + genesis_config + .native_instruction_processors + .push(solana_budget_program!()); - let leader_voting_keypair = Arc::new(voting_keypair); - let storage_keypair = Arc::new(Keypair::new()); - let config = ValidatorConfig { - rpc_ports: Some((node.info.rpc.port(), node.info.rpc_pubsub.port())), - ..ValidatorConfig::default() - }; - let node = Validator::new( - node, - &node_keypair, - &ledger_path, - &leader_voting_keypair.pubkey(), - &leader_voting_keypair, - &storage_keypair, - None, - true, - &config, - ); - discover_cluster(&contact_info.gossip, 1).expect("Node startup failed"); - ( - node, - contact_info, - mint_keypair, - ledger_path, - leader_voting_keypair.pubkey(), - ) + genesis_config.rent.lamports_per_byte_year = 1; + genesis_config.rent.exemption_threshold = 1.0; + genesis_config.fee_calculator = FeeCalculator::new(fees, 0); + + let (ledger_path, blockhash) = create_new_tmp_ledger!(&genesis_config); + + let leader_voting_keypair = Arc::new(voting_keypair); + let storage_keypair = Arc::new(Keypair::new()); + let config = ValidatorConfig { + rpc_ports: Some((node.info.rpc.port(), node.info.rpc_pubsub.port())), + ..ValidatorConfig::default() + }; + let node = Validator::new( + node, + &node_keypair, + &ledger_path, + &leader_voting_keypair.pubkey(), + &leader_voting_keypair, + &storage_keypair, + None, + true, + &config, + ); + discover_cluster(&contact_info.gossip, 1).expect("Node startup failed"); + TestValidator { + server: node, + leader_data: contact_info, + alice: mint_keypair, + ledger_path, + genesis_hash: blockhash, + vote_pubkey: leader_voting_keypair.pubkey(), + } + } } fn report_target_features() { diff --git a/core/tests/client.rs b/core/tests/client.rs index 4ecfdd1d4..be06e8421 100644 --- a/core/tests/client.rs +++ b/core/tests/client.rs @@ -4,7 +4,7 @@ use solana_client::{ }; use solana_core::{ rpc_pubsub_service::PubSubService, rpc_subscriptions::RpcSubscriptions, - validator::new_validator_for_tests, + validator::TestValidator, }; use solana_sdk::{ commitment_config::CommitmentConfig, pubkey::Pubkey, rpc_port, signature::Signer, @@ -26,7 +26,13 @@ use systemstat::Ipv4Addr; fn test_rpc_client() { solana_logger::setup(); - let (server, leader_data, alice, ledger_path) = new_validator_for_tests(); + let TestValidator { + server, + leader_data, + alice, + ledger_path, + .. + } = TestValidator::run(); let bob_pubkey = Pubkey::new_rand(); let client = RpcClient::new_socket(leader_data.rpc); diff --git a/core/tests/rpc.rs b/core/tests/rpc.rs index 8617605a7..8c51a6c02 100644 --- a/core/tests/rpc.rs +++ b/core/tests/rpc.rs @@ -1,21 +1,38 @@ use bincode::serialize; +use jsonrpc_core::futures::{ + future::{self, Future}, + stream::Stream, +}; +use jsonrpc_core_client::transports::ws; use log::*; use reqwest::{self, header::CONTENT_TYPE}; use serde_json::{json, Value}; use solana_client::rpc_client::get_rpc_request_str; -use solana_core::validator::new_validator_for_tests; -use solana_sdk::hash::Hash; -use solana_sdk::pubkey::Pubkey; -use solana_sdk::system_transaction; -use std::fs::remove_dir_all; -use std::thread::sleep; -use std::time::Duration; +use solana_core::{rpc_pubsub::gen_client::Client as PubsubClient, validator::TestValidator}; +use solana_sdk::{hash::Hash, pubkey::Pubkey, system_transaction, transaction}; +use std::{ + collections::HashSet, + fs::remove_dir_all, + net::UdpSocket, + sync::mpsc::channel, + sync::{Arc, Mutex}, + thread::sleep, + time::Duration, + time::SystemTime, +}; +use tokio::runtime::Runtime; #[test] fn test_rpc_send_tx() { solana_logger::setup(); - let (server, leader_data, alice, ledger_path) = new_validator_for_tests(); + let TestValidator { + server, + leader_data, + alice, + ledger_path, + .. + } = TestValidator::run(); let bob_pubkey = Pubkey::new_rand(); let client = reqwest::blocking::Client::new(); @@ -100,7 +117,12 @@ fn test_rpc_send_tx() { fn test_rpc_invalid_requests() { solana_logger::setup(); - let (server, leader_data, _alice, ledger_path) = new_validator_for_tests(); + let TestValidator { + server, + leader_data, + ledger_path, + .. + } = TestValidator::run(); let bob_pubkey = Pubkey::new_rand(); // test invalid get_balance request @@ -166,3 +188,82 @@ fn test_rpc_invalid_requests() { server.close().unwrap(); remove_dir_all(ledger_path).unwrap(); } + +#[test] +fn test_rpc_subscriptions() { + solana_logger::setup(); + + let TestValidator { + server, + leader_data, + alice, + ledger_path, + genesis_hash, + .. + } = TestValidator::run(); + + // Create transaction signatures to subscribe to + let transactions_socket = UdpSocket::bind("0.0.0.0:0").unwrap(); + let mut signature_set: HashSet = (0..1000) + .map(|_| { + let tx = system_transaction::transfer(&alice, &Pubkey::new_rand(), 1, genesis_hash); + transactions_socket + .send_to(&bincode::serialize(&tx).unwrap(), leader_data.tpu) + .unwrap(); + tx.signatures[0].to_string() + }) + .collect(); + + // Create the pub sub runtime + let mut rt = Runtime::new().unwrap(); + let rpc_pubsub_url = format!("ws://{}/", leader_data.rpc_pubsub); + let (sender, receiver) = channel::<(String, transaction::Result<()>)>(); + let sender = Arc::new(Mutex::new(sender)); + + rt.spawn({ + let connect = ws::try_connect::(&rpc_pubsub_url).unwrap(); + let signature_set = signature_set.clone(); + connect + .and_then(move |client| { + for sig in signature_set { + let sender = sender.clone(); + tokio::spawn( + client + .signature_subscribe(sig.clone(), None) + .and_then(move |sig_stream| { + sig_stream.for_each(move |result| { + sender.lock().unwrap().send((sig.clone(), result)).unwrap(); + future::ok(()) + }) + }) + .map_err(|err| { + eprintln!("sig sub err: {:#?}", err); + }), + ); + } + future::ok(()) + }) + .map_err(|_| ()) + }); + + // Wait for all signature subscriptions + let now = SystemTime::now(); + let timeout = Duration::from_secs(5); + while !signature_set.is_empty() { + assert!(now.elapsed().unwrap() < timeout); + match receiver.recv_timeout(Duration::from_secs(1)) { + Ok((sig, result)) => { + assert!(result.is_ok()); + assert!(signature_set.remove(&sig)); + } + Err(_err) => { + eprintln!("unexpected receive timeout"); + assert!(false) + } + } + } + + rt.shutdown_now().wait().unwrap(); + server.close().unwrap(); + remove_dir_all(ledger_path).unwrap(); +}