diff --git a/Cargo.lock b/Cargo.lock index 2122467..e81682a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -24,7 +24,7 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877" dependencies = [ - "generic-array", + "generic-array 0.14.6", ] [[package]] @@ -36,7 +36,7 @@ dependencies = [ "cfg-if 1.0.0", "cipher 0.3.0", "cpufeatures", - "opaque-debug", + "opaque-debug 0.3.0", ] [[package]] @@ -62,7 +62,7 @@ checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" dependencies = [ "getrandom 0.2.8", "once_cell", - "version_check", + "version_check 0.9.4", ] [[package]] @@ -73,7 +73,7 @@ checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" dependencies = [ "cfg-if 1.0.0", "once_cell", - "version_check", + "version_check 0.9.4", ] [[package]] @@ -457,6 +457,17 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" +[[package]] +name = "async-channel" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf46fee83e5ccffc220104713af3292ff9bc7c64c7de289f66dae8e38d826833" +dependencies = [ + "concurrent-queue", + "event-listener", + "futures-core", +] + [[package]] name = "async-compression" version = "0.3.15" @@ -464,7 +475,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "942c7cd7ae39e91bde4820d74132e9862e62c2f386c3aa90ccf55949f5bad63a" dependencies = [ "brotli", - "flate2", + "flate2 1.0.25", "futures-core", "memchr", "pin-project-lite", @@ -523,6 +534,15 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "autocfg" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dde43e75fd43e8a1bf86103336bc699aa8d17ad1be60c76c0bdfd4828e19b78" +dependencies = [ + "autocfg 1.1.0", +] + [[package]] name = "autocfg" version = "1.1.0" @@ -547,15 +567,15 @@ dependencies = [ "async-trait", "axum-core", "bitflags", - "bytes", + "bytes 1.4.0", "futures-util", "http", "http-body", - "hyper", + "hyper 0.14.24", "itoa", "matchit", "memchr", - "mime", + "mime 0.3.16", "percent-encoding 2.2.0", "pin-project-lite", "rustversion", @@ -574,11 +594,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1cae3e661676ffbacb30f1a824089a8c9150e71017f7e1e38f2aa32009188d34" dependencies = [ "async-trait", - "bytes", + "bytes 1.4.0", "futures-util", "http", "http-body", - "mime", + "mime 0.3.16", "rustversion", "tower-layer", "tower-service", @@ -604,6 +624,25 @@ dependencies = [ "tokio", ] +[[package]] +name = "base64" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" +dependencies = [ + "byteorder", + "safemem", +] + +[[package]] +name = "base64" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" +dependencies = [ + "byteorder", +] + [[package]] name = "base64" version = "0.12.3" @@ -686,14 +725,26 @@ dependencies = [ "digest 0.10.6", ] +[[package]] +name = "block-buffer" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" +dependencies = [ + "block-padding 0.1.5", + "byte-tools", + "byteorder", + "generic-array 0.12.4", +] + [[package]] name = "block-buffer" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" dependencies = [ - "block-padding", - "generic-array", + "block-padding 0.2.1", + "generic-array 0.14.6", ] [[package]] @@ -702,7 +753,16 @@ version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" dependencies = [ - "generic-array", + "generic-array 0.14.6", +] + +[[package]] +name = "block-padding" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" +dependencies = [ + "byte-tools", ] [[package]] @@ -844,6 +904,16 @@ dependencies = [ "serde", ] +[[package]] +name = "buf_redux" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b953a6887648bb07a535631f2bc00fbdb2a2216f135552cb3f534ed136b9c07f" +dependencies = [ + "memchr", + "safemem", +] + [[package]] name = "bumpalo" version = "3.12.0" @@ -860,6 +930,12 @@ dependencies = [ "serde", ] +[[package]] +name = "byte-tools" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" + [[package]] name = "bytecheck" version = "0.6.9" @@ -907,6 +983,16 @@ version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +[[package]] +name = "bytes" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" +dependencies = [ + "byteorder", + "iovec", +] + [[package]] name = "bytes" version = "1.4.0" @@ -1005,7 +1091,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" dependencies = [ - "generic-array", + "generic-array 0.14.6", ] [[package]] @@ -1069,6 +1155,15 @@ dependencies = [ "os_str_bytes", ] +[[package]] +name = "cloudabi" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +dependencies = [ + "bitflags", +] + [[package]] name = "codespan-reporting" version = "0.11.1" @@ -1092,6 +1187,15 @@ dependencies = [ "unreachable", ] +[[package]] +name = "concurrent-queue" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c278839b831783b70278b14df4d45e1beb1aad306c07bb796637de9a0e323e8e" +dependencies = [ + "crossbeam-utils 0.8.14", +] + [[package]] name = "console" version = "0.15.5" @@ -1121,7 +1225,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "501a375961cef1a0d44767200e66e4a559283097e91d0730b1d75dfb2f8a1494" dependencies = [ - "log", + "log 0.4.17", "web-sys", ] @@ -1202,7 +1306,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" dependencies = [ "cfg-if 1.0.0", - "crossbeam-utils", + "crossbeam-utils 0.8.14", ] [[package]] @@ -1213,7 +1317,7 @@ checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" dependencies = [ "cfg-if 1.0.0", "crossbeam-epoch", - "crossbeam-utils", + "crossbeam-utils 0.8.14", ] [[package]] @@ -1222,13 +1326,24 @@ version = "0.9.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a" dependencies = [ - "autocfg", + "autocfg 1.1.0", "cfg-if 1.0.0", - "crossbeam-utils", + "crossbeam-utils 0.8.14", "memoffset 0.7.1", "scopeguard", ] +[[package]] +name = "crossbeam-utils" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" +dependencies = [ + "autocfg 1.1.0", + "cfg-if 0.1.10", + "lazy_static", +] + [[package]] name = "crossbeam-utils" version = "0.8.14" @@ -1250,7 +1365,7 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ - "generic-array", + "generic-array 0.14.6", "typenum", ] @@ -1260,7 +1375,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" dependencies = [ - "generic-array", + "generic-array 0.14.6", "subtle", ] @@ -1469,13 +1584,22 @@ dependencies = [ "zeroize", ] +[[package]] +name = "digest" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" +dependencies = [ + "generic-array 0.12.4", +] + [[package]] name = "digest" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" dependencies = [ - "generic-array", + "generic-array 0.14.6", ] [[package]] @@ -1675,7 +1799,7 @@ checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7" dependencies = [ "atty", "humantime", - "log", + "log 0.4.17", "regex", "termcolor", ] @@ -1701,6 +1825,12 @@ version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" +[[package]] +name = "fake-simd" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" + [[package]] name = "fast-math" version = "0.1.1" @@ -1801,6 +1931,16 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" +[[package]] +name = "flate2" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6234dd4468ae5d1e2dbb06fe2b058696fdc50a339c68a393aefbf00bc81e423" +dependencies = [ + "libc", + "miniz-sys", +] + [[package]] name = "flate2" version = "1.0.25" @@ -1853,6 +1993,22 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" +[[package]] +name = "fuchsia-zircon" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" +dependencies = [ + "bitflags", + "fuchsia-zircon-sys", +] + +[[package]] +name = "fuchsia-zircon-sys" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" + [[package]] name = "futures" version = "0.1.31" @@ -1950,6 +2106,15 @@ dependencies = [ "slab", ] +[[package]] +name = "generic-array" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" +dependencies = [ + "typenum", +] + [[package]] name = "generic-array" version = "0.14.6" @@ -1958,7 +2123,7 @@ checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" dependencies = [ "serde", "typenum", - "version_check", + "version_check 0.9.4", ] [[package]] @@ -2012,7 +2177,7 @@ dependencies = [ "aho-corasick", "bstr", "fnv", - "log", + "log 0.4.17", "regex", ] @@ -2024,7 +2189,7 @@ checksum = "f8af59a261bcf42f45d1b261232847b9b850ba0a1419d6100698246fb66e9240" dependencies = [ "arc-swap", "futures 0.3.26", - "log", + "log 0.4.17", "reqwest", "serde", "serde_derive", @@ -2041,7 +2206,7 @@ version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7666983ed0dd8d21a6f6576ee00053ca0926fb281a5522577a4dbd0f1b54143" dependencies = [ - "log", + "log 0.4.17", "plain", "scroll", ] @@ -2052,7 +2217,7 @@ version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f9f29bc9dda355256b2916cf526ab02ce0aeaaaf2bad60d65ef3f12f11dd0f4" dependencies = [ - "bytes", + "bytes 1.4.0", "fnv", "futures-core", "futures-sink", @@ -2115,11 +2280,11 @@ checksum = "f3e372db8e5c0d213e0cd0b9be18be2aca3d44cf2fe30a9d46a65581cd454584" dependencies = [ "base64 0.13.1", "bitflags", - "bytes", + "bytes 1.4.0", "headers-core", "http", "httpdate", - "mime", + "mime 0.3.16", "sha1", ] @@ -2197,7 +2362,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17ea0a1394df5b6574da6e0c1ade9e78868c9fb0a4e5ef4428e32da4676b85b1" dependencies = [ "digest 0.9.0", - "generic-array", + "generic-array 0.14.6", "hmac 0.8.1", ] @@ -2207,7 +2372,7 @@ version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" dependencies = [ - "bytes", + "bytes 1.4.0", "fnv", "itoa", ] @@ -2218,7 +2383,7 @@ version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" dependencies = [ - "bytes", + "bytes 1.4.0", "http", "pin-project-lite", ] @@ -2247,13 +2412,32 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +[[package]] +name = "hyper" +version = "0.10.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a0652d9a2609a968c14be1a9ea00bf4b1d64e2e1f53a1b51b6fff3a6e829273" +dependencies = [ + "base64 0.9.3", + "httparse", + "language-tags", + "log 0.3.9", + "mime 0.2.6", + "num_cpus", + "time 0.1.45", + "traitobject", + "typeable", + "unicase 1.4.2", + "url 1.7.2", +] + [[package]] name = "hyper" version = "0.14.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e011372fa0b68db8350aa7a248930ecc7839bf46d8485577d69f117a75f164c" dependencies = [ - "bytes", + "bytes 1.4.0", "futures-channel", "futures-core", "futures-util", @@ -2277,11 +2461,11 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca815a891b24fdfb243fa3239c86154392b0953ee584aa1a2a1f66d20cbe75cc" dependencies = [ - "bytes", + "bytes 1.4.0", "futures 0.3.26", "headers", "http", - "hyper", + "hyper 0.14.24", "hyper-tls", "native-tls", "tokio", @@ -2296,7 +2480,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1788965e61b367cd03a62950836d5cd41560c3577d90e40e0819373194d1661c" dependencies = [ "http", - "hyper", + "hyper 0.14.24", "rustls 0.20.8", "tokio", "tokio-rustls 0.23.4", @@ -2308,7 +2492,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" dependencies = [ - "hyper", + "hyper 0.14.24", "pin-project-lite", "tokio", "tokio-io-timeout", @@ -2320,8 +2504,8 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" dependencies = [ - "bytes", - "hyper", + "bytes 1.4.0", + "hyper 0.14.24", "native-tls", "tokio", "tokio-native-tls", @@ -2397,7 +2581,7 @@ dependencies = [ "serde", "sized-chunks", "typenum", - "version_check", + "version_check 0.9.4", ] [[package]] @@ -2412,7 +2596,7 @@ version = "1.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" dependencies = [ - "autocfg", + "autocfg 1.1.0", "hashbrown 0.12.3", "rayon", ] @@ -2435,7 +2619,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" dependencies = [ - "generic-array", + "generic-array 0.14.6", ] [[package]] @@ -2447,6 +2631,15 @@ dependencies = [ "cfg-if 1.0.0", ] +[[package]] +name = "iovec" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" +dependencies = [ + "libc", +] + [[package]] name = "ipnet" version = "2.7.1" @@ -2509,17 +2702,19 @@ dependencies = [ [[package]] name = "jsonrpc-client-transports" version = "18.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2b99d4207e2a04fb4581746903c2bb7eb376f88de9c699d0f3e10feeac0cd3a" +source = "git+https://github.com/ckamm/jsonrpc.git?branch=ckamm/http-with-gzip#3e83f454313b218a75be25d3d4cfc2c4e76bb8bd" dependencies = [ "derive_more", + "flate2 0.2.20", "futures 0.3.26", - "jsonrpc-core", - "jsonrpc-pubsub", - "log", + "hyper 0.14.24", + "jsonrpc-core 18.0.0 (git+https://github.com/ckamm/jsonrpc.git?branch=ckamm/http-with-gzip)", + "jsonrpc-pubsub 18.0.0 (git+https://github.com/ckamm/jsonrpc.git?branch=ckamm/http-with-gzip)", + "log 0.4.17", "serde", "serde_json", - "url 1.7.2", + "tokio", + "websocket", ] [[package]] @@ -2531,7 +2726,21 @@ dependencies = [ "futures 0.3.26", "futures-executor", "futures-util", - "log", + "log 0.4.17", + "serde", + "serde_derive", + "serde_json", +] + +[[package]] +name = "jsonrpc-core" +version = "18.0.0" +source = "git+https://github.com/ckamm/jsonrpc.git?branch=ckamm/http-with-gzip#3e83f454313b218a75be25d3d4cfc2c4e76bb8bd" +dependencies = [ + "futures 0.3.26", + "futures-executor", + "futures-util", + "log 0.4.17", "serde", "serde_derive", "serde_json", @@ -2540,8 +2749,7 @@ dependencies = [ [[package]] name = "jsonrpc-core-client" version = "18.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b51da17abecbdab3e3d4f26b01c5ec075e88d3abe3ab3b05dc9aa69392764ec0" +source = "git+https://github.com/ckamm/jsonrpc.git?branch=ckamm/http-with-gzip#3e83f454313b218a75be25d3d4cfc2c4e76bb8bd" dependencies = [ "futures 0.3.26", "jsonrpc-client-transports", @@ -2566,13 +2774,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1dea6e07251d9ce6a552abfb5d7ad6bc290a4596c8dcc3d795fae2bbdc1f3ff" dependencies = [ "futures 0.3.26", - "hyper", - "jsonrpc-core", + "hyper 0.14.24", + "jsonrpc-core 18.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-server-utils", - "log", + "log 0.4.17", "net2", "parking_lot 0.11.2", - "unicase", + "unicase 2.6.0", ] [[package]] @@ -2582,9 +2790,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240f87695e6c6f62fb37f05c02c04953cf68d6408b8c1c89de85c7a0125b1011" dependencies = [ "futures 0.3.26", - "jsonrpc-core", + "jsonrpc-core 18.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static", - "log", + "log 0.4.17", + "parking_lot 0.11.2", + "rand 0.7.3", + "serde", +] + +[[package]] +name = "jsonrpc-pubsub" +version = "18.0.0" +source = "git+https://github.com/ckamm/jsonrpc.git?branch=ckamm/http-with-gzip#3e83f454313b218a75be25d3d4cfc2c4e76bb8bd" +dependencies = [ + "futures 0.3.26", + "jsonrpc-core 18.0.0 (git+https://github.com/ckamm/jsonrpc.git?branch=ckamm/http-with-gzip)", + "lazy_static", + "log 0.4.17", "parking_lot 0.11.2", "rand 0.7.3", "serde", @@ -2596,16 +2818,16 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa4fdea130485b572c39a460d50888beb00afb3e35de23ccd7fad8ff19f0e0d4" dependencies = [ - "bytes", + "bytes 1.4.0", "futures 0.3.26", "globset", - "jsonrpc-core", + "jsonrpc-core 18.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static", - "log", + "log 0.4.17", "tokio", "tokio-stream", "tokio-util 0.6.10", - "unicase", + "unicase 2.6.0", ] [[package]] @@ -2627,6 +2849,12 @@ dependencies = [ "winapi-build", ] +[[package]] +name = "language-tags" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" + [[package]] name = "lazy_static" version = "1.4.0" @@ -2749,16 +2977,34 @@ version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" +[[package]] +name = "lock_api" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75" +dependencies = [ + "scopeguard", +] + [[package]] name = "lock_api" version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" dependencies = [ - "autocfg", + "autocfg 1.1.0", "scopeguard", ] +[[package]] +name = "log" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" +dependencies = [ + "log 0.4.17", +] + [[package]] name = "log" version = "0.4.17" @@ -2896,7 +3142,7 @@ version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" dependencies = [ - "autocfg", + "autocfg 1.1.0", ] [[package]] @@ -2905,7 +3151,7 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" dependencies = [ - "autocfg", + "autocfg 1.1.0", ] [[package]] @@ -2914,7 +3160,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" dependencies = [ - "autocfg", + "autocfg 1.1.0", ] [[package]] @@ -2929,12 +3175,31 @@ dependencies = [ "zeroize", ] +[[package]] +name = "mime" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0" +dependencies = [ + "log 0.3.9", +] + [[package]] name = "mime" version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" +[[package]] +name = "mime_guess" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" +dependencies = [ + "mime 0.3.16", + "unicase 2.6.0", +] + [[package]] name = "min-max-heap" version = "1.3.0" @@ -2947,6 +3212,16 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" +[[package]] +name = "miniz-sys" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9e3ae51cea1576ceba0dde3d484d30e6e5b86dee0b2d412fe3a16a15c98202" +dependencies = [ + "cc", + "libc", +] + [[package]] name = "miniz_oxide" version = "0.6.2" @@ -2956,6 +3231,25 @@ dependencies = [ "adler", ] +[[package]] +name = "mio" +version = "0.6.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4" +dependencies = [ + "cfg-if 0.1.10", + "fuchsia-zircon", + "fuchsia-zircon-sys", + "iovec", + "kernel32-sys", + "libc", + "log 0.4.17", + "miow 0.2.2", + "net2", + "slab", + "winapi 0.2.8", +] + [[package]] name = "mio" version = "0.7.14" @@ -2963,12 +3257,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc" dependencies = [ "libc", - "log", - "miow", + "log 0.4.17", + "miow 0.3.7", "ntapi", "winapi 0.3.9", ] +[[package]] +name = "miow" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d" +dependencies = [ + "kernel32-sys", + "net2", + "winapi 0.2.8", + "ws2_32-sys", +] + [[package]] name = "miow" version = "0.3.7" @@ -3005,6 +3311,24 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" +[[package]] +name = "multipart" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00dec633863867f29cb39df64a397cdf4a6354708ddd7759f70c7fb51c5f9182" +dependencies = [ + "buf_redux", + "httparse", + "log 0.4.17", + "mime 0.3.16", + "mime_guess", + "quick-error", + "rand 0.8.5", + "safemem", + "tempfile", + "twoway", +] + [[package]] name = "multiqueue" version = "0.3.2" @@ -3026,7 +3350,7 @@ checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" dependencies = [ "lazy_static", "libc", - "log", + "log 0.4.17", "openssl", "openssl-probe", "openssl-sys", @@ -3053,7 +3377,7 @@ version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f346ff70e7dbfd675fe90590b92d59ef2de15a8779ae305ebcbfd3f0caf59be4" dependencies = [ - "autocfg", + "autocfg 1.1.0", "bitflags", "cfg-if 1.0.0", "libc", @@ -3109,7 +3433,7 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304" dependencies = [ - "autocfg", + "autocfg 1.1.0", "num-integer", "num-traits", ] @@ -3120,7 +3444,7 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" dependencies = [ - "autocfg", + "autocfg 1.1.0", "num-integer", "num-traits", ] @@ -3131,7 +3455,7 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6b19411a9719e753aff12e5187b74d60d3dc449ec3f4dc21e3989c3f554bc95" dependencies = [ - "autocfg", + "autocfg 1.1.0", "num-traits", ] @@ -3152,7 +3476,7 @@ version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" dependencies = [ - "autocfg", + "autocfg 1.1.0", "num-traits", ] @@ -3162,7 +3486,7 @@ version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" dependencies = [ - "autocfg", + "autocfg 1.1.0", "num-integer", "num-traits", ] @@ -3173,7 +3497,7 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef" dependencies = [ - "autocfg", + "autocfg 1.1.0", "num-bigint 0.2.6", "num-integer", "num-traits", @@ -3185,7 +3509,7 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" dependencies = [ - "autocfg", + "autocfg 1.1.0", ] [[package]] @@ -3240,6 +3564,12 @@ version = "1.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" +[[package]] +name = "opaque-debug" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" + [[package]] name = "opaque-debug" version = "0.3.0" @@ -3293,7 +3623,7 @@ version = "0.9.80" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23bbbf7854cd45b83958ebe919f0e8e516793727652e27fda10a8384cfc790b7" dependencies = [ - "autocfg", + "autocfg 1.1.0", "cc", "libc", "openssl-src", @@ -3347,6 +3677,17 @@ dependencies = [ "thread-id", ] +[[package]] +name = "parking_lot" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" +dependencies = [ + "lock_api 0.3.4", + "parking_lot_core 0.6.3", + "rustc_version 0.2.3", +] + [[package]] name = "parking_lot" version = "0.11.2" @@ -3354,7 +3695,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" dependencies = [ "instant", - "lock_api", + "lock_api 0.4.9", "parking_lot_core 0.8.6", ] @@ -3364,7 +3705,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ - "lock_api", + "lock_api 0.4.9", "parking_lot_core 0.9.7", ] @@ -3380,6 +3721,21 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "parking_lot_core" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66b810a62be75176a80873726630147a5ca780cd33921e0b5709033e66b0a" +dependencies = [ + "cfg-if 0.1.10", + "cloudabi", + "libc", + "redox_syscall 0.1.57", + "rustc_version 0.2.3", + "smallvec 0.6.14", + "winapi 0.3.9", +] + [[package]] name = "parking_lot_core" version = "0.8.6" @@ -3584,7 +3940,7 @@ checksum = "8419d2b623c7c0896ff2d5d96e2cb4ede590fed28fcc34934f4c33c036e620a1" dependencies = [ "cfg-if 1.0.0", "cpufeatures", - "opaque-debug", + "opaque-debug 0.3.0", "universal-hash", ] @@ -3639,7 +3995,7 @@ dependencies = [ "proc-macro2 1.0.51", "quote 1.0.23", "syn 1.0.107", - "version_check", + "version_check 0.9.4", ] [[package]] @@ -3650,7 +4006,7 @@ checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ "proc-macro2 1.0.51", "quote 1.0.23", - "version_check", + "version_check 0.9.4", ] [[package]] @@ -3680,7 +4036,7 @@ dependencies = [ "proc-macro2 1.0.51", "quote 1.0.23", "syn 1.0.107", - "version_check", + "version_check 0.9.4", "yansi", ] @@ -3690,7 +4046,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "444879275cb4fd84958b1a1d5420d15e6fcf7c235fe47f053c9c2a80aceb6001" dependencies = [ - "bytes", + "bytes 1.4.0", "prost-derive 0.9.0", ] @@ -3700,7 +4056,7 @@ version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21dc42e00223fc37204bd4aa177e69420c604ca4a183209a8f9de30c6d934698" dependencies = [ - "bytes", + "bytes 1.4.0", "prost-derive 0.11.6", ] @@ -3710,11 +4066,11 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62941722fb675d463659e49c4f3fe1fe792ff24fe5bbaa9c08cd3b98a1c354f5" dependencies = [ - "bytes", + "bytes 1.4.0", "heck 0.3.3", "itertools 0.10.5", "lazy_static", - "log", + "log 0.4.17", "multimap", "petgraph", "prost 0.9.0", @@ -3730,11 +4086,11 @@ version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3f8ad728fb08fe212df3c05169e940fbb6d9d16a877ddde14644a983ba2012e" dependencies = [ - "bytes", + "bytes 1.4.0", "heck 0.4.1", "itertools 0.10.5", "lazy_static", - "log", + "log 0.4.17", "multimap", "petgraph", "prettyplease", @@ -3778,7 +4134,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "534b7a0e836e3c482d2693070f982e39e7611da9695d4d1f5a4b186b51faef0a" dependencies = [ - "bytes", + "bytes 1.4.0", "prost 0.9.0", ] @@ -3788,7 +4144,7 @@ version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a5e0526209433e96d83d750dd81a99118edbc55739e7e61a46764fd2ad537788" dependencies = [ - "bytes", + "bytes 1.4.0", "prost 0.11.6", ] @@ -3846,6 +4202,12 @@ dependencies = [ "percent-encoding 2.2.0", ] +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + [[package]] name = "quick-protobuf" version = "0.8.0" @@ -3861,7 +4223,7 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "445cbfe2382fa023c4f2f3c7e1c95c03dcc1df2bf23cebcb2b13e1402c4394d1" dependencies = [ - "bytes", + "bytes 1.4.0", "pin-project-lite", "quinn-proto", "quinn-udp", @@ -3879,7 +4241,7 @@ version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72ef4ced82a24bb281af338b9e8f94429b6eca01b4e66d899f40031f074e74c9" dependencies = [ - "bytes", + "bytes 1.4.0", "rand 0.8.5", "ring", "rustc-hash", @@ -3936,6 +4298,25 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "rand" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" +dependencies = [ + "autocfg 0.1.8", + "libc", + "rand_chacha 0.1.1", + "rand_core 0.4.2", + "rand_hc 0.1.0", + "rand_isaac", + "rand_jitter", + "rand_os", + "rand_pcg", + "rand_xorshift", + "winapi 0.3.9", +] + [[package]] name = "rand" version = "0.7.3" @@ -3946,7 +4327,7 @@ dependencies = [ "libc", "rand_chacha 0.2.2", "rand_core 0.5.1", - "rand_hc", + "rand_hc 0.2.0", ] [[package]] @@ -3960,6 +4341,16 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "rand_chacha" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" +dependencies = [ + "autocfg 0.1.8", + "rand_core 0.3.1", +] + [[package]] name = "rand_chacha" version = "0.2.2" @@ -4013,6 +4404,15 @@ dependencies = [ "getrandom 0.2.8", ] +[[package]] +name = "rand_hc" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" +dependencies = [ + "rand_core 0.3.1", +] + [[package]] name = "rand_hc" version = "0.2.0" @@ -4022,6 +4422,59 @@ dependencies = [ "rand_core 0.5.1", ] +[[package]] +name = "rand_isaac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" +dependencies = [ + "rand_core 0.3.1", +] + +[[package]] +name = "rand_jitter" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" +dependencies = [ + "libc", + "rand_core 0.4.2", + "winapi 0.3.9", +] + +[[package]] +name = "rand_os" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" +dependencies = [ + "cloudabi", + "fuchsia-cprng", + "libc", + "rand_core 0.4.2", + "rdrand", + "winapi 0.3.9", +] + +[[package]] +name = "rand_pcg" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" +dependencies = [ + "autocfg 0.1.8", + "rand_core 0.4.2", +] + +[[package]] +name = "rand_xorshift" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" +dependencies = [ + "rand_core 0.3.1", +] + [[package]] name = "rand_xoshiro" version = "0.6.0" @@ -4049,7 +4502,7 @@ checksum = "356a0625f1954f730c0201cdab48611198dc6ce21f4acff55089b5a78e6e835b" dependencies = [ "crossbeam-channel", "crossbeam-deque", - "crossbeam-utils", + "crossbeam-utils 0.8.14", "num_cpus", ] @@ -4158,26 +4611,26 @@ checksum = "21eed90ec8570952d53b772ecf8f206aa1ec9a3d76b2521c56c42973f2d91ee9" dependencies = [ "async-compression", "base64 0.21.0", - "bytes", + "bytes 1.4.0", "encoding_rs", "futures-core", "futures-util", "h2", "http", "http-body", - "hyper", + "hyper 0.14.24", "hyper-rustls", "hyper-tls", "ipnet", "js-sys", - "log", - "mime", + "log 0.4.17", + "mime 0.3.16", "native-tls", "once_cell", "percent-encoding 2.2.0", "pin-project-lite", "rustls 0.20.8", - "rustls-pemfile", + "rustls-pemfile 1.0.2", "serde", "serde_json", "serde_urlencoded", @@ -4284,7 +4737,7 @@ dependencies = [ "borsh 0.10.2", "bytecheck", "byteorder", - "bytes", + "bytes 1.4.0", "num-traits", "rand 0.8.5", "rkyv", @@ -4314,6 +4767,15 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver 0.9.0", +] + [[package]] name = "rustc_version" version = "0.3.3" @@ -4348,7 +4810,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35edb675feee39aec9c99fa5ff985081995a06d594114ae14cbe797ad7b7a6d7" dependencies = [ "base64 0.13.1", - "log", + "log 0.4.17", "ring", "sct 0.6.1", "webpki 0.21.4", @@ -4360,7 +4822,7 @@ version = "0.20.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fff78fc74d175294f4e83b28343315ffcfb114b156f0185e9741cb5570f50e2f" dependencies = [ - "log", + "log 0.4.17", "ring", "sct 0.7.0", "webpki 0.22.0", @@ -4373,11 +4835,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0167bac7a9f490495f3c33013e7722b53cb087ecbe082fb0c6387c96f634ea50" dependencies = [ "openssl-probe", - "rustls-pemfile", + "rustls-pemfile 1.0.2", "schannel", "security-framework", ] +[[package]] +name = "rustls-pemfile" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eebeaeb360c87bfb72e84abdb3447159c0eaececf1bef2aecd65a8be949d1c9" +dependencies = [ + "base64 0.13.1", +] + [[package]] name = "rustls-pemfile" version = "1.0.2" @@ -4405,6 +4876,12 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98a01dab6acf992653be49205bdd549f32f17cb2803e8eacf1560bf97259aae8" +[[package]] +name = "safemem" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" + [[package]] name = "same-file" version = "1.0.6" @@ -4423,6 +4900,12 @@ dependencies = [ "windows-sys 0.42.0", ] +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + [[package]] name = "scopeguard" version = "1.1.0" @@ -4504,13 +4987,22 @@ dependencies = [ "libc", ] +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser 0.7.0", +] + [[package]] name = "semver" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" dependencies = [ - "semver-parser", + "semver-parser 0.10.2", ] [[package]] @@ -4519,6 +5011,12 @@ version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a" +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + [[package]] name = "semver-parser" version = "0.10.2" @@ -4650,6 +5148,18 @@ dependencies = [ "without-alloc", ] +[[package]] +name = "sha-1" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df" +dependencies = [ + "block-buffer 0.7.3", + "digest 0.8.1", + "fake-simd", + "opaque-debug 0.2.3", +] + [[package]] name = "sha-1" version = "0.9.8" @@ -4660,7 +5170,7 @@ dependencies = [ "cfg-if 1.0.0", "cpufeatures", "digest 0.9.0", - "opaque-debug", + "opaque-debug 0.3.0", ] [[package]] @@ -4695,7 +5205,7 @@ dependencies = [ "cfg-if 1.0.0", "cpufeatures", "digest 0.9.0", - "opaque-debug", + "opaque-debug 0.3.0", ] [[package]] @@ -4718,7 +5228,7 @@ dependencies = [ "block-buffer 0.9.0", "digest 0.9.0", "keccak", - "opaque-debug", + "opaque-debug 0.3.0", ] [[package]] @@ -4780,7 +5290,7 @@ version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" dependencies = [ - "autocfg", + "autocfg 1.1.0", ] [[package]] @@ -4811,7 +5321,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95b6ff8c21c74ce7744643a7cddbb02579a44f1f77e4316bff1ddb741aca8ac9" dependencies = [ "base64 0.13.1", - "log", + "log 0.4.17", "openssl", "serde", "serde_derive", @@ -4837,10 +5347,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41d1c5305e39e09653383c2c7244f2f78b3bcae37cf50c64cb4789c9f5096ec2" dependencies = [ "base64 0.13.1", - "bytes", + "bytes 1.4.0", "futures 0.3.26", "httparse", - "log", + "log 0.4.17", "rand 0.8.5", "sha-1 0.9.8", ] @@ -4875,7 +5385,7 @@ source = "git+https://github.com/solana-labs/solana.git?branch=v1.15#b1bdeb1e8b6 dependencies = [ "bincode", "bytemuck", - "log", + "log 0.4.17", "num-derive", "num-traits", "rustc_version 0.4.0", @@ -4892,23 +5402,33 @@ dependencies = [ name = "solana-bench-mango" version = "1.10.26" dependencies = [ + "anyhow", + "arrayref", + "async-channel", + "async-trait", "borsh 0.9.3", + "bytemuck", "chrono", "clap 2.34.0", "crossbeam-channel", "csv", "fixed", "fixed-macro", - "log", + "futures 0.3.26", + "jsonrpc-core 18.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core-client", + "log 0.4.17", "mango", "mango-common", "multiqueue", + "prost 0.9.0", "rand 0.8.5", "rayon", "serde", "serde_derive", "serde_json", "serde_yaml 0.8.26", + "solana-account-decoder", "solana-clap-utils", "solana-cli-config", "solana-client", @@ -4924,6 +5444,10 @@ dependencies = [ "solana-transaction-status", "solana-version", "thiserror", + "tokio", + "tonic 0.6.2", + "tonic-build 0.6.2", + "warp", ] [[package]] @@ -4933,7 +5457,7 @@ source = "git+https://github.com/solana-labs/solana.git?branch=v1.15#b1bdeb1e8b6 dependencies = [ "bv", "fnv", - "log", + "log 0.4.17", "rand 0.7.3", "rayon", "rustc_version 0.4.0", @@ -4952,7 +5476,7 @@ dependencies = [ "bincode", "byteorder", "libsecp256k1", - "log", + "log 0.4.17", "rand 0.7.3", "solana-measure", "solana-program-runtime", @@ -4967,7 +5491,7 @@ name = "solana-bucket-map" version = "1.15.3" source = "git+https://github.com/solana-labs/solana.git?branch=v1.15#b1bdeb1e8b6b29b24fbd4ce811469bb60dc4b11f" dependencies = [ - "log", + "log 0.4.17", "memmap2", "modular-bitfield", "rand 0.7.3", @@ -5020,7 +5544,7 @@ dependencies = [ "futures-util", "indexmap", "indicatif", - "log", + "log 0.4.17", "quinn", "rand 0.7.3", "rayon", @@ -5073,7 +5597,7 @@ dependencies = [ "bincode", "futures-util", "indexmap", - "log", + "log 0.4.17", "rand 0.7.3", "rayon", "solana-measure", @@ -5102,7 +5626,7 @@ dependencies = [ "histogram", "itertools 0.10.5", "lazy_static", - "log", + "log 0.4.17", "lru", "min-max-heap", "num_enum", @@ -5157,7 +5681,7 @@ dependencies = [ "dlopen", "dlopen_derive", "lazy_static", - "log", + "log 0.4.17", "rand 0.7.3", "rayon", "serde", @@ -5178,7 +5702,7 @@ dependencies = [ "byteorder", "clap 2.34.0", "crossbeam-channel", - "log", + "log 0.4.17", "serde", "serde_derive", "solana-clap-utils", @@ -5206,12 +5730,12 @@ dependencies = [ "byteorder", "cc", "either", - "generic-array", + "generic-array 0.14.6", "getrandom 0.1.16", "hashbrown 0.12.3", "im", "lazy_static", - "log", + "log 0.4.17", "memmap2", "once_cell", "rand_core 0.6.4", @@ -5239,12 +5763,12 @@ dependencies = [ "byteorder", "cc", "either", - "generic-array", + "generic-array 0.14.6", "getrandom 0.1.16", "hashbrown 0.12.3", "im", "lazy_static", - "log", + "log 0.4.17", "memmap2", "once_cell", "rand_core 0.6.4", @@ -5287,7 +5811,7 @@ name = "solana-geyser-plugin-interface" version = "1.15.3" source = "git+https://github.com/solana-labs/solana.git?branch=v1.15#b1bdeb1e8b6b29b24fbd4ce811469bb60dc4b11f" dependencies = [ - "log", + "log 0.4.17", "solana-sdk 1.15.3", "solana-transaction-status", "thiserror", @@ -5302,7 +5826,7 @@ dependencies = [ "crossbeam-channel", "json5", "libloading", - "log", + "log 0.4.17", "serde_json", "solana-geyser-plugin-interface", "solana-measure", @@ -5323,10 +5847,10 @@ dependencies = [ "bv", "clap 2.34.0", "crossbeam-channel", - "flate2", + "flate2 1.0.25", "indexmap", "itertools 0.10.5", - "log", + "log 0.4.17", "lru", "matches", "num-traits", @@ -5379,7 +5903,7 @@ dependencies = [ "itertools 0.10.5", "lazy_static", "libc", - "log", + "log 0.4.17", "lru", "num_cpus", "num_enum", @@ -5428,7 +5952,7 @@ checksum = "170714ca3612e4df75f57c2c14c8ab74654b3b66f668986aeed456cedcf24446" dependencies = [ "env_logger", "lazy_static", - "log", + "log 0.4.17", ] [[package]] @@ -5438,7 +5962,7 @@ source = "git+https://github.com/solana-labs/solana.git?branch=v1.15#b1bdeb1e8b6 dependencies = [ "env_logger", "lazy_static", - "log", + "log 0.4.17", ] [[package]] @@ -5446,7 +5970,7 @@ name = "solana-measure" version = "1.15.3" source = "git+https://github.com/solana-labs/solana.git?branch=v1.15#b1bdeb1e8b6b29b24fbd4ce811469bb60dc4b11f" dependencies = [ - "log", + "log 0.4.17", "solana-sdk 1.15.3", ] @@ -5468,7 +5992,7 @@ dependencies = [ "crossbeam-channel", "gethostname", "lazy_static", - "log", + "log 0.4.17", "reqwest", "solana-sdk 1.15.3", ] @@ -5481,7 +6005,7 @@ dependencies = [ "bincode", "clap 3.2.23", "crossbeam-channel", - "log", + "log 0.4.17", "nix", "rand 0.7.3", "serde", @@ -5509,7 +6033,7 @@ dependencies = [ "fnv", "lazy_static", "libc", - "log", + "log 0.4.17", "nix", "rand 0.7.3", "rayon", @@ -5527,7 +6051,7 @@ source = "git+https://github.com/solana-labs/solana.git?branch=v1.15#b1bdeb1e8b6 dependencies = [ "core_affinity", "crossbeam-channel", - "log", + "log 0.4.17", "solana-entry", "solana-ledger", "solana-measure", @@ -5567,7 +6091,7 @@ dependencies = [ "lazy_static", "libc", "libsecp256k1", - "log", + "log 0.4.17", "memoffset 0.8.0", "num-bigint 0.4.3", "num-derive", @@ -5620,7 +6144,7 @@ dependencies = [ "lazy_static", "libc", "libsecp256k1", - "log", + "log 0.4.17", "memoffset 0.8.0", "num-bigint 0.4.3", "num-derive", @@ -5657,7 +6181,7 @@ dependencies = [ "itertools 0.10.5", "libc", "libloading", - "log", + "log 0.4.17", "num-derive", "num-traits", "rand 0.7.3", @@ -5679,7 +6203,7 @@ source = "git+https://github.com/solana-labs/solana.git?branch=v1.15#b1bdeb1e8b6 dependencies = [ "crossbeam-channel", "futures-util", - "log", + "log 0.4.17", "reqwest", "semver 1.0.16", "serde", @@ -5706,7 +6230,7 @@ dependencies = [ "futures 0.3.26", "itertools 0.10.5", "lazy_static", - "log", + "log 0.4.17", "quinn", "quinn-proto", "quinn-udp", @@ -5739,7 +6263,7 @@ source = "git+https://github.com/solana-labs/solana.git?branch=v1.15#b1bdeb1e8b6 dependencies = [ "console", "dialoguer", - "log", + "log 0.4.17", "num-derive", "num-traits", "parking_lot 0.12.1", @@ -5761,13 +6285,13 @@ dependencies = [ "crossbeam-channel", "dashmap", "itertools 0.10.5", - "jsonrpc-core", + "jsonrpc-core 18.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-core-client", "jsonrpc-derive", "jsonrpc-http-server", - "jsonrpc-pubsub", + "jsonrpc-pubsub 18.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc", - "log", + "log 0.4.17", "rayon", "regex", "serde", @@ -5814,7 +6338,7 @@ dependencies = [ "bincode", "bs58 0.4.0", "indicatif", - "log", + "log 0.4.17", "reqwest", "semver 1.0.16", "serde", @@ -5836,7 +6360,7 @@ source = "git+https://github.com/solana-labs/solana.git?branch=v1.15#b1bdeb1e8b6 dependencies = [ "base64 0.13.1", "bs58 0.4.0", - "jsonrpc-core", + "jsonrpc-core 18.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "reqwest", "semver 1.0.16", "serde", @@ -5877,13 +6401,13 @@ dependencies = [ "crossbeam-channel", "dashmap", "dir-diff", - "flate2", + "flate2 1.0.25", "fnv", "im", "index_list", "itertools 0.10.5", "lazy_static", - "log", + "log 0.4.17", "lru", "lz4", "memmap2", @@ -5943,13 +6467,13 @@ dependencies = [ "digest 0.10.6", "ed25519-dalek", "ed25519-dalek-bip32", - "generic-array", + "generic-array 0.14.6", "hmac 0.12.1", "itertools 0.10.5", "js-sys", "lazy_static", "libsecp256k1", - "log", + "log 0.4.17", "memmap2", "num-derive", "num-traits", @@ -5995,13 +6519,13 @@ dependencies = [ "digest 0.10.6", "ed25519-dalek", "ed25519-dalek-bip32", - "generic-array", + "generic-array 0.14.6", "hmac 0.12.1", "itertools 0.10.5", "js-sys", "lazy_static", "libsecp256k1", - "log", + "log 0.4.17", "memmap2", "num-derive", "num-traits", @@ -6060,7 +6584,7 @@ version = "1.15.3" source = "git+https://github.com/solana-labs/solana.git?branch=v1.15#b1bdeb1e8b6b29b24fbd4ce811469bb60dc4b11f" dependencies = [ "crossbeam-channel", - "log", + "log 0.4.17", "solana-client", "solana-measure", "solana-metrics", @@ -6075,7 +6599,7 @@ version = "1.15.3" source = "git+https://github.com/solana-labs/solana.git?branch=v1.15#b1bdeb1e8b6b29b24fbd4ce811469bb60dc4b11f" dependencies = [ "bincode", - "log", + "log 0.4.17", "rustc_version 0.4.0", "solana-config-program", "solana-program-runtime", @@ -6090,16 +6614,16 @@ source = "git+https://github.com/solana-labs/solana.git?branch=v1.15#b1bdeb1e8b6 dependencies = [ "backoff", "bincode", - "bytes", + "bytes 1.4.0", "bzip2", "enum-iterator", - "flate2", + "flate2 1.0.25", "futures 0.3.26", "goauth", "http", - "hyper", + "hyper 0.14.24", "hyper-proxy", - "log", + "log 0.4.17", "openssl", "prost 0.11.6", "prost-types 0.11.6", @@ -6143,7 +6667,7 @@ dependencies = [ "indexmap", "itertools 0.10.5", "libc", - "log", + "log 0.4.17", "nix", "pem", "percentage", @@ -6169,7 +6693,7 @@ source = "git+https://github.com/solana-labs/solana.git?branch=v1.15#b1bdeb1e8b6 dependencies = [ "clap 2.34.0", "libc", - "log", + "log 0.4.17", "nix", "solana-logger 1.15.3", "solana-version", @@ -6184,7 +6708,7 @@ version = "1.15.3" source = "git+https://github.com/solana-labs/solana.git?branch=v1.15#b1bdeb1e8b6b29b24fbd4ce811469bb60dc4b11f" dependencies = [ "bincode", - "log", + "log 0.4.17", "rayon", "solana-connection-cache", "solana-rpc-client", @@ -6203,7 +6727,7 @@ dependencies = [ "futures-util", "indexmap", "indicatif", - "log", + "log 0.4.17", "rand 0.7.3", "rayon", "solana-connection-cache", @@ -6229,7 +6753,7 @@ dependencies = [ "borsh 0.9.3", "bs58 0.4.0", "lazy_static", - "log", + "log 0.4.17", "serde", "serde_derive", "serde_json", @@ -6263,7 +6787,7 @@ name = "solana-version" version = "1.15.3" source = "git+https://github.com/solana-labs/solana.git?branch=v1.15#b1bdeb1e8b6b29b24fbd4ce811469bb60dc4b11f" dependencies = [ - "log", + "log 0.4.17", "rustc_version 0.4.0", "semver 1.0.16", "serde", @@ -6279,7 +6803,7 @@ version = "1.15.3" source = "git+https://github.com/solana-labs/solana.git?branch=v1.15#b1bdeb1e8b6b29b24fbd4ce811469bb60dc4b11f" dependencies = [ "bincode", - "log", + "log 0.4.17", "num-derive", "num-traits", "rustc_version 0.4.0", @@ -6380,7 +6904,7 @@ dependencies = [ "goblin", "hash32", "libc", - "log", + "log 0.4.17", "rand 0.8.5", "rustc-demangle", "scroll", @@ -6797,11 +7321,11 @@ version = "1.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9d0183f6f6001549ab68f8c7585093bb732beefbcf6d23a10b9b95c73a1dd49" dependencies = [ - "autocfg", - "bytes", + "autocfg 1.1.0", + "bytes 1.4.0", "libc", "memchr", - "mio", + "mio 0.7.14", "num_cpus", "once_cell", "parking_lot 0.11.2", @@ -6811,6 +7335,38 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "tokio-codec" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25b2998660ba0e70d18684de5d06b70b70a3a747469af9dea7618cc59e75976b" +dependencies = [ + "bytes 0.4.12", + "futures 0.1.31", + "tokio-io", +] + +[[package]] +name = "tokio-executor" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb2d1b8f4548dbf5e1f7818512e9c406860678f29c300cdf0ebac72d1a3a1671" +dependencies = [ + "crossbeam-utils 0.7.2", + "futures 0.1.31", +] + +[[package]] +name = "tokio-io" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57fc868aae093479e3131e3d165c93b1c7474109d13c90ec0dda2a1bbfff0674" +dependencies = [ + "bytes 0.4.12", + "futures 0.1.31", + "log 0.4.17", +] + [[package]] name = "tokio-io-timeout" version = "1.2.0" @@ -6842,6 +7398,25 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-reactor" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09bc590ec4ba8ba87652da2068d150dcada2cfa2e07faae270a5e0409aa51351" +dependencies = [ + "crossbeam-utils 0.7.2", + "futures 0.1.31", + "lazy_static", + "log 0.4.17", + "mio 0.6.23", + "num_cpus", + "parking_lot 0.9.0", + "slab", + "tokio-executor", + "tokio-io", + "tokio-sync", +] + [[package]] name = "tokio-rustls" version = "0.22.0" @@ -6875,6 +7450,41 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-sync" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edfe50152bc8164fcc456dab7891fa9bf8beaf01c5ee7e1dd43a397c3cf87dee" +dependencies = [ + "fnv", + "futures 0.1.31", +] + +[[package]] +name = "tokio-tcp" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98df18ed66e3b72e742f185882a9e201892407957e45fbff8da17ae7a7c51f72" +dependencies = [ + "bytes 0.4.12", + "futures 0.1.31", + "iovec", + "mio 0.6.23", + "tokio-io", + "tokio-reactor", +] + +[[package]] +name = "tokio-tls" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "354b8cd83825b3c20217a9dc174d6a0c67441a2fae5c41bcb1ea6679f6ae0f7c" +dependencies = [ + "futures 0.1.31", + "native-tls", + "tokio-io", +] + [[package]] name = "tokio-tungstenite" version = "0.17.2" @@ -6882,7 +7492,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f714dd15bead90401d77e04243611caec13726c2408afd5b31901dfcdcb3b181" dependencies = [ "futures-util", - "log", + "log 0.4.17", "rustls 0.20.8", "tokio", "tokio-rustls 0.23.4", @@ -6897,11 +7507,11 @@ version = "0.6.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "36943ee01a6d67977dd3f84a5a1d2efeb4ada3a1ae771cadfaa535d9d9fc6507" dependencies = [ - "bytes", + "bytes 1.4.0", "futures-core", "futures-io", "futures-sink", - "log", + "log 0.4.17", "pin-project-lite", "tokio", ] @@ -6912,7 +7522,7 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f988a1a1adc2fb21f9c12aa96441da33a1728193ae0b95d2be22dbd17fcb4e5c" dependencies = [ - "bytes", + "bytes 1.4.0", "futures-core", "futures-sink", "pin-project-lite", @@ -6955,13 +7565,14 @@ dependencies = [ "async-stream", "async-trait", "base64 0.13.1", - "bytes", + "bytes 1.4.0", + "flate2 1.0.25", "futures-core", "futures-util", "h2", "http", "http-body", - "hyper", + "hyper 0.14.24", "hyper-timeout", "percent-encoding 2.2.0", "pin-project", @@ -6988,19 +7599,19 @@ dependencies = [ "async-trait", "axum", "base64 0.13.1", - "bytes", + "bytes 1.4.0", "futures-core", "futures-util", "h2", "http", "http-body", - "hyper", + "hyper 0.14.24", "hyper-timeout", "percent-encoding 2.2.0", "pin-project", "prost 0.11.6", "prost-derive 0.11.6", - "rustls-pemfile", + "rustls-pemfile 1.0.2", "tokio", "tokio-rustls 0.23.4", "tokio-stream", @@ -7064,7 +7675,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f873044bf02dd1e8239e9c1293ea39dad76dc594ec16185d0a1bf31d8dc8d858" dependencies = [ "bitflags", - "bytes", + "bytes 1.4.0", "futures-core", "futures-util", "http", @@ -7095,7 +7706,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" dependencies = [ "cfg-if 1.0.0", - "log", + "log 0.4.17", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -7131,6 +7742,12 @@ dependencies = [ "tracing", ] +[[package]] +name = "traitobject" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" + [[package]] name = "trees" version = "0.4.2" @@ -7151,10 +7768,10 @@ checksum = "e27992fd6a8c29ee7eef28fc78349aa244134e10ad447ce3b9f0ac0ed0fa4ce0" dependencies = [ "base64 0.13.1", "byteorder", - "bytes", + "bytes 1.4.0", "http", "httparse", - "log", + "log 0.4.17", "rand 0.8.5", "rustls 0.20.8", "sha-1 0.10.1", @@ -7165,6 +7782,21 @@ dependencies = [ "webpki-roots", ] +[[package]] +name = "twoway" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59b11b2b5241ba34be09c3cc85a36e56e48f9888862e19cedf23336d35316ed1" +dependencies = [ + "memchr", +] + +[[package]] +name = "typeable" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" + [[package]] name = "typenum" version = "1.16.0" @@ -7177,13 +7809,22 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81" +[[package]] +name = "unicase" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" +dependencies = [ + "version_check 0.1.5", +] + [[package]] name = "unicase" version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" dependencies = [ - "version_check", + "version_check 0.9.4", ] [[package]] @@ -7237,7 +7878,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05" dependencies = [ - "generic-array", + "generic-array 0.14.6", "subtle", ] @@ -7271,7 +7912,7 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fa7a7a734c1a5664a662ddcea0b6c9472a21da8888c957c7f1eaa09dba7a939" dependencies = [ - "autocfg", + "autocfg 1.1.0", ] [[package]] @@ -7319,7 +7960,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa4227e95324a443c9fcb06e03d4d85e91aabe9a5a02aa818688b6918b6af486" dependencies = [ "libc", - "log", + "log 0.4.17", ] [[package]] @@ -7340,6 +7981,12 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" +[[package]] +name = "version_check" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" + [[package]] name = "version_check" version = "0.9.4" @@ -7369,10 +8016,41 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" dependencies = [ - "log", + "log 0.4.17", "try-lock", ] +[[package]] +name = "warp" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed7b8be92646fc3d18b06147664ebc5f48d222686cb11a8755e561a735aacc6d" +dependencies = [ + "bytes 1.4.0", + "futures-channel", + "futures-util", + "headers", + "http", + "hyper 0.14.24", + "log 0.4.17", + "mime 0.3.16", + "mime_guess", + "multipart", + "percent-encoding 2.2.0", + "pin-project", + "rustls-pemfile 0.2.1", + "scoped-tls", + "serde", + "serde_json", + "serde_urlencoded", + "tokio", + "tokio-stream", + "tokio-tungstenite", + "tokio-util 0.7.2", + "tower-service", + "tracing", +] + [[package]] name = "wasi" version = "0.9.0+wasi-snapshot-preview1" @@ -7408,7 +8086,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" dependencies = [ "bumpalo", - "log", + "log 0.4.17", "once_cell", "proc-macro2 1.0.51", "quote 1.0.23", @@ -7496,6 +8174,47 @@ dependencies = [ "webpki 0.22.0", ] +[[package]] +name = "websocket" +version = "0.26.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92aacab060eea423e4036820ddd28f3f9003b2c4d8048cbda985e5a14e18038d" +dependencies = [ + "bytes 0.4.12", + "futures 0.1.31", + "hyper 0.10.16", + "native-tls", + "rand 0.6.5", + "tokio-codec", + "tokio-io", + "tokio-reactor", + "tokio-tcp", + "tokio-tls", + "unicase 1.4.2", + "url 1.7.2", + "websocket-base", +] + +[[package]] +name = "websocket-base" +version = "0.26.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49aec794b07318993d1db16156d5a9c750120597a5ee40c6b928d416186cb138" +dependencies = [ + "base64 0.10.1", + "bitflags", + "byteorder", + "bytes 0.4.12", + "futures 0.1.31", + "native-tls", + "rand 0.6.5", + "sha-1 0.8.2", + "tokio-codec", + "tokio-io", + "tokio-tcp", + "tokio-tls", +] + [[package]] name = "which" version = "4.4.0" @@ -7650,6 +8369,16 @@ dependencies = [ "unsize", ] +[[package]] +name = "ws2_32-sys" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] + [[package]] name = "x509-parser" version = "0.14.0" diff --git a/Cargo.toml b/Cargo.toml index 6101b85..f1e1d6b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,10 +40,27 @@ solana-version = { git = "https://github.com/solana-labs/solana.git", branch="v1 solana-logger = { git = "https://github.com/solana-labs/solana.git", branch="v1.15" } solana-transaction-status = { git = "https://github.com/solana-labs/solana.git", branch="v1.15" } solana-quic-client = { git = "https://github.com/solana-labs/solana.git", branch="v1.15" } +solana-account-decoder = { git = "https://github.com/solana-labs/solana.git", branch="v1.15" } + thiserror = "1.0" solana-program = ">=1.9.0" csv = "1.0.0" +tonic = { version = "0.6", features = ["tls", "compression"] } +tokio = { version = "1", features = ["full"] } +anyhow = "1.0" +async-channel = "1.6" +async-trait = "0.1" +prost = "0.9" +warp = "0.3" +futures = "0.3.17" +jsonrpc-core = "18.0.0" +jsonrpc-core-client = { version = "18.0.0", features = ["ws", "http"] } +arrayref = "*" +bytemuck = "1.7.2" + +[build-dependencies] +tonic-build = { version = "0.6", features = ["compression"] } [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] @@ -51,4 +68,8 @@ targets = ["x86_64-unknown-linux-gnu"] exclude = [ "deps/solana", "deps/mango-v3", -] \ No newline at end of file +] + +[patch.crates-io] +# for gzip encoded responses +jsonrpc-core-client = { git = "https://github.com/ckamm/jsonrpc.git", branch = "ckamm/http-with-gzip" } diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..e335e39 --- /dev/null +++ b/build.rs @@ -0,0 +1,4 @@ +fn main() { + tonic_build::compile_protos("./proto/geyser.proto") + .unwrap_or_else(|e| panic!("Failed to compile protos {:?}", e)); +} diff --git a/proto/geyser.proto b/proto/geyser.proto new file mode 100644 index 0000000..5b27388 --- /dev/null +++ b/proto/geyser.proto @@ -0,0 +1,92 @@ +syntax = "proto3"; + +import public "solana-storage-v1.10.40.proto"; + +package geyser; + +service Geyser { + rpc Subscribe(stream SubscribeRequest) returns (stream SubscribeUpdate) {} +} + +message SubscribeRequest { + map accounts = 1; + map slots = 2; + map transactions = 3; + map blocks = 4; +} + +message SubscribeRequestFilterAccounts { + repeated string account = 2; + repeated string owner = 3; +} + +message SubscribeRequestFilterSlots {} + +message SubscribeRequestFilterTransactions { + optional bool vote = 1; + optional bool failed = 2; + repeated string account_include = 3; + repeated string account_exclude = 4; +} + +message SubscribeRequestFilterBlocks {} + +message SubscribeUpdate { + repeated string filters = 1; + oneof update_oneof { + SubscribeUpdateAccount account = 2; + SubscribeUpdateSlot slot = 3; + SubscribeUpdateTransaction transaction = 4; + SubscribeUpdateBlock block = 5; + } +} + +message SubscribeUpdateAccount { + SubscribeUpdateAccountInfo account = 1; + uint64 slot = 2; + bool is_startup = 3; +} + +message SubscribeUpdateAccountInfo { + bytes pubkey = 1; + uint64 lamports = 2; + bytes owner = 3; + bool executable = 4; + uint64 rent_epoch = 5; + bytes data = 6; + uint64 write_version = 7; + // bytes txn_signature = 8; +} + +message SubscribeUpdateSlot { + uint64 slot = 1; + optional uint64 parent = 2; + SubscribeUpdateSlotStatus status = 3; +} + +enum SubscribeUpdateSlotStatus { + PROCESSED = 0; + CONFIRMED = 1; + FINALIZED = 2; +} + +message SubscribeUpdateTransaction { + SubscribeUpdateTransactionInfo transaction = 1; + uint64 slot = 2; +} + +message SubscribeUpdateTransactionInfo { + bytes signature = 1; + bool is_vote = 2; + solana.storage.ConfirmedBlock.Transaction transaction = 3; + solana.storage.ConfirmedBlock.TransactionStatusMeta meta = 4; + // uint64 index = 5; +} + +message SubscribeUpdateBlock { + uint64 slot = 1; + string blockhash = 2; + solana.storage.ConfirmedBlock.Rewards rewards = 3; + solana.storage.ConfirmedBlock.UnixTimestamp block_time = 4; + solana.storage.ConfirmedBlock.BlockHeight block_height = 5; +} diff --git a/proto/solana-storage-v1.10.40.proto b/proto/solana-storage-v1.10.40.proto new file mode 100644 index 0000000..6ae8da5 --- /dev/null +++ b/proto/solana-storage-v1.10.40.proto @@ -0,0 +1,118 @@ +syntax = "proto3"; + +package solana.storage.ConfirmedBlock; + +message ConfirmedBlock { + string previous_blockhash = 1; + string blockhash = 2; + uint64 parent_slot = 3; + repeated ConfirmedTransaction transactions = 4; + repeated Reward rewards = 5; + UnixTimestamp block_time = 6; + BlockHeight block_height = 7; +} + +message ConfirmedTransaction { + Transaction transaction = 1; + TransactionStatusMeta meta = 2; +} + +message Transaction { + repeated bytes signatures = 1; + Message message = 2; +} + +message Message { + MessageHeader header = 1; + repeated bytes account_keys = 2; + bytes recent_blockhash = 3; + repeated CompiledInstruction instructions = 4; + bool versioned = 5; + repeated MessageAddressTableLookup address_table_lookups = 6; +} + +message MessageHeader { + uint32 num_required_signatures = 1; + uint32 num_readonly_signed_accounts = 2; + uint32 num_readonly_unsigned_accounts = 3; +} + +message MessageAddressTableLookup { + bytes account_key = 1; + bytes writable_indexes = 2; + bytes readonly_indexes = 3; +} + +message TransactionStatusMeta { + TransactionError err = 1; + uint64 fee = 2; + repeated uint64 pre_balances = 3; + repeated uint64 post_balances = 4; + repeated InnerInstructions inner_instructions = 5; + bool inner_instructions_none = 10; + repeated string log_messages = 6; + bool log_messages_none = 11; + repeated TokenBalance pre_token_balances = 7; + repeated TokenBalance post_token_balances = 8; + repeated Reward rewards = 9; + repeated bytes loaded_writable_addresses = 12; + repeated bytes loaded_readonly_addresses = 13; +} + +message TransactionError { + bytes err = 1; +} + +message InnerInstructions { + uint32 index = 1; + repeated CompiledInstruction instructions = 2; +} + +message CompiledInstruction { + uint32 program_id_index = 1; + bytes accounts = 2; + bytes data = 3; +} + +message TokenBalance { + uint32 account_index = 1; + string mint = 2; + UiTokenAmount ui_token_amount = 3; + string owner = 4; + string program_id = 5; +} + +message UiTokenAmount { + double ui_amount = 1; + uint32 decimals = 2; + string amount = 3; + string ui_amount_string = 4; +} + +enum RewardType { + Unspecified = 0; + Fee = 1; + Rent = 2; + Staking = 3; + Voting = 4; +} + +message Reward { + string pubkey = 1; + int64 lamports = 2; + uint64 post_balance = 3; + RewardType reward_type = 4; + string commission = 5; +} + +message Rewards { + repeated Reward rewards = 1; +} + +message UnixTimestamp { + int64 timestamp = 1; +} + +message BlockHeight { + uint64 block_height = 1; +} diff --git a/src/account_write_filter.rs b/src/account_write_filter.rs new file mode 100644 index 0000000..801d54e --- /dev/null +++ b/src/account_write_filter.rs @@ -0,0 +1,134 @@ +use crate::{ + chain_data::{AccountData, AccountWrite, SlotUpdate, ChainData, SlotData}, + metrics::Metrics, +}; + +use async_trait::async_trait; +use solana_sdk::{account::WritableAccount, stake_history::Epoch, pubkey::Pubkey}; +use std::{ + collections::{BTreeSet, HashMap}, + sync::Arc, + time::{Duration, Instant}, +}; + +#[async_trait] +pub trait AccountWriteSink { + async fn process(&self, pubkey: &Pubkey, account: &AccountData) -> Result<(), String>; +} + +#[derive(Clone)] +pub struct AccountWriteRoute { + pub matched_pubkeys: Vec, + pub sink: Arc, + pub timeout_interval: Duration, +} + +#[derive(Clone, Debug)] +struct AcountWriteRecord { + slot: u64, + write_version: u64, + timestamp: Instant, +} + +pub fn init( + routes: Vec, + metrics_sender: Metrics, +) -> anyhow::Result<( + async_channel::Sender, + async_channel::Sender, +)> { + // The actual message may want to also contain a retry count, if it self-reinserts on failure? + let (account_write_queue_sender, account_write_queue_receiver) = + async_channel::unbounded::(); + + // Slot updates flowing from the outside into the single processing thread. From + // there they'll flow into the postgres sending thread. + let (slot_queue_sender, slot_queue_receiver) = async_channel::unbounded::(); + + let mut chain_data = ChainData::new(metrics_sender); + let mut last_updated = HashMap::::new(); + + let all_queue_pks: BTreeSet = routes + .iter() + .flat_map(|r| r.matched_pubkeys.iter()) + .map(|pk| pk.clone()) + .collect(); + + // update handling thread, reads both sloths and account updates + tokio::spawn(async move { + loop { + tokio::select! { + Ok(account_write) = account_write_queue_receiver.recv() => { + if all_queue_pks.contains(&account_write.pubkey) { + continue; + } + + chain_data.update_account( + account_write.pubkey, + AccountData { + slot: account_write.slot, + write_version: account_write.write_version, + account: WritableAccount::create( + account_write.lamports, + account_write.data.clone(), + account_write.owner, + account_write.executable, + account_write.rent_epoch as Epoch, + ), + }, + ); + } + Ok(slot_update) = slot_queue_receiver.recv() => { + chain_data.update_slot(SlotData { + slot: slot_update.slot, + parent: slot_update.parent, + status: slot_update.status, + chain: 0, + }); + + } + } + + for route in routes.iter() { + for pk in route.matched_pubkeys.iter() { + match chain_data.account(&pk) { + Ok(account_info) => { + let pk_b58 = pk.to_string(); + if let Some(record) = last_updated.get(&pk_b58) { + let is_unchanged = account_info.slot == record.slot + && account_info.write_version == record.write_version; + let is_throttled = + record.timestamp.elapsed() < route.timeout_interval; + if is_unchanged || is_throttled { + continue; + } + }; + + match route.sink.process(pk, account_info).await { + Ok(()) => { + // todo: metrics + last_updated.insert( + pk_b58.clone(), + AcountWriteRecord { + slot: account_info.slot, + write_version: account_info.write_version, + timestamp: Instant::now(), + }, + ); + } + Err(_skip_reason) => { + // todo: metrics + } + } + } + Err(_) => { + // todo: metrics + } + } + } + } + } + }); + + Ok((account_write_queue_sender, slot_queue_sender)) +} diff --git a/src/blockhash_poller.rs b/src/blockhash_poller.rs new file mode 100644 index 0000000..b9c6f9b --- /dev/null +++ b/src/blockhash_poller.rs @@ -0,0 +1,45 @@ +use log::*; +use solana_client::nonblocking::rpc_client::RpcClient; +use solana_sdk::{clock::DEFAULT_MS_PER_SLOT, commitment_config::CommitmentConfig, hash::Hash}; +use std::{ + sync::{Arc, RwLock}, + time::Duration, +}; +use tokio::{spawn, time::sleep}; + +const RETRY_INTERVAL: Duration = Duration::from_millis(5 * DEFAULT_MS_PER_SLOT); + +pub async fn poll_loop(blockhash: Arc>, client: Arc) { + let cfg = CommitmentConfig::processed(); + loop { + let old_blockhash = *blockhash.read().unwrap(); + if let Ok((new_blockhash, _)) = client.get_latest_blockhash_with_commitment(cfg).await { + if new_blockhash != old_blockhash { + debug!("new blockhash ({:?})", blockhash); + *blockhash.write().unwrap() = new_blockhash; + } + } + + // Retry every few slots + sleep(RETRY_INTERVAL).await; + } +} + +pub async fn init(client: Arc) -> Arc> { + // get the first blockhash + let blockhash = Arc::new(RwLock::new( + client + .get_latest_blockhash() + .await + .expect("fetch initial blockhash"), + )); + + // launch task + let _join_hdl = { + // create a thread-local reference to blockhash + let blockhash_c = blockhash.clone(); + spawn(async move { poll_loop(blockhash_c, client).await }) + }; + + return blockhash; +} diff --git a/src/chain_data.rs b/src/chain_data.rs new file mode 100644 index 0000000..25dd811 --- /dev/null +++ b/src/chain_data.rs @@ -0,0 +1,268 @@ +use crate::metrics::{MetricType, MetricU64, Metrics}; + +use { + solana_sdk::account::{Account, AccountSharedData, ReadableAccount}, + solana_sdk::pubkey::Pubkey, + std::collections::HashMap, +}; + +#[derive(Clone, Copy, Debug, PartialEq)] +pub enum SlotStatus { + Rooted, + Confirmed, + Processed, +} + +#[derive(Clone, Debug)] +pub struct SlotData { + pub slot: u64, + pub parent: Option, + pub status: SlotStatus, + pub chain: u64, // the top slot that this is in a chain with. uncles will have values < tip +} + +#[derive(Clone, Debug)] +pub struct AccountData { + pub slot: u64, + pub write_version: u64, + pub account: AccountSharedData, +} + + +#[derive(Clone, PartialEq, Debug)] +pub struct AccountWrite { + pub pubkey: Pubkey, + pub slot: u64, + pub write_version: u64, + pub lamports: u64, + pub owner: Pubkey, + pub executable: bool, + pub rent_epoch: u64, + pub data: Vec, + pub is_selected: bool, +} + +impl AccountWrite { + pub fn from(pubkey: Pubkey, slot: u64, write_version: u64, account: Account) -> AccountWrite { + AccountWrite { + pubkey, + slot: slot, + write_version, + lamports: account.lamports, + owner: account.owner, + executable: account.executable, + rent_epoch: account.rent_epoch, + data: account.data, + is_selected: true, + } + } +} + +#[derive(Clone, Debug)] +pub struct SlotUpdate { + pub slot: u64, + pub parent: Option, + pub status: SlotStatus, +} + + +/// Track slots and account writes +/// +/// - use account() to retrieve the current best data for an account. +/// - update_from_snapshot() and update_from_websocket() update the state for new messages +pub struct ChainData { + /// only slots >= newest_rooted_slot are retained + slots: HashMap, + /// writes to accounts, only the latest rooted write an newer are retained + accounts: HashMap>, + newest_rooted_slot: u64, + newest_processed_slot: u64, + account_versions_stored: usize, + account_bytes_stored: usize, + metric_accounts_stored: MetricU64, + metric_account_versions_stored: MetricU64, + metric_account_bytes_stored: MetricU64, +} + +impl ChainData { + pub fn new(metrics_sender: Metrics) -> Self { + Self { + slots: HashMap::new(), + accounts: HashMap::new(), + newest_rooted_slot: 0, + newest_processed_slot: 0, + account_versions_stored: 0, + account_bytes_stored: 0, + metric_accounts_stored: metrics_sender + .register_u64("chaindata_accounts_stored".into(), MetricType::Gauge), + metric_account_versions_stored: metrics_sender.register_u64( + "chaindata_account_versions_stored".into(), + MetricType::Gauge, + ), + metric_account_bytes_stored: metrics_sender + .register_u64("chaindata_account_bytes_stored".into(), MetricType::Gauge), + } + } + + pub fn update_slot(&mut self, new_slot: SlotData) { + let new_processed_head = new_slot.slot > self.newest_processed_slot; + if new_processed_head { + self.newest_processed_slot = new_slot.slot; + } + + let new_rooted_head = + new_slot.slot > self.newest_rooted_slot && new_slot.status == SlotStatus::Rooted; + if new_rooted_head { + self.newest_rooted_slot = new_slot.slot; + } + + let mut parent_update = false; + + use std::collections::hash_map::Entry; + match self.slots.entry(new_slot.slot) { + Entry::Vacant(v) => { + v.insert(new_slot); + } + Entry::Occupied(o) => { + let v = o.into_mut(); + parent_update = v.parent != new_slot.parent && new_slot.parent.is_some(); + v.parent = v.parent.or(new_slot.parent); + v.status = new_slot.status; + } + }; + + if new_processed_head || parent_update { + // update the "chain" field down to the first rooted slot + let mut slot = self.newest_processed_slot; + loop { + if let Some(data) = self.slots.get_mut(&slot) { + data.chain = self.newest_processed_slot; + if data.status == SlotStatus::Rooted { + break; + } + if let Some(parent) = data.parent { + slot = parent; + continue; + } + } + break; + } + } + + if new_rooted_head { + // for each account, preserve only writes > newest_rooted_slot, or the newest + // rooted write + self.account_versions_stored = 0; + self.account_bytes_stored = 0; + + for (_, writes) in self.accounts.iter_mut() { + let newest_rooted_write = writes + .iter() + .rev() + .find(|w| { + w.slot <= self.newest_rooted_slot + && self + .slots + .get(&w.slot) + .map(|s| { + // sometimes we seem not to get notifications about slots + // getting rooted, hence assume non-uncle slots < newest_rooted_slot + // are rooted too + s.status == SlotStatus::Rooted + || s.chain == self.newest_processed_slot + }) + // preserved account writes for deleted slots <= newest_rooted_slot + // are expected to be rooted + .unwrap_or(true) + }) + .map(|w| w.slot) + // no rooted write found: produce no effect, since writes > newest_rooted_slot are retained anyway + .unwrap_or(self.newest_rooted_slot + 1); + writes + .retain(|w| w.slot == newest_rooted_write || w.slot > self.newest_rooted_slot); + self.account_versions_stored += writes.len(); + self.account_bytes_stored += writes + .iter() + .map(|w| w.account.data().len()) + .fold(0, |acc, l| acc + l) + } + + // now it's fine to drop any slots before the new rooted head + // as account writes for non-rooted slots before it have been dropped + self.slots.retain(|s, _| *s >= self.newest_rooted_slot); + + self.metric_accounts_stored.set(self.accounts.len() as u64); + self.metric_account_versions_stored + .set(self.account_versions_stored as u64); + self.metric_account_bytes_stored + .set(self.account_bytes_stored as u64); + } + } + + pub fn update_account(&mut self, pubkey: Pubkey, account: AccountData) { + use std::collections::hash_map::Entry; + match self.accounts.entry(pubkey) { + Entry::Vacant(v) => { + self.account_versions_stored += 1; + self.account_bytes_stored += account.account.data().len(); + v.insert(vec![account]); + } + Entry::Occupied(o) => { + let v = o.into_mut(); + // v is ordered by slot ascending. find the right position + // overwrite if an entry for the slot already exists, otherwise insert + let rev_pos = v + .iter() + .rev() + .position(|d| d.slot <= account.slot) + .unwrap_or(v.len()); + let pos = v.len() - rev_pos; + if pos < v.len() && v[pos].slot == account.slot { + if v[pos].write_version < account.write_version { + v[pos] = account; + } + } else { + self.account_versions_stored += 1; + self.account_bytes_stored += account.account.data().len(); + v.insert(pos, account); + } + } + }; + } + + fn is_account_write_live(&self, write: &AccountData) -> bool { + self.slots + .get(&write.slot) + // either the slot is rooted or in the current chain + .map(|s| s.status == SlotStatus::Rooted || s.chain == self.newest_processed_slot) + // if the slot can't be found but preceeds newest rooted, use it too (old rooted slots are removed) + .unwrap_or( + write.slot <= self.newest_rooted_slot || write.slot > self.newest_processed_slot, + ) + } + + /// Cloned snapshot of all the most recent live writes per pubkey + pub fn accounts_snapshot(&self) -> HashMap { + self.accounts + .iter() + .filter_map(|(pubkey, writes)| { + let latest_good_write = writes + .iter() + .rev() + .find(|w| self.is_account_write_live(w))?; + Some((pubkey.clone(), latest_good_write.clone())) + }) + .collect() + } + + /// Ref to the most recent live write of the pubkey + pub fn account<'a>(&'a self, pubkey: &Pubkey) -> anyhow::Result<&'a AccountData> { + self.accounts + .get(pubkey) + .ok_or(anyhow::anyhow!("account {} not found", pubkey))? + .iter() + .rev() + .find(|w| self.is_account_write_live(w)) + .ok_or(anyhow::anyhow!("account {} has no live data", pubkey)) + } +} diff --git a/src/crank.rs b/src/crank.rs new file mode 100644 index 0000000..57afe43 --- /dev/null +++ b/src/crank.rs @@ -0,0 +1,73 @@ +use std::{thread::{JoinHandle, Builder}, sync::{Arc, RwLock}, str::FromStr, time::Duration}; + +// use solana_client::rpc_client::RpcClient; +use solana_sdk::{pubkey::Pubkey, signature::Keypair, instruction::Instruction}; + +use crate::{mango::GroupConfig, account_write_filter::AccountWriteRoute, mango_v3_perp_crank_sink::MangoV3PerpCrankSink}; + + + + +// pub async fn send_tx_loop( +// ixs_rx: async_channel::Receiver>, +// blockhash: Arc>, +// client: Arc, +// keypair: Keypair, +// ) { +// info!("signing with keypair pk={:?}", keypair.pubkey()); +// let cfg = RpcSendTransactionConfig { +// skip_preflight: true, +// ..RpcSendTransactionConfig::default() +// }; +// loop { +// if let Ok(ixs) = ixs_rx.recv().await { +// // TODO add priority fee +// let tx = Transaction::new_signed_with_payer( +// &ixs, +// Some(&keypair.pubkey()), +// &[&keypair], +// *blockhash.read().unwrap(), +// ); +// // TODO: collect metrics +// info!("send tx={:?} ok={:?}", tx.signatures[0], client.send_transaction_with_config(&tx, cfg).await); +// } +// } +// } + + +fn start_crank_thread( + identity: Keypair, + group: GroupConfig +) -> JoinHandle<()> { + + let perp_queue_pks: Vec<_> = group.perp_markets.iter().map(|m| (Pubkey::from_str(&m.public_key).unwrap(), Pubkey::from_str(&m.events_key).unwrap())).collect(); + let group_pk = Pubkey::from_str(&group.public_key).unwrap(); + + return Builder::new() + .name("crank".to_string()) + .spawn(move || { + + + + // Event queue updates can be consumed by client connections + let (instruction_sender, instruction_receiver) = async_channel::unbounded::>(); + + + + let routes = vec![ + AccountWriteRoute { + matched_pubkeys: perp_queue_pks + .iter() + .map(|(_, evq_pk)| evq_pk.clone()) + .collect(), + sink: Arc::new(MangoV3PerpCrankSink::new( + perp_queue_pks, + group_pk, + instruction_sender.clone(), + )), + timeout_interval: Duration::default(), + }]; + + }).expect("launch crank thread") + +} diff --git a/src/grpc_plugin_source.rs b/src/grpc_plugin_source.rs new file mode 100644 index 0000000..790f4b4 --- /dev/null +++ b/src/grpc_plugin_source.rs @@ -0,0 +1,609 @@ +use futures::stream::once; +use geyser::geyser_client::GeyserClient; +use jsonrpc_core::futures::StreamExt; +use jsonrpc_core_client::transports::http; + +use serde::Deserialize; +use solana_account_decoder::{UiAccount, UiAccountEncoding}; +use solana_client::rpc_config::{RpcAccountInfoConfig, RpcProgramAccountsConfig}; +use solana_client::rpc_response::{OptionalContext, RpcKeyedAccount}; +use solana_rpc::rpc::rpc_accounts::AccountsDataClient; +use solana_rpc::rpc::rpc_accounts_scan::AccountsScanClient; +use solana_sdk::{account::Account, commitment_config::CommitmentConfig, pubkey::Pubkey}; + +use futures::{future, future::FutureExt}; +use tonic::{ + metadata::MetadataValue, + transport::{Certificate, Channel, ClientTlsConfig, Identity}, + Request, +}; + +use log::*; +use std::{collections::HashMap, env, str::FromStr, time::Duration}; + +pub mod geyser { + tonic::include_proto!("geyser"); +} + +pub mod solana { + pub mod storage { + pub mod confirmed_block { + tonic::include_proto!("solana.storage.confirmed_block"); + } + } +} + +pub use geyser::*; +pub use solana::storage::confirmed_block::*; + +use crate::{ + chain_data::{AccountWrite, SlotStatus, SlotUpdate}, + metrics::{MetricType, Metrics}, + AnyhowWrap, +}; + +#[derive(Clone, Debug, Deserialize)] +pub struct SourceConfig { + pub dedup_queue_size: usize, + pub grpc_sources: Vec, + pub snapshot: SnapshotSourceConfig, + pub rpc_ws_url: String, +} + +#[derive(Clone, Debug, Deserialize)] +pub struct GrpcSourceConfig { + pub name: String, + pub connection_string: String, + pub retry_connection_sleep_secs: u64, + pub tls: Option, +} + +#[derive(Clone, Debug, Deserialize)] +pub struct TlsConfig { + pub ca_cert_path: String, + pub client_cert_path: String, + pub client_key_path: String, + pub domain_name: String, +} + +#[derive(Clone, Debug, Deserialize)] +pub struct FilterConfig { + pub program_ids: Vec, + pub account_ids: Vec, +} + +#[derive(Clone, Debug, Deserialize)] +pub struct SnapshotSourceConfig { + pub rpc_http_url: String, + pub program_id: String, +} + +//use solana_geyser_connector_plugin_grpc::compression::zstd_decompress; + +struct SnapshotData { + slot: u64, + accounts: Vec<(String, Option)>, +} +enum Message { + GrpcUpdate(geyser::SubscribeUpdate), + Snapshot(SnapshotData), +} + +async fn get_snapshot_gpa( + rpc_http_url: String, + program_id: String, +) -> anyhow::Result>> { + let rpc_client = http::connect_with_options::(&rpc_http_url, true) + .await + .map_err_anyhow()?; + + let account_info_config = RpcAccountInfoConfig { + encoding: Some(UiAccountEncoding::Base64), + commitment: Some(CommitmentConfig::finalized()), + data_slice: None, + min_context_slot: None, + }; + let program_accounts_config = RpcProgramAccountsConfig { + filters: None, + with_context: Some(true), + account_config: account_info_config.clone(), + }; + + info!("requesting snapshot {}", program_id); + let account_snapshot = rpc_client + .get_program_accounts(program_id.clone(), Some(program_accounts_config.clone())) + .await + .map_err_anyhow()?; + info!("snapshot received {}", program_id); + Ok(account_snapshot) +} + +async fn get_snapshot_gma( + rpc_http_url: String, + ids: Vec, +) -> anyhow::Result>>> { + let rpc_client = http::connect_with_options::(&rpc_http_url, true) + .await + .map_err_anyhow()?; + + let account_info_config = RpcAccountInfoConfig { + encoding: Some(UiAccountEncoding::Base64), + commitment: Some(CommitmentConfig::finalized()), + data_slice: None, + min_context_slot: None, + }; + + info!("requesting snapshot {:?}", ids); + let account_snapshot = rpc_client + .get_multiple_accounts(ids.clone(), Some(account_info_config)) + .await + .map_err_anyhow()?; + info!("snapshot received {:?}", ids); + Ok(account_snapshot) +} + +async fn feed_data_geyser( + grpc_config: &GrpcSourceConfig, + tls_config: Option, + snapshot_config: &SnapshotSourceConfig, + filter_config: &FilterConfig, + sender: async_channel::Sender, +) -> anyhow::Result<()> { + let connection_string = match &grpc_config.connection_string.chars().next().unwrap() { + '$' => env::var(&grpc_config.connection_string[1..]) + .expect("reading connection string from env"), + _ => grpc_config.connection_string.clone(), + }; + let rpc_http_url = match &snapshot_config.rpc_http_url.chars().next().unwrap() { + '$' => env::var(&snapshot_config.rpc_http_url[1..]) + .expect("reading connection string from env"), + _ => snapshot_config.rpc_http_url.clone(), + }; + info!("connecting {}", connection_string); + let endpoint = Channel::from_shared(connection_string)?; + let channel = if let Some(tls) = tls_config { + endpoint.tls_config(tls)? + } else { + endpoint + } + .connect() + .await?; + let token: MetadataValue<_> = "eed31807f710e4bb098779fb9f67".parse()?; + let mut client = GeyserClient::with_interceptor(channel, move |mut req: Request<()>| { + req.metadata_mut().insert("x-token", token.clone()); + Ok(req) + }); + + // If account_ids are provided, snapshot will be gMA. If only program_ids, then only the first id will be snapshot + // TODO: handle this better + if filter_config.program_ids.len() > 1 { + warn!("only one program id is supported for gPA snapshots") + } + let mut accounts = HashMap::new(); + accounts.insert( + "client".to_owned(), + SubscribeRequestFilterAccounts { + account: filter_config.account_ids.clone(), + owner: filter_config.program_ids.clone(), + }, + ); + let mut slots = HashMap::new(); + slots.insert("client".to_owned(), SubscribeRequestFilterSlots {}); + let blocks = HashMap::new(); + let transactions = HashMap::new(); + + let request = SubscribeRequest { + accounts, + blocks, + slots, + transactions, + }; + info!("Going to send request: {:?}", request); + + let response = client.subscribe(once(async move { request })).await?; + let mut update_stream = response.into_inner(); + + // We can't get a snapshot immediately since the finalized snapshot would be for a + // slot in the past and we'd be missing intermediate updates. + // + // Delay the request until the first slot we received all writes for becomes rooted + // to avoid that problem - partially. The rooted slot will still be larger than the + // finalized slot, so add a number of slots as a buffer. + // + // If that buffer isn't sufficient, there'll be a retry. + + // The first slot that we will receive _all_ account writes for + let mut first_full_slot: u64 = u64::MAX; + + // If a snapshot should be performed when ready. + let mut snapshot_needed = true; + + // The highest "rooted" slot that has been seen. + let mut max_rooted_slot = 0; + + // Data for slots will arrive out of order. This value defines how many + // slots after a slot was marked "rooted" we assume it'll not receive + // any more account write information. + // + // This is important for the write_version mapping (to know when slots can + // be dropped). + let max_out_of_order_slots = 40; + + // Number of slots that we expect "finalized" commitment to lag + // behind "rooted". This matters for getProgramAccounts based snapshots, + // which will have "finalized" commitment. + let mut rooted_to_finalized_slots = 30; + + let mut snapshot_gma = future::Fuse::terminated(); + let mut snapshot_gpa = future::Fuse::terminated(); + + // The plugin sends a ping every 5s or so + let fatal_idle_timeout = Duration::from_secs(60); + + // Highest slot that an account write came in for. + let mut newest_write_slot: u64 = 0; + + struct WriteVersion { + // Write version seen on-chain + global: u64, + // The per-pubkey per-slot write version + slot: u32, + } + + // map slot -> (pubkey -> WriteVersion) + // + // Since the write_version is a private indentifier per node it can't be used + // to deduplicate events from multiple nodes. Here we rewrite it such that each + // pubkey and each slot has a consecutive numbering of writes starting at 1. + // + // That number will be consistent for each node. + let mut slot_pubkey_writes = HashMap::>::new(); + + loop { + tokio::select! { + update = update_stream.next() => { + use geyser::{subscribe_update::UpdateOneof}; + let mut update = update.ok_or(anyhow::anyhow!("geyser plugin has closed the stream"))??; + match update.update_oneof.as_mut().expect("invalid grpc") { + UpdateOneof::Slot(slot_update) => { + let status = slot_update.status; + if status == SubscribeUpdateSlotStatus::Finalized as i32 { + if first_full_slot == u64::MAX { + // TODO: is this equivalent to before? what was highesy_write_slot? + first_full_slot = slot_update.slot + 1; + } + if slot_update.slot > max_rooted_slot { + max_rooted_slot = slot_update.slot; + + // drop data for slots that are well beyond rooted + slot_pubkey_writes.retain(|&k, _| k >= max_rooted_slot - max_out_of_order_slots); + } + + if snapshot_needed && max_rooted_slot - rooted_to_finalized_slots > first_full_slot { + snapshot_needed = false; + if filter_config.account_ids.len() > 0 { + snapshot_gma = tokio::spawn(get_snapshot_gma(rpc_http_url.clone(), filter_config.account_ids.clone())).fuse(); + } else if filter_config.program_ids.len() > 0 { + snapshot_gpa = tokio::spawn(get_snapshot_gpa(rpc_http_url.clone(), filter_config.program_ids[0].clone())).fuse(); + } + } + } + }, + UpdateOneof::Account(info) => { + if info.slot < first_full_slot { + // Don't try to process data for slots where we may have missed writes: + // We could not map the write_version correctly for them. + continue; + } + + if info.slot > newest_write_slot { + newest_write_slot = info.slot; + } else if max_rooted_slot > 0 && info.slot < max_rooted_slot - max_out_of_order_slots { + anyhow::bail!("received write {} slots back from max rooted slot {}", max_rooted_slot - info.slot, max_rooted_slot); + } + + let pubkey_writes = slot_pubkey_writes.entry(info.slot).or_default(); + let mut write = match info.account.clone() { + Some(x) => x, + None => { + // TODO: handle error + continue; + }, + }; + + let pubkey_bytes = Pubkey::new(&write.pubkey).to_bytes(); + let write_version_mapping = pubkey_writes.entry(pubkey_bytes).or_insert(WriteVersion { + global: write.write_version, + slot: 1, // write version 0 is reserved for snapshots + }); + + // We assume we will receive write versions for each pubkey in sequence. + // If this is not the case, logic here does not work correctly because + // a later write could arrive first. + if write.write_version < write_version_mapping.global { + anyhow::bail!("unexpected write version: got {}, expected >= {}", write.write_version, write_version_mapping.global); + } + + // Rewrite the update to use the local write version and bump it + write.write_version = write_version_mapping.slot as u64; + write_version_mapping.slot += 1; + }, + UpdateOneof::Block(_) => {}, + UpdateOneof::Transaction(_) => {}, + } + sender.send(Message::GrpcUpdate(update)).await.expect("send success"); + }, + snapshot = &mut snapshot_gma => { + let snapshot = snapshot??; + info!("snapshot is for slot {}, first full slot was {}", snapshot.context.slot, first_full_slot); + if snapshot.context.slot >= first_full_slot { + let accounts: Vec<(String, Option)> = filter_config.account_ids.iter().zip(snapshot.value).map(|x| (x.0.clone(), x.1)).collect(); + sender + .send(Message::Snapshot(SnapshotData { + accounts, + slot: snapshot.context.slot, + })) + .await + .expect("send success"); + } else { + info!( + "snapshot is too old: has slot {}, expected {} minimum", + snapshot.context.slot, + first_full_slot + ); + // try again in another 10 slots + snapshot_needed = true; + rooted_to_finalized_slots += 10; + } + }, + snapshot = &mut snapshot_gpa => { + let snapshot = snapshot??; + if let OptionalContext::Context(snapshot_data) = snapshot { + info!("snapshot is for slot {}, first full slot was {}", snapshot_data.context.slot, first_full_slot); + if snapshot_data.context.slot >= first_full_slot { + let accounts: Vec<(String, Option)> = snapshot_data.value.iter().map(|x| { + let deref = x.clone(); + (deref.pubkey, Some(deref.account)) + }).collect(); + sender + .send(Message::Snapshot(SnapshotData { + accounts, + slot: snapshot_data.context.slot, + })) + .await + .expect("send success"); + } else { + info!( + "snapshot is too old: has slot {}, expected {} minimum", + snapshot_data.context.slot, + first_full_slot + ); + // try again in another 10 slots + snapshot_needed = true; + rooted_to_finalized_slots += 10; + } + } else { + anyhow::bail!("bad snapshot format"); + } + }, + _ = tokio::time::sleep(fatal_idle_timeout) => { + anyhow::bail!("geyser plugin hasn't sent a message in too long"); + } + } + } +} + +fn make_tls_config(config: &TlsConfig) -> ClientTlsConfig { + let server_root_ca_cert = match &config.ca_cert_path.chars().next().unwrap() { + '$' => env::var(&config.ca_cert_path[1..]) + .expect("reading server root ca cert from env") + .into_bytes(), + _ => std::fs::read(&config.ca_cert_path).expect("reading server root ca cert from file"), + }; + let server_root_ca_cert = Certificate::from_pem(server_root_ca_cert); + let client_cert = match &config.client_cert_path.chars().next().unwrap() { + '$' => env::var(&config.client_cert_path[1..]) + .expect("reading client cert from env") + .into_bytes(), + _ => std::fs::read(&config.client_cert_path).expect("reading client cert from file"), + }; + let client_key = match &config.client_key_path.chars().next().unwrap() { + '$' => env::var(&config.client_key_path[1..]) + .expect("reading client key from env") + .into_bytes(), + _ => std::fs::read(&config.client_key_path).expect("reading client key from file"), + }; + let client_identity = Identity::from_pem(client_cert, client_key); + let domain_name = match &config.domain_name.chars().next().unwrap() { + '$' => env::var(&config.domain_name[1..]).expect("reading domain name from env"), + _ => config.domain_name.clone(), + }; + ClientTlsConfig::new() + .ca_certificate(server_root_ca_cert) + .identity(client_identity) + .domain_name(domain_name) +} + +pub async fn process_events( + config: &SourceConfig, + filter_config: &FilterConfig, + account_write_queue_sender: async_channel::Sender, + slot_queue_sender: async_channel::Sender, + metrics_sender: Metrics, +) { + // Subscribe to geyser + let (msg_sender, msg_receiver) = async_channel::bounded::(config.dedup_queue_size); + for grpc_source in config.grpc_sources.clone() { + let msg_sender = msg_sender.clone(); + let snapshot_source = config.snapshot.clone(); + let metrics_sender = metrics_sender.clone(); + let f = filter_config.clone(); + + // Make TLS config if configured + let tls_config = grpc_source.tls.as_ref().map(make_tls_config); + + tokio::spawn(async move { + let mut metric_retries = metrics_sender.register_u64( + format!("grpc_source_{}_connection_retries", grpc_source.name,), + MetricType::Counter, + ); + let metric_connected = + metrics_sender.register_bool(format!("grpc_source_{}_status", grpc_source.name)); + + // Continuously reconnect on failure + loop { + metric_connected.set(true); + let out = feed_data_geyser( + &grpc_source, + tls_config.clone(), + &snapshot_source, + &f, + msg_sender.clone(), + ); + let result = out.await; + assert!(result.is_err()); + if let Err(err) = result { + warn!( + "error during communication with the geyser plugin. retrying. {:?}", + err + ); + } + + metric_connected.set(false); + metric_retries.increment(); + + tokio::time::sleep(std::time::Duration::from_secs( + grpc_source.retry_connection_sleep_secs, + )) + .await; + } + }); + } + + // slot -> (pubkey -> write_version) + // + // To avoid unnecessarily sending requests to SQL, we track the latest write_version + // for each (slot, pubkey). If an already-seen write_version comes in, it can be safely + // discarded. + let mut latest_write = HashMap::>::new(); + + // Number of slots to retain in latest_write + let latest_write_retention = 50; + + let mut metric_account_writes = + metrics_sender.register_u64("grpc_account_writes".into(), MetricType::Counter); + let mut metric_account_queue = + metrics_sender.register_u64("grpc_account_write_queue".into(), MetricType::Gauge); + let mut metric_dedup_queue = + metrics_sender.register_u64("grpc_dedup_queue".into(), MetricType::Gauge); + let mut metric_slot_queue = + metrics_sender.register_u64("grpc_slot_update_queue".into(), MetricType::Gauge); + let mut metric_slot_updates = + metrics_sender.register_u64("grpc_slot_updates".into(), MetricType::Counter); + let mut metric_snapshots = + metrics_sender.register_u64("grpc_snapshots".into(), MetricType::Counter); + let mut metric_snapshot_account_writes = + metrics_sender.register_u64("grpc_snapshot_account_writes".into(), MetricType::Counter); + + loop { + metric_dedup_queue.set(msg_receiver.len() as u64); + let msg = msg_receiver.recv().await.expect("sender must not close"); + use geyser::subscribe_update::UpdateOneof; + match msg { + Message::GrpcUpdate(update) => { + match update.update_oneof.expect("invalid grpc") { + UpdateOneof::Account(info) => { + let update = match info.account.clone() { + Some(x) => x, + None => { + // TODO: handle error + continue; + } + }; + assert!(update.pubkey.len() == 32); + assert!(update.owner.len() == 32); + + metric_account_writes.increment(); + metric_account_queue.set(account_write_queue_sender.len() as u64); + + // Skip writes that a different server has already sent + let pubkey_writes = latest_write.entry(info.slot).or_default(); + let pubkey_bytes = Pubkey::new(&update.pubkey).to_bytes(); + let writes = pubkey_writes.entry(pubkey_bytes).or_insert(0); + if update.write_version <= *writes { + continue; + } + *writes = update.write_version; + latest_write.retain(|&k, _| k >= info.slot - latest_write_retention); + // let mut uncompressed: Vec = Vec::new(); + // zstd_decompress(&update.data, &mut uncompressed).unwrap(); + account_write_queue_sender + .send(AccountWrite { + pubkey: Pubkey::new(&update.pubkey), + slot: info.slot, + write_version: update.write_version, + lamports: update.lamports, + owner: Pubkey::new(&update.owner), + executable: update.executable, + rent_epoch: update.rent_epoch, + data: update.data, + // TODO: what should this be? related to account deletes? + is_selected: true, + }) + .await + .expect("send success"); + } + UpdateOneof::Slot(update) => { + metric_slot_updates.increment(); + metric_slot_queue.set(slot_queue_sender.len() as u64); + + let status = + SubscribeUpdateSlotStatus::from_i32(update.status).map(|v| match v { + SubscribeUpdateSlotStatus::Processed => SlotStatus::Processed, + SubscribeUpdateSlotStatus::Confirmed => SlotStatus::Confirmed, + SubscribeUpdateSlotStatus::Finalized => SlotStatus::Rooted, + }); + if status.is_none() { + error!("unexpected slot status: {}", update.status); + continue; + } + let slot_update = SlotUpdate { + slot: update.slot, + parent: update.parent, + status: status.expect("qed"), + }; + + slot_queue_sender + .send(slot_update) + .await + .expect("send success"); + } + UpdateOneof::Block(_) => {} + UpdateOneof::Transaction(_) => {} + } + } + Message::Snapshot(update) => { + metric_snapshots.increment(); + info!("processing snapshot..."); + for account in update.accounts.iter() { + metric_snapshot_account_writes.increment(); + metric_account_queue.set(account_write_queue_sender.len() as u64); + + match account { + (key, Some(ui_account)) => { + // TODO: Resnapshot on invalid data? + let pubkey = Pubkey::from_str(key).unwrap(); + let account: Account = ui_account.decode().unwrap(); + account_write_queue_sender + .send(AccountWrite::from(pubkey, update.slot, 0, account)) + .await + .expect("send success"); + } + (key, None) => warn!("account not found {}", key), + } + } + info!("processing snapshot done"); + } + } + } +} diff --git a/src/lib.rs b/src/lib.rs index bc83105..8bbe3b2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,26 @@ +pub mod account_write_filter; +pub mod blockhash_poller; pub mod cli; +pub mod chain_data; pub mod confirmation_strategies; +pub mod crank; +pub mod grpc_plugin_source; pub mod helpers; pub mod mango; +pub mod mango_v3_perp_crank_sink; pub mod market_markers; +pub mod metrics; pub mod rotating_queue; pub mod states; + +trait AnyhowWrap { + type Value; + fn map_err_anyhow(self) -> anyhow::Result; +} + +impl AnyhowWrap for Result { + type Value = T; + fn map_err_anyhow(self) -> anyhow::Result { + self.map_err(|err| anyhow::anyhow!("{:?}", err)) + } +} \ No newline at end of file diff --git a/src/mango.rs b/src/mango.rs index 2717b91..167df81 100644 --- a/src/mango.rs +++ b/src/mango.rs @@ -64,3 +64,4 @@ pub struct MarketConfig { pub asks_key: String, pub events_key: String, } + diff --git a/src/mango_v3_perp_crank_sink.rs b/src/mango_v3_perp_crank_sink.rs new file mode 100644 index 0000000..4f6255b --- /dev/null +++ b/src/mango_v3_perp_crank_sink.rs @@ -0,0 +1,136 @@ +use std::{ + cell::RefCell, + collections::{BTreeMap}, + convert::TryFrom, + mem::size_of, +}; + +use arrayref::array_ref; +use async_channel::Sender; +use async_trait::async_trait; +use mango::{ + instruction::consume_events, + queue::{AnyEvent, EventQueueHeader, EventType, FillEvent, OutEvent, Queue}, +}; +use solana_sdk::{ + account::ReadableAccount, + instruction::{Instruction}, + pubkey::Pubkey, +}; + +use bytemuck::cast_ref; + +use crate::{account_write_filter::AccountWriteSink, chain_data::AccountData}; + +const MAX_BACKLOG: usize = 2; +const MAX_EVENTS_PER_TX: usize = 10; + +pub struct MangoV3PerpCrankSink { + pks: BTreeMap, + group_pk: Pubkey, + cache_pk: Pubkey, + mango_v3_program: Pubkey, + instruction_sender: Sender>, +} + +impl MangoV3PerpCrankSink { + pub fn new( + pks: Vec<(Pubkey, Pubkey)>, + group_pk: Pubkey, + cache_pk: Pubkey, + mango_v3_program: Pubkey, + instruction_sender: Sender>, + ) -> Self { + Self { + pks: pks.iter().map(|e| e.clone()).collect(), + group_pk, + cache_pk, + mango_v3_program, + instruction_sender, + } + } +} + +// couldn't compile the correct struct size / math on m1, fixed sizes resolve this issue +const EVENT_SIZE: usize = 200; //size_of::(); +const QUEUE_LEN: usize = 256; +type EventQueueEvents = [AnyEvent; QUEUE_LEN]; + +#[async_trait] +impl AccountWriteSink for MangoV3PerpCrankSink { + async fn process(&self, pk: &Pubkey, account: &AccountData) -> Result<(), String> { + let account = &account.account; + + let ix: Result = { + const HEADER_SIZE: usize = size_of::(); + let header_data = array_ref![account.data(), 0, HEADER_SIZE]; + let header = RefCell::::new(*bytemuck::from_bytes(header_data)); + // trace!("evq {} seq_num {}", mkt.name, header.seq_num); + + const QUEUE_SIZE: usize = EVENT_SIZE * QUEUE_LEN; + let events_data = array_ref![account.data(), HEADER_SIZE, QUEUE_SIZE]; + let events = RefCell::::new(*bytemuck::from_bytes(events_data)); + let event_queue = Queue { + header: header.borrow_mut(), + buf: events.borrow_mut(), + }; + + // only crank if at least 1 fill or a sufficient events of other categories are buffered + let contains_fill_events = event_queue + .iter() + .find(|e| e.event_type == EventType::Fill as u8) + .is_some(); + let has_backlog = event_queue.iter().count() > MAX_BACKLOG; + if !contains_fill_events && !has_backlog { + return Err("throttled".into()); + } + + let mut mango_accounts: Vec<_> = event_queue + .iter() + .take(MAX_EVENTS_PER_TX) + .flat_map( + |e| match EventType::try_from(e.event_type).expect("mango v4 event") { + EventType::Fill => { + let fill: &FillEvent = cast_ref(e); + vec![fill.maker, fill.taker] + } + EventType::Out => { + let out: &OutEvent = cast_ref(e); + vec![out.owner] + } + EventType::Liquidate => vec![], + }, + ) + .collect(); + + let mkt_pk = self + .pks + .get(pk) + .expect(&format!("{pk:?} is a known public key")); + + let ix = consume_events( + &self.mango_v3_program, + &self.group_pk, + &self.cache_pk, + mkt_pk, + pk, + &mut mango_accounts, + MAX_EVENTS_PER_TX, + ) + .unwrap(); + + Ok(ix) + }; + + // info!( + // "evq={pk:?} count={} limit=10", + // event_queue.iter().count() + // ); + + if let Err(e) = self.instruction_sender.send(vec![ix?]).await { + return Err(e.to_string()); + } + + Ok(()) + } +} \ No newline at end of file diff --git a/src/metrics.rs b/src/metrics.rs new file mode 100644 index 0000000..5c67e94 --- /dev/null +++ b/src/metrics.rs @@ -0,0 +1,338 @@ +use serde::Deserialize; + +use { + log::*, + std::collections::HashMap, + std::fmt, + std::sync::{atomic, Arc, Mutex, RwLock}, + tokio::time, + warp::{Filter, Rejection, Reply}, +}; + +#[derive(Debug)] +enum Value { + U64 { + value: Arc, + metric_type: MetricType, + }, + I64 { + value: Arc, + metric_type: MetricType, + }, + Bool { + value: Arc>, + metric_type: MetricType, + }, +} + +#[derive(Debug, Clone)] +pub enum MetricType { + Counter, + Gauge, +} + +impl fmt::Display for MetricType { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + MetricType::Counter => { + write!(f, "counter") + } + MetricType::Gauge => { + write!(f, "gauge") + } + } + } +} + +#[derive(Debug)] +enum PrevValue { + U64(u64), + I64(i64), + Bool(bool), +} + +#[derive(Clone)] +pub struct MetricU64 { + value: Arc, +} +impl MetricU64 { + pub fn value(&self) -> u64 { + self.value.load(atomic::Ordering::Acquire) + } + + pub fn set(&mut self, value: u64) { + self.value.store(value, atomic::Ordering::Release); + } + + pub fn set_max(&mut self, value: u64) { + self.value.fetch_max(value, atomic::Ordering::AcqRel); + } + + pub fn add(&mut self, value: u64) { + self.value.fetch_add(value, atomic::Ordering::AcqRel); + } + + pub fn increment(&mut self) { + self.value.fetch_add(1, atomic::Ordering::AcqRel); + } + + pub fn decrement(&mut self) { + self.value.fetch_sub(1, atomic::Ordering::AcqRel); + } +} + +#[derive(Clone)] +pub struct MetricI64 { + value: Arc, +} +impl MetricI64 { + pub fn set(&mut self, value: i64) { + self.value.store(value, atomic::Ordering::Release); + } + + pub fn increment(&mut self) { + self.value.fetch_add(1, atomic::Ordering::AcqRel); + } + + pub fn decrement(&mut self) { + self.value.fetch_sub(1, atomic::Ordering::AcqRel); + } +} + +#[derive(Clone)] +pub struct MetricBool { + value: Arc>, +} + +impl MetricBool { + pub fn set(&self, value: bool) { + *self.value.lock().unwrap() = value; + } +} + +#[derive(Clone)] +pub struct Metrics { + registry: Arc>>, + labels: HashMap, +} + +impl Metrics { + pub fn register_u64(&self, name: String, metric_type: MetricType) -> MetricU64 { + let mut registry = self.registry.write().unwrap(); + let value = registry.entry(name).or_insert(Value::U64 { + value: Arc::new(atomic::AtomicU64::new(0)), + metric_type: metric_type, + }); + MetricU64 { + value: match value { + Value::U64 { + value: v, + metric_type: _, + } => v.clone(), + _ => panic!("bad metric type"), + }, + } + } + + pub fn register_i64(&self, name: String, metric_type: MetricType) -> MetricI64 { + let mut registry = self.registry.write().unwrap(); + let value = registry.entry(name).or_insert(Value::I64 { + value: Arc::new(atomic::AtomicI64::new(0)), + metric_type: metric_type, + }); + MetricI64 { + value: match value { + Value::I64 { + value: v, + metric_type: _, + } => v.clone(), + _ => panic!("bad metric type"), + }, + } + } + + pub fn register_bool(&self, name: String) -> MetricBool { + let mut registry = self.registry.write().unwrap(); + let value = registry.entry(name).or_insert(Value::Bool { + value: Arc::new(Mutex::new(false)), + metric_type: MetricType::Gauge, + }); + MetricBool { + value: match value { + Value::Bool { + value: v, + metric_type: _, + } => v.clone(), + _ => panic!("bad metric type"), + }, + } + } + + pub fn get_registry_vec(&self) -> Vec<(String, String, String)> { + let mut vec: Vec<(String, String, String)> = Vec::new(); + let metrics = self.registry.read().unwrap(); + for (name, value) in metrics.iter() { + let (value_str, type_str) = match value { + Value::U64 { + value: v, + metric_type: t, + } => ( + format!("{}", v.load(atomic::Ordering::Acquire)), + t.to_string(), + ), + Value::I64 { + value: v, + metric_type: t, + } => ( + format!("{}", v.load(atomic::Ordering::Acquire)), + t.to_string(), + ), + Value::Bool { + value: v, + metric_type: t, + } => { + let bool_to_int = if *v.lock().unwrap() { 1 } else { 0 }; + (format!("{}", bool_to_int), t.to_string()) + } + }; + vec.push((name.clone(), value_str, type_str)); + } + vec + } +} + +async fn handle_prometheus_poll(metrics: Metrics) -> Result { + debug!("handle_prometheus_poll"); + let label_strings_vec: Vec = metrics + .labels + .iter() + .map(|(name, value)| format!("{}=\"{}\"", name, value)) + .collect(); + let lines: Vec = metrics + .get_registry_vec() + .iter() + .map(|(name, value, type_name)| { + let sanitized_name = str::replace(name, "-", "_"); + format!( + "# HELP {} \n# TYPE {} {}\n{}{{{}}} {}", + sanitized_name, + sanitized_name, + type_name, + sanitized_name, + label_strings_vec.join(","), + value + ) + }) + .collect(); + Ok(format!("{}\n", lines.join("\n"))) +} + +pub fn with_metrics( + metrics: Metrics, +) -> impl Filter + Clone { + warp::any().map(move || metrics.clone()) +} + +#[derive(Clone, Debug, Deserialize)] +pub struct MetricsConfig { + pub output_stdout: bool, + pub output_http: bool, + // TODO: add configurable port and endpoint url + // TODO: add configurable write interval +} + + +pub fn start(config: MetricsConfig, process_name: String) -> Metrics { + let mut write_interval = time::interval(time::Duration::from_secs(60)); + + let registry = Arc::new(RwLock::new(HashMap::::new())); + let registry_c = Arc::clone(®istry); + let labels = HashMap::from([(String::from("process"), process_name)]); + let metrics_tx = Metrics { registry, labels }; + let metrics_route = warp::path!("metrics") + .and(with_metrics(metrics_tx.clone())) + .and_then(handle_prometheus_poll); + + if config.output_http { + // serve prometheus metrics endpoint + tokio::spawn(async move { + warp::serve(metrics_route).run(([0, 0, 0, 0], 9091)).await; + }); + } + + if config.output_stdout { + // periodically log to stdout + tokio::spawn(async move { + let mut previous_values = HashMap::::new(); + loop { + write_interval.tick().await; + + // Nested locking! Safe because the only other user locks registry for writing and doesn't + // acquire any interior locks. + let metrics = registry_c.read().unwrap(); + for (name, value) in metrics.iter() { + let previous_value = previous_values.get_mut(name); + match value { + Value::U64 { + value: v, + metric_type: _, + } => { + let new_value = v.load(atomic::Ordering::Acquire); + let previous_value = if let Some(PrevValue::U64(v)) = previous_value { + let prev = *v; + *v = new_value; + prev + } else { + previous_values.insert(name.clone(), PrevValue::U64(new_value)); + 0 + }; + let diff = new_value.wrapping_sub(previous_value) as i64; + info!("metric: {}: {} ({:+})", name, new_value, diff); + } + Value::I64 { + value: v, + metric_type: _, + } => { + let new_value = v.load(atomic::Ordering::Acquire); + let previous_value = if let Some(PrevValue::I64(v)) = previous_value { + let prev = *v; + *v = new_value; + prev + } else { + previous_values.insert(name.clone(), PrevValue::I64(new_value)); + 0 + }; + let diff = new_value - previous_value; + info!("metric: {}: {} ({:+})", name, new_value, diff); + } + Value::Bool { + value: v, + metric_type: _, + } => { + let new_value = v.lock().unwrap(); + let previous_value = if let Some(PrevValue::Bool(v)) = previous_value { + let mut prev = new_value.clone(); + std::mem::swap(&mut prev, v); + prev + } else { + previous_values + .insert(name.clone(), PrevValue::Bool(new_value.clone())); + false + }; + if *new_value == previous_value { + info!("metric: {}: {} (unchanged)", name, &*new_value); + } else { + info!( + "metric: {}: {} (before: {})", + name, &*new_value, previous_value + ); + } + } + } + } + } + }); + } + + metrics_tx +}